@rowsncolumns/spreadsheet 10.5.17 → 10.6.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (202) hide show
  1. package/dist/cjs/api/cf-data-bar.d.ts +73 -0
  2. package/dist/cjs/api/cf-data-bar.d.ts.map +1 -0
  3. package/dist/cjs/api/cf-data-bar.js +182 -0
  4. package/dist/cjs/api/cf-icons.d.ts +73 -0
  5. package/dist/cjs/api/cf-icons.d.ts.map +1 -0
  6. package/dist/cjs/api/cf-icons.js +322 -0
  7. package/dist/cjs/api/cf-overlays.d.ts +89 -3
  8. package/dist/cjs/api/cf-overlays.d.ts.map +1 -1
  9. package/dist/cjs/api/cf-overlays.js +256 -80
  10. package/dist/cjs/api/cf-priority.d.ts +34 -0
  11. package/dist/cjs/api/cf-priority.d.ts.map +1 -0
  12. package/dist/cjs/api/cf-priority.js +94 -0
  13. package/dist/cjs/api/heatmap.d.ts +7 -1
  14. package/dist/cjs/api/heatmap.d.ts.map +1 -1
  15. package/dist/cjs/api/heatmap.js +27 -11
  16. package/dist/cjs/api/selections.d.ts +2 -2
  17. package/dist/cjs/api/validation.d.ts +6 -0
  18. package/dist/cjs/api/validation.d.ts.map +1 -1
  19. package/dist/cjs/api/validation.js +10 -1
  20. package/dist/cjs/atoms/goal-seek-dialog.atom.d.ts +8 -3
  21. package/dist/cjs/atoms/goal-seek-dialog.atom.d.ts.map +1 -1
  22. package/dist/cjs/atoms/index.d.ts +4 -0
  23. package/dist/cjs/atoms/index.d.ts.map +1 -1
  24. package/dist/cjs/atoms/index.js +4 -0
  25. package/dist/cjs/components/canvas-grid/index.d.ts.map +1 -1
  26. package/dist/cjs/components/canvas-grid/index.js +194 -51
  27. package/dist/cjs/components/canvas-grid/overflow.d.ts +37 -0
  28. package/dist/cjs/components/canvas-grid/overflow.d.ts.map +1 -0
  29. package/dist/cjs/components/canvas-grid/overflow.js +49 -0
  30. package/dist/cjs/components/canvas-grid/page-breaks.d.ts +15 -0
  31. package/dist/cjs/components/canvas-grid/page-breaks.d.ts.map +1 -0
  32. package/dist/cjs/components/canvas-grid/page-breaks.js +77 -0
  33. package/dist/cjs/components/canvas-grid/typings.d.ts +32 -3
  34. package/dist/cjs/components/canvas-grid/typings.d.ts.map +1 -1
  35. package/dist/cjs/components/cell/alignment.d.ts +58 -1
  36. package/dist/cjs/components/cell/alignment.d.ts.map +1 -1
  37. package/dist/cjs/components/cell/alignment.js +144 -1
  38. package/dist/cjs/components/cell/cell-background.d.ts +2 -0
  39. package/dist/cjs/components/cell/cell-background.d.ts.map +1 -1
  40. package/dist/cjs/components/cell/cell-background.js +5 -6
  41. package/dist/cjs/components/cell/cell-backgrounds.d.ts.map +1 -1
  42. package/dist/cjs/components/cell/cell-backgrounds.js +5 -1
  43. package/dist/cjs/components/cell/cell-text-runs.js +1 -1
  44. package/dist/cjs/components/cell/index.d.ts.map +1 -1
  45. package/dist/cjs/components/cell/index.js +378 -37
  46. package/dist/cjs/components/cell/number-format-layout.d.ts +35 -0
  47. package/dist/cjs/components/cell/number-format-layout.d.ts.map +1 -0
  48. package/dist/cjs/components/cell/number-format-layout.js +106 -0
  49. package/dist/cjs/components/cell/typings.d.ts +22 -0
  50. package/dist/cjs/components/cell/typings.d.ts.map +1 -1
  51. package/dist/cjs/components/cell-editor/index.js +2 -2
  52. package/dist/cjs/components/cell-filter/index.d.ts.map +1 -1
  53. package/dist/cjs/components/cell-filter/index.js +3 -3
  54. package/dist/cjs/components/cell-overlay/index.d.ts +20 -0
  55. package/dist/cjs/components/cell-overlay/index.d.ts.map +1 -1
  56. package/dist/cjs/components/cell-overlay/index.js +155 -28
  57. package/dist/cjs/components/cf-icon-preview/index.d.ts +16 -0
  58. package/dist/cjs/components/cf-icon-preview/index.d.ts.map +1 -0
  59. package/dist/cjs/components/cf-icon-preview/index.js +48 -0
  60. package/dist/cjs/components/context-menu/index.d.ts.map +1 -1
  61. package/dist/cjs/components/context-menu/index.js +11 -3
  62. package/dist/cjs/components/embeds/embed-component.d.ts.map +1 -1
  63. package/dist/cjs/components/embeds/embed-component.js +3 -2
  64. package/dist/cjs/components/goal-seek-dialog/index.d.ts +15 -5
  65. package/dist/cjs/components/goal-seek-dialog/index.d.ts.map +1 -1
  66. package/dist/cjs/components/goal-seek-dialog/index.js +145 -42
  67. package/dist/cjs/components/hidden-markers/index.d.ts.map +1 -1
  68. package/dist/cjs/components/hidden-markers/index.js +8 -7
  69. package/dist/cjs/components/hidden-markers/style.d.ts +7 -0
  70. package/dist/cjs/components/hidden-markers/style.d.ts.map +1 -1
  71. package/dist/cjs/components/hidden-markers/style.js +13 -2
  72. package/dist/cjs/components/protect-sheet-dialog/index.d.ts +67 -0
  73. package/dist/cjs/components/protect-sheet-dialog/index.d.ts.map +1 -0
  74. package/dist/cjs/components/protect-sheet-dialog/index.js +196 -0
  75. package/dist/cjs/components/toolbar/types.d.ts +1 -1
  76. package/dist/cjs/components/toolbar/types.d.ts.map +1 -1
  77. package/dist/cjs/config.d.ts +13 -1
  78. package/dist/cjs/config.d.ts.map +1 -1
  79. package/dist/cjs/config.js +15 -3
  80. package/dist/cjs/helpers.d.ts +10 -5
  81. package/dist/cjs/helpers.d.ts.map +1 -1
  82. package/dist/cjs/helpers.js +43 -31
  83. package/dist/cjs/hooks/use-border-styles.d.ts.map +1 -1
  84. package/dist/cjs/hooks/use-border-styles.js +5 -28
  85. package/dist/cjs/hooks/use-cell-renderer.d.ts +35 -3
  86. package/dist/cjs/hooks/use-cell-renderer.d.ts.map +1 -1
  87. package/dist/cjs/hooks/use-cell-renderer.js +85 -47
  88. package/dist/cjs/hooks/use-conditional-formatting.d.ts +13 -1
  89. package/dist/cjs/hooks/use-conditional-formatting.d.ts.map +1 -1
  90. package/dist/cjs/hooks/use-conditional-formatting.js +281 -230
  91. package/dist/cjs/index.d.ts +7 -0
  92. package/dist/cjs/index.d.ts.map +1 -1
  93. package/dist/cjs/index.js +13 -1
  94. package/dist/cjs/release-date.js +1 -1
  95. package/dist/cjs/themes.d.ts +8 -0
  96. package/dist/cjs/themes.d.ts.map +1 -1
  97. package/dist/cjs/themes.js +21 -3
  98. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  99. package/dist/cjs/types.d.ts +115 -5
  100. package/dist/cjs/types.d.ts.map +1 -1
  101. package/dist/esm/api/cf-data-bar.d.ts +73 -0
  102. package/dist/esm/api/cf-data-bar.d.ts.map +1 -0
  103. package/dist/esm/api/cf-data-bar.js +178 -0
  104. package/dist/esm/api/cf-icons.d.ts +73 -0
  105. package/dist/esm/api/cf-icons.d.ts.map +1 -0
  106. package/dist/esm/api/cf-icons.js +306 -0
  107. package/dist/esm/api/cf-overlays.d.ts +89 -3
  108. package/dist/esm/api/cf-overlays.d.ts.map +1 -1
  109. package/dist/esm/api/cf-overlays.js +223 -67
  110. package/dist/esm/api/cf-priority.d.ts +34 -0
  111. package/dist/esm/api/cf-priority.d.ts.map +1 -0
  112. package/dist/esm/api/cf-priority.js +61 -0
  113. package/dist/esm/api/heatmap.d.ts +7 -1
  114. package/dist/esm/api/heatmap.d.ts.map +1 -1
  115. package/dist/esm/api/heatmap.js +24 -9
  116. package/dist/esm/api/selections.d.ts +2 -2
  117. package/dist/esm/api/validation.d.ts +6 -0
  118. package/dist/esm/api/validation.d.ts.map +1 -1
  119. package/dist/esm/api/validation.js +6 -0
  120. package/dist/esm/atoms/goal-seek-dialog.atom.d.ts +8 -3
  121. package/dist/esm/atoms/goal-seek-dialog.atom.d.ts.map +1 -1
  122. package/dist/esm/atoms/index.d.ts +4 -0
  123. package/dist/esm/atoms/index.d.ts.map +1 -1
  124. package/dist/esm/atoms/index.js +4 -0
  125. package/dist/esm/components/canvas-grid/index.d.ts.map +1 -1
  126. package/dist/esm/components/canvas-grid/index.js +163 -47
  127. package/dist/esm/components/canvas-grid/overflow.d.ts +37 -0
  128. package/dist/esm/components/canvas-grid/overflow.d.ts.map +1 -0
  129. package/dist/esm/components/canvas-grid/overflow.js +39 -0
  130. package/dist/esm/components/canvas-grid/page-breaks.d.ts +15 -0
  131. package/dist/esm/components/canvas-grid/page-breaks.d.ts.map +1 -0
  132. package/dist/esm/components/canvas-grid/page-breaks.js +50 -0
  133. package/dist/esm/components/canvas-grid/typings.d.ts +32 -3
  134. package/dist/esm/components/canvas-grid/typings.d.ts.map +1 -1
  135. package/dist/esm/components/cell/alignment.d.ts +58 -1
  136. package/dist/esm/components/cell/alignment.d.ts.map +1 -1
  137. package/dist/esm/components/cell/alignment.js +110 -1
  138. package/dist/esm/components/cell/cell-background.d.ts +2 -0
  139. package/dist/esm/components/cell/cell-background.d.ts.map +1 -1
  140. package/dist/esm/components/cell/cell-background.js +4 -5
  141. package/dist/esm/components/cell/cell-backgrounds.d.ts.map +1 -1
  142. package/dist/esm/components/cell/cell-backgrounds.js +5 -1
  143. package/dist/esm/components/cell/cell-text-runs.js +2 -2
  144. package/dist/esm/components/cell/index.d.ts.map +1 -1
  145. package/dist/esm/components/cell/index.js +339 -39
  146. package/dist/esm/components/cell/number-format-layout.d.ts +35 -0
  147. package/dist/esm/components/cell/number-format-layout.d.ts.map +1 -0
  148. package/dist/esm/components/cell/number-format-layout.js +99 -0
  149. package/dist/esm/components/cell/typings.d.ts +22 -0
  150. package/dist/esm/components/cell/typings.d.ts.map +1 -1
  151. package/dist/esm/components/cell-editor/index.js +2 -2
  152. package/dist/esm/components/cell-filter/index.d.ts.map +1 -1
  153. package/dist/esm/components/cell-filter/index.js +4 -4
  154. package/dist/esm/components/cell-overlay/index.d.ts +20 -0
  155. package/dist/esm/components/cell-overlay/index.d.ts.map +1 -1
  156. package/dist/esm/components/cell-overlay/index.js +111 -25
  157. package/dist/esm/components/cf-icon-preview/index.d.ts +16 -0
  158. package/dist/esm/components/cf-icon-preview/index.d.ts.map +1 -0
  159. package/dist/esm/components/cf-icon-preview/index.js +41 -0
  160. package/dist/esm/components/context-menu/index.d.ts.map +1 -1
  161. package/dist/esm/components/context-menu/index.js +11 -3
  162. package/dist/esm/components/embeds/embed-component.d.ts.map +1 -1
  163. package/dist/esm/components/embeds/embed-component.js +4 -3
  164. package/dist/esm/components/goal-seek-dialog/index.d.ts +15 -5
  165. package/dist/esm/components/goal-seek-dialog/index.d.ts.map +1 -1
  166. package/dist/esm/components/goal-seek-dialog/index.js +126 -29
  167. package/dist/esm/components/hidden-markers/index.d.ts.map +1 -1
  168. package/dist/esm/components/hidden-markers/index.js +9 -8
  169. package/dist/esm/components/hidden-markers/style.d.ts +7 -0
  170. package/dist/esm/components/hidden-markers/style.d.ts.map +1 -1
  171. package/dist/esm/components/hidden-markers/style.js +8 -1
  172. package/dist/esm/components/protect-sheet-dialog/index.d.ts +67 -0
  173. package/dist/esm/components/protect-sheet-dialog/index.d.ts.map +1 -0
  174. package/dist/esm/components/protect-sheet-dialog/index.js +154 -0
  175. package/dist/esm/components/toolbar/types.d.ts +1 -1
  176. package/dist/esm/components/toolbar/types.d.ts.map +1 -1
  177. package/dist/esm/config.d.ts +13 -1
  178. package/dist/esm/config.d.ts.map +1 -1
  179. package/dist/esm/config.js +13 -1
  180. package/dist/esm/helpers.d.ts +10 -5
  181. package/dist/esm/helpers.d.ts.map +1 -1
  182. package/dist/esm/helpers.js +40 -28
  183. package/dist/esm/hooks/use-border-styles.d.ts.map +1 -1
  184. package/dist/esm/hooks/use-border-styles.js +5 -26
  185. package/dist/esm/hooks/use-cell-renderer.d.ts +35 -3
  186. package/dist/esm/hooks/use-cell-renderer.d.ts.map +1 -1
  187. package/dist/esm/hooks/use-cell-renderer.js +83 -42
  188. package/dist/esm/hooks/use-conditional-formatting.d.ts +13 -1
  189. package/dist/esm/hooks/use-conditional-formatting.d.ts.map +1 -1
  190. package/dist/esm/hooks/use-conditional-formatting.js +215 -120
  191. package/dist/esm/index.d.ts +7 -0
  192. package/dist/esm/index.d.ts.map +1 -1
  193. package/dist/esm/index.js +7 -0
  194. package/dist/esm/release-date.js +1 -1
  195. package/dist/esm/themes.d.ts +8 -0
  196. package/dist/esm/themes.d.ts.map +1 -1
  197. package/dist/esm/themes.js +20 -3
  198. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  199. package/dist/esm/types.d.ts +115 -5
  200. package/dist/esm/types.d.ts.map +1 -1
  201. package/dist/spreadsheet.min.css +1 -1
  202. package/package.json +4 -4
