@rowsncolumns/spreadsheet 10.2.74 → 10.2.75

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 (194) hide show
  1. package/dist/cjs/api/excel-validation-kinds.d.ts +71 -0
  2. package/dist/cjs/api/excel-validation-kinds.d.ts.map +1 -0
  3. package/dist/cjs/api/excel-validation-kinds.js +304 -0
  4. package/dist/cjs/api/go-to-special.d.ts +32 -0
  5. package/dist/cjs/api/go-to-special.d.ts.map +1 -0
  6. package/dist/cjs/api/go-to-special.js +111 -0
  7. package/dist/cjs/api/validation-tooltip.d.ts +17 -0
  8. package/dist/cjs/api/validation-tooltip.d.ts.map +1 -0
  9. package/dist/cjs/api/validation-tooltip.js +42 -0
  10. package/dist/cjs/atoms/advanced-filter-dialog.atom.d.ts +28 -0
  11. package/dist/cjs/atoms/advanced-filter-dialog.atom.d.ts.map +1 -0
  12. package/dist/cjs/atoms/advanced-filter-dialog.atom.js +32 -0
  13. package/dist/cjs/atoms/go-to-dialog.atom.d.ts +11 -1
  14. package/dist/cjs/atoms/go-to-dialog.atom.d.ts.map +1 -1
  15. package/dist/cjs/atoms/goal-seek-dialog.atom.d.ts +29 -0
  16. package/dist/cjs/atoms/goal-seek-dialog.atom.d.ts.map +1 -0
  17. package/dist/cjs/atoms/goal-seek-dialog.atom.js +30 -0
  18. package/dist/cjs/atoms/index.d.ts +1 -0
  19. package/dist/cjs/atoms/index.d.ts.map +1 -1
  20. package/dist/cjs/atoms/index.js +1 -0
  21. package/dist/cjs/atoms/subtotal-dialog.atom.d.ts +39 -0
  22. package/dist/cjs/atoms/subtotal-dialog.atom.d.ts.map +1 -0
  23. package/dist/cjs/atoms/subtotal-dialog.atom.js +30 -0
  24. package/dist/cjs/atoms/text-to-columns-dialog.atom.d.ts +34 -0
  25. package/dist/cjs/atoms/text-to-columns-dialog.atom.d.ts.map +1 -0
  26. package/dist/cjs/atoms/text-to-columns-dialog.atom.js +36 -0
  27. package/dist/cjs/atoms/watch-window.atom.d.ts +37 -0
  28. package/dist/cjs/atoms/watch-window.atom.d.ts.map +1 -0
  29. package/dist/cjs/atoms/watch-window.atom.js +61 -0
  30. package/dist/cjs/components/advanced-filter-dialog/index.d.ts +28 -0
  31. package/dist/cjs/components/advanced-filter-dialog/index.d.ts.map +1 -0
  32. package/dist/cjs/components/advanced-filter-dialog/index.js +134 -0
  33. package/dist/cjs/components/calculation-options-dialog/index.d.ts +33 -0
  34. package/dist/cjs/components/calculation-options-dialog/index.d.ts.map +1 -0
  35. package/dist/cjs/components/calculation-options-dialog/index.js +69 -0
  36. package/dist/cjs/components/canvas-grid/index.d.ts.map +1 -1
  37. package/dist/cjs/components/canvas-grid/index.js +104 -21
  38. package/dist/cjs/components/canvas-grid/typings.d.ts +19 -2
  39. package/dist/cjs/components/canvas-grid/typings.d.ts.map +1 -1
  40. package/dist/cjs/components/cell/alignment.d.ts +30 -0
  41. package/dist/cjs/components/cell/alignment.d.ts.map +1 -1
  42. package/dist/cjs/components/cell/alignment.js +56 -1
  43. package/dist/cjs/components/cell/index.d.ts.map +1 -1
  44. package/dist/cjs/components/cell/index.js +15 -7
  45. package/dist/cjs/components/cell-diff/index.d.ts +3 -2
  46. package/dist/cjs/components/cell-diff/index.d.ts.map +1 -1
  47. package/dist/cjs/components/cell-editor/index.d.ts.map +1 -1
  48. package/dist/cjs/components/cell-editor/index.js +2 -1
  49. package/dist/cjs/components/context-menu/index.d.ts +6 -1
  50. package/dist/cjs/components/context-menu/index.d.ts.map +1 -1
  51. package/dist/cjs/components/context-menu/index.js +146 -3
  52. package/dist/cjs/components/embeds/embed-component.d.ts.map +1 -1
  53. package/dist/cjs/components/embeds/embed-component.js +16 -1
  54. package/dist/cjs/components/go-to-dialog/index.d.ts +11 -1
  55. package/dist/cjs/components/go-to-dialog/index.d.ts.map +1 -1
  56. package/dist/cjs/components/go-to-dialog/index.js +67 -24
  57. package/dist/cjs/components/goal-seek-dialog/index.d.ts +32 -0
  58. package/dist/cjs/components/goal-seek-dialog/index.d.ts.map +1 -0
  59. package/dist/cjs/components/goal-seek-dialog/index.js +149 -0
  60. package/dist/cjs/components/subtotal-dialog/index.d.ts +30 -0
  61. package/dist/cjs/components/subtotal-dialog/index.d.ts.map +1 -0
  62. package/dist/cjs/components/subtotal-dialog/index.js +126 -0
  63. package/dist/cjs/components/text-to-columns-dialog/index.d.ts +37 -0
  64. package/dist/cjs/components/text-to-columns-dialog/index.d.ts.map +1 -0
  65. package/dist/cjs/components/text-to-columns-dialog/index.js +166 -0
  66. package/dist/cjs/components/toolbar/background-color-selector.d.ts +13 -1
  67. package/dist/cjs/components/toolbar/background-color-selector.d.ts.map +1 -1
  68. package/dist/cjs/components/toolbar/background-color-selector.js +57 -11
  69. package/dist/cjs/components/toolbar/cell-style-selector.d.ts +15 -2
  70. package/dist/cjs/components/toolbar/cell-style-selector.d.ts.map +1 -1
  71. package/dist/cjs/components/toolbar/cell-style-selector.js +56 -3
  72. package/dist/cjs/components/toolbar/fill-selectors.d.ts +49 -0
  73. package/dist/cjs/components/toolbar/fill-selectors.d.ts.map +1 -0
  74. package/dist/cjs/components/toolbar/fill-selectors.js +196 -0
  75. package/dist/cjs/components/toolbar/index.d.ts +1 -0
  76. package/dist/cjs/components/toolbar/index.d.ts.map +1 -1
  77. package/dist/cjs/components/toolbar/index.js +1 -0
  78. package/dist/cjs/components/toolbar/text-horizontal-align-selector.d.ts +8 -0
  79. package/dist/cjs/components/toolbar/text-horizontal-align-selector.d.ts.map +1 -1
  80. package/dist/cjs/components/toolbar/text-horizontal-align-selector.js +23 -4
  81. package/dist/cjs/components/watch-window/index.d.ts +25 -0
  82. package/dist/cjs/components/watch-window/index.d.ts.map +1 -0
  83. package/dist/cjs/components/watch-window/index.js +63 -0
  84. package/dist/cjs/hooks/use-cell-renderer.d.ts.map +1 -1
  85. package/dist/cjs/hooks/use-cell-renderer.js +17 -6
  86. package/dist/cjs/hooks/use-get-tooltip.d.ts.map +1 -1
  87. package/dist/cjs/hooks/use-get-tooltip.js +7 -2
  88. package/dist/cjs/hooks/use-keyboard-handler.d.ts.map +1 -1
  89. package/dist/cjs/hooks/use-keyboard-handler.js +24 -12
  90. package/dist/cjs/index.d.ts +8 -0
  91. package/dist/cjs/index.d.ts.map +1 -1
  92. package/dist/cjs/index.js +8 -0
  93. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  94. package/dist/cjs/types.d.ts +117 -4
  95. package/dist/cjs/types.d.ts.map +1 -1
  96. package/dist/cjs/types.js +19 -1
  97. package/dist/esm/api/excel-validation-kinds.d.ts +71 -0
  98. package/dist/esm/api/excel-validation-kinds.d.ts.map +1 -0
  99. package/dist/esm/api/excel-validation-kinds.js +287 -0
  100. package/dist/esm/api/go-to-special.d.ts +32 -0
  101. package/dist/esm/api/go-to-special.d.ts.map +1 -0
  102. package/dist/esm/api/go-to-special.js +96 -0
  103. package/dist/esm/api/validation-tooltip.d.ts +17 -0
  104. package/dist/esm/api/validation-tooltip.d.ts.map +1 -0
  105. package/dist/esm/api/validation-tooltip.js +34 -0
  106. package/dist/esm/atoms/advanced-filter-dialog.atom.d.ts +28 -0
  107. package/dist/esm/atoms/advanced-filter-dialog.atom.d.ts.map +1 -0
  108. package/dist/esm/atoms/advanced-filter-dialog.atom.js +21 -0
  109. package/dist/esm/atoms/go-to-dialog.atom.d.ts +11 -1
  110. package/dist/esm/atoms/go-to-dialog.atom.d.ts.map +1 -1
  111. package/dist/esm/atoms/goal-seek-dialog.atom.d.ts +29 -0
  112. package/dist/esm/atoms/goal-seek-dialog.atom.d.ts.map +1 -0
  113. package/dist/esm/atoms/goal-seek-dialog.atom.js +21 -0
  114. package/dist/esm/atoms/index.d.ts +1 -0
  115. package/dist/esm/atoms/index.d.ts.map +1 -1
  116. package/dist/esm/atoms/index.js +1 -0
  117. package/dist/esm/atoms/subtotal-dialog.atom.d.ts +39 -0
  118. package/dist/esm/atoms/subtotal-dialog.atom.d.ts.map +1 -0
  119. package/dist/esm/atoms/subtotal-dialog.atom.js +21 -0
  120. package/dist/esm/atoms/text-to-columns-dialog.atom.d.ts +34 -0
  121. package/dist/esm/atoms/text-to-columns-dialog.atom.d.ts.map +1 -0
  122. package/dist/esm/atoms/text-to-columns-dialog.atom.js +25 -0
  123. package/dist/esm/atoms/watch-window.atom.d.ts +37 -0
  124. package/dist/esm/atoms/watch-window.atom.d.ts.map +1 -0
  125. package/dist/esm/atoms/watch-window.atom.js +37 -0
  126. package/dist/esm/components/advanced-filter-dialog/index.d.ts +28 -0
  127. package/dist/esm/components/advanced-filter-dialog/index.d.ts.map +1 -0
  128. package/dist/esm/components/advanced-filter-dialog/index.js +125 -0
  129. package/dist/esm/components/calculation-options-dialog/index.d.ts +33 -0
  130. package/dist/esm/components/calculation-options-dialog/index.d.ts.map +1 -0
  131. package/dist/esm/components/calculation-options-dialog/index.js +61 -0
  132. package/dist/esm/components/canvas-grid/index.d.ts.map +1 -1
  133. package/dist/esm/components/canvas-grid/index.js +99 -20
  134. package/dist/esm/components/canvas-grid/typings.d.ts +19 -2
  135. package/dist/esm/components/canvas-grid/typings.d.ts.map +1 -1
  136. package/dist/esm/components/cell/alignment.d.ts +30 -0
  137. package/dist/esm/components/cell/alignment.d.ts.map +1 -1
  138. package/dist/esm/components/cell/alignment.js +51 -0
  139. package/dist/esm/components/cell/index.d.ts.map +1 -1
  140. package/dist/esm/components/cell/index.js +16 -8
  141. package/dist/esm/components/cell-diff/index.d.ts +3 -2
  142. package/dist/esm/components/cell-diff/index.d.ts.map +1 -1
  143. package/dist/esm/components/cell-editor/index.d.ts.map +1 -1
  144. package/dist/esm/components/cell-editor/index.js +2 -1
  145. package/dist/esm/components/context-menu/index.d.ts +6 -1
  146. package/dist/esm/components/context-menu/index.d.ts.map +1 -1
  147. package/dist/esm/components/context-menu/index.js +139 -4
  148. package/dist/esm/components/embeds/embed-component.d.ts.map +1 -1
  149. package/dist/esm/components/embeds/embed-component.js +17 -1
  150. package/dist/esm/components/go-to-dialog/index.d.ts +11 -1
  151. package/dist/esm/components/go-to-dialog/index.d.ts.map +1 -1
  152. package/dist/esm/components/go-to-dialog/index.js +63 -23
  153. package/dist/esm/components/goal-seek-dialog/index.d.ts +32 -0
  154. package/dist/esm/components/goal-seek-dialog/index.d.ts.map +1 -0
  155. package/dist/esm/components/goal-seek-dialog/index.js +125 -0
  156. package/dist/esm/components/subtotal-dialog/index.d.ts +30 -0
  157. package/dist/esm/components/subtotal-dialog/index.d.ts.map +1 -0
  158. package/dist/esm/components/subtotal-dialog/index.js +115 -0
  159. package/dist/esm/components/text-to-columns-dialog/index.d.ts +37 -0
  160. package/dist/esm/components/text-to-columns-dialog/index.d.ts.map +1 -0
  161. package/dist/esm/components/text-to-columns-dialog/index.js +147 -0
  162. package/dist/esm/components/toolbar/background-color-selector.d.ts +13 -1
  163. package/dist/esm/components/toolbar/background-color-selector.d.ts.map +1 -1
  164. package/dist/esm/components/toolbar/background-color-selector.js +61 -11
  165. package/dist/esm/components/toolbar/cell-style-selector.d.ts +15 -2
  166. package/dist/esm/components/toolbar/cell-style-selector.d.ts.map +1 -1
  167. package/dist/esm/components/toolbar/cell-style-selector.js +46 -2
  168. package/dist/esm/components/toolbar/fill-selectors.d.ts +49 -0
  169. package/dist/esm/components/toolbar/fill-selectors.d.ts.map +1 -0
  170. package/dist/esm/components/toolbar/fill-selectors.js +162 -0
  171. package/dist/esm/components/toolbar/index.d.ts +1 -0
  172. package/dist/esm/components/toolbar/index.d.ts.map +1 -1
  173. package/dist/esm/components/toolbar/index.js +1 -0
  174. package/dist/esm/components/toolbar/text-horizontal-align-selector.d.ts +8 -0
  175. package/dist/esm/components/toolbar/text-horizontal-align-selector.d.ts.map +1 -1
  176. package/dist/esm/components/toolbar/text-horizontal-align-selector.js +21 -5
  177. package/dist/esm/components/watch-window/index.d.ts +25 -0
  178. package/dist/esm/components/watch-window/index.d.ts.map +1 -0
  179. package/dist/esm/components/watch-window/index.js +54 -0
  180. package/dist/esm/hooks/use-cell-renderer.d.ts.map +1 -1
  181. package/dist/esm/hooks/use-cell-renderer.js +17 -6
  182. package/dist/esm/hooks/use-get-tooltip.d.ts.map +1 -1
  183. package/dist/esm/hooks/use-get-tooltip.js +7 -2
  184. package/dist/esm/hooks/use-keyboard-handler.d.ts.map +1 -1
  185. package/dist/esm/hooks/use-keyboard-handler.js +24 -12
  186. package/dist/esm/index.d.ts +8 -0
  187. package/dist/esm/index.d.ts.map +1 -1
  188. package/dist/esm/index.js +8 -0
  189. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  190. package/dist/esm/types.d.ts +117 -4
  191. package/dist/esm/types.d.ts.map +1 -1
  192. package/dist/esm/types.js +18 -0
  193. package/dist/spreadsheet.min.css +1 -1
  194. package/package.json +6 -6
