@svgrid/enterprise 3.0.2 → 3.0.3

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 (364) hide show
  1. package/LICENSE +94 -24
  2. package/README.md +36 -4
  3. package/dist/SvAdvancedFilter.svelte +1 -1
  4. package/dist/SvAlertsManager.svelte +2 -1
  5. package/dist/SvBoard.svelte +2 -1
  6. package/dist/SvExportMenu.svelte +4 -1
  7. package/dist/SvExportMenu.svelte.d.ts +0 -13
  8. package/dist/SvExpressionEditor.svelte +3 -3
  9. package/dist/SvFormulaBar.svelte +94 -20
  10. package/dist/SvFormulaBar.svelte.d.ts +7 -0
  11. package/dist/SvGridAlerts.svelte +49 -9
  12. package/dist/SvGridBoard.svelte +13 -8
  13. package/dist/SvGridBulkEditDrawer.svelte +26 -2
  14. package/dist/SvGridEditPanel.svelte +3 -0
  15. package/dist/SvGridScheduler.svelte +69 -40
  16. package/dist/SvGridSelectionBar.svelte +10 -3
  17. package/dist/SvPivotDesigner.svelte +198 -40
  18. package/dist/SvPivotDesigner.svelte.d.ts +27 -20
  19. package/dist/SvSheet.svelte +4043 -243
  20. package/dist/SvSheet.svelte.d.ts +76 -3
  21. package/dist/SvSheetChartSetup.svelte +151 -0
  22. package/dist/SvSheetChartSetup.svelte.d.ts +18 -0
  23. package/dist/SvSheetComment.svelte +216 -31
  24. package/dist/SvSheetComment.svelte.d.ts +11 -11
  25. package/dist/SvSheetConditionalFormat.svelte +28 -31
  26. package/dist/SvSheetDataValidation.svelte +66 -42
  27. package/dist/SvSheetEditRanges.svelte +217 -0
  28. package/dist/SvSheetEditRanges.svelte.d.ts +15 -0
  29. package/dist/SvSheetErrors.svelte +125 -0
  30. package/dist/SvSheetErrors.svelte.d.ts +20 -0
  31. package/dist/SvSheetEvaluate.svelte +133 -0
  32. package/dist/SvSheetEvaluate.svelte.d.ts +15 -0
  33. package/dist/SvSheetFilterMenu.svelte +137 -34
  34. package/dist/SvSheetFilterMenu.svelte.d.ts +5 -0
  35. package/dist/SvSheetFindReplace.svelte +19 -19
  36. package/dist/SvSheetFormatCells.svelte +125 -81
  37. package/dist/SvSheetGoalSeek.svelte +17 -16
  38. package/dist/SvSheetInsertFunction.svelte +15 -13
  39. package/dist/SvSheetIteration.svelte +81 -0
  40. package/dist/SvSheetIteration.svelte.d.ts +10 -0
  41. package/dist/SvSheetLink.svelte +99 -0
  42. package/dist/SvSheetLink.svelte.d.ts +17 -0
  43. package/dist/SvSheetListPicker.svelte +4 -2
  44. package/dist/SvSheetListPicker.svelte.d.ts +0 -6
  45. package/dist/SvSheetManageRules.svelte +20 -18
  46. package/dist/SvSheetNameManager.svelte +17 -15
  47. package/dist/SvSheetPageSetup.svelte +159 -0
  48. package/dist/SvSheetPageSetup.svelte.d.ts +13 -0
  49. package/dist/SvSheetPasteSpecial.svelte +22 -20
  50. package/dist/SvSheetPivot.svelte +220 -0
  51. package/dist/SvSheetPivot.svelte.d.ts +21 -0
  52. package/dist/SvSheetProtectSheet.svelte +81 -0
  53. package/dist/SvSheetProtectSheet.svelte.d.ts +11 -0
  54. package/dist/SvSheetRemoveDuplicates.svelte +13 -10
  55. package/dist/SvSheetRibbon.svelte +104 -51
  56. package/dist/SvSheetSizeDialog.svelte +4 -2
  57. package/dist/SvSheetSort.svelte +218 -0
  58. package/dist/SvSheetSort.svelte.d.ts +28 -0
  59. package/dist/SvSheetSparklines.svelte +135 -0
  60. package/dist/SvSheetSparklines.svelte.d.ts +14 -0
  61. package/dist/SvSheetTable.svelte +160 -0
  62. package/dist/SvSheetTable.svelte.d.ts +24 -0
  63. package/dist/SvSheetTabs.svelte +161 -31
  64. package/dist/SvSheetTabs.svelte.d.ts +22 -8
  65. package/dist/SvSheetTextToColumns.svelte +20 -20
  66. package/dist/SvSheetValidationAlert.svelte +8 -6
  67. package/dist/advanced-filter-enable.js +1 -1
  68. package/dist/alerts/alert-engine.d.ts +6 -0
  69. package/dist/alerts/alert-engine.js +21 -4
  70. package/dist/alerts/alert-formats.js +2 -0
  71. package/dist/alerts/alert-types.d.ts +1 -1
  72. package/dist/alerts.d.ts +1 -1
  73. package/dist/alerts.js +2 -2
  74. package/dist/board.js +2 -2
  75. package/dist/bulk-edit.d.ts +3 -1
  76. package/dist/bulk-edit.js +1 -1
  77. package/dist/cdn/svgrid-enterprise.svelte-external.js +39827 -16429
  78. package/dist/designer/assets/GridMenus-8gTNssgV.js +8 -0
  79. package/dist/designer/assets/{SvChartMenu-D9hEeHar.js → SvChartMenu-BDoeqGz6.js} +1 -1
  80. package/dist/designer/assets/{SvDateTimePicker-DARvKUL2.js → SvDateTimePicker-DCPg7WGN.js} +1 -1
  81. package/dist/designer/assets/SvGridCellEditor-DMoWJjEI.js +4 -0
  82. package/dist/designer/assets/{SvGridChart-B8j1SSy3.js → SvGridChart-Cy1ATrWh.js} +2 -2
  83. package/dist/designer/assets/SvGridChartBuilder-eQ3mn0L9.js +1 -0
  84. package/dist/designer/assets/{SvGridChartPanel-pT6ITc2P.js → SvGridChartPanel-CATdVc9X.js} +3 -3
  85. package/dist/designer/assets/{SvGridChartView-bg281UA1.js → SvGridChartView-CmsZtCED.js} +1 -1
  86. package/dist/designer/assets/SvGridDropdown-Cjz0H-fI.js +1 -0
  87. package/dist/designer/assets/{SvTabs-UFCMTHXS.js → SvTabs-2mHC6oaz.js} +1 -1
  88. package/dist/designer/assets/cell-formatting-BbubJTVz.js +1 -0
  89. package/dist/designer/assets/{chart-cIPUsbM5.js → chart-Cn7MnNqA.js} +1 -1
  90. package/dist/designer/assets/{chart-panel-messages-DtTxpBUU.js → chart-panel-messages-Dz7PTIqT.js} +1 -1
  91. package/dist/designer/assets/{chart-summary-Czu_5epb.js → chart-summary-BD1qYB2R.js} +1 -1
  92. package/dist/designer/assets/{chart-trend-D5I5VEe8.js → chart-trend-B8xr5LuD.js} +1 -1
  93. package/dist/designer/assets/{dismissable-BO547MH9.js → dismissable-ChWRPkoa.js} +1 -1
  94. package/dist/designer/assets/{export-format-D-eP4b2l.js → export-format-DGckmgKr.js} +1 -1
  95. package/dist/designer/assets/{focus-trap-CAreAhlU.js → focus-trap-V2-6Fy9I.js} +1 -1
  96. package/dist/designer/assets/{index-DwU7CAMm.js → index-D5bVbuzI.js} +317 -315
  97. package/dist/designer/assets/index-_JVFxt02.css +1 -0
  98. package/dist/designer/assets/row-resize-BInFWCpr.js +1 -0
  99. package/dist/designer/assets/server-block-cache-CXJKkJpy.js +1 -0
  100. package/dist/designer/assets/src-DUQ4xE3x.js +58 -0
  101. package/dist/designer/assets/validate-C3B8QKsM.js +1 -0
  102. package/dist/designer/index.html +17 -16
  103. package/dist/export-pdf.d.ts +75 -0
  104. package/dist/export-pdf.js +216 -15
  105. package/dist/export.js +10 -2
  106. package/dist/gantt/SvGridGantt.svelte +2890 -0
  107. package/dist/gantt/SvGridGantt.svelte.d.ts +30 -0
  108. package/dist/gantt/gantt-config.d.ts +73 -0
  109. package/dist/gantt/gantt-config.js +1 -0
  110. package/dist/gantt/gantt-critical-path.d.ts +67 -0
  111. package/dist/gantt/gantt-critical-path.js +207 -0
  112. package/dist/gantt/gantt-model.d.ts +257 -0
  113. package/dist/gantt/gantt-model.js +651 -0
  114. package/dist/gantt/gantt-resources.d.ts +59 -0
  115. package/dist/gantt/gantt-resources.js +71 -0
  116. package/dist/gantt/gantt.d.ts +7 -0
  117. package/dist/gantt/gantt.js +36 -0
  118. package/dist/gantt/index.d.ts +15 -0
  119. package/dist/gantt/index.js +22 -0
  120. package/dist/gantt/timeline-arrows.d.ts +102 -0
  121. package/dist/gantt/timeline-arrows.js +181 -0
  122. package/dist/import.d.ts +2 -2
  123. package/dist/import.js +1 -1
  124. package/dist/index.d.ts +34 -7
  125. package/dist/index.js +44 -7
  126. package/dist/install.js +8 -1
  127. package/dist/license-core.d.ts +17 -1
  128. package/dist/license-core.js +16 -5
  129. package/dist/license.d.ts +18 -2
  130. package/dist/license.js +71 -6
  131. package/dist/node/studio.js +140 -8
  132. package/dist/pivot-enable.js +2 -2
  133. package/dist/scheduler-dependencies.d.ts +35 -0
  134. package/dist/scheduler-dependencies.js +36 -1
  135. package/dist/scheduler.js +2 -2
  136. package/dist/selection-bar.js +2 -2
  137. package/dist/server/SvGroupCell.svelte +213 -0
  138. package/dist/server/SvGroupCell.svelte.d.ts +62 -0
  139. package/dist/server/SvRowGroupPanel.svelte +322 -0
  140. package/dist/server/SvRowGroupPanel.svelte.d.ts +37 -0
  141. package/dist/server/enable.d.ts +17 -0
  142. package/dist/server/enable.js +49 -0
  143. package/dist/server/index.d.ts +22 -0
  144. package/dist/server/index.js +24 -0
  145. package/dist/server/messages.d.ts +45 -0
  146. package/dist/server/messages.js +35 -0
  147. package/dist/server/server-group-model.d.ts +104 -0
  148. package/dist/server/server-group-model.js +272 -0
  149. package/dist/server/server-pivot.d.ts +46 -0
  150. package/dist/server/server-pivot.js +57 -0
  151. package/dist/server/server-row-model.d.ts +547 -0
  152. package/dist/server/server-row-model.js +1551 -0
  153. package/dist/server/server-selection.d.ts +99 -0
  154. package/dist/server/server-selection.js +215 -0
  155. package/dist/server/svgrid-adapter.d.ts +155 -0
  156. package/dist/server/svgrid-adapter.js +202 -0
  157. package/dist/sheet/ast.d.ts +45 -1
  158. package/dist/sheet/ast.js +14 -0
  159. package/dist/sheet/auto-filter.d.ts +58 -4
  160. package/dist/sheet/auto-filter.js +159 -11
  161. package/dist/sheet/autocomplete.d.ts +9 -0
  162. package/dist/sheet/autocomplete.js +90 -4
  163. package/dist/sheet/cell-images.d.ts +39 -0
  164. package/dist/sheet/cell-images.js +90 -0
  165. package/dist/sheet/cell-types.d.ts +58 -0
  166. package/dist/sheet/cell-types.js +96 -0
  167. package/dist/sheet/coerce.d.ts +40 -0
  168. package/dist/sheet/coerce.js +170 -3
  169. package/dist/sheet/comments.d.ts +43 -9
  170. package/dist/sheet/comments.js +85 -27
  171. package/dist/sheet/conditional-formats.d.ts +29 -6
  172. package/dist/sheet/conditional-formats.js +37 -12
  173. package/dist/sheet/csv.d.ts +32 -0
  174. package/dist/sheet/csv.js +158 -0
  175. package/dist/sheet/culture.d.ts +87 -0
  176. package/dist/sheet/culture.js +247 -0
  177. package/dist/sheet/delta.d.ts +102 -0
  178. package/dist/sheet/delta.js +203 -0
  179. package/dist/sheet/deps.d.ts +45 -1
  180. package/dist/sheet/deps.js +77 -2
  181. package/dist/sheet/document.d.ts +106 -4
  182. package/dist/sheet/document.js +204 -3
  183. package/dist/sheet/engine.d.ts +67 -0
  184. package/dist/sheet/engine.js +19 -0
  185. package/dist/sheet/entry.d.ts +8 -4
  186. package/dist/sheet/entry.js +171 -21
  187. package/dist/sheet/error-check.d.ts +49 -0
  188. package/dist/sheet/error-check.js +83 -0
  189. package/dist/sheet/evaluate-steps.d.ts +48 -0
  190. package/dist/sheet/evaluate-steps.js +196 -0
  191. package/dist/sheet/evaluate.d.ts +67 -0
  192. package/dist/sheet/evaluate.js +725 -13
  193. package/dist/sheet/filter-files.d.ts +37 -0
  194. package/dist/sheet/filter-files.js +465 -0
  195. package/dist/sheet/format-store.d.ts +15 -0
  196. package/dist/sheet/format-store.js +11 -1
  197. package/dist/sheet/from-rows.d.ts +14 -0
  198. package/dist/sheet/from-rows.js +50 -0
  199. package/dist/sheet/function-catalog.d.ts +1 -1
  200. package/dist/sheet/function-catalog.js +296 -5
  201. package/dist/sheet/functions.js +363 -91
  202. package/dist/sheet/index.d.ts +35 -8
  203. package/dist/sheet/index.js +35 -8
  204. package/dist/sheet/links.d.ts +57 -0
  205. package/dist/sheet/links.js +174 -0
  206. package/dist/sheet/messages.d.ts +778 -0
  207. package/dist/sheet/messages.js +806 -0
  208. package/dist/sheet/number-format.d.ts +52 -5
  209. package/dist/sheet/number-format.js +465 -68
  210. package/dist/sheet/objects.d.ts +106 -0
  211. package/dist/sheet/objects.js +149 -0
  212. package/dist/sheet/ods-document.d.ts +44 -0
  213. package/dist/sheet/ods-document.js +1275 -0
  214. package/dist/sheet/open-file.d.ts +26 -0
  215. package/dist/sheet/open-file.js +56 -0
  216. package/dist/sheet/outline.d.ts +82 -0
  217. package/dist/sheet/outline.js +228 -0
  218. package/dist/sheet/packs/array.d.ts +16 -0
  219. package/dist/sheet/packs/array.js +172 -0
  220. package/dist/sheet/packs/database.d.ts +42 -0
  221. package/dist/sheet/packs/database.js +142 -0
  222. package/dist/sheet/packs/engineering.d.ts +2 -0
  223. package/dist/sheet/packs/engineering.js +296 -0
  224. package/dist/sheet/packs/financial.d.ts +5 -0
  225. package/dist/sheet/packs/financial.js +220 -0
  226. package/dist/sheet/packs/math-stats.d.ts +2 -0
  227. package/dist/sheet/packs/math-stats.js +372 -0
  228. package/dist/sheet/packs/special.d.ts +44 -0
  229. package/dist/sheet/packs/special.js +187 -0
  230. package/dist/sheet/packs/stats-dist.d.ts +2 -0
  231. package/dist/sheet/packs/stats-dist.js +785 -0
  232. package/dist/sheet/packs/text-date.d.ts +2 -0
  233. package/dist/sheet/packs/text-date.js +332 -0
  234. package/dist/sheet/packs/trig.d.ts +2 -0
  235. package/dist/sheet/packs/trig.js +73 -0
  236. package/dist/sheet/page-setup.d.ts +73 -0
  237. package/dist/sheet/page-setup.js +73 -0
  238. package/dist/sheet/parse.js +42 -10
  239. package/dist/sheet/paste-special.d.ts +22 -0
  240. package/dist/sheet/paste-special.js +14 -5
  241. package/dist/sheet/pivot-range.d.ts +160 -0
  242. package/dist/sheet/pivot-range.js +333 -0
  243. package/dist/sheet/presence.d.ts +73 -0
  244. package/dist/sheet/presence.js +79 -0
  245. package/dist/sheet/print.d.ts +104 -0
  246. package/dist/sheet/print.js +169 -0
  247. package/dist/sheet/protection.d.ts +55 -1
  248. package/dist/sheet/protection.js +55 -2
  249. package/dist/sheet/rects.d.ts +1 -1
  250. package/dist/sheet/refs.d.ts +48 -0
  251. package/dist/sheet/refs.js +155 -8
  252. package/dist/sheet/ribbon-icons.d.ts +1 -1
  253. package/dist/sheet/ribbon-icons.js +186 -0
  254. package/dist/sheet/ribbon.d.ts +1 -1
  255. package/dist/sheet/ribbon.js +324 -23
  256. package/dist/sheet/sheet-kinds.d.ts +74 -0
  257. package/dist/sheet/sheet-kinds.js +91 -0
  258. package/dist/sheet/shortcuts.d.ts +13 -3
  259. package/dist/sheet/shortcuts.js +63 -12
  260. package/dist/sheet/sort.d.ts +51 -0
  261. package/dist/sheet/sort.js +107 -0
  262. package/dist/sheet/sparklines.d.ts +111 -0
  263. package/dist/sheet/sparklines.js +204 -0
  264. package/dist/sheet/table-styles.d.ts +74 -0
  265. package/dist/sheet/table-styles.js +152 -0
  266. package/dist/sheet/tables.d.ts +19 -0
  267. package/dist/sheet/tables.js +31 -0
  268. package/dist/sheet/tokenize.d.ts +18 -1
  269. package/dist/sheet/tokenize.js +60 -9
  270. package/dist/sheet/validation.d.ts +16 -0
  271. package/dist/sheet/validation.js +37 -0
  272. package/dist/sheet/workbook.d.ts +148 -3
  273. package/dist/sheet/workbook.js +742 -31
  274. package/dist/sheet/xls-cfb.d.ts +32 -0
  275. package/dist/sheet/xls-cfb.js +290 -0
  276. package/dist/sheet/xls-document.d.ts +10 -0
  277. package/dist/sheet/xls-document.js +1243 -0
  278. package/dist/sheet/xls-formula.d.ts +40 -0
  279. package/dist/sheet/xls-formula.js +569 -0
  280. package/dist/sheet/xlsx-document.d.ts +108 -0
  281. package/dist/sheet/xlsx-document.js +1849 -0
  282. package/dist/sheet/xlsx-drawing.d.ts +99 -0
  283. package/dist/sheet/xlsx-drawing.js +420 -0
  284. package/dist/sheet-enable.js +6 -7
  285. package/dist/sheet-text.d.ts +7 -0
  286. package/dist/sheet-text.js +29 -0
  287. package/dist/sources/auth-supabase.js +2 -2
  288. package/dist/sources/realtime-supabase.js +2 -2
  289. package/dist/sources/rest.d.ts +6 -2
  290. package/dist/sources/rest.js +42 -7
  291. package/dist/sources/supabase.d.ts +10 -1
  292. package/dist/sources/supabase.js +73 -40
  293. package/dist/studio/emit-project.js +14 -1
  294. package/dist/studio/index.js +1 -1
  295. package/dist/studio/project.d.ts +11 -2
  296. package/dist/studio/project.js +5 -2
  297. package/dist/studio/ui-components.generated.js +107 -2
  298. package/dist/sveltekit/in-memory.d.ts +2 -2
  299. package/dist/sveltekit/in-memory.js +125 -4
  300. package/dist/sveltekit/index.d.ts +1 -1
  301. package/dist/sveltekit/index.js +1 -1
  302. package/dist/sveltekit/query-plan.d.ts +50 -4
  303. package/dist/sveltekit/query-plan.js +25 -3
  304. package/dist/sveltekit/sql-source.d.ts +6 -0
  305. package/dist/sveltekit/sql-source.js +34 -6
  306. package/dist/sveltekit/sql.d.ts +31 -0
  307. package/dist/sveltekit/sql.js +135 -25
  308. package/dist/sveltekit/transport.d.ts +10 -2
  309. package/dist/sveltekit/transport.js +30 -6
  310. package/dist/upgrade-prompt.d.ts +1 -1
  311. package/dist/version.d.ts +1 -1
  312. package/dist/version.js +1 -1
  313. package/dist/watermark.js +35 -2
  314. package/dist/wc/GridMenus-By9vPuq0.js +1088 -0
  315. package/dist/wc/SvChartMenu-CQNrQGT2.js +308 -0
  316. package/dist/wc/SvDateRangeInput-DR6m7bSM.js +199 -0
  317. package/dist/wc/SvDateTimePicker-D-vRnaMo.js +771 -0
  318. package/dist/wc/SvField-B_kurx_P.js +149 -0
  319. package/dist/wc/SvGrid.helpers-BdVDtjUm.js +135 -0
  320. package/dist/wc/SvGridCellEditor-Bnf1Kr5C.js +560 -0
  321. package/dist/wc/SvGridChart-BqUJh2pG.js +3572 -0
  322. package/dist/wc/SvGridChartBuilder-CGycC5cn.js +988 -0
  323. package/dist/wc/SvGridChartPanel-CRnizsHD.js +1746 -0
  324. package/dist/wc/SvGridChartView-D1pa_xMy.js +47 -0
  325. package/dist/wc/SvGridDropdown-45WsObLL.js +259 -0
  326. package/dist/wc/SvModal-DrfOYYyX.js +189 -0
  327. package/dist/wc/cell-formatting-CBfgahv1.js +86 -0
  328. package/dist/wc/chart-6OXlybVT.js +4341 -0
  329. package/dist/wc/chart-export-CeSADGfi.js +135 -0
  330. package/dist/wc/chart-export-pdf-BGko7MER.js +104 -0
  331. package/dist/wc/chart-summary-2m3ia1-n.js +137 -0
  332. package/dist/wc/chart-trend-CQOQtTMl.js +50 -0
  333. package/dist/wc/chart-validate-CD6ptiwg.js +180 -0
  334. package/dist/wc/client-DQIzjDBG.js +3064 -0
  335. package/dist/wc/column-resize-DUPgynvc.js +101 -0
  336. package/dist/wc/date-format-DS-z_h9v.js +1130 -0
  337. package/dist/wc/dismissable-CQ6XFXsk.js +45 -0
  338. package/dist/wc/editor-contract-peBDxir_.js +22 -0
  339. package/dist/wc/editor-registry-DxGKqcvx.js +24 -0
  340. package/dist/wc/focus-trap-Dbb2tJxb.js +65 -0
  341. package/dist/wc/list-option-DrRyivWp.js +82 -0
  342. package/dist/wc/popover-WsGlvtQv.js +69 -0
  343. package/dist/wc/positioning-BiKLfu1E.js +112 -0
  344. package/dist/wc/react.d.ts +41 -0
  345. package/dist/wc/react.js +90 -0
  346. package/dist/wc/rolldown-runtime-Dy4uBu1J.js +11 -0
  347. package/dist/wc/row-drag-touch-CycRR65n.js +93 -0
  348. package/dist/wc/row-resize-limG_N1z.js +111 -0
  349. package/dist/wc/sv-sheet-element.d.ts +97 -0
  350. package/dist/wc/sv-sheet-element.js +44213 -0
  351. package/dist/wc/svelte-virtualizer.svelte-CXtQy2TQ.js +530 -0
  352. package/dist/wc/validate-BqDthkNr.js +88 -0
  353. package/dist/wc/vue.d.ts +31 -0
  354. package/dist/wc/vue.js +75 -0
  355. package/package.json +30 -5
  356. package/dist/designer/assets/GridMenus-BlsvL_aU.js +0 -8
  357. package/dist/designer/assets/SvGridCellEditor-C7uQXYds.js +0 -4
  358. package/dist/designer/assets/SvGridChartBuilder-kvyIU_Rl.js +0 -1
  359. package/dist/designer/assets/SvGridDropdown-Bb3HH2Aj.js +0 -1
  360. package/dist/designer/assets/cell-formatting-wr5wm7US.js +0 -1
  361. package/dist/designer/assets/index-CMFgAoVV.css +0 -1
  362. package/dist/designer/assets/row-resize-DLktcqUK.js +0 -1
  363. package/dist/designer/assets/src-EdI3Xqds.js +0 -58
  364. package/dist/designer/assets/validate-h-aslRV9.js +0 -1
