UPDATE: Adds cell context menu
This commit is contained in:
committed by
Nicolás Hatcher Andrés
parent
f96481feb8
commit
99125f1fea
@@ -8,12 +8,20 @@
|
|||||||
- New document server (Thanks Dani!)
|
- New document server (Thanks Dani!)
|
||||||
- New function FORMULATEXT
|
- New function FORMULATEXT
|
||||||
- Name Manager ([#212](https://github.com/ironcalc/IronCalc/pull/212) [#220](https://github.com/ironcalc/IronCalc/pull/220))
|
- Name Manager ([#212](https://github.com/ironcalc/IronCalc/pull/212) [#220](https://github.com/ironcalc/IronCalc/pull/220))
|
||||||
|
- Add context menu. We can now insert rows and columns. Freeze and unfreeze rows and columns. Delete rows and columns [#271]
|
||||||
|
- Add nodejs bindings [#254]
|
||||||
|
- Add python bindings for all platforms
|
||||||
|
- Add is split into the product and widget
|
||||||
|
- Add Python documentation [#260]
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fixed several issues with pasting content
|
- Fixed several issues with pasting content
|
||||||
- Fixed several issues with borders
|
- Fixed several issues with borders
|
||||||
- Fixed bug where columns and rows could be resized to negative width and height, respectively
|
- Fixed bug where columns and rows could be resized to negative width and height, respectively
|
||||||
|
- Undo/redo when add/delete sheet now works [#270]
|
||||||
|
- Numerous small fixes
|
||||||
|
- Multiple fixes to the documentation
|
||||||
|
|
||||||
## [0.2.0] - 2024-11-06 (The HN release)
|
## [0.2.0] - 2024-11-06 (The HN release)
|
||||||
|
|
||||||
|
|||||||
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -1070,7 +1070,7 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm"
|
name = "wasm"
|
||||||
version = "0.3.0"
|
version = "0.3.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ironcalc_base",
|
"ironcalc_base",
|
||||||
"serde",
|
"serde",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "wasm"
|
name = "wasm"
|
||||||
version = "0.3.0"
|
version = "0.3.2"
|
||||||
authors = ["Nicolas Hatcher <nicolas@theuniverse.today>"]
|
authors = ["Nicolas Hatcher <nicolas@theuniverse.today>"]
|
||||||
description = "IronCalc Web bindings"
|
description = "IronCalc Web bindings"
|
||||||
license = "MIT/Apache-2.0"
|
license = "MIT/Apache-2.0"
|
||||||
|
|||||||
188
webapp/IronCalc/package-lock.json
generated
188
webapp/IronCalc/package-lock.json
generated
@@ -45,7 +45,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"../../bindings/wasm/pkg": {
|
"../../bindings/wasm/pkg": {
|
||||||
"version": "0.3.0",
|
"version": "0.3.2",
|
||||||
"license": "MIT/Apache-2.0"
|
"license": "MIT/Apache-2.0"
|
||||||
},
|
},
|
||||||
"node_modules/@adobe/css-tools": {
|
"node_modules/@adobe/css-tools": {
|
||||||
@@ -1383,9 +1383,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-android-arm-eabi": {
|
"node_modules/@rollup/rollup-android-arm-eabi": {
|
||||||
"version": "4.34.2",
|
"version": "4.34.6",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.2.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.6.tgz",
|
||||||
"integrity": "sha512-6Fyg9yQbwJR+ykVdT9sid1oc2ewejS6h4wzQltmJfSW53N60G/ah9pngXGANdy9/aaE/TcUFpWosdm7JXS1WTQ==",
|
"integrity": "sha512-+GcCXtOQoWuC7hhX1P00LqjjIiS/iOouHXhMdiDSnq/1DGTox4SpUvO52Xm+div6+106r+TcvOeo/cxvyEyTgg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
@@ -1396,9 +1396,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-android-arm64": {
|
"node_modules/@rollup/rollup-android-arm64": {
|
||||||
"version": "4.34.2",
|
"version": "4.34.6",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.2.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.6.tgz",
|
||||||
"integrity": "sha512-K5GfWe+vtQ3kyEbihrimM38UgX57UqHp+oME7X/EX9Im6suwZfa7Hsr8AtzbJvukTpwMGs+4s29YMSO3rwWtsw==",
|
"integrity": "sha512-E8+2qCIjciYUnCa1AiVF1BkRgqIGW9KzJeesQqVfyRITGQN+dFuoivO0hnro1DjT74wXLRZ7QF8MIbz+luGaJA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -1409,9 +1409,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-darwin-arm64": {
|
"node_modules/@rollup/rollup-darwin-arm64": {
|
||||||
"version": "4.34.2",
|
"version": "4.34.6",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.2.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.6.tgz",
|
||||||
"integrity": "sha512-PSN58XG/V/tzqDb9kDGutUruycgylMlUE59f40ny6QIRNsTEIZsrNQTJKUN2keMMSmlzgunMFqyaGLmly39sug==",
|
"integrity": "sha512-z9Ib+OzqN3DZEjX7PDQMHEhtF+t6Mi2z/ueChQPLS/qUMKY7Ybn5A2ggFoKRNRh1q1T03YTQfBTQCJZiepESAg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -1422,9 +1422,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-darwin-x64": {
|
"node_modules/@rollup/rollup-darwin-x64": {
|
||||||
"version": "4.34.2",
|
"version": "4.34.6",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.2.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.6.tgz",
|
||||||
"integrity": "sha512-gQhK788rQJm9pzmXyfBB84VHViDERhAhzGafw+E5mUpnGKuxZGkMVDa3wgDFKT6ukLC5V7QTifzsUKdNVxp5qQ==",
|
"integrity": "sha512-PShKVY4u0FDAR7jskyFIYVyHEPCPnIQY8s5OcXkdU8mz3Y7eXDJPdyM/ZWjkYdR2m0izD9HHWA8sGcXn+Qrsyg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -1435,9 +1435,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-freebsd-arm64": {
|
"node_modules/@rollup/rollup-freebsd-arm64": {
|
||||||
"version": "4.34.2",
|
"version": "4.34.6",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.2.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.6.tgz",
|
||||||
"integrity": "sha512-eiaHgQwGPpxLC3+zTAcdKl4VsBl3r0AiJOd1Um/ArEzAjN/dbPK1nROHrVkdnoE6p7Svvn04w3f/jEZSTVHunA==",
|
"integrity": "sha512-YSwyOqlDAdKqs0iKuqvRHLN4SrD2TiswfoLfvYXseKbL47ht1grQpq46MSiQAx6rQEN8o8URtpXARCpqabqxGQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -1448,9 +1448,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-freebsd-x64": {
|
"node_modules/@rollup/rollup-freebsd-x64": {
|
||||||
"version": "4.34.2",
|
"version": "4.34.6",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.2.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.6.tgz",
|
||||||
"integrity": "sha512-lhdiwQ+jf8pewYOTG4bag0Qd68Jn1v2gO1i0mTuiD+Qkt5vNfHVK/jrT7uVvycV8ZchlzXp5HDVmhpzjC6mh0g==",
|
"integrity": "sha512-HEP4CgPAY1RxXwwL5sPFv6BBM3tVeLnshF03HMhJYCNc6kvSqBgTMmsEjb72RkZBAWIqiPUyF1JpEBv5XT9wKQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -1461,9 +1461,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
||||||
"version": "4.34.2",
|
"version": "4.34.6",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.2.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.6.tgz",
|
||||||
"integrity": "sha512-lfqTpWjSvbgQP1vqGTXdv+/kxIznKXZlI109WkIFPbud41bjigjNmOAAKoazmRGx+k9e3rtIdbq2pQZPV1pMig==",
|
"integrity": "sha512-88fSzjC5xeH9S2Vg3rPgXJULkHcLYMkh8faix8DX4h4TIAL65ekwuQMA/g2CXq8W+NJC43V6fUpYZNjaX3+IIg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
@@ -1474,9 +1474,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
|
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
|
||||||
"version": "4.34.2",
|
"version": "4.34.6",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.2.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.6.tgz",
|
||||||
"integrity": "sha512-RGjqULqIurqqv+NJTyuPgdZhka8ImMLB32YwUle2BPTDqDoXNgwFjdjQC59FbSk08z0IqlRJjrJ0AvDQ5W5lpw==",
|
"integrity": "sha512-wM4ztnutBqYFyvNeR7Av+reWI/enK9tDOTKNF+6Kk2Q96k9bwhDDOlnCUNRPvromlVXo04riSliMBs/Z7RteEg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
@@ -1487,9 +1487,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
||||||
"version": "4.34.2",
|
"version": "4.34.6",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.2.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.6.tgz",
|
||||||
"integrity": "sha512-ZvkPiheyXtXlFqHpsdgscx+tZ7hoR59vOettvArinEspq5fxSDSgfF+L5wqqJ9R4t+n53nyn0sKxeXlik7AY9Q==",
|
"integrity": "sha512-9RyprECbRa9zEjXLtvvshhw4CMrRa3K+0wcp3KME0zmBe1ILmvcVHnypZ/aIDXpRyfhSYSuN4EPdCCj5Du8FIA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -1500,9 +1500,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
||||||
"version": "4.34.2",
|
"version": "4.34.6",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.2.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.6.tgz",
|
||||||
"integrity": "sha512-UlFk+E46TZEoxD9ufLKDBzfSG7Ki03fo6hsNRRRHF+KuvNZ5vd1RRVQm8YZlGsjcJG8R252XFK0xNPay+4WV7w==",
|
"integrity": "sha512-qTmklhCTyaJSB05S+iSovfo++EwnIEZxHkzv5dep4qoszUMX5Ca4WM4zAVUMbfdviLgCSQOu5oU8YoGk1s6M9Q==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -1513,9 +1513,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-loongarch64-gnu": {
|
"node_modules/@rollup/rollup-linux-loongarch64-gnu": {
|
||||||
"version": "4.34.2",
|
"version": "4.34.6",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.2.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.6.tgz",
|
||||||
"integrity": "sha512-hJhfsD9ykx59jZuuoQgYT1GEcNNi3RCoEmbo5OGfG8RlHOiVS7iVNev9rhLKh7UBYq409f4uEw0cclTXx8nh8Q==",
|
"integrity": "sha512-4Qmkaps9yqmpjY5pvpkfOerYgKNUGzQpFxV6rnS7c/JfYbDSU0y6WpbbredB5cCpLFGJEqYX40WUmxMkwhWCjw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"loong64"
|
"loong64"
|
||||||
],
|
],
|
||||||
@@ -1526,9 +1526,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
|
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
|
||||||
"version": "4.34.2",
|
"version": "4.34.6",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.2.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.6.tgz",
|
||||||
"integrity": "sha512-g/O5IpgtrQqPegvqopvmdCF9vneLE7eqYfdPWW8yjPS8f63DNam3U4ARL1PNNB64XHZDHKpvO2Giftf43puB8Q==",
|
"integrity": "sha512-Zsrtux3PuaxuBTX/zHdLaFmcofWGzaWW1scwLU3ZbW/X+hSsFbz9wDIp6XvnT7pzYRl9MezWqEqKy7ssmDEnuQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ppc64"
|
"ppc64"
|
||||||
],
|
],
|
||||||
@@ -1539,9 +1539,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
||||||
"version": "4.34.2",
|
"version": "4.34.6",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.2.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.6.tgz",
|
||||||
"integrity": "sha512-bSQijDC96M6PuooOuXHpvXUYiIwsnDmqGU8+br2U7iPoykNi9JtMUpN7K6xml29e0evK0/g0D1qbAUzWZFHY5Q==",
|
"integrity": "sha512-aK+Zp+CRM55iPrlyKiU3/zyhgzWBxLVrw2mwiQSYJRobCURb781+XstzvA8Gkjg/hbdQFuDw44aUOxVQFycrAg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"riscv64"
|
"riscv64"
|
||||||
],
|
],
|
||||||
@@ -1552,9 +1552,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-s390x-gnu": {
|
"node_modules/@rollup/rollup-linux-s390x-gnu": {
|
||||||
"version": "4.34.2",
|
"version": "4.34.6",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.2.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.6.tgz",
|
||||||
"integrity": "sha512-49TtdeVAsdRuiUHXPrFVucaP4SivazetGUVH8CIxVsNsaPHV4PFkpLmH9LeqU/R4Nbgky9lzX5Xe1NrzLyraVA==",
|
"integrity": "sha512-WoKLVrY9ogmaYPXwTH326+ErlCIgMmsoRSx6bO+l68YgJnlOXhygDYSZe/qbUJCSiCiZAQ+tKm88NcWuUXqOzw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"s390x"
|
"s390x"
|
||||||
],
|
],
|
||||||
@@ -1565,9 +1565,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
||||||
"version": "4.34.2",
|
"version": "4.34.6",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.2.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.6.tgz",
|
||||||
"integrity": "sha512-j+jFdfOycLIQ7FWKka9Zd3qvsIyugg5LeZuHF6kFlXo6MSOc6R1w37YUVy8VpAKd81LMWGi5g9J25P09M0SSIw==",
|
"integrity": "sha512-Sht4aFvmA4ToHd2vFzwMFaQCiYm2lDFho5rPcvPBT5pCdC+GwHG6CMch4GQfmWTQ1SwRKS0dhDYb54khSrjDWw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -1578,9 +1578,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-x64-musl": {
|
"node_modules/@rollup/rollup-linux-x64-musl": {
|
||||||
"version": "4.34.2",
|
"version": "4.34.6",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.2.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.6.tgz",
|
||||||
"integrity": "sha512-aDPHyM/D2SpXfSNCVWCxyHmOqN9qb7SWkY1+vaXqMNMXslZYnwh9V/UCudl6psyG0v6Ukj7pXanIpfZwCOEMUg==",
|
"integrity": "sha512-zmmpOQh8vXc2QITsnCiODCDGXFC8LMi64+/oPpPx5qz3pqv0s6x46ps4xoycfUiVZps5PFn1gksZzo4RGTKT+A==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -1591,9 +1591,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
||||||
"version": "4.34.2",
|
"version": "4.34.6",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.2.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.6.tgz",
|
||||||
"integrity": "sha512-LQRkCyUBnAo7r8dbEdtNU08EKLCJMgAk2oP5H3R7BnUlKLqgR3dUjrLBVirmc1RK6U6qhtDw29Dimeer8d5hzQ==",
|
"integrity": "sha512-3/q1qUsO/tLqGBaD4uXsB6coVGB3usxw3qyeVb59aArCgedSF66MPdgRStUd7vbZOsko/CgVaY5fo2vkvPLWiA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -1604,9 +1604,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
||||||
"version": "4.34.2",
|
"version": "4.34.6",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.2.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.6.tgz",
|
||||||
"integrity": "sha512-wt8OhpQUi6JuPFkm1wbVi1BByeag87LDFzeKSXzIdGcX4bMLqORTtKxLoCbV57BHYNSUSOKlSL4BYYUghainYA==",
|
"integrity": "sha512-oLHxuyywc6efdKVTxvc0135zPrRdtYVjtVD5GUm55I3ODxhU/PwkQFD97z16Xzxa1Fz0AEe4W/2hzRtd+IfpOA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ia32"
|
"ia32"
|
||||||
],
|
],
|
||||||
@@ -1617,9 +1617,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
||||||
"version": "4.34.2",
|
"version": "4.34.6",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.2.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.6.tgz",
|
||||||
"integrity": "sha512-rUrqINax0TvrPBXrFKg0YbQx18NpPN3NNrgmaao9xRNbTwek7lOXObhx8tQy8gelmQ/gLaGy1WptpU2eKJZImg==",
|
"integrity": "sha512-0PVwmgzZ8+TZ9oGBmdZoQVXflbvuwzN/HRclujpl4N/q3i+y0lqLw8n1bXA8ru3sApDjlmONaNAuYr38y1Kr9w==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -3020,9 +3020,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/caniuse-lite": {
|
"node_modules/caniuse-lite": {
|
||||||
"version": "1.0.30001697",
|
"version": "1.0.30001698",
|
||||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001697.tgz",
|
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001698.tgz",
|
||||||
"integrity": "sha512-GwNPlWJin8E+d7Gxq96jxM6w0w+VFeyyXRsjU58emtkYqnbwHqXm5uT2uCmO0RQE9htWknOP4xtBlLmM/gWxvQ==",
|
"integrity": "sha512-xJ3km2oiG/MbNU8G6zIq6XRZ6HtAOVXsbOrP/blGazi52kc5Yy7b6sDA5O+FbROzRrV7BSTllLHuNvmawYUJjw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -3295,9 +3295,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/electron-to-chromium": {
|
"node_modules/electron-to-chromium": {
|
||||||
"version": "1.5.91",
|
"version": "1.5.96",
|
||||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.91.tgz",
|
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.96.tgz",
|
||||||
"integrity": "sha512-sNSHHyq048PFmZY4S90ax61q+gLCs0X0YmcOII9wG9S2XwbVr+h4VW2wWhnbp/Eys3cCwTxVF292W3qPaxIapQ==",
|
"integrity": "sha512-8AJUW6dh75Fm/ny8+kZKJzI1pgoE8bKLZlzDU2W1ENd+DXKJrx7I7l9hb8UWR4ojlnb5OlixMt00QWiYJoVw1w==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/entities": {
|
"node_modules/entities": {
|
||||||
@@ -4252,9 +4252,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/possible-typed-array-names": {
|
"node_modules/possible-typed-array-names": {
|
||||||
"version": "1.0.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
|
||||||
"integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==",
|
"integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
@@ -4550,9 +4550,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/rollup": {
|
"node_modules/rollup": {
|
||||||
"version": "4.34.2",
|
"version": "4.34.6",
|
||||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.2.tgz",
|
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.6.tgz",
|
||||||
"integrity": "sha512-sBDUoxZEaqLu9QeNalL8v3jw6WjPku4wfZGyTU7l7m1oC+rpRihXc/n/H+4148ZkGz5Xli8CHMns//fFGKvpIQ==",
|
"integrity": "sha512-wc2cBWqJgkU3Iz5oztRkQbfVkbxoz5EhnCGOrnJvnLnQ7O0WhQUYyv18qQI79O8L7DdHrrlJNeCHd4VGpnaXKQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/estree": "1.0.6"
|
"@types/estree": "1.0.6"
|
||||||
@@ -4565,25 +4565,25 @@
|
|||||||
"npm": ">=8.0.0"
|
"npm": ">=8.0.0"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@rollup/rollup-android-arm-eabi": "4.34.2",
|
"@rollup/rollup-android-arm-eabi": "4.34.6",
|
||||||
"@rollup/rollup-android-arm64": "4.34.2",
|
"@rollup/rollup-android-arm64": "4.34.6",
|
||||||
"@rollup/rollup-darwin-arm64": "4.34.2",
|
"@rollup/rollup-darwin-arm64": "4.34.6",
|
||||||
"@rollup/rollup-darwin-x64": "4.34.2",
|
"@rollup/rollup-darwin-x64": "4.34.6",
|
||||||
"@rollup/rollup-freebsd-arm64": "4.34.2",
|
"@rollup/rollup-freebsd-arm64": "4.34.6",
|
||||||
"@rollup/rollup-freebsd-x64": "4.34.2",
|
"@rollup/rollup-freebsd-x64": "4.34.6",
|
||||||
"@rollup/rollup-linux-arm-gnueabihf": "4.34.2",
|
"@rollup/rollup-linux-arm-gnueabihf": "4.34.6",
|
||||||
"@rollup/rollup-linux-arm-musleabihf": "4.34.2",
|
"@rollup/rollup-linux-arm-musleabihf": "4.34.6",
|
||||||
"@rollup/rollup-linux-arm64-gnu": "4.34.2",
|
"@rollup/rollup-linux-arm64-gnu": "4.34.6",
|
||||||
"@rollup/rollup-linux-arm64-musl": "4.34.2",
|
"@rollup/rollup-linux-arm64-musl": "4.34.6",
|
||||||
"@rollup/rollup-linux-loongarch64-gnu": "4.34.2",
|
"@rollup/rollup-linux-loongarch64-gnu": "4.34.6",
|
||||||
"@rollup/rollup-linux-powerpc64le-gnu": "4.34.2",
|
"@rollup/rollup-linux-powerpc64le-gnu": "4.34.6",
|
||||||
"@rollup/rollup-linux-riscv64-gnu": "4.34.2",
|
"@rollup/rollup-linux-riscv64-gnu": "4.34.6",
|
||||||
"@rollup/rollup-linux-s390x-gnu": "4.34.2",
|
"@rollup/rollup-linux-s390x-gnu": "4.34.6",
|
||||||
"@rollup/rollup-linux-x64-gnu": "4.34.2",
|
"@rollup/rollup-linux-x64-gnu": "4.34.6",
|
||||||
"@rollup/rollup-linux-x64-musl": "4.34.2",
|
"@rollup/rollup-linux-x64-musl": "4.34.6",
|
||||||
"@rollup/rollup-win32-arm64-msvc": "4.34.2",
|
"@rollup/rollup-win32-arm64-msvc": "4.34.6",
|
||||||
"@rollup/rollup-win32-ia32-msvc": "4.34.2",
|
"@rollup/rollup-win32-ia32-msvc": "4.34.6",
|
||||||
"@rollup/rollup-win32-x64-msvc": "4.34.2",
|
"@rollup/rollup-win32-x64-msvc": "4.34.6",
|
||||||
"fsevents": "~2.3.2"
|
"fsevents": "~2.3.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -5031,14 +5031,14 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/vite": {
|
"node_modules/vite": {
|
||||||
"version": "6.0.11",
|
"version": "6.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/vite/-/vite-6.0.11.tgz",
|
"resolved": "https://registry.npmjs.org/vite/-/vite-6.1.0.tgz",
|
||||||
"integrity": "sha512-4VL9mQPKoHy4+FE0NnRE/kbY51TOfaknxAjt3fJbGJxhIpBZiqVzlZDEesWWsuREXHwNdAoOFZ9MkPEVXczHwg==",
|
"integrity": "sha512-RjjMipCKVoR4hVfPY6GQTgveinjNuyLw+qruksLDvA5ktI1150VmcMBKmQaEWJhg/j6Uaf6dNCNA0AfdzUb/hQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"esbuild": "^0.24.2",
|
"esbuild": "^0.24.2",
|
||||||
"postcss": "^8.4.49",
|
"postcss": "^8.5.1",
|
||||||
"rollup": "^4.23.0"
|
"rollup": "^4.30.1"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"vite": "bin/vite.js"
|
"vite": "bin/vite.js"
|
||||||
|
|||||||
286
webapp/IronCalc/src/components/CellContextMenu.tsx
Normal file
286
webapp/IronCalc/src/components/CellContextMenu.tsx
Normal file
@@ -0,0 +1,286 @@
|
|||||||
|
import { Menu, MenuItem, styled } from "@mui/material";
|
||||||
|
import {
|
||||||
|
BetweenHorizontalStart,
|
||||||
|
BetweenVerticalStart,
|
||||||
|
ChevronRight,
|
||||||
|
Snowflake,
|
||||||
|
Trash2,
|
||||||
|
} from "lucide-react";
|
||||||
|
import { useRef, useState } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
|
const red_color = "rgb(235, 12, 12)";
|
||||||
|
|
||||||
|
interface CellContextMenuProps {
|
||||||
|
open: boolean;
|
||||||
|
onClose: () => void;
|
||||||
|
anchorEl: HTMLDivElement | null;
|
||||||
|
onInsertRowAbove: () => void;
|
||||||
|
onInsertRowBelow: () => void;
|
||||||
|
onInsertColumnLeft: () => void;
|
||||||
|
onInsertColumnRight: () => void;
|
||||||
|
onFreezeColumns: () => void;
|
||||||
|
onFreezeRows: () => void;
|
||||||
|
onUnfreezeColumns: () => void;
|
||||||
|
onUnfreezeRows: () => void;
|
||||||
|
onDeleteRow: () => void;
|
||||||
|
onDeleteColumn: () => void;
|
||||||
|
row: number;
|
||||||
|
column: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CellContextMenu = (properties: CellContextMenuProps) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const {
|
||||||
|
open,
|
||||||
|
onClose,
|
||||||
|
anchorEl,
|
||||||
|
onInsertRowAbove,
|
||||||
|
onInsertRowBelow,
|
||||||
|
onInsertColumnLeft,
|
||||||
|
onInsertColumnRight,
|
||||||
|
onFreezeColumns,
|
||||||
|
onFreezeRows,
|
||||||
|
onUnfreezeColumns,
|
||||||
|
onUnfreezeRows,
|
||||||
|
onDeleteRow,
|
||||||
|
onDeleteColumn,
|
||||||
|
row,
|
||||||
|
column,
|
||||||
|
} = properties;
|
||||||
|
const [freezeMenuOpen, setFreezeMenuOpen] = useState(false);
|
||||||
|
const freezeRef = useRef(null);
|
||||||
|
|
||||||
|
const [insertRowMenuOpen, setInsertRowMenuOpen] = useState(false);
|
||||||
|
const insertRowRef = useRef(null);
|
||||||
|
|
||||||
|
const [insertColumnMenuOpen, setInsertColumnMenuOpen] = useState(false);
|
||||||
|
const insertColumnRef = useRef(null);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<StyledMenu
|
||||||
|
open={open}
|
||||||
|
onClose={onClose}
|
||||||
|
anchorEl={anchorEl}
|
||||||
|
anchorOrigin={{
|
||||||
|
vertical: "top",
|
||||||
|
horizontal: "left",
|
||||||
|
}}
|
||||||
|
transformOrigin={{
|
||||||
|
vertical: "bottom",
|
||||||
|
horizontal: 6,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<StyledMenuItem
|
||||||
|
ref={insertColumnRef}
|
||||||
|
onClick={() => setInsertColumnMenuOpen(true)}
|
||||||
|
>
|
||||||
|
<BetweenVerticalStartStyled />
|
||||||
|
<ItemNameStyled>{t("cell_context.insert_column")}</ItemNameStyled>
|
||||||
|
<ChevronRightStyled />
|
||||||
|
</StyledMenuItem>
|
||||||
|
<StyledMenuItem
|
||||||
|
ref={insertRowRef}
|
||||||
|
onClick={() => setInsertRowMenuOpen(true)}
|
||||||
|
>
|
||||||
|
<BetweenHorizontalStartStyled />
|
||||||
|
<ItemNameStyled>{t("cell_context.insert_row")}</ItemNameStyled>
|
||||||
|
<ChevronRightStyled />
|
||||||
|
</StyledMenuItem>
|
||||||
|
<MenuDivider />
|
||||||
|
<StyledMenuItem ref={freezeRef} onClick={() => setFreezeMenuOpen(true)}>
|
||||||
|
<StyledSnowflake />
|
||||||
|
<ItemNameStyled>{t("cell_context.freeze")}</ItemNameStyled>
|
||||||
|
<ChevronRightStyled />
|
||||||
|
</StyledMenuItem>
|
||||||
|
<MenuDivider />
|
||||||
|
<StyledMenuItem onClick={onDeleteRow}>
|
||||||
|
<StyledTrash />
|
||||||
|
<ItemNameStyled style={{ color: red_color }}>
|
||||||
|
{t("cell_context.delete_row", { row })}
|
||||||
|
</ItemNameStyled>
|
||||||
|
</StyledMenuItem>
|
||||||
|
<StyledMenuItem onClick={onDeleteColumn}>
|
||||||
|
<StyledTrash />
|
||||||
|
<ItemNameStyled style={{ color: red_color }}>
|
||||||
|
{t("cell_context.delete_column", { column })}
|
||||||
|
</ItemNameStyled>
|
||||||
|
</StyledMenuItem>
|
||||||
|
</StyledMenu>
|
||||||
|
<StyledMenu
|
||||||
|
open={insertRowMenuOpen}
|
||||||
|
onClose={() => setInsertRowMenuOpen(false)}
|
||||||
|
anchorEl={insertRowRef.current}
|
||||||
|
anchorOrigin={{
|
||||||
|
vertical: "top",
|
||||||
|
horizontal: "right",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<StyledMenuItem
|
||||||
|
onClick={() => {
|
||||||
|
setInsertRowMenuOpen(false);
|
||||||
|
onInsertRowAbove();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ItemNameStyled>{t("cell_context.insert_row_above")}</ItemNameStyled>
|
||||||
|
</StyledMenuItem>
|
||||||
|
<StyledMenuItem
|
||||||
|
onClick={() => {
|
||||||
|
setInsertRowMenuOpen(false);
|
||||||
|
onInsertRowBelow();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ItemNameStyled>{t("cell_context.insert_row_below")}</ItemNameStyled>
|
||||||
|
</StyledMenuItem>
|
||||||
|
</StyledMenu>
|
||||||
|
<StyledMenu
|
||||||
|
open={insertColumnMenuOpen}
|
||||||
|
onClose={() => setInsertColumnMenuOpen(false)}
|
||||||
|
anchorEl={insertColumnRef.current}
|
||||||
|
anchorOrigin={{
|
||||||
|
vertical: "top",
|
||||||
|
horizontal: "right",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<StyledMenuItem
|
||||||
|
onClick={() => {
|
||||||
|
setInsertColumnMenuOpen(false);
|
||||||
|
onInsertColumnLeft();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ItemNameStyled>
|
||||||
|
{t("cell_context.insert_column_before")}
|
||||||
|
</ItemNameStyled>
|
||||||
|
</StyledMenuItem>
|
||||||
|
<StyledMenuItem
|
||||||
|
onClick={() => {
|
||||||
|
setInsertColumnMenuOpen(false);
|
||||||
|
onInsertColumnRight();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ItemNameStyled>
|
||||||
|
{t("cell_context.insert_column_after")}
|
||||||
|
</ItemNameStyled>
|
||||||
|
</StyledMenuItem>
|
||||||
|
</StyledMenu>
|
||||||
|
<StyledMenu
|
||||||
|
open={freezeMenuOpen}
|
||||||
|
onClose={() => setFreezeMenuOpen(false)}
|
||||||
|
anchorEl={freezeRef.current}
|
||||||
|
anchorOrigin={{
|
||||||
|
vertical: "top",
|
||||||
|
horizontal: "right",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<StyledMenuItem
|
||||||
|
onClick={() => {
|
||||||
|
onFreezeColumns();
|
||||||
|
setFreezeMenuOpen(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ItemNameStyled>
|
||||||
|
{t("cell_context.freeze_columns", { column })}
|
||||||
|
</ItemNameStyled>
|
||||||
|
</StyledMenuItem>
|
||||||
|
<StyledMenuItem
|
||||||
|
onClick={() => {
|
||||||
|
onFreezeRows();
|
||||||
|
setFreezeMenuOpen(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ItemNameStyled>
|
||||||
|
{t("cell_context.freeze_rows", { row })}
|
||||||
|
</ItemNameStyled>
|
||||||
|
</StyledMenuItem>
|
||||||
|
<StyledMenuItem
|
||||||
|
onClick={() => {
|
||||||
|
onUnfreezeColumns();
|
||||||
|
setFreezeMenuOpen(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ItemNameStyled>{t("cell_context.unfreeze_columns")}</ItemNameStyled>
|
||||||
|
</StyledMenuItem>
|
||||||
|
<StyledMenuItem
|
||||||
|
onClick={() => {
|
||||||
|
onUnfreezeRows();
|
||||||
|
setFreezeMenuOpen(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ItemNameStyled>{t("cell_context.unfreeze_rows")}</ItemNameStyled>
|
||||||
|
</StyledMenuItem>
|
||||||
|
</StyledMenu>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const BetweenVerticalStartStyled = styled(BetweenVerticalStart)`
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
color: #333333;
|
||||||
|
padding-right: 10px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const BetweenHorizontalStartStyled = styled(BetweenHorizontalStart)`
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
color: #333333;
|
||||||
|
padding-right: 10px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledSnowflake = styled(Snowflake)`
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
color: #333333;
|
||||||
|
padding-right: 10px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledTrash = styled(Trash2)`
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
color: ${red_color};
|
||||||
|
padding-right: 10px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledMenu = styled(Menu)({
|
||||||
|
"& .MuiPaper-root": {
|
||||||
|
borderRadius: 8,
|
||||||
|
padding: 4,
|
||||||
|
},
|
||||||
|
"& .MuiList-padding": {
|
||||||
|
padding: 0,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const StyledMenuItem = styled(MenuItem)`
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-start;
|
||||||
|
font-size: 14px;
|
||||||
|
width: calc(100% - 8px);
|
||||||
|
min-width: 172px;
|
||||||
|
margin: 0px 4px;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 8px;
|
||||||
|
height: 32px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const MenuDivider = styled("div")`
|
||||||
|
width: 100%;
|
||||||
|
margin: auto;
|
||||||
|
margin-top: 4px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
border-top: 1px solid #eeeeee;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const ItemNameStyled = styled("div")`
|
||||||
|
font-size: 12px;
|
||||||
|
color: #333;
|
||||||
|
flex-grow: 2;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const ChevronRightStyled = styled(ChevronRight)`
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default CellContextMenu;
|
||||||
@@ -240,7 +240,6 @@ const usePointer = (options: PointerSettings): PointerEvents => {
|
|||||||
onPointerMove,
|
onPointerMove,
|
||||||
onPointerUp,
|
onPointerUp,
|
||||||
onPointerHandleDown,
|
onPointerHandleDown,
|
||||||
// onContextMenu,
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import type { Model } from "@ironcalc/wasm";
|
import { type Model, columnNameFromNumber } from "@ironcalc/wasm";
|
||||||
import { styled } from "@mui/material/styles";
|
import { styled } from "@mui/material/styles";
|
||||||
import { useEffect, useLayoutEffect, useRef, useState } from "react";
|
import { useEffect, useLayoutEffect, useRef, useState } from "react";
|
||||||
|
import CellContextMenu from "./CellContextMenu";
|
||||||
import {
|
import {
|
||||||
COLUMN_WIDTH_SCALE,
|
COLUMN_WIDTH_SCALE,
|
||||||
ROW_HEIGH_SCALE,
|
ROW_HEIGH_SCALE,
|
||||||
@@ -52,6 +53,8 @@ function Worksheet(props: {
|
|||||||
const columnHeaders = useRef<HTMLDivElement>(null);
|
const columnHeaders = useRef<HTMLDivElement>(null);
|
||||||
const worksheetCanvas = useRef<WorksheetCanvas | null>(null);
|
const worksheetCanvas = useRef<WorksheetCanvas | null>(null);
|
||||||
|
|
||||||
|
const [contextMenuOpen, setContextMenuOpen] = useState(false);
|
||||||
|
|
||||||
const ignoreScrollEventRef = useRef(false);
|
const ignoreScrollEventRef = useRef(false);
|
||||||
|
|
||||||
const { model, workbookState, refresh } = props;
|
const { model, workbookState, refresh } = props;
|
||||||
@@ -147,174 +150,175 @@ function Worksheet(props: {
|
|||||||
worksheetCanvas.current = canvas;
|
worksheetCanvas.current = canvas;
|
||||||
});
|
});
|
||||||
|
|
||||||
const {
|
const { onPointerMove, onPointerDown, onPointerHandleDown, onPointerUp } =
|
||||||
onPointerMove,
|
usePointer({
|
||||||
onPointerDown,
|
model,
|
||||||
onPointerHandleDown,
|
workbookState,
|
||||||
onPointerUp,
|
refresh,
|
||||||
// onContextMenu,
|
onCellSelected: (cell: Cell, event: React.MouseEvent) => {
|
||||||
} = usePointer({
|
event.preventDefault();
|
||||||
model,
|
event.stopPropagation();
|
||||||
workbookState,
|
model.setSelectedCell(cell.row, cell.column);
|
||||||
refresh,
|
refresh();
|
||||||
onCellSelected: (cell: Cell, event: React.MouseEvent) => {
|
},
|
||||||
event.preventDefault();
|
onAreaSelecting: (cell: Cell) => {
|
||||||
event.stopPropagation();
|
|
||||||
model.setSelectedCell(cell.row, cell.column);
|
|
||||||
refresh();
|
|
||||||
},
|
|
||||||
onAreaSelecting: (cell: Cell) => {
|
|
||||||
const canvas = worksheetCanvas.current;
|
|
||||||
if (!canvas) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const { row, column } = cell;
|
|
||||||
model.onAreaSelecting(row, column);
|
|
||||||
canvas.renderSheet();
|
|
||||||
refresh();
|
|
||||||
},
|
|
||||||
onAreaSelected: () => {
|
|
||||||
const styles = workbookState.getCopyStyles();
|
|
||||||
if (styles?.length) {
|
|
||||||
model.onPasteStyles(styles);
|
|
||||||
const canvas = worksheetCanvas.current;
|
const canvas = worksheetCanvas.current;
|
||||||
if (!canvas) {
|
if (!canvas) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const { row, column } = cell;
|
||||||
|
model.onAreaSelecting(row, column);
|
||||||
canvas.renderSheet();
|
canvas.renderSheet();
|
||||||
}
|
refresh();
|
||||||
workbookState.setCopyStyles(null);
|
},
|
||||||
if (worksheetElement.current) {
|
onAreaSelected: () => {
|
||||||
worksheetElement.current.style.cursor = "auto";
|
const styles = workbookState.getCopyStyles();
|
||||||
}
|
if (styles?.length) {
|
||||||
refresh();
|
model.onPasteStyles(styles);
|
||||||
},
|
const canvas = worksheetCanvas.current;
|
||||||
onExtendToCell: (cell) => {
|
if (!canvas) {
|
||||||
const canvas = worksheetCanvas.current;
|
return;
|
||||||
if (!canvas) {
|
}
|
||||||
return;
|
canvas.renderSheet();
|
||||||
}
|
|
||||||
const { row, column } = cell;
|
|
||||||
const {
|
|
||||||
range: [rowStart, columnStart, rowEnd, columnEnd],
|
|
||||||
} = model.getSelectedView();
|
|
||||||
// We are either extending by rows or by columns
|
|
||||||
// And we could be doing it in the positive direction (downwards or right)
|
|
||||||
// or the negative direction (upwards or left)
|
|
||||||
|
|
||||||
if (
|
|
||||||
row > rowEnd &&
|
|
||||||
((column <= columnEnd && column >= columnStart) ||
|
|
||||||
(column < columnStart && columnStart - column < row - rowEnd) ||
|
|
||||||
(column > columnEnd && column - columnEnd < row - rowEnd))
|
|
||||||
) {
|
|
||||||
// rows downwards
|
|
||||||
const area = {
|
|
||||||
type: AreaType.rowsDown,
|
|
||||||
rowStart: rowEnd + 1,
|
|
||||||
rowEnd: row,
|
|
||||||
columnStart,
|
|
||||||
columnEnd,
|
|
||||||
};
|
|
||||||
workbookState.setExtendToArea(area);
|
|
||||||
canvas.renderSheet();
|
|
||||||
} else if (
|
|
||||||
row < rowStart &&
|
|
||||||
((column <= columnEnd && column >= columnStart) ||
|
|
||||||
(column < columnStart && columnStart - column < rowStart - row) ||
|
|
||||||
(column > columnEnd && column - columnEnd < rowStart - row))
|
|
||||||
) {
|
|
||||||
// rows upwards
|
|
||||||
const area = {
|
|
||||||
type: AreaType.rowsUp,
|
|
||||||
rowStart: row,
|
|
||||||
rowEnd: rowStart,
|
|
||||||
columnStart,
|
|
||||||
columnEnd,
|
|
||||||
};
|
|
||||||
workbookState.setExtendToArea(area);
|
|
||||||
canvas.renderSheet();
|
|
||||||
} else if (
|
|
||||||
column > columnEnd &&
|
|
||||||
((row <= rowEnd && row >= rowStart) ||
|
|
||||||
(row < rowStart && rowStart - row < column - columnEnd) ||
|
|
||||||
(row > rowEnd && row - rowEnd < column - columnEnd))
|
|
||||||
) {
|
|
||||||
// columns right
|
|
||||||
const area = {
|
|
||||||
type: AreaType.columnsRight,
|
|
||||||
rowStart,
|
|
||||||
rowEnd,
|
|
||||||
columnStart: columnEnd + 1,
|
|
||||||
columnEnd: column,
|
|
||||||
};
|
|
||||||
workbookState.setExtendToArea(area);
|
|
||||||
canvas.renderSheet();
|
|
||||||
} else if (
|
|
||||||
column < columnStart &&
|
|
||||||
((row <= rowEnd && row >= rowStart) ||
|
|
||||||
(row < rowStart && rowStart - row < columnStart - column) ||
|
|
||||||
(row > rowEnd && row - rowEnd < columnStart - column))
|
|
||||||
) {
|
|
||||||
// columns left
|
|
||||||
const area = {
|
|
||||||
type: AreaType.columnsLeft,
|
|
||||||
rowStart,
|
|
||||||
rowEnd,
|
|
||||||
columnStart: column,
|
|
||||||
columnEnd: columnStart,
|
|
||||||
};
|
|
||||||
workbookState.setExtendToArea(area);
|
|
||||||
canvas.renderSheet();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onExtendToEnd: () => {
|
|
||||||
const canvas = worksheetCanvas.current;
|
|
||||||
if (!canvas) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const { sheet, range } = model.getSelectedView();
|
|
||||||
const extendedArea = workbookState.getExtendToArea();
|
|
||||||
if (!extendedArea) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const rowStart = Math.min(range[0], range[2]);
|
|
||||||
const height = Math.abs(range[2] - range[0]) + 1;
|
|
||||||
const width = Math.abs(range[3] - range[1]) + 1;
|
|
||||||
const columnStart = Math.min(range[1], range[3]);
|
|
||||||
|
|
||||||
const area = { sheet, row: rowStart, column: columnStart, width, height };
|
|
||||||
|
|
||||||
switch (extendedArea.type) {
|
|
||||||
case AreaType.rowsDown:
|
|
||||||
model.autoFillRows(area, extendedArea.rowEnd);
|
|
||||||
break;
|
|
||||||
case AreaType.rowsUp: {
|
|
||||||
model.autoFillRows(area, extendedArea.rowStart);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case AreaType.columnsRight: {
|
workbookState.setCopyStyles(null);
|
||||||
model.autoFillColumns(area, extendedArea.columnEnd);
|
if (worksheetElement.current) {
|
||||||
break;
|
worksheetElement.current.style.cursor = "auto";
|
||||||
}
|
}
|
||||||
case AreaType.columnsLeft: {
|
refresh();
|
||||||
model.autoFillColumns(area, extendedArea.columnStart);
|
},
|
||||||
break;
|
onExtendToCell: (cell) => {
|
||||||
|
const canvas = worksheetCanvas.current;
|
||||||
|
if (!canvas) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
const { row, column } = cell;
|
||||||
model.setSelectedRange(
|
const {
|
||||||
Math.min(rowStart, extendedArea.rowStart),
|
range: [rowStart, columnStart, rowEnd, columnEnd],
|
||||||
Math.min(columnStart, extendedArea.columnStart),
|
} = model.getSelectedView();
|
||||||
Math.max(rowStart + height - 1, extendedArea.rowEnd),
|
// We are either extending by rows or by columns
|
||||||
Math.max(columnStart + width - 1, extendedArea.columnEnd),
|
// And we could be doing it in the positive direction (downwards or right)
|
||||||
);
|
// or the negative direction (upwards or left)
|
||||||
workbookState.clearExtendToArea();
|
|
||||||
canvas.renderSheet();
|
if (
|
||||||
},
|
row > rowEnd &&
|
||||||
canvasElement,
|
((column <= columnEnd && column >= columnStart) ||
|
||||||
worksheetElement,
|
(column < columnStart && columnStart - column < row - rowEnd) ||
|
||||||
worksheetCanvas,
|
(column > columnEnd && column - columnEnd < row - rowEnd))
|
||||||
});
|
) {
|
||||||
|
// rows downwards
|
||||||
|
const area = {
|
||||||
|
type: AreaType.rowsDown,
|
||||||
|
rowStart: rowEnd + 1,
|
||||||
|
rowEnd: row,
|
||||||
|
columnStart,
|
||||||
|
columnEnd,
|
||||||
|
};
|
||||||
|
workbookState.setExtendToArea(area);
|
||||||
|
canvas.renderSheet();
|
||||||
|
} else if (
|
||||||
|
row < rowStart &&
|
||||||
|
((column <= columnEnd && column >= columnStart) ||
|
||||||
|
(column < columnStart && columnStart - column < rowStart - row) ||
|
||||||
|
(column > columnEnd && column - columnEnd < rowStart - row))
|
||||||
|
) {
|
||||||
|
// rows upwards
|
||||||
|
const area = {
|
||||||
|
type: AreaType.rowsUp,
|
||||||
|
rowStart: row,
|
||||||
|
rowEnd: rowStart,
|
||||||
|
columnStart,
|
||||||
|
columnEnd,
|
||||||
|
};
|
||||||
|
workbookState.setExtendToArea(area);
|
||||||
|
canvas.renderSheet();
|
||||||
|
} else if (
|
||||||
|
column > columnEnd &&
|
||||||
|
((row <= rowEnd && row >= rowStart) ||
|
||||||
|
(row < rowStart && rowStart - row < column - columnEnd) ||
|
||||||
|
(row > rowEnd && row - rowEnd < column - columnEnd))
|
||||||
|
) {
|
||||||
|
// columns right
|
||||||
|
const area = {
|
||||||
|
type: AreaType.columnsRight,
|
||||||
|
rowStart,
|
||||||
|
rowEnd,
|
||||||
|
columnStart: columnEnd + 1,
|
||||||
|
columnEnd: column,
|
||||||
|
};
|
||||||
|
workbookState.setExtendToArea(area);
|
||||||
|
canvas.renderSheet();
|
||||||
|
} else if (
|
||||||
|
column < columnStart &&
|
||||||
|
((row <= rowEnd && row >= rowStart) ||
|
||||||
|
(row < rowStart && rowStart - row < columnStart - column) ||
|
||||||
|
(row > rowEnd && row - rowEnd < columnStart - column))
|
||||||
|
) {
|
||||||
|
// columns left
|
||||||
|
const area = {
|
||||||
|
type: AreaType.columnsLeft,
|
||||||
|
rowStart,
|
||||||
|
rowEnd,
|
||||||
|
columnStart: column,
|
||||||
|
columnEnd: columnStart,
|
||||||
|
};
|
||||||
|
workbookState.setExtendToArea(area);
|
||||||
|
canvas.renderSheet();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onExtendToEnd: () => {
|
||||||
|
const canvas = worksheetCanvas.current;
|
||||||
|
if (!canvas) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const { sheet, range } = model.getSelectedView();
|
||||||
|
const extendedArea = workbookState.getExtendToArea();
|
||||||
|
if (!extendedArea) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const rowStart = Math.min(range[0], range[2]);
|
||||||
|
const height = Math.abs(range[2] - range[0]) + 1;
|
||||||
|
const width = Math.abs(range[3] - range[1]) + 1;
|
||||||
|
const columnStart = Math.min(range[1], range[3]);
|
||||||
|
|
||||||
|
const area = {
|
||||||
|
sheet,
|
||||||
|
row: rowStart,
|
||||||
|
column: columnStart,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (extendedArea.type) {
|
||||||
|
case AreaType.rowsDown:
|
||||||
|
model.autoFillRows(area, extendedArea.rowEnd);
|
||||||
|
break;
|
||||||
|
case AreaType.rowsUp: {
|
||||||
|
model.autoFillRows(area, extendedArea.rowStart);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case AreaType.columnsRight: {
|
||||||
|
model.autoFillColumns(area, extendedArea.columnEnd);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case AreaType.columnsLeft: {
|
||||||
|
model.autoFillColumns(area, extendedArea.columnStart);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
model.setSelectedRange(
|
||||||
|
Math.min(rowStart, extendedArea.rowStart),
|
||||||
|
Math.min(columnStart, extendedArea.columnStart),
|
||||||
|
Math.max(rowStart + height - 1, extendedArea.rowEnd),
|
||||||
|
Math.max(columnStart + width - 1, extendedArea.columnEnd),
|
||||||
|
);
|
||||||
|
workbookState.clearExtendToArea();
|
||||||
|
canvas.renderSheet();
|
||||||
|
},
|
||||||
|
canvasElement,
|
||||||
|
worksheetElement,
|
||||||
|
worksheetCanvas,
|
||||||
|
});
|
||||||
|
|
||||||
const onScroll = (): void => {
|
const onScroll = (): void => {
|
||||||
if (!scrollElement.current || !worksheetCanvas.current) {
|
if (!scrollElement.current || !worksheetCanvas.current) {
|
||||||
@@ -340,6 +344,11 @@ function Worksheet(props: {
|
|||||||
onPointerDown={onPointerDown}
|
onPointerDown={onPointerDown}
|
||||||
onPointerMove={onPointerMove}
|
onPointerMove={onPointerMove}
|
||||||
onPointerUp={onPointerUp}
|
onPointerUp={onPointerUp}
|
||||||
|
onContextMenu={(event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
setContextMenuOpen(true);
|
||||||
|
}}
|
||||||
onDoubleClick={(event) => {
|
onDoubleClick={(event) => {
|
||||||
// Starts editing cell
|
// Starts editing cell
|
||||||
const { sheet, row, column } = model.getSelectedView();
|
const { sheet, row, column } = model.getSelectedView();
|
||||||
@@ -392,6 +401,63 @@ function Worksheet(props: {
|
|||||||
<RowResizeGuide ref={rowResizeGuide} />
|
<RowResizeGuide ref={rowResizeGuide} />
|
||||||
<ColumnHeaders ref={columnHeaders} />
|
<ColumnHeaders ref={columnHeaders} />
|
||||||
</SheetContainer>
|
</SheetContainer>
|
||||||
|
<CellContextMenu
|
||||||
|
open={contextMenuOpen}
|
||||||
|
onClose={() => setContextMenuOpen(false)}
|
||||||
|
anchorEl={cellOutline.current}
|
||||||
|
onInsertRowAbove={(): void => {
|
||||||
|
const view = model.getSelectedView();
|
||||||
|
model.insertRow(view.sheet, view.row);
|
||||||
|
setContextMenuOpen(false);
|
||||||
|
}}
|
||||||
|
onInsertRowBelow={(): void => {
|
||||||
|
const view = model.getSelectedView();
|
||||||
|
model.insertRow(view.sheet, view.row + 1);
|
||||||
|
setContextMenuOpen(false);
|
||||||
|
}}
|
||||||
|
onInsertColumnLeft={(): void => {
|
||||||
|
const view = model.getSelectedView();
|
||||||
|
model.insertColumn(view.sheet, view.column);
|
||||||
|
setContextMenuOpen(false);
|
||||||
|
}}
|
||||||
|
onInsertColumnRight={(): void => {
|
||||||
|
const view = model.getSelectedView();
|
||||||
|
model.insertColumn(view.sheet, view.column + 1);
|
||||||
|
setContextMenuOpen(false);
|
||||||
|
}}
|
||||||
|
onFreezeColumns={(): void => {
|
||||||
|
const view = model.getSelectedView();
|
||||||
|
model.setFrozenColumnsCount(view.sheet, view.column);
|
||||||
|
setContextMenuOpen(false);
|
||||||
|
}}
|
||||||
|
onFreezeRows={(): void => {
|
||||||
|
const view = model.getSelectedView();
|
||||||
|
model.setFrozenRowsCount(view.sheet, view.row);
|
||||||
|
setContextMenuOpen(false);
|
||||||
|
}}
|
||||||
|
onUnfreezeColumns={(): void => {
|
||||||
|
const sheet = model.getSelectedSheet();
|
||||||
|
model.setFrozenColumnsCount(sheet, 0);
|
||||||
|
setContextMenuOpen(false);
|
||||||
|
}}
|
||||||
|
onUnfreezeRows={(): void => {
|
||||||
|
const sheet = model.getSelectedSheet();
|
||||||
|
model.setFrozenRowsCount(sheet, 0);
|
||||||
|
setContextMenuOpen(false);
|
||||||
|
}}
|
||||||
|
onDeleteRow={(): void => {
|
||||||
|
const view = model.getSelectedView();
|
||||||
|
model.deleteRow(view.sheet, view.row);
|
||||||
|
setContextMenuOpen(false);
|
||||||
|
}}
|
||||||
|
onDeleteColumn={(): void => {
|
||||||
|
const view = model.getSelectedView();
|
||||||
|
model.deleteColumn(view.sheet, view.column);
|
||||||
|
setContextMenuOpen(false);
|
||||||
|
}}
|
||||||
|
row={model.getSelectedView().row}
|
||||||
|
column={columnNameFromNumber(model.getSelectedView().column)}
|
||||||
|
/>
|
||||||
</Wrapper>
|
</Wrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,5 +100,20 @@
|
|||||||
"edit": "Edit Range",
|
"edit": "Edit Range",
|
||||||
"apply": "Apply changes",
|
"apply": "Apply changes",
|
||||||
"discard": "Discard changes"
|
"discard": "Discard changes"
|
||||||
|
},
|
||||||
|
"cell_context": {
|
||||||
|
"insert_row_above": "Insert 1 row above",
|
||||||
|
"insert_row_below": "Insert 1 row below",
|
||||||
|
"insert_column_before": "Insert 1 column left",
|
||||||
|
"insert_column_after": "Insert 1 column right",
|
||||||
|
"freeze_columns": "Freeze up to column '{{column}}'",
|
||||||
|
"freeze_rows": "Freeze up to row '{{row}}'",
|
||||||
|
"unfreeze_rows": "Unfreeze rows",
|
||||||
|
"unfreeze_columns": "Unfreeze columns",
|
||||||
|
"delete_row": "Delete row '{{row}}'",
|
||||||
|
"delete_column": "Delete column '{{column}}'",
|
||||||
|
"freeze": "Freeze",
|
||||||
|
"insert_row": "Insert row",
|
||||||
|
"insert_column": "Insert column"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user