@@ -9,13 +9,17 @@ var utils_1 = require("@rowsncolumns/utils");
9
9
  var react_1 = tslib_1.__importStar(require("react"));
10
10
  var validation_1 = require("../../api/validation");
11
11
  var atoms_1 = require("../../atoms");
12
+ var advanced_filter_dialog_atom_1 = require("../../atoms/advanced-filter-dialog.atom");
13
+ var goal_seek_dialog_atom_1 = require("../../atoms/goal-seek-dialog.atom");
12
14
  var remove_duplicates_dialog_atom_1 = require("../../atoms/remove-duplicates-dialog.atom");
15
+ var subtotal_dialog_atom_1 = require("../../atoms/subtotal-dialog.atom");
16
+ var text_to_columns_dialog_atom_1 = require("../../atoms/text-to-columns-dialog.atom");
13
17
  var config_1 = require("../../config");
14
18
  var helpers_1 = require("../../helpers");
15
19
  var total_row_functions_1 = require("./total-row-functions");
16
20
  var ContextMenu = function (_a) {
17
21
  var _b;
18
- var isRowHeader = _a.isRowHeader, isColumnHeader = _a.isColumnHeader, activeCell = _a.activeCell, selections = _a.selections, basicFilter = _a.basicFilter, isTableHeader = _a.isTableHeader, onClearContents = _a.onClearContents, onHideColumn = _a.onHideColumn, onHideRow = _a.onHideRow, onGroupRows = _a.onGroupRows, onUngroupRows = _a.onUngroupRows, onGroupColumns = _a.onGroupColumns, onUngroupColumns = _a.onUngroupColumns, onDeleteRow = _a.onDeleteRow, onDeleteColumn = _a.onDeleteColumn, onInsertColumn = _a.onInsertColumn, onInsertRow = _a.onInsertRow, onInsertCellsShiftDown = _a.onInsertCellsShiftDown, onInsertCellsShiftRight = _a.onInsertCellsShiftRight, onDeleteCellsShiftLeft = _a.onDeleteCellsShiftLeft, onDeleteCellsShiftUp = _a.onDeleteCellsShiftUp, onFreezeRow = _a.onFreezeRow, onFreezeColumn = _a.onFreezeColumn, onCopy = _a.onCopy, onCut = _a.onCut, onPaste = _a.onPaste, onRequestPasteSpecial = _a.onRequestPasteSpecial, onRequestEvaluateFormula = _a.onRequestEvaluateFormula, isActiveCellFormula = _a.isActiveCellFormula, onInsertNote = _a.onInsertNote, onProtectRange = _a.onProtectRange, onUnProtectRange = _a.onUnProtectRange, onSortRange = _a.onSortRange, onSortColumn = _a.onSortColumn, onRequestDefineNamedRange = _a.onRequestDefineNamedRange, onRequestResize = _a.onRequestResize, onRequestEditTable = _a.onRequestEditTable, onRequestEditPivotTable = _a.onRequestEditPivotTable, onRequestDeletePivotTable = _a.onRequestDeletePivotTable, onPivotDrillDown = _a.onPivotDrillDown, onRequestFormatCells = _a.onRequestFormatCells, onRequestConditionalFormat = _a.onRequestConditionalFormat, onRequestDataValidation = _a.onRequestDataValidation, onRemoveTable = _a.onRemoveTable, onClearFormatting = _a.onClearFormatting, onCreateTable = _a.onCreateTable, onCreateBasicFilter = _a.onCreateBasicFilter, onFilterTable = _a.onFilterTable, onSortTable = _a.onSortTable, getFormattedValuesFromRange = _a.getFormattedValuesFromRange, focusSheet = _a.focusSheet, isSheetFocused = _a.isSheetFocused, getFormattedValue = _a.getFormattedValue, onInsertTableColumn = _a.onInsertTableColumn, onDeleteTableColumn = _a.onDeleteTableColumn, onInsertTableRow = _a.onInsertTableRow, onDeleteTableRow = _a.onDeleteTableRow, onSplitTextToColumns = _a.onSplitTextToColumns, onRemoveDuplicates = _a.onRemoveDuplicates, onChange = _a.onChange, getCellData = _a.getCellData, isHiddenColumn = _a.isHiddenColumn, isHiddenRow = _a.isHiddenRow, onShowColumn = _a.onShowColumn, onShowRow = _a.onShowRow, tables = _a.tables, pivotTables = _a.pivotTables, protectedRanges = _a.protectedRanges, sheetId = _a.sheetId, frozenRows = _a.frozenRows, frozenColumns = _a.frozenColumns, selectedRowHeadersIds = _a.selectedRowHeadersIds, selectedColumnHeadersIds = _a.selectedColumnHeadersIds, _c = _a.readonly, readonly = _c === void 0 ? false : _c, onAddQuickEdit = _a.onAddQuickEdit, enableMagicFill = _a.enableMagicFill;
22
+ var isRowHeader = _a.isRowHeader, isColumnHeader = _a.isColumnHeader, activeCell = _a.activeCell, selections = _a.selections, basicFilter = _a.basicFilter, isTableHeader = _a.isTableHeader, onClearContents = _a.onClearContents, onHideColumn = _a.onHideColumn, onHideRow = _a.onHideRow, onGroupRows = _a.onGroupRows, onUngroupRows = _a.onUngroupRows, onGroupColumns = _a.onGroupColumns, onUngroupColumns = _a.onUngroupColumns, onDeleteRow = _a.onDeleteRow, onDeleteColumn = _a.onDeleteColumn, onInsertColumn = _a.onInsertColumn, onInsertRow = _a.onInsertRow, onInsertCellsShiftDown = _a.onInsertCellsShiftDown, onInsertCellsShiftRight = _a.onInsertCellsShiftRight, onDeleteCellsShiftLeft = _a.onDeleteCellsShiftLeft, onDeleteCellsShiftUp = _a.onDeleteCellsShiftUp, onFreezeRow = _a.onFreezeRow, onFreezeColumn = _a.onFreezeColumn, onCopy = _a.onCopy, onCut = _a.onCut, onPaste = _a.onPaste, onRequestPasteSpecial = _a.onRequestPasteSpecial, onRequestEvaluateFormula = _a.onRequestEvaluateFormula, onRequestAddWatch = _a.onRequestAddWatch, isActiveCellFormula = _a.isActiveCellFormula, onInsertNote = _a.onInsertNote, onProtectRange = _a.onProtectRange, onUnProtectRange = _a.onUnProtectRange, onSortRange = _a.onSortRange, onSortColumn = _a.onSortColumn, onRequestDefineNamedRange = _a.onRequestDefineNamedRange, onRequestResize = _a.onRequestResize, onRequestEditTable = _a.onRequestEditTable, onRequestEditPivotTable = _a.onRequestEditPivotTable, onRequestDeletePivotTable = _a.onRequestDeletePivotTable, onPivotDrillDown = _a.onPivotDrillDown, onRequestFormatCells = _a.onRequestFormatCells, onRequestConditionalFormat = _a.onRequestConditionalFormat, onRequestDataValidation = _a.onRequestDataValidation, onRemoveTable = _a.onRemoveTable, onClearFormatting = _a.onClearFormatting, onCreateTable = _a.onCreateTable, onCreateBasicFilter = _a.onCreateBasicFilter, onFilterTable = _a.onFilterTable, onSortTable = _a.onSortTable, getFormattedValuesFromRange = _a.getFormattedValuesFromRange, focusSheet = _a.focusSheet, isSheetFocused = _a.isSheetFocused, getFormattedValue = _a.getFormattedValue, onInsertTableColumn = _a.onInsertTableColumn, onDeleteTableColumn = _a.onDeleteTableColumn, onInsertTableRow = _a.onInsertTableRow, onDeleteTableRow = _a.onDeleteTableRow, onSplitTextToColumns = _a.onSplitTextToColumns, onRemoveDuplicates = _a.onRemoveDuplicates, onGoalSeek = _a.onGoalSeek, onSubtotal = _a.onSubtotal, onAdvancedFilter = _a.onAdvancedFilter, onChange = _a.onChange, getCellData = _a.getCellData, isHiddenColumn = _a.isHiddenColumn, isHiddenRow = _a.isHiddenRow, onShowColumn = _a.onShowColumn, onShowRow = _a.onShowRow, tables = _a.tables, pivotTables = _a.pivotTables, protectedRanges = _a.protectedRanges, sheetId = _a.sheetId, frozenRows = _a.frozenRows, frozenColumns = _a.frozenColumns, selectedRowHeadersIds = _a.selectedRowHeadersIds, selectedColumnHeadersIds = _a.selectedColumnHeadersIds, _c = _a.readonly, readonly = _c === void 0 ? false : _c, onAddQuickEdit = _a.onAddQuickEdit, enableMagicFill = _a.enableMagicFill;
19
23
  var isHeader = isColumnHeader || isRowHeader;
20
24
  var shouldFocusSheetRef = (0, react_1.useRef)(true);
21
25
  var multiColumnTitle = (0, helpers_1.generateMultiDimTitle)(selectedColumnHeadersIds, "y");
@@ -55,6 +59,122 @@ var ContextMenu = function (_a) {
55
59
  var lastSelectedRowIndex = selectedRowHeadersIds.reduce(function (m, v) { return (v > m ? v : m); }, -Infinity);
56
60
  // Get contentful range
57
61
  var getContentfulRangeAroundCell = (0, atoms_1.useGetContentfulRangeAroundCell)();
62
+ // The data block the data tools act on: a table's own rows, the selection,
63
+ // or (from a lone cell) the contentful region around it — like Excel.
64
+ var dataRangeAroundSelection = (0, react_1.useCallback)(function () {
65
+ var _a;
66
+ if (activeTable) {
67
+ return tslib_1.__assign(tslib_1.__assign({}, activeTable.range), { endRowIndex: activeTable.range.endRowIndex - (activeTable.totalRow ? 1 : 0) });
68
+ }
69
+ if (selections.length) {
70
+ return selection.range;
71
+ }
72
+ return (_a = getContentfulRangeAroundCell === null || getContentfulRangeAroundCell === void 0 ? void 0 : getContentfulRangeAroundCell(sheetId, activeCell)) !== null && _a !== void 0 ? _a : selection.range;
73
+ }, [activeTable, selections.length, selection.range, getContentfulRangeAroundCell, sheetId, activeCell]);
74
+ // Excel pre-ticks "my data has headers" when the first row reads as labels:
75
+ // every cell filled and none of them a number.
76
+ var headerColumnsOf = (0, react_1.useCallback)(function (range) {
77
+ var _a, _b, _c, _d;
78
+ var columns = [];
79
+ for (var columnIndex = range.startColumnIndex; columnIndex <= range.endColumnIndex; columnIndex++) {
80
+ var header = (_c = (_b = (_a = activeTable === null || activeTable === void 0 ? void 0 : activeTable.columns) === null || _a === void 0 ? void 0 : _a[columnIndex - activeTable.range.startColumnIndex]) === null || _b === void 0 ? void 0 : _b.name) !== null && _c !== void 0 ? _c : getFormattedValue(sheetId, range.startRowIndex, columnIndex);
81
+ columns.push({
82
+ columnIndex: columnIndex,
83
+ label: "Column ".concat((0, utils_1.number2Alpha)(columnIndex - 1)),
84
+ header: header || undefined,
85
+ });
86
+ }
87
+ var hasHeader = activeTable
88
+ ? ((_d = activeTable.headerRow) !== null && _d !== void 0 ? _d : true)
89
+ : range.endRowIndex > range.startRowIndex &&
90
+ columns.every(function (column) { return !!column.header && Number.isNaN(Number(column.header)); });
91
+ return { columns: columns, hasHeader: hasHeader };
92
+ }, [activeTable, getFormattedValue, sheetId]);
93
+ var rangeAddress = function (range) {
94
+ return "".concat((0, utils_1.cellToAddress)({ rowIndex: range.startRowIndex, columnIndex: range.startColumnIndex }), ":").concat((0, utils_1.cellToAddress)({ rowIndex: range.endRowIndex, columnIndex: range.endColumnIndex }));
95
+ };
96
+ // Text to Columns → Fixed width (dialog with a ruler over the selected column).
97
+ var isTextToColumnsDialogMounted = (0, text_to_columns_dialog_atom_1.useIsTextToColumnsDialogMounted)();
98
+ var openTextToColumnsDialog = (0, text_to_columns_dialog_atom_1.useOpenTextToColumnsDialog)();
99
+ var handleTextToColumnsDialog = (0, react_1.useCallback)(function () {
100
+ var _a;
101
+ var range = selections.length ? selection.range : dataRangeAroundSelection();
102
+ var columnIndex = selections.length ? range.startColumnIndex : activeCell.columnIndex;
103
+ var preview = [];
104
+ var firstRow = selections.length ? range.startRowIndex : activeCell.rowIndex;
105
+ var lastRow = selections.length ? range.endRowIndex : range.endRowIndex;
106
+ for (var rowIndex = firstRow; rowIndex <= lastRow && preview.length < 8; rowIndex++) {
107
+ preview.push((_a = getFormattedValue(sheetId, rowIndex, columnIndex)) !== null && _a !== void 0 ? _a : "");
108
+ }
109
+ var target = selections.length
110
+ ? selections
111
+ : [
112
+ {
113
+ range: {
114
+ startRowIndex: activeCell.rowIndex,
115
+ endRowIndex: range.endRowIndex,
116
+ startColumnIndex: columnIndex,
117
+ endColumnIndex: columnIndex,
118
+ },
119
+ },
120
+ ];
121
+ openTextToColumnsDialog({
122
+ preview: preview,
123
+ onApply: function (_a) {
124
+ var delimiter = _a.delimiter, columnBreaks = _a.columnBreaks;
125
+ return onSplitTextToColumns === null || onSplitTextToColumns === void 0 ? void 0 : onSplitTextToColumns(sheetId, activeCell, target, delimiter, { columnBreaks: columnBreaks });
126
+ },
127
+ });
128
+ }, [
129
+ selections,
130
+ selection.range,
131
+ dataRangeAroundSelection,
132
+ activeCell,
133
+ getFormattedValue,
134
+ sheetId,
135
+ openTextToColumnsDialog,
136
+ onSplitTextToColumns,
137
+ ]);
138
+ // Data → Subtotal.
139
+ var isSubtotalDialogMounted = (0, subtotal_dialog_atom_1.useIsSubtotalDialogMounted)();
140
+ var openSubtotalDialog = (0, subtotal_dialog_atom_1.useOpenSubtotalDialog)();
141
+ var handleSubtotal = (0, react_1.useCallback)(function () {
142
+ var range = dataRangeAroundSelection();
143
+ var _a = headerColumnsOf(range), columns = _a.columns, hasHeader = _a.hasHeader;
144
+ openSubtotalDialog({
145
+ columns: columns,
146
+ hasHeader: hasHeader,
147
+ onApply: function (choices) { return onSubtotal === null || onSubtotal === void 0 ? void 0 : onSubtotal(sheetId, tslib_1.__assign({ range: range }, choices)); },
148
+ });
149
+ }, [dataRangeAroundSelection, headerColumnsOf, openSubtotalDialog, onSubtotal, sheetId]);
150
+ // Data → Advanced filter.
151
+ var isAdvancedFilterDialogMounted = (0, advanced_filter_dialog_atom_1.useIsAdvancedFilterDialogMounted)();
152
+ var openAdvancedFilterDialog = (0, advanced_filter_dialog_atom_1.useOpenAdvancedFilterDialog)();
153
+ var handleAdvancedFilter = (0, react_1.useCallback)(function () {
154
+ openAdvancedFilterDialog({
155
+ listRange: rangeAddress(dataRangeAroundSelection()),
156
+ onApply: function (options) { return onAdvancedFilter === null || onAdvancedFilter === void 0 ? void 0 : onAdvancedFilter(sheetId, options); },
157
+ });
158
+ }, [openAdvancedFilterDialog, dataRangeAroundSelection, onAdvancedFilter, sheetId]);
159
+ // Data → What-If Analysis → Goal Seek.
160
+ var isGoalSeekDialogMounted = (0, goal_seek_dialog_atom_1.useIsGoalSeekDialogMounted)();
161
+ var openGoalSeekDialog = (0, goal_seek_dialog_atom_1.useOpenGoalSeekDialog)();
162
+ var handleGoalSeek = (0, react_1.useCallback)(function () {
163
+ var _a;
164
+ openGoalSeekDialog({
165
+ setCell: (_a = (0, utils_1.cellToAddress)(activeCell)) !== null && _a !== void 0 ? _a : "",
166
+ onApply: function (setCellAddress, targetValue, changingCellAddress) { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
167
+ var setCell, changingCell;
168
+ return tslib_1.__generator(this, function (_a) {
169
+ setCell = (0, utils_1.addressToCell)(setCellAddress);
170
+ changingCell = (0, utils_1.addressToCell)(changingCellAddress);
171
+ if (!setCell || !changingCell || !onGoalSeek)
172
+ return [2 /*return*/, undefined];
173
+ return [2 /*return*/, onGoalSeek(sheetId, setCell, targetValue, changingCell)];
174
+ });
175
+ }); },
176
+ });
177
+ }, [openGoalSeekDialog, activeCell, onGoalSeek, sheetId]);
58
178
  // Remove duplicates — Excel's dialog (column checklist + "my data has