@@ -1 +1 @@
1
- {"version":3,"file":"embed-component.d.ts","sourceRoot":"","sources":["../../../../components/embeds/embed-component.tsx"],"names":[],"mappings":"AASA,OAAO,KAAe,MAAM,OAAO,CAAC;AAEpC,OAAO,KAAK,EACV,cAAc,EAKf,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAKhF,MAAM,MAAM,mBAAmB,GAAG;IAChC,KAAK,EAAE,cAAc,CAAC;IACtB,KAAK,EAAE,gBAAgB,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,aAAa,EAAE,eAAe,CAAC,eAAe,CAAC,CAAC;IAChD,kBAAkB,EAAE,eAAe,CAAC,oBAAoB,CAAC,CAAC;CAC3D,CAAC;AAEF,eAAO,MAAM,cAAc,wHAUtB,mBAAmB,uBA4NvB,CAAC"}
1
+ {"version":3,"file":"embed-component.d.ts","sourceRoot":"","sources":["../../../../components/embeds/embed-component.tsx"],"names":[],"mappings":"AASA,OAAO,KAAe,MAAM,OAAO,CAAC;AAEpC,OAAO,KAAK,EACV,cAAc,EAKf,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAKhF,MAAM,MAAM,mBAAmB,GAAG;IAChC,KAAK,EAAE,cAAc,CAAC;IACtB,KAAK,EAAE,gBAAgB,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,aAAa,EAAE,eAAe,CAAC,eAAe,CAAC,CAAC;IAChD,kBAAkB,EAAE,eAAe,CAAC,oBAAoB,CAAC,CAAC;CAC3D,CAAC;AAEF,eAAO,MAAM,cAAc,wHAUtB,mBAAmB,uBA+NvB,CAAC"}
@@ -20,7 +20,7 @@ exports.EmbedComponent = (0, react_1.memo)(function (_a) {
20
20
  ? (0, themes_1.getStringifiedColor)(spec.textFormat.color, theme)
21
21
  : undefined;
22
22
  var textStyle = {
23
- fontFamily: ((_b = spec.textFormat) === null || _b === void 0 ? void 0 : _b.fontFamily) || undefined,
23
+ fontFamily: (0, themes_1.resolveThemeFontFamily)((_b = spec.textFormat) === null || _b === void 0 ? void 0 : _b.fontFamily, theme) || undefined,
24
24
  fontSize: ((_c = spec.textFormat) === null || _c === void 0 ? void 0 : _c.fontSize)
25
25
  ? "".concat(spec.textFormat.fontSize * (((_d = spec.textFormat) === null || _d === void 0 ? void 0 : _d.baselineOffset) ? 0.58 : 1), "px")
26
26
  : ((_e = spec.textFormat) === null || _e === void 0 ? void 0 : _e.baselineOffset)
@@ -80,7 +80,8 @@ exports.EmbedComponent = (0, react_1.memo)(function (_a) {
80
80
  react_1.default.createElement("div", { style: textStyle }, spec.richText.map(function (run, index) {
81
81
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
82
82
  var runStyle = {
83
- fontFamily: ((_a = run.format) === null || _a === void 0 ? void 0 : _a.fontFamily) || undefined,
83
+ fontFamily: (0, themes_1.resolveThemeFontFamily)((_a = run.format) === null || _a === void 0 ? void 0 : _a.fontFamily, theme) ||
84
+ undefined,
84
85
  fontSize: ((_b = run.format) === null || _b === void 0 ? void 0 : _b.fontSize)
85
86
  ? "".concat(run.format.fontSize * (((_c = run.format) === null || _c === void 0 ? void 0 : _c.baselineOffset) ? 0.58 : 1), "px")
86
87
  : ((_d = run.format) === null || _d === void 0 ? void 0 : _d.baselineOffset)
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import type { GoalSeekResult } from "../../types";
2
+ import type { GoalSeekResult, GoalSeekTargetOptions } from "../../types";
3
3
  export type GoalSeekDialogProps = {
4
4
  /** Controls visibility. */
5
5
  open: boolean;
@@ -9,17 +9,27 @@ export type GoalSeekDialogProps = {
9
9
  /**
10
10
  * Runs the search with the three fields (A1 references + the numeric
11
11
  * target). Resolves to the result, or `undefined` when the engine reports
12
- * none (the rnc engine iterates natively and streams the cells back).
12
+ * none. With `options` (a one-sided target or a round answer) it only
13
+ * proposes `candidates`; nothing is written until `onCommit`.
13
14
  */
14
- onApply(setCell: string, targetValue: number, changingCell: string): Promise<GoalSeekResult | undefined>;
15
+ onApply(setCell: string, targetValue: number, changingCell: string, options?: GoalSeekTargetOptions): Promise<GoalSeekResult | undefined>;
16
+ /** Writes the candidate the user picked into the changing cell. */
17
+ onCommit?(changingCell: string, value: number): void;
15
18
  };
16
19
  /** Excel's status sentence for a finished search. */
17
20
  export declare const goalSeekStatusText: (setCell: string, result: GoalSeekResult | undefined) => string;
21
+ /** A one-sided or rounded search's default tolerance: 1% of the target (0.001 for zero). */
22
+ export declare const defaultGoalSeekTolerance: (targetValue: number) => number;
23
+ /** The status sentence of a one-sided or rounded search. */
24
+ export declare const goalSeekCandidatesStatusText: (setCell: string, result: GoalSeekResult | undefined, targetValue: number, options: GoalSeekTargetOptions) => string;
18
25
  /**
19
26
  * Excel's Goal Seek dialog: Set cell / To value / By changing cell, then the
20
- * Goal Seek Status sentence with target and current value.
27
+ * Goal Seek Status sentence with target and current value. Beyond Excel, the
28
+ * target can be one-sided ("at least" / "at most") and the answer rounded to a
29
+ * natural number within a tolerance: the status then lists up to three
30
+ * candidates, and the picked one is applied.
21
31
  */
22
- export declare const GoalSeekDialog: React.MemoExoticComponent<({ open, onOpenChange, initialSetCell, onApply }: GoalSeekDialogProps) => React.JSX.Element>;
32
+ export declare const GoalSeekDialog: React.MemoExoticComponent<({ open, onOpenChange, initialSetCell, onApply, onCommit }: GoalSeekDialogProps) => React.JSX.Element>;
23
33
  /**
24
34
  * Host-mounted, atom-driven wrapper around {@link GoalSeekDialog}. Mount
25
35
  * once in the host; the context menu opens it via `useOpenGoalSeekDialog`
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../components/goal-seek-dialog/index.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAiD,MAAM,OAAO,CAAC;AAMtE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,MAAM,MAAM,mBAAmB,GAAG;IAChC,2BAA2B;IAC3B,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;IAClC,4DAA4D;IAC5D,cAAc,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,OAAO,CACL,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC,CAAC;CACxC,CAAC;AAKF,qDAAqD;AACrD,eAAO,MAAM,kBAAkB,GAC7B,SAAS,MAAM,EACf,QAAQ,cAAc,GAAG,SAAS,KACjC,MAKF,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,cAAc,8EACyB,mBAAmB,uBAyJtE,CAAC;AAIF;;;;GAIG;AACH,eAAO,MAAM,kBAAkB;;;CAkB9B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../components/goal-seek-dialog/index.tsx"],"names":[],"mappings":"AAaA,OAAO,KAA0D,MAAM,OAAO,CAAC;AAM/E,OAAO,KAAK,EAEV,cAAc,EACd,qBAAqB,EACtB,MAAM,aAAa,CAAC;AAErB,MAAM,MAAM,mBAAmB,GAAG;IAChC,2BAA2B;IAC3B,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;IAClC,4DAA4D;IAC5D,cAAc,EAAE,MAAM,CAAC;IACvB;;;;;OAKG;IACH,OAAO,CACL,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,qBAAqB,GAC9B,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC,CAAC;IACvC,mEAAmE;IACnE,QAAQ,CAAC,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtD,CAAC;AAKF,qDAAqD;AACrD,eAAO,MAAM,kBAAkB,GAC7B,SAAS,MAAM,EACf,QAAQ,cAAc,GAAG,SAAS,KACjC,MAKF,CAAC;AAEF,4FAA4F;AAC5F,eAAO,MAAM,wBAAwB,GAAI,aAAa,MAAM,WACF,CAAC;AAW3D,4DAA4D;AAC5D,eAAO,MAAM,4BAA4B,GACvC,SAAS,MAAM,EACf,QAAQ,cAAc,GAAG,SAAS,EAClC,aAAa,MAAM,EACnB,SAAS,qBAAqB,KAC7B,MASF,CAAC;AAUF;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,wFACmC,mBAAmB,uBA0ShF,CAAC;AAIF;;;;GAIG;AACH,eAAO,MAAM,kBAAkB;;;CAqB9B,CAAC"}
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.GoalSeekDialogHost = exports.GoalSeekDialog = exports.goalSeekStatusText = void 0;
3
+ exports.GoalSeekDialogHost = exports.GoalSeekDialog = exports.goalSeekCandidatesStatusText = exports.defaultGoalSeekTolerance = exports.goalSeekStatusText = void 0;
4
4
  var tslib_1 = require("tslib");
5
5
  var icons_1 = require("@rowsncolumns/icons");
6
6
  var ui_1 = require("@rowsncolumns/ui");
@@ -19,37 +19,75 @@ var goalSeekStatusText = function (setCell, result) {
19
19
  : "Goal Seeking with Cell ".concat(setCell, " may not have found a solution.");
20
20
  };
21
21
  exports.goalSeekStatusText = goalSeekStatusText;
22
+ /** A one-sided or rounded search's default tolerance: 1% of the target (0.001 for zero). */
23
+ var defaultGoalSeekTolerance = function (targetValue) {
24
+ return targetValue === 0 ? 0.001 : Math.abs(targetValue) * 0.01;
25
+ };
26
+ exports.defaultGoalSeekTolerance = defaultGoalSeekTolerance;
27
+ /** A value as the status list shows it: up to 12 significant digits, no binary noise. */
28
+ var formatGoalSeekNumber = function (value) { return String(Number(value.toPrecision(12))); };
29
+ var MODE_LABELS = {
30
+ exact: "exactly",
31
+ atLeast: "at least",
32
+ atMost: "at most",
33
+ };
34
+ /** The status sentence of a one-sided or rounded search. */
35
+ var goalSeekCandidatesStatusText = function (setCell, result, targetValue, options) {
36
+ var _a, _b, _c, _d;
37
+ var count = (_b = (_a = result === null || result === void 0 ? void 0 : result.candidates) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0;
38
+ var goal = "".concat(MODE_LABELS[(_c = options.mode) !== null && _c !== void 0 ? _c : "exact"], " ").concat(formatGoalSeekNumber(targetValue));
39
+ if (count === 0) {
40
+ var within = (_d = options.tolerance) !== null && _d !== void 0 ? _d : (0, exports.defaultGoalSeekTolerance)(targetValue);
41
+ return "Goal Seeking with Cell ".concat(setCell, " found no value ").concat(goal, " within ").concat(formatGoalSeekNumber(within), ".");
42
+ }
43
+ var answers = count === 1 ? "1 value" : "".concat(count, " values");
44
+ return "Goal Seeking with Cell ".concat(setCell, " found ").concat(answers, " ").concat(goal, ".");
45
+ };
46
+ exports.goalSeekCandidatesStatusText = goalSeekCandidatesStatusText;
22
47
  /**
23
48
  * Excel's Goal Seek dialog: Set cell / To value / By changing cell, then the
24
- * Goal Seek Status sentence with target and current value.
49
+ * Goal Seek Status sentence with target and current value. Beyond Excel, the
50
+ * target can be one-sided ("at least" / "at most") and the answer rounded to a
51
+ * natural number within a tolerance: the status then lists up to three
52
+ * candidates, and the picked one is applied.
25
53
  */
26
54
  exports.GoalSeekDialog = (0, react_1.memo)(function (_a) {
27
- var open = _a.open, onOpenChange = _a.onOpenChange, initialSetCell = _a.initialSetCell, onApply = _a.onApply;
55
+ var open = _a.open, onOpenChange = _a.onOpenChange, initialSetCell = _a.initialSetCell, onApply = _a.onApply, onCommit = _a.onCommit;
28
56
  var _b = tslib_1.__read((0, react_1.useState)(initialSetCell), 2), setCell = _b[0], setSetCell = _b[1];
29
57
  var _c = tslib_1.__read((0, react_1.useState)(""), 2), target = _c[0], setTarget = _c[1];
30
58
  var _d = tslib_1.__read((0, react_1.useState)(""), 2), changingCell = _d[0], setChangingCell = _d[1];
31
- var _e = tslib_1.__read((0, react_1.useState)(undefined), 2), error = _e[0], setError = _e[1];
32
- var _f = tslib_1.__read((0, react_1.useState)(false), 2), busy = _f[0], setBusy = _f[1];
33
- var _g = tslib_1.__read((0, react_1.useState)(undefined), 2), result = _g[0], setResult = _g[1];
59
+ var _e = tslib_1.__read((0, react_1.useState)("exact"), 2), mode = _e[0], setMode = _e[1];
60
+ var _f = tslib_1.__read((0, react_1.useState)(false), 2), round = _f[0], setRound = _f[1];
61
+ var _g = tslib_1.__read((0, react_1.useState)(""), 2), tolerance = _g[0], setTolerance = _g[1];
62
+ var _h = tslib_1.__read((0, react_1.useState)(undefined), 2), error = _h[0], setError = _h[1];
63
+ var _j = tslib_1.__read((0, react_1.useState)(false), 2), busy = _j[0], setBusy = _j[1];
64
+ var _k = tslib_1.__read((0, react_1.useState)(undefined), 2), outcome = _k[0], setOutcome = _k[1];
65
+ var _l = tslib_1.__read((0, react_1.useState)(0), 2), picked = _l[0], setPicked = _l[1];
34
66
  (0, react_1.useEffect)(function () {
35
67
  if (open) {
36
68
  setSetCell(initialSetCell);
37
69
  setTarget("");
38
70
  setChangingCell("");
71
+ setMode("exact");
72
+ setRound(false);
73
+ setTolerance("");
39
74
  setError(undefined);
40
75
  setBusy(false);
41
- setResult(undefined);
76
+ setOutcome(undefined);
77
+ setPicked(0);
42
78
  }
43
79
  // Only reset on open transitions.
44
80
  // eslint-disable-next-line react-hooks/exhaustive-deps
45
81
  }, [open]);
82
+ var beyondExcel = round || mode !== "exact";
46
83
  var submit = (0, react_1.useCallback)(function (event) { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
47
- var targetValue, outcome, err_1;
48
- return tslib_1.__generator(this, function (_a) {
49
- switch (_a.label) {
84
+ var targetValue, toleranceValue, options, set, changing, result, _a, err_1;
85
+ return tslib_1.__generator(this, function (_b) {
86
+ switch (_b.label) {
50
87
  case 0:
51
88
  event.preventDefault();
52
89
  targetValue = Number(target.trim());
90
+ toleranceValue = Number(tolerance.trim());
53
91
  if (!isCellReference(setCell)) {
54
92
  setError("Set cell must be a single cell reference, e.g. B4.");
55
93
  return [2 /*return*/];
@@ -62,63 +100,126 @@ exports.GoalSeekDialog = (0, react_1.memo)(function (_a) {
62
100
  setError("By changing cell must be a single cell reference, e.g. A1.");
63
101
  return [2 /*return*/];
64
102
  }
103
+ if (beyondExcel &&
104
+ tolerance.trim() !== "" &&
105
+ (!Number.isFinite(toleranceValue) || toleranceValue < 0)) {
106
+ setError("Within must be a positive number.");
107
+ return [2 /*return*/];
108
+ }
109
+ options = beyondExcel
110
+ ? tslib_1.__assign({ mode: mode, round: round }, (tolerance.trim() !== "" ? { tolerance: toleranceValue } : {})) : undefined;
111
+ set = setCell.trim().toUpperCase();
112
+ changing = changingCell.trim().toUpperCase();
65
113
  setError(undefined);
66
114
  setBusy(true);
67
- _a.label = 1;
115
+ _b.label = 1;
68
116
  case 1:
69
- _a.trys.push([1, 3, 4, 5]);
70
- return [4 /*yield*/, onApply(setCell.trim().toUpperCase(), targetValue, changingCell.trim().toUpperCase())];
117
+ _b.trys.push([1, 6, 7, 8]);
118
+ if (!options) return [3 /*break*/, 3];
119
+ return [4 /*yield*/, onApply(set, targetValue, changing, options)];
71
120
  case 2:
72
- outcome = _a.sent();
73
- setResult({ setCell: setCell.trim().toUpperCase(), result: outcome });
74
- return [3 /*break*/, 5];
75
- case 3:
76
- err_1 = _a.sent();
77
- setError(err_1 instanceof Error ? err_1.message : "Goal Seek failed.");
121
+ _a = _b.sent();
78
122
  return [3 /*break*/, 5];
123
+ case 3: return [4 /*yield*/, onApply(set, targetValue, changing)];
79
124
  case 4:
125
+ _a = _b.sent();
126
+ _b.label = 5;
127
+ case 5:
128
+ result = _a;
129
+ setPicked(0);
130
+ setOutcome({ setCell: set, changingCell: changing, targetValue: targetValue, options: options, result: result });
131
+ return [3 /*break*/, 8];
132
+ case 6:
133
+ err_1 = _b.sent();
134
+ setError(err_1 instanceof Error ? err_1.message : "Goal Seek failed.");
135
+ return [3 /*break*/, 8];
136
+ case 7:
80
137
  setBusy(false);
81
138
  return [7 /*endfinally*/];
82
- case 5: return [2 /*return*/];
139
+ case 8: return [2 /*return*/];
83
140
  }
84
141
  });
85
- }); }, [setCell, target, changingCell, onApply]);
86
- return (react_1.default.createElement(ui_1.Dialog, { open: open, onOpenChange: onOpenChange },
87
- react_1.default.createElement(ui_1.DialogContent, { className: "w-[360px] max-w-[92vw] pointer-events-auto" },
88
- react_1.default.createElement(ui_1.DialogTitle, null, result ? "Goal Seek Status" : "Goal Seek"),
89
- react_1.default.createElement(ui_1.DialogDescription, null, "Find the input value that makes a formula reach a target."),
90
- react_1.default.createElement(ui_1.DialogCloseButton, { onClick: function () { return onOpenChange(false); } },
91
- react_1.default.createElement(icons_1.Cross1Icon, null)),
92
- react_1.default.createElement(ui_1.DialogBody, { className: "flex flex-col gap-3 font-system text-sm" }, result ? (react_1.default.createElement("div", { className: "flex flex-col gap-2", role: "status" },
93
- react_1.default.createElement("div", null, (0, exports.goalSeekStatusText)(result.setCell, result.result)),
94
- result.result ? (react_1.default.createElement("dl", { className: "grid grid-cols-2 gap-1 text-xs" },
142
+ }); }, [setCell, target, changingCell, mode, round, tolerance, beyondExcel, onApply]);
143
+ var candidates = (0, react_1.useMemo)(function () { var _a, _b; return ((outcome === null || outcome === void 0 ? void 0 : outcome.options) ? ((_b = (_a = outcome.result) === null || _a === void 0 ? void 0 : _a.candidates) !== null && _b !== void 0 ? _b : []) : []); }, [outcome]);
144
+ var applyPicked = (0, react_1.useCallback)(function () {
145
+ var candidate = candidates[picked];
146
+ if (outcome && candidate)
147
+ onCommit === null || onCommit === void 0 ? void 0 : onCommit(outcome.changingCell, candidate.value);
148
+ onOpenChange(false);
149
+ }, [candidates, picked, outcome, onCommit, onOpenChange]);
150
+ var renderStatus = function (current) {
151
+ if (!current.options) {
152
+ return (react_1.default.createElement(react_1.default.Fragment, null,
153
+ react_1.default.createElement("div", null, (0, exports.goalSeekStatusText)(current.setCell, current.result)),
154
+ current.result ? (react_1.default.createElement("dl", { className: "grid grid-cols-2 gap-1 text-xs" },
95
155
  react_1.default.createElement("dt", { className: "text-rnc-foreground/70" }, "Target value:"),
96
- react_1.default.createElement("dd", null, result.result.targetValue),
156
+ react_1.default.createElement("dd", null, current.result.targetValue),
97
157
  react_1.default.createElement("dt", { className: "text-rnc-foreground/70" }, "Current value:"),
98
- react_1.default.createElement("dd", null, result.result.currentValue === undefined
158
+ react_1.default.createElement("dd", null, current.result.currentValue === undefined
99
159
  ? "—"
100
- : String(result.result.currentValue)))) : null,
160
+ : String(current.result.currentValue)))) : null,
101
161
  react_1.default.createElement(ui_1.Separator, null),
102
162
  react_1.default.createElement("div", { className: "flex justify-end gap-2" },
103
- react_1.default.createElement(ui_1.Button, { size: "sm", type: "button", onClick: function () { return onOpenChange(false); } }, "OK")))) : (react_1.default.createElement("form", { className: "flex flex-col gap-3", onSubmit: submit },
163
+ react_1.default.createElement(ui_1.Button, { size: "sm", type: "button", onClick: function () { return onOpenChange(false); } }, "OK"))));
164
+ }
165
+ return (react_1.default.createElement(react_1.default.Fragment, null,
166
+ react_1.default.createElement("div", null, (0, exports.goalSeekCandidatesStatusText)(current.setCell, current.result, current.targetValue, current.options)),
167
+ candidates.length > 0 ? (react_1.default.createElement("fieldset", { className: "flex flex-col gap-1 min-w-0" },
168
+ react_1.default.createElement("legend", { className: "text-xs font-medium mb-1" },
169
+ "Value for ",
170
+ current.changingCell,
171
+ ":"),
172
+ candidates.map(function (candidate, index) { return (react_1.default.createElement("label", { key: candidate.value, className: "flex items-center gap-2 text-xs py-0.5 cursor-pointer" },
173
+ react_1.default.createElement("input", { type: "radio", name: "goal-seek-candidate", value: index, checked: picked === index, onChange: function () { return setPicked(index); } }),
174
+ react_1.default.createElement("span", null,
175
+ formatGoalSeekNumber(candidate.value),
176
+ react_1.default.createElement("span", { className: "text-rnc-foreground/70" },
177
+ " ",
178
+ "\u2192 ",
179
+ current.setCell,
180
+ " = ",
181
+ formatGoalSeekNumber(candidate.currentValue))))); }))) : null,
182
+ react_1.default.createElement(ui_1.Separator, null),
183
+ react_1.default.createElement("div", { className: "flex justify-end gap-2" }, candidates.length > 0 ? (react_1.default.createElement(react_1.default.Fragment, null,
184
+ react_1.default.createElement(ui_1.Button, { type: "button", variant: "outline", size: "sm", onClick: function () { return onOpenChange(false); } }, "Cancel"),
185
+ react_1.default.createElement(ui_1.Button, { size: "sm", type: "button", onClick: applyPicked }, "Apply"))) : (react_1.default.createElement(ui_1.Button, { size: "sm", type: "button", onClick: function () { return onOpenChange(false); } }, "OK")))));
186
+ };
187
+ return (react_1.default.createElement(ui_1.Dialog, { open: open, onOpenChange: onOpenChange },
188
+ react_1.default.createElement(ui_1.DialogContent, { className: "w-[360px] max-w-[92vw] pointer-events-auto" },
189
+ react_1.default.createElement(ui_1.DialogTitle, null, outcome ? "Goal Seek Status" : "Goal Seek"),
190
+ react_1.default.createElement(ui_1.DialogDescription, null, "Find the input value that makes a formula reach a target."),
191
+ react_1.default.createElement(ui_1.DialogCloseButton, { onClick: function () { return onOpenChange(false); } },
192
+ react_1.default.createElement(icons_1.Cross1Icon, null)),
193
+ react_1.default.createElement(ui_1.DialogBody, { className: "flex flex-col gap-3 font-system text-sm" }, outcome ? (react_1.default.createElement("div", { className: "flex flex-col gap-2", role: "status" }, renderStatus(outcome))) : (react_1.default.createElement("form", { className: "flex flex-col gap-3", onSubmit: submit },
104
194
  react_1.default.createElement("label", { className: "flex flex-col gap-1 text-xs font-medium" },
105
195
  "Set cell:",
106
196
  react_1.default.createElement(ui_1.Input, { autoFocus: true, value: setCell, "aria-label": "Set cell", onChange: function (e) {
107
197
  setSetCell(e.target.value);
108
198
  setError(undefined);
109
199
  } })),
110
- react_1.default.createElement("label", { className: "flex flex-col gap-1 text-xs font-medium" },
200
+ react_1.default.createElement("div", { className: "flex flex-col gap-1 text-xs font-medium" },
111
201
  "To value:",
112
- react_1.default.createElement(ui_1.Input, { value: target, "aria-label": "To value", inputMode: "decimal", onChange: function (e) {
113
- setTarget(e.target.value);
114
- setError(undefined);
115
- } })),
202
+ react_1.default.createElement("div", { className: "flex gap-2" },
203
+ react_1.default.createElement("select", { className: "h-8 rounded border border-rnc-border bg-transparent px-2 text-sm", value: mode, "aria-label": "Target", onChange: function (e) { return setMode(e.target.value); } }, Object.keys(MODE_LABELS).map(function (key) { return (react_1.default.createElement("option", { key: key, value: key }, MODE_LABELS[key])); })),
204
+ react_1.default.createElement(ui_1.Input, { value: target, "aria-label": "To value", inputMode: "decimal", onChange: function (e) {
205
+ setTarget(e.target.value);
206
+ setError(undefined);
207
+ } }))),
116
208
  react_1.default.createElement("label", { className: "flex flex-col gap-1 text-xs font-medium" },
117
209
  "By changing cell:",
118
210
  react_1.default.createElement(ui_1.Input, { value: changingCell, "aria-label": "By changing cell", onChange: function (e) {
119
211
  setChangingCell(e.target.value);
120
212
  setError(undefined);
121
213
  } })),
214
+ react_1.default.createElement("label", { className: "flex items-center gap-2 text-xs" },
215
+ react_1.default.createElement("input", { type: "checkbox", checked: round, onChange: function (e) { return setRound(e.target.checked); } }),
216
+ "Round to a natural number"),
217
+ beyondExcel ? (react_1.default.createElement("label", { className: "flex flex-col gap-1 text-xs font-medium" },
218
+ "Within:",
219
+ react_1.default.createElement(ui_1.Input, { value: tolerance, "aria-label": "Within", inputMode: "decimal", placeholder: "1% of the target", onChange: function (e) {
220
+ setTolerance(e.target.value);
221
+ setError(undefined);
222
+ } }))) : null,
122
223
  error ? (react_1.default.createElement("div", { role: "alert", className: "text-xs text-rnc-destructive" }, error)) : null,
123
224
  react_1.default.createElement(ui_1.Separator, null),
124
225
  react_1.default.createElement("div", { className: "flex justify-end gap-2" },
@@ -139,11 +240,13 @@ var GoalSeekDialogHost = function () {
139
240
  return (react_1.default.createElement(exports.GoalSeekDialog, { open: request != null, onOpenChange: function (open) {
140
241
  if (!open)
141
242
  close();
142
- }, initialSetCell: (_a = request === null || request === void 0 ? void 0 : request.setCell) !== null && _a !== void 0 ? _a : "", onApply: function (setCell, targetValue, changingCell) {
243
+ }, initialSetCell: (_a = request === null || request === void 0 ? void 0 : request.setCell) !== null && _a !== void 0 ? _a : "", onApply: function (setCell, targetValue, changingCell, options) {
143
244
  return request
144
- ? request.onApply(setCell, targetValue, changingCell)
245
+ ? options
246
+ ? request.onApply(setCell, targetValue, changingCell, options)
247
+ : request.onApply(setCell, targetValue, changingCell)
145
248
  : Promise.resolve(undefined);
146
- } }));
249
+ }, onCommit: function (changingCell, value) { var _a; return (_a = request === null || request === void 0 ? void 0 : request.onCommit) === null || _a === void 0 ? void 0 : _a.call(request, changingCell, value); } }));
147
250
  };
148
251
  exports.GoalSeekDialogHost = GoalSeekDialogHost;
149
252
  exports.GoalSeekDialogHost.displayName = "GoalSeekDialogHost";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../components/hidden-markers/index.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,KAAK,UAAU,GAAG;IAChB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,kBAAkB,EAAE,MAAM,EAAE,EAAE,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG,UAAU,GAAG;IAClD,YAAY,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;CAC3C,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG,UAAU,GAAG;IAC/C,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;CACxC,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAAI,yDAIjC,wBAAwB,sBAyB1B,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,sDAI9B,qBAAqB,sBA6BvB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../components/hidden-markers/index.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,KAAK,UAAU,GAAG;IAChB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,kBAAkB,EAAE,MAAM,EAAE,EAAE,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG,UAAU,GAAG;IAClD,YAAY,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;CAC3C,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG,UAAU,GAAG;IAC/C,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;CACxC,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAAI,yDAIjC,wBAAwB,sBA0B1B,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,sDAI9B,qBAAqB,sBA8BvB,CAAC"}
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.HiddenRowMarkers = exports.HiddenColumnMarkers = void 0;
4
4
  var tslib_1 = require("tslib");
5
5
  var grid_1 = require("@rowsncolumns/grid");
6
- var icons_1 = require("@rowsncolumns/icons");
7
6
  var react_1 = tslib_1.__importDefault(require("react"));
8
7
  var style_1 = require("./style");
9
8
  var HiddenColumnMarkers = function (_a) {
@@ -14,12 +13,13 @@ var HiddenColumnMarkers = function (_a) {
14
13
  rowIndex: 0,
15
14
  columnIndex: columnIndex,
16
15
  });
17
- var _a = position !== null && position !== void 0 ? position : {}, _b = _a.x, x = _b === void 0 ? 0 : _b, _c = _a.y, y = _c === void 0 ? 0 : _c;
16
+ var _a = position !== null && position !== void 0 ? position : {}, _b = _a.x, x = _b === void 0 ? 0 : _b, _c = _a.y, y = _c === void 0 ? 0 : _c, _d = _a.height, height = _d === void 0 ? 0 : _d;
17
+ // Excel marks hidden columns with a double line on the header boundary.
18
18
  return (react_1.default.createElement(style_1.StyledHiddenMarkerButton, { style: {
19
19
  transform: "translate3d(".concat(x, "px, ").concat(y, "px, 0)"),
20
+ height: height,
20
21
  }, key: columnIndex, onClick: function () { return onShowColumn === null || onShowColumn === void 0 ? void 0 : onShowColumn(expandedDimensions[index]); }, "aria-label": "Show column", tooltip: "Show column" },
21
- react_1.default.createElement(icons_1.TriangleLeftIcon, null),
22
- react_1.default.createElement(icons_1.TriangleRightIcon, null)));
22
+ react_1.default.createElement(style_1.HiddenDoubleLine, null)));
23
23
  });
24
24
  return react_1.default.createElement(react_1.default.Fragment, null, markers);
25
25
  };
@@ -32,15 +32,16 @@ var HiddenRowMarkers = function (_a) {
32
32
  rowIndex: rowIndex,
33
33
  columnIndex: 0,
34
34
  });
35
- var _a = position !== null && position !== void 0 ? position : {}, _b = _a.x, x = _b === void 0 ? 0 : _b, _c = _a.y, y = _c === void 0 ? 0 : _c;
35
+ var _a = position !== null && position !== void 0 ? position : {}, _b = _a.x, x = _b === void 0 ? 0 : _b, _c = _a.y, y = _c === void 0 ? 0 : _c, _d = _a.width, width = _d === void 0 ? 0 : _d;
36
+ // Excel marks hidden rows with a double line on the header boundary.
36
37
  return (react_1.default.createElement(style_1.StyledHiddenMarkerButton, { style: {
37
38
  position: "absolute",
38
39
  left: x,
39
40
  top: y,
41
+ width: width,
40
42
  pointerEvents: "all",
41
43
  }, key: rowIndex, onClick: function () { return onShowRow === null || onShowRow === void 0 ? void 0 : onShowRow(expandedDimensions[index]); }, isVertical: true, "aria-label": "Show row", tooltip: "Show row" },
42
- react_1.default.createElement(icons_1.TriangleUpIcon, null),
43
- react_1.default.createElement(icons_1.TriangleDownIcon, null)));
44
+ react_1.default.createElement(style_1.HiddenDoubleLine, { isVertical: true })));
44
45
  });
45
46
  return react_1.default.createElement(react_1.default.Fragment, null, markers);
46
47
  };
@@ -2,4 +2,11 @@ import React from "react";
2
2
  export declare const StyledHiddenMarkerButton: React.ForwardRefExoticComponent<Omit<import("@rowsncolumns/ui").IconButtonProps & React.RefAttributes<HTMLButtonElement>, "ref"> & {
3
3
  isVertical?: boolean;
4
4
  } & React.RefAttributes<HTMLButtonElement>>;
5
+ /**
6
+ * Two 1 px lines with a 1 px gap — Excel's marker for hidden rows / columns
7
+ * in the headers.
8
+ */
9
+ export declare const HiddenDoubleLine: ({ isVertical }: {
10
+ isVertical?: boolean;
11
+ }) => React.JSX.Element;
5
12
  //# sourceMappingURL=style.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"style.d.ts","sourceRoot":"","sources":["../../../../components/hidden-markers/style.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,eAAO,MAAM,wBAAwB;iBAEgC,OAAO;2CAY1E,CAAC"}
1
+ {"version":3,"file":"style.d.ts","sourceRoot":"","sources":["../../../../components/hidden-markers/style.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,eAAO,MAAM,wBAAwB;iBAEgC,OAAO;2CAY1E,CAAC;AAIH;;;GAGG;AACH,eAAO,MAAM,gBAAgB,GAAI,gBAAgB;IAAE,UAAU,CAAC,EAAE,OAAO,CAAA;CAAE,sBAWxE,CAAC"}
@@ -1,11 +1,22 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.StyledHiddenMarkerButton = void 0;
3
+ exports.HiddenDoubleLine = exports.StyledHiddenMarkerButton = void 0;
4
4
  var tslib_1 = require("tslib");
5
5
  var ui_1 = require("@rowsncolumns/ui");
6
6
  var react_1 = tslib_1.__importDefault(require("react"));
7
7
  exports.StyledHiddenMarkerButton = react_1.default.forwardRef(function (_a, ref) {
8
8
  var className = _a.className, isVertical = _a.isVertical, props = tslib_1.__rest(_a, ["className", "isVertical"]);
9
- return (react_1.default.createElement(ui_1.IconButton, tslib_1.__assign({ ref: ref, className: (0, ui_1.cn)("flex absolute border-none p-0 rounded-sm bg-none left-0 top-0 pointer-events-auto w-[30px] h-[15px] mt-[5px] -ml-[15px]", "bg-transparent text-rnc-foreground hover:bg-rnc-background hover:shadow-md print:hidden min-h-0 min-w-0", isVertical ? "w-[15px] h-[30px] ml-px -mt-[15px] flex-col" : undefined, className) }, props)));
9
+ return (react_1.default.createElement(ui_1.IconButton, tslib_1.__assign({ ref: ref, className: (0, ui_1.cn)("flex absolute border-none p-0 rounded-none left-0 top-0 pointer-events-auto w-[5px] -ml-[2px] justify-center items-stretch", "bg-transparent hover:bg-transparent print:hidden min-h-0 min-w-0", isVertical ? "h-[5px] -mt-[2px] ml-0 flex-col" : undefined, className) }, props)));
10
10
  });
11
11
  exports.StyledHiddenMarkerButton.displayName = "StyledHiddenMarkerButton";
12
+ /**
13
+ * Two 1 px lines with a 1 px gap — Excel's marker for hidden rows / columns
14
+ * in the headers.
15
+ */
16
+ var HiddenDoubleLine = function (_a) {
17
+ var isVertical = _a.isVertical;
18
+ return (react_1.default.createElement("span", { "aria-hidden": true, "data-hidden-double-line": "", className: (0, ui_1.cn)("block border-rnc-foreground/60", isVertical
19
+ ? "w-full h-[3px] border-y border-solid"
20
+ : "h-full w-[3px] border-x border-solid") }));
21
+ };
22
+ exports.HiddenDoubleLine = HiddenDoubleLine;
@@ -0,0 +1,67 @@
1
+ import React from "react";
2
+ import type { SheetProtection } from "../../types";
3
+ /** An OOXML `CT_SheetProtection` action flag the Protect Sheet dialog offers. */
4
+ export type SheetProtectionAllowFlag = "selectLockedCells" | "selectUnlockedCells" | "formatCells" | "formatColumns" | "formatRows" | "insertColumns" | "insertRows" | "insertHyperlinks" | "deleteColumns" | "deleteRows" | "sort" | "autoFilter" | "pivotTables" | "objects" | "scenarios";
5
+ /**
6
+ * Excel's "Allow all users of this worksheet to:" list, in the dialog's order
7
+ * (support.microsoft.com "Protect a worksheet"), with the dialog defaults:
8
+ * only selecting locked and unlocked cells is ticked.
9
+ */
10
+ export declare const SHEET_PROTECTION_ALLOW_OPTIONS: ReadonlyArray<{
11
+ flag: SheetProtectionAllowFlag;
12
+ label: string;
13
+ defaultAllowed: boolean;
14
+ }>;
15
+ export type SheetProtectionAllowState = Record<SheetProtectionAllowFlag, boolean>;
16
+ /** The dialog's ticked boxes for a sheet's last protection (or the defaults). */
17
+ export declare const sheetProtectionToAllowState: (protection?: SheetProtection | null) => SheetProtectionAllowState;
18
+ /**
19
+ * The ticked boxes → OOXML flags, where `true` PROHIBITS the action. Every
20
+ * flag is written explicitly so the stored protection never depends on a
21
+ * schema default.
22
+ */
23
+ export declare const allowStateToSheetProtection: (state: SheetProtectionAllowState) => Omit<SheetProtection, "password" | "algorithmName" | "hashValue" | "saltValue" | "spinCount">;
24
+ /** Excel's text when the re-entered password differs. */
25
+ export declare const CONFIRM_PASSWORD_MISMATCH = "Confirmation password is not identical.";
26
+ export type ProtectSheetDialogProps = {
27
+ open: boolean;
28
+ onOpenChange(open: boolean): void;
29
+ /** The sheet's previous protection, to pre-tick its choices. */
30
+ initial?: SheetProtection | null;
31
+ /**
32
+ * OK: the OOXML flags and the plaintext password (empty = none). rnc engine:
33
+ * `onProtectSheet(sheetId, { sheetProtection, password })`, which stores only
34
+ * the password's hash.
35
+ */
36
+ onConfirm(options: {
37
+ sheetProtection: ReturnType<typeof allowStateToSheetProtection>;
38
+ password?: string;
39
+ }): void;
40
+ };
41
+ /** Review ▸ Protect Sheet (support.microsoft.com "Protect a worksheet"). */
42
+ export declare const ProtectSheetDialog: React.MemoExoticComponent<({ open, onOpenChange, initial, onConfirm }: ProtectSheetDialogProps) => React.JSX.Element>;
43
+ export type ProtectWorkbookDialogProps = {
44
+ open: boolean;
45
+ onOpenChange(open: boolean): void;
46
+ /** OK: rnc engine `onProtectWorkbook({ lockStructure, password })`. */
47
+ onConfirm(options: {
48
+ lockStructure: boolean;
49
+ password?: string;
50
+ }): void;
51
+ };
52
+ /** Review ▸ Protect Workbook (support.microsoft.com "Protect a workbook"). */
53
+ export declare const ProtectWorkbookDialog: React.MemoExoticComponent<({ open, onOpenChange, onConfirm }: ProtectWorkbookDialogProps) => React.JSX.Element>;
54
+ export type UnprotectDialogProps = {
55
+ open: boolean;
56
+ onOpenChange(open: boolean): void;
57
+ /** `"Unprotect Sheet"` or `"Unprotect Workbook"`. */
58
+ title: string;
59
+ /**
60
+ * OK with the typed password. The engine verifies it and refuses a wrong one
61
+ * (`incorrect-password`, shown by the host's rejection dialog).
62
+ */
63
+ onConfirm(password: string): void;
64
+ };
65
+ /** The password prompt Excel shows for Unprotect Sheet / Unprotect Workbook. */
66
+ export declare const UnprotectDialog: React.MemoExoticComponent<({ open, onOpenChange, title, onConfirm }: UnprotectDialogProps) => React.JSX.Element>;
67
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../components/protect-sheet-dialog/index.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAyB,MAAM,OAAO,CAAC;AAE9C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,iFAAiF;AACjF,MAAM,MAAM,wBAAwB,GAChC,mBAAmB,GACnB,qBAAqB,GACrB,aAAa,GACb,eAAe,GACf,YAAY,GACZ,eAAe,GACf,YAAY,GACZ,kBAAkB,GAClB,eAAe,GACf,YAAY,GACZ,MAAM,GACN,YAAY,GACZ,aAAa,GACb,SAAS,GACT,WAAW,CAAC;AAEhB;;;;GAIG;AACH,eAAO,MAAM,8BAA8B,EAAE,aAAa,CAAC;IACzD,IAAI,EAAE,wBAAwB,CAAC;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,OAAO,CAAC;CACzB,CAgBA,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG,MAAM,CAAC,wBAAwB,EAAE,OAAO,CAAC,CAAC;AAElF,iFAAiF;AACjF,eAAO,MAAM,2BAA2B,GACtC,aAAa,eAAe,GAAG,IAAI,KAClC,yBAOF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,2BAA2B,GACtC,OAAO,yBAAyB,KAC/B,IAAI,CACL,eAAe,EACf,UAAU,GAAG,eAAe,GAAG,WAAW,GAAG,WAAW,GAAG,WAAW,CAOvE,CAAC;AAEF,yDAAyD;AACzD,eAAO,MAAM,yBAAyB,4CAA4C,CAAC;AA4DnF,MAAM,MAAM,uBAAuB,GAAG;IACpC,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;IAClC,gEAAgE;IAChE,OAAO,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IACjC;;;;OAIG;IACH,SAAS,CAAC,OAAO,EAAE;QACjB,eAAe,EAAE,UAAU,CAAC,OAAO,2BAA2B,CAAC,CAAC;QAChE,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,GAAG,IAAI,CAAC;CACV,CAAC;AAEF,4EAA4E;AAC5E,eAAO,MAAM,kBAAkB,yEACgB,uBAAuB,uBAoErE,CAAC;AAIF,MAAM,MAAM,0BAA0B,GAAG;IACvC,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;IAClC,uEAAuE;IACvE,SAAS,CAAC,OAAO,EAAE;QAAE,aAAa,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CACzE,CAAC;AAEF,8EAA8E;AAC9E,eAAO,MAAM,qBAAqB,gEACI,0BAA0B,uBAwD/D,CAAC;AAIF,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;IAClC,qDAAqD;IACrD,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC,CAAC;AAEF,gFAAgF;AAChF,eAAO,MAAM,eAAe,uEACiB,oBAAoB,uBAmChE,CAAC"}