@@ -8511,6 +8511,7 @@ var GENERATED_UI_SURFACE = {
8511
8511
  "key": "data",
8512
8512
  "label": "Data",
8513
8513
  "type": "json",
8514
+ "description": "The rows to render. Optional only because `rowModel` can supply them instead; a grid with neither renders empty. When both are present `data` wins.",
8514
8515
  "group": "common"
8515
8516
  },
8516
8517
  {
@@ -8533,6 +8534,13 @@ var GENERATED_UI_SURFACE = {
8533
8534
  "description": "Scheduler / calendar mode. When set, the grid renders its rows as events on a Month / Week / Day / Agenda calendar instead of a table. See .",
8534
8535
  "group": "common"
8535
8536
  },
8537
+ {
8538
+ "key": "gantt",
8539
+ "label": "Gantt",
8540
+ "type": "json",
8541
+ "description": "Gantt mode. When set, the grid renders its rows as a task table beside a time chart: one bar per row by start / end, a work-breakdown tree from `parentField`, and dependency arrows. See . A view of the grid like the board and scheduler; the renderer ships in `@svgrid/enterprise` (call `enableGanttView()`).",
8542
+ "group": "common"
8543
+ },
8536
8544
  {
8537
8545
  "key": "chart",
8538
8546
  "label": "Chart",
@@ -8964,6 +8972,14 @@ var GENERATED_UI_SURFACE = {
8964
8972
  "code": true,
8965
8973
  "group": "advanced"
8966
8974
  },
8975
+ {
8976
+ "key": "includeCollapsedRows",
8977
+ "label": "Include Collapsed Rows",
8978
+ "type": "json",
8979
+ "description": "Whether a collapsed row still takes part in a copy or a fill that spans it. Left out, both skip every collapsed row, which is what \"filter, copy, paste\" needs and what a fill dragged over a filtered list expects: the series runs over the rows that show. A spreadsheet answers per row: a row hidden by hand is copied and filled, as Excel does, while a row a filter folded away is not.",
8980
+ "code": true,
8981
+ "group": "advanced"
8982
+ },
8967
8983
  {
8968
8984
  "key": "clipboardHtml",
8969
8985
  "label": "Clipboard Html",
@@ -9169,6 +9185,34 @@ var GENERATED_UI_SURFACE = {
9169
9185
  "description": "Which rows feed the min/max range that `colorScale` / `dataBar` formats scale against. - `filtered` (default): every row that survives the filters, ignoring the page slice. The scale follows what you filtered to but does not shift when you page, so the same value keeps the same colour on page 1 and page 2. - `visible`: only the rows currently on screen. Rescales per page - use it when you want each page's heat map normalized to that page. - `all`: the full unfiltered dataset, for a scale that stays put as you filter.",
9170
9186
  "group": "common"
9171
9187
  },
9188
+ {
9189
+ "key": "rowPlaceholder",
9190
+ "label": "Row Placeholder",
9191
+ "type": "json",
9192
+ "description": "Marks a row as one whose data has not arrived: `\"loading\"` draws a shimmer in every cell, `\"failed\"` draws a full-width \"could not load\" row with a Retry button, and `null` (the default for every row) renders normally. Placeholder rows are inert - not selectable, not editable, and skipped by cell navigation - because there is nothing there to act on yet. `createServerDataSource` in `infinite` mode fills the gaps with rows this recognises, so the usual wiring is `rowPlaceholder={rowPlaceholderState}` (or nothing at all, via `rowModel`).",
9193
+ "code": true,
9194
+ "group": "advanced"
9195
+ },
9196
+ {
9197
+ "key": "rowModel",
9198
+ "label": "Row Model",
9199
+ "type": "json",
9200
+ "description": "Drive the grid from a row model instead of wiring a dozen props. `createServerDataSource` returns one, and so does the Enterprise server-side row model, so server-backed grids become: ```svelte <SvGrid rowModel={ctl} {columns} /> ``` The model supplies `data`, `loading`, `getRowId`, the external sort and filter wiring, the visible range, placeholder rows, group accessors, selection and paging - each one only if it implements that part. A prop written explicitly on the grid always wins, so you can adopt it and still override one piece.",
9201
+ "group": "common"
9202
+ },
9203
+ {
9204
+ "key": "pivotResultColumns",
9205
+ "label": "Pivot Result Columns",
9206
+ "type": "json",
9207
+ "description": "Columns that REPLACE `columns` while set. The server-side row model supplies them in pivot mode - one column per pivoted value, grouped under a header per pivot key - and clears them when pivot mode ends, so `columns` stays the app's own list. Rarely set by hand.",
9208
+ "group": "common"
9209
+ },
9210
+ {
9211
+ "key": "rowSelectionModel",
9212
+ "label": "Row Selection Model",
9213
+ "type": "json",
9214
+ "group": "common"
9215
+ },
9172
9216
  {
9173
9217
  "key": "isDetailRow",
9174
9218
  "label": "Is Detail Row",
@@ -9177,11 +9221,41 @@ var GENERATED_UI_SURFACE = {
9177
9221
  "code": true,
9178
9222
  "group": "advanced"
9179
9223
  },
9224
+ {
9225
+ "key": "detailRowHeight",
9226
+ "label": "Detail Row Height",
9227
+ "type": "number",
9228
+ "description": "The height of a detail row, in px, or a function of its data. With it the virtualizer can size detail rows, so master-detail works with `virtualization` on (the panel scrolls inside its cell when taller). Without it a detail row is auto height, which needs `virtualization={false}`.",
9229
+ "group": "common"
9230
+ },
9231
+ {
9232
+ "key": "showDetailToggle",
9233
+ "label": "Show Detail Toggle",
9234
+ "type": "boolean",
9235
+ "description": "A row-header column of chevrons that open and close detail rows. It sits with the row-number and selection columns: sticky at the left, no column menu, not resizable, not reorderable, outside the active cell and the selection. The chevron calls `onDetailToggle` (or, on a server row model, the model's own toggle) and reads `isDetailOpen` for its direction; `hasDetail` hides it on rows that have nothing to open. Detail rows themselves get an empty cell.",
9236
+ "group": "common"
9237
+ },
9238
+ {
9239
+ "key": "isDetailOpen",
9240
+ "label": "Is Detail Open",
9241
+ "type": "json",
9242
+ "description": "Whether the detail under a row is open: the chevron's direction and `aria-expanded`.",
9243
+ "code": true,
9244
+ "group": "advanced"
9245
+ },
9246
+ {
9247
+ "key": "hasDetail",
9248
+ "label": "Has Detail",
9249
+ "type": "json",
9250
+ "description": "Whether a row has a detail to open; the chevron is left out where this returns false.",
9251
+ "code": true,
9252
+ "group": "advanced"
9253
+ },
9180
9254
  {
9181
9255
  "key": "serverGroup",
9182
9256
  "label": "Server Group",
9183
9257
  "type": "json",
9184
- "description": "Server-side group / tree keyboard + accessibility, built into the grid. When set, the grid uses the treegrid role and marks matching rows with `aria-level` / `aria-expanded`, and ArrowRight / ArrowLeft expand / collapse the focused group row (no app-level key handling). Pair with `serverGroupRows` + `SvGroupCell` for the visual expander. Every accessor receives the row data.",
9258
+ "description": "Server-side group / tree keyboard + accessibility, built into the grid. When set, the grid uses the treegrid role and marks matching rows with `aria-level` / `aria-expanded`, and ArrowRight / ArrowLeft expand / collapse the focused group row (no app-level key handling). Pair with `serverGroupRows` + `SvGroupCell` from `@svgrid/enterprise` for the visual expander, or drive it from your own tree state. Every accessor receives the row data.",
9185
9259
  "group": "common"
9186
9260
  },
9187
9261
  {
@@ -9206,6 +9280,13 @@ var GENERATED_UI_SURFACE = {
9206
9280
  "description": "Freeze the first N rows: they stay under the header while the body scrolls, and unlike `pinnedTopRows` they are the grid's own rows, still editable, selectable and numbered as rows 1..N. Excel's Freeze Panes, for the row half; the column half is `columnPinning`. Under `virtualization` the frozen rows are always rendered and the window skips them.",
9207
9281
  "group": "common"
9208
9282
  },
9283
+ {
9284
+ "key": "stickyGroupRows",
9285
+ "label": "Sticky Group Rows",
9286
+ "type": "boolean",
9287
+ "description": "Keep the group a row belongs to in view: while the rows of an open group scroll past, the group's row (and its parents' rows) stay under the header, the way a section heading stays put in a long list, so a screen deep inside a 60,000-row group still says which group it is. Works for server-side groups (`rowModel` / `serverGroup`), client grouping and tree data. Under `virtualization` the band shows a copy of each ancestor row; without it the rows themselves stick. Off by default.",
9288
+ "group": "common"
9289
+ },
9209
9290
  {
9210
9291
  "key": "mergedCells",
9211
9292
  "label": "Merged Cells",
@@ -9323,7 +9404,7 @@ var GENERATED_UI_SURFACE = {
9323
9404
  "key": "cellSelectionChange",
9324
9405
  "label": "Cell Selection Change",
9325
9406
  "prop": "onCellSelectionChange",
9326
- "description": "Fires whenever the cell-selection rectangle changes (mouse, keyboard, or `api.selectCells()`). `ranges` matches `api.getSelected()` - `[rowStart, colStart, rowEnd, colEnd]` rectangles in grid coords. Empty array when the user clears the selection."
9407
+ "description": "Fires whenever the cell selection changes (mouse, keyboard, or `api.selectCells()`). `ranges` is every selected rectangle, matching `api.getSelected()`: the ones a Ctrl+click committed and the active one last, each `[rowStart, colStart, rowEnd, colEnd]` in grid coords. Empty array when the user clears the selection."
9327
9408
  },
9328
9409
  {
9329
9410
  "key": "sortingChange",
@@ -9391,6 +9472,24 @@ var GENERATED_UI_SURFACE = {
9391
9472
  "prop": "onScrollBottomReached",
9392
9473
  "description": "Fires once each time the body is scrolled to (within ~32px of) the bottom. Re-arms after the user scrolls back up. The canonical hook for infinite / lazy loading - append more rows to `data` when it fires."
9393
9474
  },
9475
+ {
9476
+ "key": "visibleRangeChange",
9477
+ "label": "Visible Range Change",
9478
+ "prop": "onVisibleRangeChange",
9479
+ "description": "Fires when the range of rows on screen changes, with the first and last row INDEX (not pixels). Coalesced to one call per frame, so it is cheap to wire to something that fetches. This is the hook a block-loading data source needs and `onScrollBottomReached` cannot give it: \"the user is looking at rows 4,000-4,020\" answers which block to fetch and which to keep, while \"they hit the bottom\" only ever means \"append more\". Both are free; use this one with `createServerDataSource({ mode: 'infinite' })`, or let `rowModel` wire it for you. Reports `0, data.length - 1` when virtualization is off, since every row really is rendered."
9480
+ },
9481
+ {
9482
+ "key": "retryRow",
9483
+ "label": "Retry Row",
9484
+ "prop": "onRetryRow",
9485
+ "description": "Called by the Retry button on a `\"failed\"` placeholder row."
9486
+ },
9487
+ {
9488
+ "key": "detailToggle",
9489
+ "label": "Detail Toggle",
9490
+ "prop": "onDetailToggle",
9491
+ "description": "Open or close the detail under a row. The chevron of `showDetailToggle` and Ctrl+Enter on a row call it; you keep the open set and insert or remove the detail row in `data`. A server row model supplies its own (the `rowModel` prop wires `toggleDetail`), so this is the client side."
9492
+ },
9394
9493
  {
9395
9494
  "key": "columnOrderChange",
9396
9495
  "label": "Column Order Change",
@@ -9402,6 +9501,12 @@ var GENERATED_UI_SURFACE = {
9402
9501
  "label": "Row Drag End",
9403
9502
  "prop": "onRowDragEnd",
9404
9503
  "description": "Fires on the TARGET grid after a managed row drag settles, with the moved row, its landing index, whether it stayed in the same grid, and the source / target grid ids. Use it to mirror the move into your own state (persistence, server sync). The grid has already applied the change to its internal data by the time this fires."
9504
+ },
9505
+ {
9506
+ "key": "rowDrop",
9507
+ "label": "Row Drop",
9508
+ "prop": "onRowDrop",
9509
+ "description": "Take the drop yourself. With this set the grid keeps the drag affordance and the drop indicator but does not touch its data: the handler gets the dragged row, the row it landed on (null for the empty space below the rows) and the side - `before` / `after`, or `into` when it landed on the middle of a group or tree row, which makes it that row's child. The path for a `rowModel`, whose rows the grid does not own: hand the move to the model (`moveRow`) or to your server. Only fires within one grid; a drop from another grid stays managed."
9405
9510
  }
9406
9511
  ]
9407
9512
  }
@@ -12148,6 +12253,10 @@ var blockPalette = [
12148
12253
  kind: "detail",
12149
12254
  label: "Detail page"
12150
12255
  },
12256
+ {
12257
+ kind: "sheet",
12258
+ label: "Spreadsheet"
12259
+ },
12151
12260
  {
12152
12261
  kind: "filter",
12153
12262
  label: "Filter panel"
@@ -12339,6 +12448,10 @@ function defaultBlockConfig(kind, entity) {
12339
12448
  ...metrics.length ? { metricFields: metrics } : {}
12340
12449
  };
12341
12450
  }
12451
+ case "sheet": return {
12452
+ kind,
12453
+ totals: entity.fields.some((f) => f.type === "number" && !f.primaryKey)
12454
+ };
12342
12455
  case "component": return {
12343
12456
  kind,
12344
12457
  component: "",
@@ -12370,6 +12483,7 @@ var DEFAULT_SPAN = {
12370
12483
  board: 3,
12371
12484
  calendar: 3,
12372
12485
  detail: 3,
12486
+ sheet: 3,
12373
12487
  component: 1
12374
12488
  };
12375
12489
  function makeBlock(kind, entity, taken) {
@@ -13289,6 +13403,7 @@ function dockPaneTitle(block) {
13289
13403
  accordion: "Accordion",
13290
13404
  kpi: "KPI",
13291
13405
  gauge: "Gauge",
13406
+ sheet: "Spreadsheet",
13292
13407
  component: "Component"
13293
13408
  }[c.kind] || "Panel";
13294
13409
  }
@@ -15913,7 +16028,7 @@ function hasFieldConditions(schema) {
15913
16028
  *
15914
16029
  * `version.test.ts` asserts this matches `package.json`, so the two cannot drift.
15915
16030
  */
15916
- var SVGRID_VERSION = "3.0.2";
16031
+ var SVGRID_VERSION = "3.0.3";
15917
16032
  //#endregion
15918
16033
  //#region src/studio/emit-project.ts
15919
16034
  var has = (blocks, kind) => blocks.some((b) => b.config.kind === kind);
@@ -16251,6 +16366,17 @@ ${panels}
16251
16366
  const onOpen = openRoute ? ` onOpen={(id) => goto('/${openRoute}?id=' + encodeURIComponent(id))}` : "";
16252
16367
  return ` <div ${wrapperStyle(block)}${cls}>
16253
16368
  <SvBoard schema={${schemaVar}} rows={allRows} loading={!allRowsReady} groupBy=${JSON.stringify(cfg.groupBy)} titleField=${JSON.stringify(asText(cfg.titleField))}${badge}${sub}${onOpen} height={${h}} onMove={(id, value) => { allRows = allRows.map((r) => String((r as Record<string, unknown>)[idField]) === String(id) ? ({ ...r, ['${cfg.groupBy}']: value }) : r) }} />
16369
+ </div>`;
16370
+ }
16371
+ case "sheet": {
16372
+ const h = block.height ?? 480;
16373
+ const specs = (cfg.fields?.length ? cfg.fields : entity.fields.map((f) => f.field)).map((field) => ({
16374
+ field,
16375
+ label: entity.fields.find((f) => f.field === field)?.label ?? field
16376
+ }));
16377
+ const sheetName = (entity.label ?? entity.name).replace(/[[\]:*?/\\]/g, " ").trim().slice(0, 31) || "Sheet1";
16378
+ return ` <div ${wrapperStyle(block, `min-height: ${h}px`)}${cls}>
16379
+ {#if allRowsReady}<SvSheet data={[{ name: ${JSON.stringify(sheetName)}, cells: sheetCellsFromRows(${rowsExpr}, ${JSON.stringify(specs)}, { totals: ${cfg.totals ? "true" : "false"} }) }]} height={${h}} />{/if}
16254
16380
  </div>`;
16255
16381
  }
16256
16382
  case "calendar": {
@@ -17586,7 +17712,7 @@ function screenPage(schema, rawSchema, screen, resolve, rawResolve, accessEnable
17586
17712
  const apiVarFor = (b) => codeGrid && b.id === codeGridBlockId ? "gridApi" : b.config.kind === "grid" && gridHasExport(b.config) ? `gridApi_${b.id.replace(/-/g, "_")}` : void 0;
17587
17713
  const exportApiVars = blocks.filter((b) => b.config.kind === "grid" && gridHasExport(b.config) && !(codeGrid && b.id === codeGridBlockId)).map((b) => `gridApi_${b.id.replace(/-/g, "_")}`);
17588
17714
  const needsGridApiType = codeGrid || exportApiVars.length > 0;
17589
- const needsAllRows = hasAgg || hasMD || hasPivot || hasBoundComponent || hasGroupedGrid || hasTreeGrid || hasSchedulerGrid || has(allBlocks, "board") || has(allBlocks, "calendar") || has(allBlocks, "detail");
17715
+ const needsAllRows = hasAgg || hasMD || hasPivot || hasBoundComponent || hasGroupedGrid || hasTreeGrid || hasSchedulerGrid || has(allBlocks, "board") || has(allBlocks, "calendar") || has(allBlocks, "detail") || has(allBlocks, "sheet");
17590
17716
  const gridSpecs = [];
17591
17717
  if (needsController) gridSpecs.push("SvGrid", "createServerDataSource", ...hasRowActions || hasCellRenderers || hasTreeGrid ? ["renderSnippet", "type CellContext"] : [], "type ServerState");
17592
17718
  if (usesScheduler) gridSpecs.push("SvGrid");
@@ -17612,6 +17738,7 @@ function screenPage(schema, rawSchema, screen, resolve, rawResolve, accessEnable
17612
17738
  if (has(allBlocks, "board")) entImports.push("SvBoard");
17613
17739
  if (has(allBlocks, "calendar")) entImports.push("schemaToColumns");
17614
17740
  if (has(allBlocks, "detail")) entImports.push("SvRecordDetail");
17741
+ if (has(allBlocks, "sheet")) entImports.push("SvSheet", "sheetCellsFromRows");
17615
17742
  if (has(allBlocks, "kpi") || has(allBlocks, "gauge") || hasAggregateBinding) entImports.push("reduceValue");
17616
17743
  const kpiCfgs = allBlocks.filter((b) => b.config.kind === "kpi").map((b) => b.config);
17617
17744
  if (kpiCfgs.some((c) => c.format && c.format !== "auto")) entImports.push("formatKpiValue");
@@ -41637,21 +41764,26 @@ function parseLicenseExpiry(key) {
41637
41764
  function checkLicenseKey(key, now = /* @__PURE__ */ new Date()) {
41638
41765
  if (key == null || key === "") return {
41639
41766
  status: "unset",
41640
- valid: false
41767
+ valid: false,
41768
+ edition: "suite"
41641
41769
  };
41642
41770
  if (!key.startsWith("SVENTERPRISE-")) return {
41643
41771
  status: "invalid",
41644
- valid: false
41772
+ valid: false,
41773
+ edition: "suite"
41645
41774
  };
41646
41775
  if (REVOKED_KEYS.has(key)) return {
41647
41776
  status: "revoked",
41648
- valid: false
41777
+ valid: false,
41778
+ edition: "suite"
41649
41779
  };
41650
41780
  const expiresAt = parseLicenseExpiry(key) ?? void 0;
41651
41781
  const expired = expiresAt ? now.getTime() > expiresAt.getTime() : void 0;
41782
+ const status = key.startsWith("SVENTERPRISE-DEV") ? "dev" : key.startsWith("SVENTERPRISE-EVAL") ? "eval" : "licensed";
41652
41783
  return {
41653
- status: key.startsWith("SVENTERPRISE-DEV") ? "dev" : key.startsWith("SVENTERPRISE-EVAL") ? "eval" : "licensed",
41784
+ status,
41654
41785
  valid: true,
41786
+ edition: status === "licensed" && key.startsWith(`SVENTERPRISE-GRID-`) ? "grid" : "suite",
41655
41787
  expiresAt,
41656
41788
  expired
41657
41789
  };
@@ -6,8 +6,8 @@
6
6
  * prop + config types for free and looks the engine up through the
7
7
  * `registerPivotEngine` seam.
8
8
  *
9
- * Soft-gated like the rest of Enterprise: it works without a license key but the
10
- * grid shows the unlicensed watermark + a one-time console nudge.
9
+ * Like the rest of Enterprise it runs without a license key during the
10
+ * evaluation; the grid shows the watermark and a one-time console notice.
11
11
  *
12
12
  * ```ts
13
13
  * import { setLicenseKey, enablePivot } from '@svgrid/enterprise'
@@ -63,6 +63,12 @@ export declare function hasCycle(deps: ReadonlyArray<SchedulerDependency>): bool
63
63
  * FS / SS / FF / SF semantics plus `lag` (minutes).
64
64
  */
65
65
  export declare function requiredStart(predTimes: EventTimes, dep: SchedulerDependency, successorDurationMs: number): Date;
66
+ /** A hard limit on where one event may be scheduled, from a planning
67
+ * constraint (`SNET`, `FNLT` and the rest). Both ends are optional. */
68
+ export type CascadeBound = {
69
+ minStart?: Date;
70
+ maxEnd?: Date;
71
+ };
66
72
  /** Options for {@link cascade}. */
67
73
  export type CascadeOptions = {
68
74
  /**
@@ -71,6 +77,35 @@ export type CascadeOptions = {
71
77
  * shifts / business hours; omit for calendar-time scheduling).
72
78
  */
73
79
  snapForward?: (start: Date) => Date;
80
+ /**
81
+ * Only what lies downstream of these keys may move: their successors,
82
+ * transitively, and never the keys themselves. A move passes the moved
83
+ * task (a phase move its whole subtree), so a task dropped too early for
84
+ * its predecessor stays where it was dropped with the link drawn as
85
+ * violated instead of springing forward, and a violation elsewhere in the
86
+ * plan is left alone until its own task moves. Omitted, every task in the
87
+ * graph is eligible.
88
+ */
89
+ from?: Iterable<string>;
90
+ /**
91
+ * Per-key limits the cascade may not push past. A `minStart` raises the floor
92
+ * (the event cannot begin before it); a `maxEnd` caps the ceiling, and a
93
+ * cascade that would need to go further stops AT the cap rather than moving
94
+ * past it. The link is then left unsatisfied, which {@link violations}
95
+ * reports - the honest outcome, because a constraint and a link that
96
+ * disagree have no schedule that satisfies both.
97
+ */
98
+ bounds?: ReadonlyMap<string, CascadeBound>;
99
+ /**
100
+ * The span a pushed event keeps. By default it keeps its calendar length:
101
+ * `end = start + (end - start)`. A day-granular planner passes working-time
102
+ * arithmetic here so a five-working-day task pushed over a weekend stays
103
+ * five working days long instead of shrinking to three. `endFor` gives the
104
+ * new end for a new start; `startFor` the new start for a capped end (the
105
+ * ceiling case). Both receive the event's times before the push.
106
+ */
107
+ endFor?: (start: Date, original: EventTimes) => Date;
108
+ startFor?: (end: Date, original: EventTimes) => Date;
74
109
  };
75
110
  /**
76
111
  * Forward-cascade successors so every dependency is satisfied. `times` maps row
@@ -120,8 +120,26 @@ export function cascade(times, deps, opts = {}) {
120
120
  const cur = new Map();
121
121
  for (const [k, v] of times)
122
122
  cur.set(k, { start: v.start, end: v.end });
123
+ // With roots, the eligible set is their downstream closure minus the roots.
124
+ let eligible = null;
125
+ if (opts.from) {
126
+ const roots = new Set(opts.from);
127
+ eligible = new Set();
128
+ const stack = [...roots];
129
+ while (stack.length) {
130
+ const k = stack.pop();
131
+ for (const dep of graph.succ.get(k) ?? []) {
132
+ if (cyclicIds.has(dep.id) || roots.has(dep.to) || eligible.has(dep.to))
133
+ continue;
134
+ eligible.add(dep.to);
135
+ stack.push(dep.to);
136
+ }
137
+ }
138
+ }
123
139
  const changed = new Map();
124
140
  for (const key of order) {
141
+ if (eligible && !eligible.has(key))
142
+ continue;
125
143
  const links = graph.pred.get(key);
126
144
  if (!links || !links.length)
127
145
  continue;
@@ -140,12 +158,29 @@ export function cascade(times, deps, opts = {}) {
140
158
  if (req > minStartMs)
141
159
  minStartMs = req;
142
160
  }
161
+ // A floor constraint applies whether or not a link moved the event.
162
+ const bound = opts.bounds?.get(key);
163
+ if (bound?.minStart && bound.minStart.getTime() > minStartMs) {
164
+ minStartMs = bound.minStart.getTime();
165
+ }
143
166
  if (minStartMs <= self.start.getTime())
144
167
  continue; // already legal - never pull earlier
145
168
  let newStart = new Date(minStartMs);
146
169
  if (opts.snapForward)
147
170
  newStart = opts.snapForward(newStart);
148
- const newEnd = new Date(newStart.getTime() + durationMs);
171
+ // A ceiling stops the cascade at the cap instead of pushing past it. The
172
+ // link stays unsatisfied and `violations` says so, rather than the
173
+ // constraint being silently overrun.
174
+ if (bound?.maxEnd) {
175
+ const latestStart = opts.startFor
176
+ ? opts.startFor(bound.maxEnd, self).getTime()
177
+ : bound.maxEnd.getTime() - durationMs;
178
+ if (newStart.getTime() > latestStart)
179
+ newStart = new Date(latestStart);
180
+ }
181
+ if (newStart.getTime() <= self.start.getTime())
182
+ continue;
183
+ const newEnd = opts.endFor ? opts.endFor(newStart, self) : new Date(newStart.getTime() + durationMs);
149
184
  const next = { start: newStart, end: newEnd };
150
185
  cur.set(key, next);
151
186
  changed.set(key, next);
package/dist/scheduler.js CHANGED
@@ -5,8 +5,8 @@
5
5
  * its config types for free; the *renderer* (SvGridScheduler) is Pro and plugs
6
6
  * in through the grid's `registerSchedulerView` seam.
7
7
  *
8
- * Soft-gated like the rest of Enterprise: it works without a license key but the
9
- * grid shows the "unlicensed" watermark + a one-time console nudge.
8
+ * Like the rest of Enterprise it runs without a license key during the
9
+ * evaluation; the grid shows the watermark and a one-time console notice.
10
10
  *
11
11
  * ```ts
12
12
  * import { setLicenseKey, enableSchedulerView } from '@svgrid/enterprise'
@@ -9,8 +9,8 @@
9
9
  * `registerSelectionBarView` seam. Without it the grid shows a short upsell
10
10
  * note where the bar would be.
11
11
  *
12
- * Soft-gated like the rest of Enterprise: it works without a license key but
13
- * the grid shows the "unlicensed" watermark + a one-time console nudge.
12
+ * Like the rest of Enterprise it runs without a license key during the
13
+ * evaluation; the grid shows the watermark and a one-time console notice.
14
14
  *
15
15
  * ```ts
16
16
  * import { setLicenseKey, enableSelectionBar } from '@svgrid/enterprise'
@@ -0,0 +1,213 @@
1
+ <!--
2
+ Built-in group cell for the server-side group/tree model. Drop it into the
3
+ grouping column and it draws the expander + indentation for group rows (and an
4
+ indented leaf value) - no hand-written cell recipe. Pair with `serverGroupRows`
5
+ to feed `<SvGrid data>`, and wire `onToggle` to the controller's `toggleGroup`.
6
+
7
+ cell: (ctx) => renderComponent(SvGroupCell, {
8
+ row: ctx.row.original, onToggle: ctl.toggleGroup, leafField: 'name',
9
+ })
10
+ -->
11
+ <script lang="ts" generics="TData">
12
+ import type { GridIcons, ServerDisplayRow, ServerPlaceholderRow } from '@svgrid/grid'
13
+ import { fillMessage, resolveServerGroupMessages, type ServerGroupMessages } from './messages'
14
+
15
+ // Rows from either model: the display-row union, plus the block-cached
16
+ // model's shared placeholder (which the grid renders itself, so it never
17
+ // reaches this cell - but the type has to admit it).
18
+ type GroupGridRow = { __group?: ServerDisplayRow<TData> | ServerPlaceholderRow } & Record<string, unknown>
19
+ type Props = {
20
+ /** The grid row from `serverGroupRows` (carries the `__group` marker). */
21
+ row: GroupGridRow
22
+ /**
23
+ * Expand / collapse a group, or load more children. Receives the grid row;
24
+ * wire to `serverGroupNav(ctl).onToggle` (which drives clicks and keyboard).
25
+ */
26
+ onToggle: (row: GroupGridRow) => void
27
+ /**
28
+ * Field to show for leaf rows in the group column (blank if omitted).
29
+ * Under `treeData` every row is a node of the same shape, so it names
30
+ * the label of expandable nodes too; a group row's key is otherwise
31
+ * the text.
32
+ */
33
+ leafField?: string
34
+ /** Pixels of indentation per level. Default 18. */
35
+ indent?: number
36
+ /**
37
+ * Icon overrides, the same map `<SvGrid icons>` takes. Only
38
+ * `chevron-right` is drawn here. You mount this component yourself, so it
39
+ * cannot inherit the grid's icons - pass the same object to both to keep
40
+ * the expander consistent with the rest of the chrome.
41
+ */
42
+ icons?: GridIcons
43
+ /**
44
+ * Strings, for localization: the "load more" row, the footer and grand
45
+ * total labels. Partial; missing keys keep the English default. Pass the
46
+ * same map to `SvRowGroupPanel` and `serverGroupText`.
47
+ */
48
+ messages?: Partial<ServerGroupMessages>
49
+ /** Locale for the child count and the "load more" number. Default: the browser's. */
50
+ locale?: string | ReadonlyArray<string>
51
+ }
52
+
53
+ let { row, onToggle, leafField, indent = 18, icons, messages, locale }: Props = $props()
54
+ const chevron = $derived(icons?.['chevron-right'])
55
+ const meta = $derived(row.__group)
56
+ const m = $derived(resolveServerGroupMessages(messages))
57
+ const num = (n: number) => n.toLocaleString(locale as string | string[] | undefined)
58
+ // A tree node's key is its id (`field` is empty under treeData); the
59
+ // label is the leaf field then, the same as for its leaves.
60
+ const label = $derived(
61
+ meta?.kind === 'group' && meta.field === '' && leafField ? String(row[leafField] ?? '') : meta?.kind === 'group' ? meta.key : '',
62
+ )
63
+ </script>
64
+
65
+ {#if meta && meta.kind === 'group' && meta.expandable === false}
66
+ <!-- Nothing opens beneath it (the innermost level under a server pivot),
67
+ so no expander: the key and the count, indented like its siblings. -->
68
+ <span class="sv-group-cell sv-group-cell-leaf" style={`padding-inline-start: ${meta.level * indent}px`}>
69
+ <span class="sv-group-chev sv-group-chev-none" aria-hidden="true"></span>
70
+ <span class="sv-group-key">{label}</span>
71
+ {#if meta.childCount != null}<span class="sv-group-count">({num(meta.childCount)})</span>{/if}
72
+ </span>
73
+ {:else if meta && meta.kind === 'group'}
74
+ <!-- The button's accessible name is the group itself ("Germany (1,234)");
75
+ expanded and busy are states, on aria-expanded / aria-busy, so a
76
+ screen reader hears what it is opening rather than "Expand group". -->
77
+ <button
78
+ type="button"
79
+ class="sv-group-cell"
80
+ style={`padding-inline-start: ${meta.level * indent}px`}
81
+ aria-expanded={meta.expanded}
82
+ aria-busy={meta.loading ? 'true' : undefined}
83
+ onclick={() => onToggle(row)}
84
+ >
85
+ {#if meta.loading}
86
+ <!-- The level's block is in flight: the expander's slot holds a
87
+ spinner until it lands, so the wait is visible on the row itself. -->
88
+ <span class="sv-group-chev sv-group-spinner" aria-hidden="true"></span>
89
+ {:else}
90
+ <!-- Same chevron the grid's own expanders and SvTree draw, so every
91
+ expander in the library looks identical. -->
92
+ <span class="sv-group-chev" class:open={meta.expanded} aria-hidden="true">
93
+ {#if chevron}
94
+ {@render chevron()}
95
+ {:else}
96
+ <svg viewBox="0 0 24 24" width="12" height="12" fill="none" stroke="currentColor"
97
+ stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6" /></svg>
98
+ {/if}
99
+ </span>
100
+ {/if}
101
+ <span class="sv-group-key">{label}</span>
102
+ {#if meta.childCount != null}<span class="sv-group-count">({num(meta.childCount)})</span>{/if}
103
+ </button>
104
+ {:else if meta && meta.kind === 'more'}
105
+ <!-- aria-disabled rather than disabled: a disabled button drops keyboard
106
+ focus the moment it is pressed, and this one is pressed to wait. -->
107
+ <button
108
+ type="button"
109
+ class="sv-group-more"
110
+ style={`padding-inline-start: ${meta.level * indent}px`}
111
+ aria-disabled={meta.loading ? 'true' : undefined}
112
+ aria-busy={meta.loading ? 'true' : undefined}
113
+ onclick={() => {
114
+ if (!meta.loading) onToggle(row)
115
+ }}
116
+ >
117
+ {meta.loading ? m.loading : fillMessage(m.loadMore, { count: num(meta.remaining) })}
118
+ </button>
119
+ {:else if meta && meta.kind === 'footer'}
120
+ <span class="sv-group-footer" style={`padding-inline-start: ${meta.level * indent}px`}>{fillMessage(m.total, { label: meta.key })}</span>
121
+ {:else if meta && meta.kind === 'skeleton'}
122
+ <span class="sv-group-skeleton" style={`margin-inline-start: ${meta.level * indent}px`} aria-hidden="true"></span>
123
+ {:else if meta && meta.kind === 'grandTotal'}
124
+ <span class="sv-group-footer sv-group-grand-total">{m.grandTotal}</span>
125
+ {:else if meta && meta.kind === 'placeholder'}
126
+ <!-- The grid draws placeholder rows itself; nothing to add here. -->
127
+ {:else if meta}
128
+ <span class="sv-group-leaf" style={`padding-inline-start: ${(meta.level + 1) * indent}px`}>
129
+ {leafField ? (row[leafField] ?? '') : ''}
130
+ </span>
131
+ {/if}
132
+
133
+ <style>
134
+ .sv-group-cell {
135
+ display: inline-flex;
136
+ align-items: center;
137
+ gap: 6px;
138
+ background: none;
139
+ border: 0;
140
+ padding: 0;
141
+ font: inherit;
142
+ color: inherit;
143
+ cursor: pointer;
144
+ border-radius: 3px;
145
+ }
146
+ .sv-group-cell-leaf { cursor: default; }
147
+ /* The same ring the grid's own tree toggle draws, so keyboard focus looks
148
+ alike whichever expander it lands on. */
149
+ .sv-group-cell:focus-visible,
150
+ .sv-group-more:focus-visible {
151
+ outline: 2px solid var(--sg-accent, #2563eb);
152
+ outline-offset: 2px;
153
+ }
154
+ .sv-group-chev {
155
+ display: inline-flex;
156
+ align-items: center;
157
+ justify-content: center;
158
+ width: 12px;
159
+ height: 12px;
160
+ transition: transform 0.15s;
161
+ color: var(--sg-muted, #64748b);
162
+ }
163
+ /* An `icons` override renders inside this wrapper, and this style block is
164
+ scoped, so its markup needs :global() to be reached. Sizing it here means
165
+ a custom chevron lands in the same box as the built-in and rotates with
166
+ the wrapper rather than needing to know the rule exists. */
167
+ .sv-group-chev :global(svg),
168
+ .sv-group-chev :global(img) {
169
+ width: 100%;
170
+ height: 100%;
171
+ display: block;
172
+ }
173
+ .sv-group-chev.open { transform: rotate(90deg); }
174
+ .sv-group-key { font-weight: 600; }
175
+ .sv-group-count { color: var(--sg-muted, #64748b); font-size: 12px; }
176
+ .sv-group-spinner {
177
+ box-sizing: border-box;
178
+ border-radius: 50%;
179
+ border: 2px solid color-mix(in srgb, var(--sg-muted, #64748b) 35%, transparent);
180
+ border-top-color: var(--sg-accent, #2563eb);
181
+ animation: sv-group-spin 0.8s linear infinite;
182
+ }
183
+ @keyframes sv-group-spin {
184
+ to { transform: rotate(360deg); }
185
+ }
186
+ @media (prefers-reduced-motion: reduce) {
187
+ .sv-group-spinner { animation: none; border-top-color: var(--sg-muted, #64748b); }
188
+ }
189
+ .sv-group-leaf { color: var(--sg-muted, #64748b); }
190
+ .sv-group-more {
191
+ background: none;
192
+ border: 0;
193
+ padding: 0;
194
+ font: inherit;
195
+ font-size: 13px;
196
+ color: var(--sg-accent, #2563eb);
197
+ cursor: pointer;
198
+ border-radius: 3px;
199
+ }
200
+ .sv-group-more[aria-disabled='true'] { color: var(--sg-muted, #64748b); cursor: default; }
201
+ .sv-group-footer { font-weight: 600; color: var(--sg-muted, #64748b); font-size: 12px; text-transform: uppercase; letter-spacing: 0.03em; }
202
+ .sv-group-skeleton {
203
+ display: inline-block;
204
+ width: 60%;
205
+ height: 10px;
206
+ border-radius: 5px;
207
+ background: linear-gradient(90deg, var(--sg-border, #e2e8f0) 25%, var(--sg-header-bg, #f1f5f9) 50%, var(--sg-border, #e2e8f0) 75%);
208
+ background-size: 200% 100%;
209
+ animation: sv-group-shimmer 1.2s infinite;
210
+ }
211
+ @keyframes sv-group-shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }
212
+ @media (prefers-reduced-motion: reduce) { .sv-group-skeleton { animation: none; } }
213
+ </style>