59
179
  // headers") when a host mounts `RemoveDuplicatesDialogHost`, otherwise the
60
180
  // one-click de-dupe over the selection.
@@ -714,7 +834,14 @@ var ContextMenu = function (_a) {
714
834
  } },
715
835
  react_1.default.createElement(ui_1.DropdownLeftSlot, null,
716
836
  react_1.default.createElement(icons_1.CodeIcon, null)),
717
- "Evaluate formula")) : null)),
837
+ "Evaluate formula")) : null,
838
+ onRequestAddWatch ? (react_1.default.createElement(ui_1.DropdownMenuItem, { onClick: function () {
839
+ shouldFocusSheetRef.current = false;
840
+ onRequestAddWatch(sheetId, activeCell);
841
+ } },
842
+ react_1.default.createElement(ui_1.DropdownLeftSlot, null,
843
+ react_1.default.createElement(icons_1.EyeOpenIcon, null)),
844
+ "Add to Watch Window")) : null)),
718
845
  react_1.default.createElement(ui_1.DropdownMenuSeparator, null),
719
846
  react_1.default.createElement(ui_1.DropdownMenuItem, { onClick: handleRemoveDuplicates, disabled: readonly },
720
847
  react_1.default.createElement(ui_1.DropdownLeftSlot, null,
@@ -742,7 +869,23 @@ var ContextMenu = function (_a) {
742
869
  } }, "Space"),
743
870
  react_1.default.createElement(ui_1.DropdownMenuItem, { onClick: function () {
744
871
  return onSplitTextToColumns === null || onSplitTextToColumns === void 0 ? void 0 : onSplitTextToColumns(sheetId, activeCell, selections, "|");
745
- } }, "Pipe"))),
872
+ } }, "Pipe"),
873
+ isTextToColumnsDialogMounted ? (react_1.default.createElement(react_1.default.Fragment, null,
874
+ react_1.default.createElement(ui_1.DropdownMenuSeparator, null),
875
+ react_1.default.createElement(ui_1.DropdownMenuItem, { onClick: handleTextToColumnsDialog }, "Fixed width\u2026"))) : null)),
876
+ (isSubtotalDialogMounted && onSubtotal) ||
877
+ (isAdvancedFilterDialogMounted && onAdvancedFilter) ||
878
+ (isGoalSeekDialogMounted && onGoalSeek) ? (react_1.default.createElement(ui_1.DropdownMenuSub, null,
879
+ react_1.default.createElement(ui_1.DropdownMenuSubTrigger, { disabled: readonly },
880
+ react_1.default.createElement(ui_1.DropdownLeftSlot, null,
881
+ react_1.default.createElement(icons_1.SpaceBetweenHorizontallyIcon, null)),
882
+ "Data tools",
883
+ react_1.default.createElement(ui_1.DropdownRightSlot, null,
884
+ react_1.default.createElement(icons_1.ChevronRightIcon, null))),
885
+ react_1.default.createElement(ui_1.DropdownMenuSubContent, { sideOffset: 2, alignOffset: -5 },
886
+ isSubtotalDialogMounted && onSubtotal ? (react_1.default.createElement(ui_1.DropdownMenuItem, { onClick: handleSubtotal }, "Subtotal\u2026")) : null,
887
+ isAdvancedFilterDialogMounted && onAdvancedFilter ? (react_1.default.createElement(ui_1.DropdownMenuItem, { onClick: handleAdvancedFilter }, "Advanced filter\u2026")) : null,
888
+ isGoalSeekDialogMounted && onGoalSeek ? (react_1.default.createElement(ui_1.DropdownMenuItem, { onClick: handleGoalSeek }, "Goal seek\u2026")) : null))) : null,
746
889
  react_1.default.createElement(ui_1.DropdownMenuSub, null,
747
890
  react_1.default.createElement(ui_1.DropdownMenuSubTrigger, { disabled: readonly },
748
891
  react_1.default.createElement(ui_1.DropdownLeftSlot, null,
@@ -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,EAIf,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAIhF,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+LvB,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,uBA4NvB,CAAC"}
@@ -6,8 +6,10 @@ var icons_1 = require("@rowsncolumns/icons");
6
6
  var ui_1 = require("@rowsncolumns/ui");
7
7
  var react_1 = tslib_1.__importStar(require("react"));
8
8
  var themes_1 = require("../../themes");
9
+ var alignment_1 = require("../cell/alignment");
9
10
  var shape_svg_1 = require("./shape-svg");
10
11
  exports.EmbedComponent = (0, react_1.memo)(function (_a) {
12
+ var _b, _c, _d;
11
13
  var embed = _a.embed, width = _a.width, height = _a.height, readonly = _a.readonly, isSelected = _a.isSelected, onDeleteEmbed = _a.onDeleteEmbed, onRequestEditEmbed = _a.onRequestEditEmbed, theme = _a.theme;
12
14
  var renderTextBox = function (spec) {
13
15
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
@@ -45,7 +47,9 @@ exports.EmbedComponent = (0, react_1.memo)(function (_a) {
45
47
  height: "100%",
46
48
  backgroundColor: backgroundColor,
47
49
  padding: spec.padding ? "".concat(spec.padding, "px") : "4px",
48
- textAlign: spec.horizontalAlignment || undefined,
50
+ textAlign: spec.horizontalAlignment
51
+ ? (0, alignment_1.resolveCanvasTextAlign)(spec.horizontalAlignment)
52
+ : undefined,
49
53
  display: "flex",
50
54
  flexDirection: "column",
51
55
  justifyContent: spec.verticalAlignment === "top"
@@ -114,6 +118,17 @@ exports.EmbedComponent = (0, react_1.memo)(function (_a) {
114
118
  (embed === null || embed === void 0 ? void 0 : embed.spec.type) === "shape" ? (react_1.default.createElement("div", { style: { position: "relative", width: "100%", height: "100%" } },
115
119
  react_1.default.createElement(shape_svg_1.ShapeSvg, { spec: embed.spec, width: width, height: height, theme: theme }),
116
120
  embed.spec.textBody ? (react_1.default.createElement("div", { style: { position: "absolute", inset: 0 } }, renderTextBox(tslib_1.__assign({ type: "textbox" }, embed.spec.textBody)))) : null)) : null,
121
+ (embed === null || embed === void 0 ? void 0 : embed.spec.type) === "formControl" ? (
122
+ // Excel form controls round-trip but are not interactive here: draw
123
+ // the caption in a control-shaped placeholder so the layout reads.
124
+ react_1.default.createElement("div", { className: "flex h-full w-full items-center gap-1 overflow-hidden whitespace-nowrap px-1 text-xs", title: (_b = embed.spec.name) !== null && _b !== void 0 ? _b : undefined },
125
+ embed.spec.objectType === "CheckBox" ||
126
+ embed.spec.objectType === "Radio" ? (react_1.default.createElement("span", { className: "inline-block h-3 w-3 shrink-0 border border-current", style: {
127
+ borderRadius: embed.spec.objectType === "Radio"
128
+ ? "50%"
129
+ : 2,
130
+ } })) : null,
131
+ react_1.default.createElement("span", { className: "truncate" }, (_d = (_c = embed.spec.text) !== null && _c !== void 0 ? _c : embed.spec.name) !== null && _d !== void 0 ? _d : embed.spec.objectType))) : null,
117
132
  readonly || !isSelected ? null : (react_1.default.createElement(ui_1.DropdownMenu, null,
118
133
  react_1.default.createElement(ui_1.DropdownMenuTrigger, { asChild: true, className: "print:hidden" },
119
134
  react_1.default.createElement(ui_1.IconButton, { className: "absolute right-1 top-1 z-10" },
@@ -1,4 +1,6 @@
1
+ import type { GridRange } from "@rowsncolumns/grid";
1
2
  import React from "react";
3
+ import { type GoToSpecialKind } from "../../api/go-to-special";
2
4
  import type { NamedRange, SheetRange } from "../../types";
3
5
  export type GoToDialogProps = {
4
6
  /** Controls visibility. */
@@ -15,6 +17,14 @@ export type GoToDialogProps = {
15
17
  resolve(reference: string): SheetRange | undefined;
16
18
  /** Receives the resolved range; the host selects and scrolls to it. */
17
19
  onNavigate(range: SheetRange): void;
20
+ /**
21
+ * Go To Special. `resolve` returns the matching cell runs for a category;
22
+ * `onSelectRanges` receives them. Omit to hide the "Special…" panel.
23
+ */
24
+ special?: {
25
+ resolve(kind: GoToSpecialKind): GridRange[];
26
+ onSelectRanges(ranges: GridRange[]): void;
27
+ };
18
28
  };
19
29
  /**
20
30
  * Excel's Go To dialog (`Ctrl+G` / `F5`): type a cell or range reference,
@@ -22,7 +32,7 @@ export type GoToDialogProps = {
22
32
  * jumps there. Resolution is delegated to `resolve` so the dialog stays
23
33
  * UI-only.
24
34
  */
25
- export declare const GoToDialog: React.MemoExoticComponent<({ open, onOpenChange, namedRanges, currentAddress, resolve, onNavigate, }: GoToDialogProps) => React.JSX.Element>;
35
+ export declare const GoToDialog: React.MemoExoticComponent<({ open, onOpenChange, namedRanges, currentAddress, resolve, onNavigate, special, }: GoToDialogProps) => React.JSX.Element>;
26
36
  /**
27
37
  * Host-mounted, atom-driven wrapper around {@link GoToDialog}. Mount it once
28
38
  * in the host alongside the other editor dialogs; the grid opens it on
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../components/go-to-dialog/index.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAQ3D,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE1D,MAAM,MAAM,eAAe,GAAG;IAC5B,2BAA2B;IAC3B,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;IAClC,gFAAgF;IAChF,WAAW,CAAC,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC;IAClC,4EAA4E;IAC5E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC;IACnD,uEAAuE;IACvE,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;CACrC,CAAC;AAIF;;;;;GAKG;AACH,eAAO,MAAM,UAAU,wGAQlB,eAAe,uBA4GnB,CAAC;AAUF;;;;GAIG;AACH,eAAO,MAAM,cAAc;;;CA8B1B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../components/go-to-dialog/index.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAEpD,OAAO,KAAsC,MAAM,OAAO,CAAC;AAG3D,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,yBAAyB,CAAC;AAMjC,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE1D,MAAM,MAAM,eAAe,GAAG;IAC5B,2BAA2B;IAC3B,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;IAClC,gFAAgF;IAChF,WAAW,CAAC,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC;IAClC,4EAA4E;IAC5E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC;IACnD,uEAAuE;IACvE,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;IACpC;;;OAGG;IACH,OAAO,CAAC,EAAE;QACR,OAAO,CAAC,IAAI,EAAE,eAAe,GAAG,SAAS,EAAE,CAAC;QAC5C,cAAc,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC;KAC3C,CAAC;CACH,CAAC;AAKF;;;;;GAKG;AACH,eAAO,MAAM,UAAU,iHASlB,eAAe,uBA0MnB,CAAC;AAUF;;;;GAIG;AACH,eAAO,MAAM,cAAc;;;CA+B1B,CAAC"}
@@ -6,8 +6,10 @@ var ui_1 = require("@rowsncolumns/ui");
6
6
  var utils_1 = require("@rowsncolumns/utils");
7
7
  var react_1 = tslib_1.__importStar(require("react"));
8
8
  var go_to_1 = require("../../api/go-to");
9
+ var go_to_special_1 = require("../../api/go-to-special");
9
10
  var go_to_dialog_atom_1 = require("../../atoms/go-to-dialog.atom");
10
11
  var INVALID_REFERENCE = "Reference is not valid.";
12
+ var NO_CELLS_FOUND = "No cells were found.";
11
13
  /**
12
14
  * Excel's Go To dialog (`Ctrl+G` / `F5`): type a cell or range reference,
13
15
  * optionally sheet-qualified, or pick a defined name, and the selection
@@ -15,9 +17,22 @@ var INVALID_REFERENCE = "Reference is not valid.";
15
17
  * UI-only.
16
18
  */
17
19
  exports.GoToDialog = (0, react_1.memo)(function (_a) {
18
- var open = _a.open, onOpenChange = _a.onOpenChange, namedRanges = _a.namedRanges, currentAddress = _a.currentAddress, resolve = _a.resolve, onNavigate = _a.onNavigate;
20
+ var open = _a.open, onOpenChange = _a.onOpenChange, namedRanges = _a.namedRanges, currentAddress = _a.currentAddress, resolve = _a.resolve, onNavigate = _a.onNavigate, special = _a.special;
19
21
  var _b = tslib_1.__read((0, react_1.useState)(""), 2), reference = _b[0], setReference = _b[1];
20
22
  var _c = tslib_1.__read((0, react_1.useState)(undefined), 2), error = _c[0], setError = _c[1];
23
+ var _d = tslib_1.__read((0, react_1.useState)(false), 2), showSpecial = _d[0], setShowSpecial = _d[1];
24
+ var _e = tslib_1.__read((0, react_1.useState)("blanks"), 2), specialKind = _e[0], setSpecialKind = _e[1];
25
+ var selectSpecial = (0, react_1.useCallback)(function () {
26
+ if (!special)
27
+ return;
28
+ var ranges = special.resolve(specialKind);
29
+ if (!ranges.length) {
30
+ setError(NO_CELLS_FOUND);
31
+ return;
32
+ }
33
+ special.onSelectRanges(ranges);
34
+ onOpenChange(false);
35
+ }, [special, specialKind, onOpenChange]);
21
36
  var navigate = (0, react_1.useCallback)(function (text) {
22
37
  var range = resolve(text);
23
38
  if (!range) {
@@ -30,30 +45,58 @@ exports.GoToDialog = (0, react_1.memo)(function (_a) {
30
45
  var names = (namedRanges !== null && namedRanges !== void 0 ? namedRanges : []).filter(function (range) { return range.range && !range.hidden; });
31
46
  return (react_1.default.createElement(ui_1.Dialog, { open: open, onOpenChange: onOpenChange, modal: true },
32
47
  react_1.default.createElement(ui_1.DialogContent, { className: "w-[360px] max-w-[92vw] pointer-events-auto" },
33
- react_1.default.createElement(ui_1.DialogTitle, null, "Go To"),
48
+ react_1.default.createElement(ui_1.DialogTitle, null, showSpecial ? "Go To Special" : "Go To"),
34
49
  react_1.default.createElement(ui_1.DialogCloseButton, null),
35
- react_1.default.createElement(ui_1.DialogBody, { className: "flex flex-col gap-3" },
36
- react_1.default.createElement("form", { className: "flex flex-col gap-3", onSubmit: function (e) {
37
- e.preventDefault();
38
- navigate(reference);
39
- } },
40
- react_1.default.createElement("div", { className: "flex flex-col gap-1" },
41
- react_1.default.createElement("span", { className: "text-xs font-medium" }, "Go to:"),
42
- react_1.default.createElement("div", { role: "listbox", "aria-label": "Defined names", className: "h-[140px] overflow-auto rounded border border-rnc-border text-xs" }, names.length === 0 ? (react_1.default.createElement("div", { className: "px-2 py-1.5 text-rnc-foreground/60" }, "No defined names")) : (names.map(function (range) { return (react_1.default.createElement("div", { key: String(range.namedRangeId), role: "option", "aria-selected": reference === range.name, className: (0, ui_1.cn)("px-2 py-1 cursor-default select-none hover:bg-rnc-accent", reference === range.name && "bg-rnc-accent"), onClick: function () {
43
- setReference(range.name);
44
- setError(undefined);
45
- }, onDoubleClick: function () { return navigate(range.name); } }, range.name)); })))),
46
- react_1.default.createElement("label", { className: "flex flex-col gap-1 text-xs font-medium" },
47
- "Reference:",
48
- react_1.default.createElement(ui_1.Input, { autoFocus: true, value: reference, placeholder: currentAddress, "aria-invalid": error ? true : undefined, onChange: function (e) {
49
- setReference(e.target.value);
50
- setError(undefined);
51
- } })),
52
- error ? (react_1.default.createElement("div", { role: "alert", className: "text-xs text-rnc-destructive" }, error)) : null,
53
- react_1.default.createElement(ui_1.Separator, null),
54
- react_1.default.createElement("div", { className: "flex justify-end gap-2" },
50
+ react_1.default.createElement(ui_1.DialogBody, { className: "flex flex-col gap-3" }, showSpecial && special ? (react_1.default.createElement("form", { className: "flex flex-col gap-3", onSubmit: function (e) {
51
+ e.preventDefault();
52
+ selectSpecial();
53
+ } },
54
+ react_1.default.createElement("fieldset", { className: "flex flex-col gap-1 border-0 p-0 m-0" },
55
+ react_1.default.createElement("legend", { className: "text-xs font-medium pb-1" }, "Select"),
56
+ go_to_special_1.GO_TO_SPECIAL_OPTIONS.map(function (_a) {
57
+ var kind = _a.kind, label = _a.label;
58
+ return (react_1.default.createElement("label", { key: kind, className: "flex items-center gap-2 text-xs cursor-pointer" },
59
+ react_1.default.createElement("input", { type: "radio", name: "goToSpecial", value: kind, checked: specialKind === kind, onChange: function () {
60
+ setSpecialKind(kind);
61
+ setError(undefined);
62
+ } }),
63
+ label));
64
+ })),
65
+ error ? (react_1.default.createElement("div", { role: "alert", className: "text-xs text-rnc-destructive" }, error)) : null,
66
+ react_1.default.createElement(ui_1.Separator, null),
67
+ react_1.default.createElement("div", { className: "flex justify-between gap-2" },
68
+ react_1.default.createElement(ui_1.Button, { type: "button", variant: "ghost", size: "sm", onClick: function () {
69
+ setShowSpecial(false);
70
+ setError(undefined);
71
+ } }, "Back"),
72
+ react_1.default.createElement("div", { className: "flex gap-2" },
73
+ react_1.default.createElement(ui_1.Button, { type: "button", variant: "outline", size: "sm", onClick: function () { return onOpenChange(false); } }, "Cancel"),
74
+ react_1.default.createElement(ui_1.Button, { type: "submit", size: "sm" }, "OK"))))) : (react_1.default.createElement("form", { className: "flex flex-col gap-3", onSubmit: function (e) {
75
+ e.preventDefault();
76
+ navigate(reference);
77
+ } },
78
+ react_1.default.createElement("div", { className: "flex flex-col gap-1" },
79
+ react_1.default.createElement("span", { className: "text-xs font-medium" }, "Go to:"),
80
+ react_1.default.createElement("div", { role: "listbox", "aria-label": "Defined names", className: "h-[140px] overflow-auto rounded border border-rnc-border text-xs" }, names.length === 0 ? (react_1.default.createElement("div", { className: "px-2 py-1.5 text-rnc-foreground/60" }, "No defined names")) : (names.map(function (range) { return (react_1.default.createElement("div", { key: String(range.namedRangeId), role: "option", "aria-selected": reference === range.name, className: (0, ui_1.cn)("px-2 py-1 cursor-default select-none hover:bg-rnc-accent", reference === range.name && "bg-rnc-accent"), onClick: function () {
81
+ setReference(range.name);
82
+ setError(undefined);
83
+ }, onDoubleClick: function () { return navigate(range.name); } }, range.name)); })))),
84
+ react_1.default.createElement("label", { className: "flex flex-col gap-1 text-xs font-medium" },
85
+ "Reference:",
86
+ react_1.default.createElement(ui_1.Input, { autoFocus: true, value: reference, placeholder: currentAddress, "aria-invalid": error ? true : undefined, onChange: function (e) {
87
+ setReference(e.target.value);
88
+ setError(undefined);
89
+ } })),
90
+ error ? (react_1.default.createElement("div", { role: "alert", className: "text-xs text-rnc-destructive" }, error)) : null,
91
+ react_1.default.createElement(ui_1.Separator, null),
92
+ react_1.default.createElement("div", { className: "flex justify-between gap-2" },
93
+ special ? (react_1.default.createElement(ui_1.Button, { type: "button", variant: "ghost", size: "sm", onClick: function () {
94
+ setShowSpecial(true);
95
+ setError(undefined);
96
+ } }, "Special\u2026")) : (react_1.default.createElement("span", null)),
97
+ react_1.default.createElement("div", { className: "flex gap-2" },
55
98
  react_1.default.createElement(ui_1.Button, { type: "button", variant: "outline", size: "sm", onClick: function () { return onOpenChange(false); } }, "Cancel"),
56
- react_1.default.createElement(ui_1.Button, { type: "submit", size: "sm", disabled: !reference.trim() }, "OK")))))));
99
+ react_1.default.createElement(ui_1.Button, { type: "submit", size: "sm", disabled: !reference.trim() }, "OK")))))))));
57
100
  });
58
101
  exports.GoToDialog.displayName = "GoToDialog";
59
102
  var currentAddressOf = function (request) {
@@ -87,7 +130,7 @@ var GoToDialogHost = function () {
87
130
  return (react_1.default.createElement(exports.GoToDialog, { open: true, onOpenChange: function (open) {
88
131
  if (!open)
89
132
  close();
90
- }, namedRanges: request.namedRanges, currentAddress: currentAddressOf(request), resolve: resolve, onNavigate: request.onNavigate }));
133
+ }, namedRanges: request.namedRanges, currentAddress: currentAddressOf(request), resolve: resolve, onNavigate: request.onNavigate, special: request.special }));
91
134
  };
92
135
  exports.GoToDialogHost = GoToDialogHost;
93
136
  exports.GoToDialogHost.displayName = "GoToDialogHost";
@@ -0,0 +1,32 @@
1
+ import React from "react";
2
+ import type { GoalSeekResult } from "../../types";
3
+ export type GoalSeekDialogProps = {
4
+ /** Controls visibility. */
5
+ open: boolean;
6
+ onOpenChange(open: boolean): void;
7
+ /** Default "Set cell" (A1 reference of the active cell). */
8
+ initialSetCell: string;
9
+ /**
10
+ * Runs the search with the three fields (A1 references + the numeric
11
+ * target). Resolves to the result, or `undefined` when the engine reports
12
+ * none (the rnc engine iterates natively and streams the cells back).
13
+ */
14
+ onApply(setCell: string, targetValue: number, changingCell: string): Promise<GoalSeekResult | undefined>;
15
+ };
16
+ /** Excel's status sentence for a finished search. */
17
+ export declare const goalSeekStatusText: (setCell: string, result: GoalSeekResult | undefined) => string;
18
+ /**
19
+ * Excel's Goal Seek dialog: Set cell / To value / By changing cell, then the
20
+ * Goal Seek Status sentence with target and current value.
21
+ */
22
+ export declare const GoalSeekDialog: React.MemoExoticComponent<({ open, onOpenChange, initialSetCell, onApply }: GoalSeekDialogProps) => React.JSX.Element>;
23
+ /**
24
+ * Host-mounted, atom-driven wrapper around {@link GoalSeekDialog}. Mount
25
+ * once in the host; the context menu opens it via `useOpenGoalSeekDialog`
26
+ * and only offers the item while a host is mounted.
27
+ */
28
+ export declare const GoalSeekDialogHost: {
29
+ (): React.JSX.Element;
30
+ displayName: string;
31
+ };
32
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,149 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GoalSeekDialogHost = exports.GoalSeekDialog = exports.goalSeekStatusText = void 0;
4
+ var tslib_1 = require("tslib");
5
+ var icons_1 = require("@rowsncolumns/icons");
6
+ var ui_1 = require("@rowsncolumns/ui");
7
+ var utils_1 = require("@rowsncolumns/utils");
8
+ var react_1 = tslib_1.__importStar(require("react"));
9
+ var goal_seek_dialog_atom_1 = require("../../atoms/goal-seek-dialog.atom");
10
+ var isCellReference = function (text) {
11
+ return /^\$?[A-Za-z]{1,3}\$?\d+$/.test(text.trim()) && (0, utils_1.addressToCell)(text.trim()) != null;
12
+ };
13
+ /** Excel's status sentence for a finished search. */
14
+ var goalSeekStatusText = function (setCell, result) {
15
+ if (!result)
16
+ return "Goal Seeking with Cell ".concat(setCell, " finished.");
17
+ return result.status === "found"
18
+ ? "Goal Seeking with Cell ".concat(setCell, " found a solution.")
19
+ : "Goal Seeking with Cell ".concat(setCell, " may not have found a solution.");
20
+ };
21
+ exports.goalSeekStatusText = goalSeekStatusText;
22
+ /**
23
+ * Excel's Goal Seek dialog: Set cell / To value / By changing cell, then the
24
+ * Goal Seek Status sentence with target and current value.
25
+ */
26
+ exports.GoalSeekDialog = (0, react_1.memo)(function (_a) {
27
+ var open = _a.open, onOpenChange = _a.onOpenChange, initialSetCell = _a.initialSetCell, onApply = _a.onApply;
28
+ var _b = tslib_1.__read((0, react_1.useState)(initialSetCell), 2), setCell = _b[0], setSetCell = _b[1];
29
+ var _c = tslib_1.__read((0, react_1.useState)(""), 2), target = _c[0], setTarget = _c[1];
30
+ 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];
34
+ (0, react_1.useEffect)(function () {
35
+ if (open) {
36
+ setSetCell(initialSetCell);
37
+ setTarget("");
38
+ setChangingCell("");
39
+ setError(undefined);
40
+ setBusy(false);
41
+ setResult(undefined);
42
+ }
43
+ // Only reset on open transitions.
44
+ // eslint-disable-next-line react-hooks/exhaustive-deps
45
+ }, [open]);
46
+ 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) {
50
+ case 0:
51
+ event.preventDefault();
52
+ targetValue = Number(target.trim());
53
+ if (!isCellReference(setCell)) {
54
+ setError("Set cell must be a single cell reference, e.g. B4.");
55
+ return [2 /*return*/];
56
+ }
57
+ if (target.trim() === "" || !Number.isFinite(targetValue)) {
58
+ setError("To value must be a number.");
59
+ return [2 /*return*/];
60
+ }
61
+ if (!isCellReference(changingCell)) {
62
+ setError("By changing cell must be a single cell reference, e.g. A1.");
63
+ return [2 /*return*/];
64
+ }
65
+ setError(undefined);
66
+ setBusy(true);
67
+ _a.label = 1;
68
+ case 1:
69
+ _a.trys.push([1, 3, 4, 5]);
70
+ return [4 /*yield*/, onApply(setCell.trim().toUpperCase(), targetValue, changingCell.trim().toUpperCase())];
71
+ 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.");
78
+ return [3 /*break*/, 5];
79
+ case 4:
80
+ setBusy(false);
81
+ return [7 /*endfinally*/];
82
+ case 5: return [2 /*return*/];
83
+ }
84
+ });
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" },
95
+ react_1.default.createElement("dt", { className: "text-rnc-foreground/70" }, "Target value:"),
96
+ react_1.default.createElement("dd", null, result.result.targetValue),
97
+ react_1.default.createElement("dt", { className: "text-rnc-foreground/70" }, "Current value:"),
98
+ react_1.default.createElement("dd", null, result.result.currentValue === undefined
99
+ ? "—"
100
+ : String(result.result.currentValue)))) : null,
101
+ react_1.default.createElement(ui_1.Separator, null),
102
+ 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 },
104
+ react_1.default.createElement("label", { className: "flex flex-col gap-1 text-xs font-medium" },
105
+ "Set cell:",
106
+ react_1.default.createElement(ui_1.Input, { autoFocus: true, value: setCell, "aria-label": "Set cell", onChange: function (e) {
107
+ setSetCell(e.target.value);
108
+ setError(undefined);
109
+ } })),
110
+ react_1.default.createElement("label", { className: "flex flex-col gap-1 text-xs font-medium" },
111
+ "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
+ } })),
116
+ react_1.default.createElement("label", { className: "flex flex-col gap-1 text-xs font-medium" },
117
+ "By changing cell:",
118
+ react_1.default.createElement(ui_1.Input, { value: changingCell, "aria-label": "By changing cell", onChange: function (e) {
119
+ setChangingCell(e.target.value);
120
+ setError(undefined);
121
+ } })),
122
+ error ? (react_1.default.createElement("div", { role: "alert", className: "text-xs text-rnc-destructive" }, error)) : null,
123
+ react_1.default.createElement(ui_1.Separator, null),
124
+ react_1.default.createElement("div", { className: "flex justify-end gap-2" },
125
+ react_1.default.createElement(ui_1.Button, { type: "button", variant: "outline", size: "sm", onClick: function () { return onOpenChange(false); } }, "Cancel"),
126
+ react_1.default.createElement(ui_1.Button, { type: "submit", size: "sm", disabled: busy }, busy ? "Seeking…" : "OK"))))))));
127
+ });
128
+ exports.GoalSeekDialog.displayName = "GoalSeekDialog";
129
+ /**
130
+ * Host-mounted, atom-driven wrapper around {@link GoalSeekDialog}. Mount
131
+ * once in the host; the context menu opens it via `useOpenGoalSeekDialog`
132
+ * and only offers the item while a host is mounted.
133
+ */
134
+ var GoalSeekDialogHost = function () {
135
+ var _a;
136
+ (0, goal_seek_dialog_atom_1.useRegisterGoalSeekDialogHost)();
137
+ var _b = tslib_1.__read((0, goal_seek_dialog_atom_1.useGoalSeekDialogState)(), 2), request = _b[0], setRequest = _b[1];
138
+ var close = (0, react_1.useCallback)(function () { return setRequest(null); }, [setRequest]);
139
+ return (react_1.default.createElement(exports.GoalSeekDialog, { open: request != null, onOpenChange: function (open) {
140
+ if (!open)
141
+ close();
142
+ }, initialSetCell: (_a = request === null || request === void 0 ? void 0 : request.setCell) !== null && _a !== void 0 ? _a : "", onApply: function (setCell, targetValue, changingCell) {
143
+ return request
144
+ ? request.onApply(setCell, targetValue, changingCell)
145
+ : Promise.resolve(undefined);
146
+ } }));
147
+ };
148
+ exports.GoalSeekDialogHost = GoalSeekDialogHost;
149
+ exports.GoalSeekDialogHost.displayName = "GoalSeekDialogHost";
@@ -0,0 +1,30 @@
1
+ import React from "react";
2
+ import { type SubtotalDialogChoices, type SubtotalDialogColumn } from "../../atoms/subtotal-dialog.atom";
3
+ export type { SubtotalDialogChoices, SubtotalDialogColumn };
4
+ export type SubtotalDialogProps = {
5
+ /** Controls visibility. */
6
+ open: boolean;
7
+ onOpenChange(open: boolean): void;
8
+ /** Columns of the range, in sheet order. */
9
+ columns: SubtotalDialogColumn[];
10
+ /** Initial state of "My data has headers". */
11
+ initialHasHeader?: boolean;
12
+ /** Emits the choices; the host adds the range and routes to `onSubtotal`. */
13
+ onApply(choices: SubtotalDialogChoices): void;
14
+ };
15
+ /**
16
+ * Excel's Subtotal dialog: "At each change in" (group column), "Use
17
+ * function", "Add subtotal to" (aggregate columns), "Replace current
18
+ * subtotals". Summary rows are always placed below the data.
19
+ */
20
+ export declare const SubtotalDialog: React.MemoExoticComponent<({ open, onOpenChange, columns, initialHasHeader, onApply, }: SubtotalDialogProps) => React.JSX.Element>;
21
+ /**
22
+ * Host-mounted, atom-driven wrapper around {@link SubtotalDialog}. Mount
23
+ * once in the host; the context menu opens it via `useOpenSubtotalDialog`
24
+ * and only offers the item while a host is mounted.
25
+ */
26
+ export declare const SubtotalDialogHost: {
27
+ (): React.JSX.Element;
28
+ displayName: string;
29
+ };
30
+ //# sourceMappingURL=index.d.ts.map