@svgrid/enterprise 3.1.8 → 3.1.10

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 (268) hide show
  1. package/README.md +1 -0
  2. package/dist/SvAlertRuleEditor.svelte +16 -5
  3. package/dist/SvGridAlerts.svelte +8 -0
  4. package/dist/SvGridAlerts.svelte.d.ts +4 -0
  5. package/dist/SvGridBoard.svelte +69 -10
  6. package/dist/SvGridBulkEditDrawer.svelte +13 -5
  7. package/dist/SvGridGallery.svelte +286 -0
  8. package/dist/SvGridGallery.svelte.d.ts +30 -0
  9. package/dist/SvGridScheduler.svelte +33 -11
  10. package/dist/SvGridSelectionBar.svelte +47 -0
  11. package/dist/advanced-filter/expr-columns-from-grid.d.ts +1 -0
  12. package/dist/advanced-filter/expr-columns-from-grid.js +11 -7
  13. package/dist/advanced-filter-enable.d.ts +6 -0
  14. package/dist/advanced-filter-enable.js +8 -0
  15. package/dist/alerts/alert-engine.d.ts +7 -0
  16. package/dist/alerts/alert-engine.js +5 -2
  17. package/dist/alerts/condition-editor.d.ts +26 -0
  18. package/dist/alerts/condition-editor.js +17 -0
  19. package/dist/base/index.d.ts +20 -0
  20. package/dist/base/index.js +20 -0
  21. package/dist/bulk-edit.d.ts +11 -0
  22. package/dist/bulk-edit.js +18 -1
  23. package/dist/cdn/svgrid-enterprise.svelte-external.js +11197 -10639
  24. package/dist/designer/assets/GridFooter-Cu8_yBlQ.js +2 -0
  25. package/dist/designer/assets/GridMenus-BUjkkAU2.js +6 -0
  26. package/dist/designer/assets/PinSplitter-BgTpgh1d.css +1 -0
  27. package/dist/designer/assets/PinSplitter-C5AwA1xV.js +1 -0
  28. package/dist/designer/assets/SvGrid.helpers-CIrmIo9U.js +1 -0
  29. package/dist/designer/assets/SvGridCellEditor-CJxThKL_.js +4 -0
  30. package/dist/designer/assets/SvListBox-CS7oUAiX.js +2 -0
  31. package/dist/designer/assets/conditional-formatting-MDWbF8_Y.js +1 -0
  32. package/dist/designer/assets/grid-extension.svelte-BZ7AqyJI.js +1 -0
  33. package/dist/designer/assets/index-BmvG99kR.css +1 -0
  34. package/dist/designer/assets/{index-Obk8sI77.js → index-CJodU3tU.js} +307 -307
  35. package/dist/designer/assets/sparkline-C-NcnB2i.js +1 -0
  36. package/dist/designer/assets/src-C_U1NKOY.js +58 -0
  37. package/dist/designer/assets/sv-grid-scrollbar-B9N6Wuj0.js +109 -0
  38. package/dist/designer/assets/validate-H5u2HEQh.js +1 -0
  39. package/dist/designer/index.html +11 -7
  40. package/dist/expressions/compile.js +10 -0
  41. package/dist/expressions/evaluate.js +18 -0
  42. package/dist/expressions/expression-types.d.ts +10 -0
  43. package/dist/expressions/kinds.d.ts +28 -0
  44. package/dist/expressions/kinds.js +19 -0
  45. package/dist/expressions/parse.js +9 -1
  46. package/dist/fields/AttachmentCell.svelte +242 -0
  47. package/dist/fields/AttachmentCell.svelte.d.ts +5 -0
  48. package/dist/fields/AttachmentDialog.svelte +357 -0
  49. package/dist/fields/AttachmentDialog.svelte.d.ts +13 -0
  50. package/dist/fields/AttachmentEditor.svelte +41 -0
  51. package/dist/fields/AttachmentEditor.svelte.d.ts +11 -0
  52. package/dist/fields/AttachmentPreview.svelte +72 -0
  53. package/dist/fields/AttachmentPreview.svelte.d.ts +8 -0
  54. package/dist/fields/BarcodeCell.svelte +20 -0
  55. package/dist/fields/BarcodeCell.svelte.d.ts +5 -0
  56. package/dist/fields/BaseAutomations.svelte +558 -0
  57. package/dist/fields/BaseAutomations.svelte.d.ts +18 -0
  58. package/dist/fields/BaseChartView.svelte +47 -0
  59. package/dist/fields/BaseChartView.svelte.d.ts +8 -0
  60. package/dist/fields/BaseTableView.svelte +185 -0
  61. package/dist/fields/BaseTableView.svelte.d.ts +37 -0
  62. package/dist/fields/BaseTabs.svelte +308 -0
  63. package/dist/fields/BaseTabs.svelte.d.ts +21 -0
  64. package/dist/fields/ButtonCell.svelte +47 -0
  65. package/dist/fields/ButtonCell.svelte.d.ts +20 -0
  66. package/dist/fields/CheckboxCell.svelte +46 -0
  67. package/dist/fields/CheckboxCell.svelte.d.ts +14 -0
  68. package/dist/fields/DeleteFieldConfirm.svelte +80 -0
  69. package/dist/fields/DeleteFieldConfirm.svelte.d.ts +8 -0
  70. package/dist/fields/DeleteRecordConfirm.svelte +48 -0
  71. package/dist/fields/DeleteRecordConfirm.svelte.d.ts +9 -0
  72. package/dist/fields/FieldCell.svelte +80 -0
  73. package/dist/fields/FieldCell.svelte.d.ts +9 -0
  74. package/dist/fields/FieldEditor.svelte +321 -0
  75. package/dist/fields/FieldEditor.svelte.d.ts +10 -0
  76. package/dist/fields/FieldInput.svelte +188 -0
  77. package/dist/fields/FieldInput.svelte.d.ts +29 -0
  78. package/dist/fields/FieldsHeaderEnd.svelte +146 -0
  79. package/dist/fields/FieldsHeaderEnd.svelte.d.ts +6 -0
  80. package/dist/fields/FootRowAdder.svelte +8 -0
  81. package/dist/fields/FootRowAdder.svelte.d.ts +6 -0
  82. package/dist/fields/GroupHeader.svelte +127 -0
  83. package/dist/fields/GroupHeader.svelte.d.ts +24 -0
  84. package/dist/fields/LinkCell.svelte +46 -0
  85. package/dist/fields/LinkCell.svelte.d.ts +9 -0
  86. package/dist/fields/LinkPickerEditor.svelte +172 -0
  87. package/dist/fields/LinkPickerEditor.svelte.d.ts +9 -0
  88. package/dist/fields/LinkPreview.svelte +60 -0
  89. package/dist/fields/LinkPreview.svelte.d.ts +7 -0
  90. package/dist/fields/LinkedRecordView.svelte +94 -0
  91. package/dist/fields/LinkedRecordView.svelte.d.ts +9 -0
  92. package/dist/fields/LinkedRecordsCell.svelte +59 -0
  93. package/dist/fields/LinkedRecordsCell.svelte.d.ts +11 -0
  94. package/dist/fields/LongTextEditor.svelte +157 -0
  95. package/dist/fields/LongTextEditor.svelte.d.ts +11 -0
  96. package/dist/fields/NumberEditor.svelte +309 -0
  97. package/dist/fields/NumberEditor.svelte.d.ts +12 -0
  98. package/dist/fields/OptionsEditor.svelte +117 -0
  99. package/dist/fields/OptionsEditor.svelte.d.ts +11 -0
  100. package/dist/fields/PercentCell.svelte +21 -0
  101. package/dist/fields/PercentCell.svelte.d.ts +8 -0
  102. package/dist/fields/PropertyInput.svelte +204 -0
  103. package/dist/fields/PropertyInput.svelte.d.ts +11 -0
  104. package/dist/fields/RatingCell.svelte +75 -0
  105. package/dist/fields/RatingCell.svelte.d.ts +16 -0
  106. package/dist/fields/RatingEditor.svelte +82 -0
  107. package/dist/fields/RatingEditor.svelte.d.ts +9 -0
  108. package/dist/fields/RecordView.svelte +310 -0
  109. package/dist/fields/RecordView.svelte.d.ts +11 -0
  110. package/dist/fields/RichTextCell.svelte +30 -0
  111. package/dist/fields/RichTextCell.svelte.d.ts +5 -0
  112. package/dist/fields/RowAdder.svelte +93 -0
  113. package/dist/fields/RowAdder.svelte.d.ts +7 -0
  114. package/dist/fields/RowHeader.svelte +99 -0
  115. package/dist/fields/RowHeader.svelte.d.ts +11 -0
  116. package/dist/fields/SelectCell.svelte +35 -0
  117. package/dist/fields/SelectCell.svelte.d.ts +15 -0
  118. package/dist/fields/SelectEditor.svelte +350 -0
  119. package/dist/fields/SelectEditor.svelte.d.ts +17 -0
  120. package/dist/fields/SummaryCell.svelte +160 -0
  121. package/dist/fields/SummaryCell.svelte.d.ts +11 -0
  122. package/dist/fields/SvBase.svelte +545 -0
  123. package/dist/fields/SvBase.svelte.d.ts +30 -0
  124. package/dist/fields/SvBaseForm.svelte +295 -0
  125. package/dist/fields/SvBaseForm.svelte.d.ts +22 -0
  126. package/dist/fields/SvBaseViewBar.svelte +644 -0
  127. package/dist/fields/SvBaseViewBar.svelte.d.ts +26 -0
  128. package/dist/fields/UserCell.svelte +39 -0
  129. package/dist/fields/UserCell.svelte.d.ts +9 -0
  130. package/dist/fields/UserFace.svelte +30 -0
  131. package/dist/fields/UserFace.svelte.d.ts +12 -0
  132. package/dist/fields/activity.svelte.d.ts +50 -0
  133. package/dist/fields/activity.svelte.js +110 -0
  134. package/dist/fields/attachments.d.ts +95 -0
  135. package/dist/fields/attachments.js +145 -0
  136. package/dist/fields/automation-outbound.d.ts +46 -0
  137. package/dist/fields/automation-outbound.js +61 -0
  138. package/dist/fields/automation-server.d.ts +53 -0
  139. package/dist/fields/automation-server.js +333 -0
  140. package/dist/fields/automations.svelte.d.ts +208 -0
  141. package/dist/fields/automations.svelte.js +437 -0
  142. package/dist/fields/bar-request.svelte.d.ts +16 -0
  143. package/dist/fields/bar-request.svelte.js +15 -0
  144. package/dist/fields/base-alerts.d.ts +24 -0
  145. package/dist/fields/base-alerts.js +64 -0
  146. package/dist/fields/base-connect.d.ts +82 -0
  147. package/dist/fields/base-connect.js +271 -0
  148. package/dist/fields/base-schema.d.ts +104 -0
  149. package/dist/fields/base-schema.js +266 -0
  150. package/dist/fields/base-sql.d.ts +62 -0
  151. package/dist/fields/base-sql.js +251 -0
  152. package/dist/fields/base-sync.d.ts +142 -0
  153. package/dist/fields/base-sync.js +499 -0
  154. package/dist/fields/base-tables.d.ts +89 -0
  155. package/dist/fields/base-tables.js +349 -0
  156. package/dist/fields/builtin-types.d.ts +13 -0
  157. package/dist/fields/builtin-types.js +773 -0
  158. package/dist/fields/button.d.ts +2 -0
  159. package/dist/fields/button.js +17 -0
  160. package/dist/fields/chart-view.d.ts +35 -0
  161. package/dist/fields/chart-view.js +154 -0
  162. package/dist/fields/column-order.d.ts +6 -0
  163. package/dist/fields/column-order.js +12 -0
  164. package/dist/fields/convert.d.ts +16 -0
  165. package/dist/fields/convert.js +176 -0
  166. package/dist/fields/copy-text.d.ts +13 -0
  167. package/dist/fields/copy-text.js +45 -0
  168. package/dist/fields/editor-request.svelte.d.ts +71 -0
  169. package/dist/fields/editor-request.svelte.js +52 -0
  170. package/dist/fields/field-ops.d.ts +72 -0
  171. package/dist/fields/field-ops.js +334 -0
  172. package/dist/fields/filter-model.d.ts +84 -0
  173. package/dist/fields/filter-model.js +446 -0
  174. package/dist/fields/format.d.ts +109 -0
  175. package/dist/fields/format.js +288 -0
  176. package/dist/fields/formula.d.ts +50 -0
  177. package/dist/fields/formula.js +530 -0
  178. package/dist/fields/grid-access.d.ts +60 -0
  179. package/dist/fields/grid-access.js +120 -0
  180. package/dist/fields/index.d.ts +34 -0
  181. package/dist/fields/index.js +312 -0
  182. package/dist/fields/linked-fields.d.ts +8 -0
  183. package/dist/fields/linked-fields.js +40 -0
  184. package/dist/fields/links.d.ts +10 -0
  185. package/dist/fields/links.js +46 -0
  186. package/dist/fields/name-list.d.ts +16 -0
  187. package/dist/fields/name-list.js +49 -0
  188. package/dist/fields/palette.d.ts +47 -0
  189. package/dist/fields/palette.js +69 -0
  190. package/dist/fields/record-delete.svelte.d.ts +12 -0
  191. package/dist/fields/record-delete.svelte.js +5 -0
  192. package/dist/fields/record-menu.d.ts +9 -0
  193. package/dist/fields/record-menu.js +78 -0
  194. package/dist/fields/registry.svelte.d.ts +176 -0
  195. package/dist/fields/registry.svelte.js +51 -0
  196. package/dist/fields/rich-text.d.ts +23 -0
  197. package/dist/fields/rich-text.js +48 -0
  198. package/dist/fields/row-color-choice.svelte.d.ts +31 -0
  199. package/dist/fields/row-color-choice.svelte.js +25 -0
  200. package/dist/fields/row-colors.d.ts +36 -0
  201. package/dist/fields/row-colors.js +90 -0
  202. package/dist/fields/row-height.d.ts +28 -0
  203. package/dist/fields/row-height.js +50 -0
  204. package/dist/fields/sources.svelte.d.ts +80 -0
  205. package/dist/fields/sources.svelte.js +131 -0
  206. package/dist/fields/summaries.d.ts +18 -0
  207. package/dist/fields/summaries.js +138 -0
  208. package/dist/fields/view-model.d.ts +129 -0
  209. package/dist/fields/view-model.js +492 -0
  210. package/dist/fields/viewbar/ChartPanel.svelte +61 -0
  211. package/dist/fields/viewbar/ChartPanel.svelte.d.ts +9 -0
  212. package/dist/fields/viewbar/ColorPanel.svelte +112 -0
  213. package/dist/fields/viewbar/ColorPanel.svelte.d.ts +9 -0
  214. package/dist/fields/viewbar/ConditionValue.svelte +153 -0
  215. package/dist/fields/viewbar/ConditionValue.svelte.d.ts +15 -0
  216. package/dist/fields/viewbar/FieldIcon.svelte +18 -0
  217. package/dist/fields/viewbar/FieldIcon.svelte.d.ts +9 -0
  218. package/dist/fields/viewbar/FilterPanel.svelte +192 -0
  219. package/dist/fields/viewbar/FilterPanel.svelte.d.ts +13 -0
  220. package/dist/fields/viewbar/GanttPanel.svelte +60 -0
  221. package/dist/fields/viewbar/GanttPanel.svelte.d.ts +10 -0
  222. package/dist/fields/viewbar/HideFieldsPanel.svelte +104 -0
  223. package/dist/fields/viewbar/HideFieldsPanel.svelte.d.ts +7 -0
  224. package/dist/fields/viewbar/SortPanel.svelte +85 -0
  225. package/dist/fields/viewbar/SortPanel.svelte.d.ts +8 -0
  226. package/dist/fields/viewbar/ViewsMenu.svelte +250 -0
  227. package/dist/fields/viewbar/ViewsMenu.svelte.d.ts +15 -0
  228. package/dist/fields/viewbar/panel-focus.d.ts +3 -0
  229. package/dist/fields/viewbar/panel-focus.js +22 -0
  230. package/dist/fields/viewbar/sort-state.d.ts +20 -0
  231. package/dist/fields/viewbar/sort-state.js +24 -0
  232. package/dist/gallery.d.ts +7 -0
  233. package/dist/gallery.js +36 -0
  234. package/dist/gantt/SvGridGantt.svelte +88 -16
  235. package/dist/gantt/gantt-config.d.ts +28 -0
  236. package/dist/index.d.ts +3 -0
  237. package/dist/index.js +6 -0
  238. package/dist/install.js +3 -0
  239. package/dist/license-core.d.ts +3 -3
  240. package/dist/license.js +1 -0
  241. package/dist/node/studio.js +105 -4
  242. package/dist/scheduler-config.d.ts +11 -0
  243. package/dist/sources/introspect-supabase.js +4 -1
  244. package/dist/sources/rest.js +6 -2
  245. package/dist/studio/ui-components.generated.js +93 -1
  246. package/dist/upgrade-prompt.d.ts +1 -1
  247. package/dist/version.d.ts +2 -2
  248. package/dist/version.js +2 -2
  249. package/dist/wc/GridFooter-f5K0aLe_.js +145 -0
  250. package/dist/wc/GridMenus-FtSN_8t9.js +1369 -0
  251. package/dist/wc/PinSplitter-D-qtDhSM.js +132 -0
  252. package/dist/wc/{SvGrid.helpers-zBkDTryR.js → SvGrid.helpers-B2GEKrxS.js} +84 -36
  253. package/dist/wc/{SvGridCellEditor-CzUKEbkI.js → SvGridCellEditor-B_cLJrsp.js} +20 -9
  254. package/dist/wc/conditional-formatting-BXis_oP1.js +189 -0
  255. package/dist/wc/grid-extension.svelte-Bufq4B4C.js +20 -0
  256. package/dist/wc/sv-sheet-element.js +7556 -7617
  257. package/dist/wc/svelte-virtualizer.svelte-ehwOupl-.js +360 -0
  258. package/dist/wc/{validate-43C03DLP.js → validate-BaMO8UPE.js} +1 -1
  259. package/package.json +14 -3
  260. package/dist/designer/assets/GridMenus-CvcASlKv.js +0 -8
  261. package/dist/designer/assets/SvGrid.helpers-DE5mmORW.js +0 -1
  262. package/dist/designer/assets/SvGridCellEditor-C7NWcnNC.js +0 -4
  263. package/dist/designer/assets/SvListBox-BlmmzYcU.js +0 -110
  264. package/dist/designer/assets/index-KmSEY7Lb.css +0 -1
  265. package/dist/designer/assets/src-DqHCqori.js +0 -58
  266. package/dist/designer/assets/validate-B71dE1Cs.js +0 -1
  267. package/dist/wc/GridMenus-fWbBUiRH.js +0 -1088
  268. package/dist/wc/svelte-virtualizer.svelte-Dntdh8Ms.js +0 -581
@@ -132,6 +132,21 @@
132
132
  return d ? toZonedLocal(d, tz) : undefined;
133
133
  };
134
134
  const fromZ = (d: Date): Date => fromZonedLocal(d, tz);
135
+ // `allDay`: a value is a day. A bare 'YYYY-MM-DD' is that local day (new Date()
136
+ // reads it as midnight UTC, the evening before west of Greenwich).
137
+ const toDay = (v: unknown): Date | undefined => {
138
+ const m = typeof v === "string" ? /^(\d{4})-(\d{2})-(\d{2})$/.exec(v) : null;
139
+ if (m) return new Date(Number(m[1]), Number(m[2]) - 1, Number(m[3]));
140
+ const d = toZ(v);
141
+ return d ? new Date(d.getFullYear(), d.getMonth(), d.getDate()) : undefined;
142
+ };
143
+ const readDate = (v: unknown): Date | undefined => (scheduler.allDay ? toDay(v) : toZ(v));
144
+ // An all-day end written as a day ('2026-10-14') is the event's LAST day; the
145
+ // calendar's ends are exclusive, so it ends at the next midnight.
146
+ const readEnd = (v: unknown): Date | undefined => {
147
+ const d = readDate(v);
148
+ return d && scheduler.allDay && typeof v === "string" && /^\d{4}-\d{2}-\d{2}$/.test(v) ? addDays(d, 1) : d;
149
+ };
135
150
  // Emit boundary: user edits are computed in pseudo-local time; convert their
136
151
  // start/end back to real instants before handing them to consumer callbacks.
137
152
  type MoveEv = Parameters<NonNullable<typeof scheduler.onEventMove>>[0];
@@ -232,12 +247,12 @@
232
247
  void tz; // re-resolve events (their positions) when the display zone changes
233
248
  return {
234
249
  getKey: (r) => key(r),
235
- getStart: (r) => startOfE[key(r)] ?? (toZ(fieldValue(r, scheduler.startField)) as never),
250
+ getStart: (r) => startOfE[key(r)] ?? (readDate(fieldValue(r, scheduler.startField)) as never),
236
251
  getEnd: (r) =>
237
252
  endOfE[key(r)] ??
238
- (scheduler.endField ? (toZ(fieldValue(r, scheduler.endField)) as never) : undefined),
253
+ (scheduler.endField ? (readEnd(fieldValue(r, scheduler.endField)) as never) : undefined),
239
254
  getAllDay: (r) =>
240
- allDayOf[key(r)] ?? (scheduler.allDayField ? !!fieldValue(r, scheduler.allDayField) : false),
255
+ allDayOf[key(r)] ?? (scheduler.allDay ? true : scheduler.allDayField ? !!fieldValue(r, scheduler.allDayField) : false),
241
256
  getTitle: (r) => (titleField ? String(fieldValue(r, titleField) ?? "") : ""),
242
257
  getColor: (r) =>
243
258
  scheduler.colorField
@@ -306,6 +321,8 @@
306
321
  // derivations below read it, and a `const` used above its declaration is a type
307
322
  // error even though `$derived` is lazy enough to work at runtime.
308
323
  const pcfg = $derived(scheduler as unknown as SchedulerProConfig<TFeatures, TData>);
324
+ // Off, events move but keep their length: no edge grips (a record with one date has none to change).
325
+ const resizable = $derived(pcfg.resizable !== false);
309
326
  // --- multi-calendar overlay ---
310
327
  const calendars = $derived(pcfg.calendars ?? []);
311
328
  const calField = $derived(pcfg.calendarField);
@@ -2404,6 +2421,11 @@
2404
2421
  rangeSel = null; // opening an event dismisses any pending cell selection
2405
2422
  tlRangeSel = null;
2406
2423
  monthRangeSel = null;
2424
+ // The app opens events itself (a record view): that wins over the drawer.
2425
+ if (pcfg.onEventOpen) {
2426
+ pcfg.onEventOpen(ev.row);
2427
+ return;
2428
+ }
2407
2429
  if (scheduler.drawer) {
2408
2430
  const row = ev.row;
2409
2431
  const next: Record<string, unknown> = {};
@@ -3364,7 +3386,7 @@
3364
3386
  onmouseleave={onEventLeave}
3365
3387
  title={s.event.title}
3366
3388
  >
3367
- {#if canEditBar && !s.continuesLeft}
3389
+ {#if canEditBar && resizable && !s.continuesLeft}
3368
3390
  <!-- svelte-ignore a11y_no_static_element_interactions -->
3369
3391
  <span
3370
3392
  class="sv-sched-chip-resize sv-sched-chip-resize-start"
@@ -3373,7 +3395,7 @@
3373
3395
  ></span>
3374
3396
  {/if}
3375
3397
  {#if scheduler.event}{@render scheduler.event(s.event.row)}{:else}{#if !s.event.allDay && !s.continuesLeft}<span class="sv-sched-dot"></span><span class="sv-sched-bar-time">{fmtTime(s.event.start)}</span>{/if}<span class="sv-sched-bar-title">{s.event.title}</span>{/if}
3376
- {#if canEditBar && !s.continuesRight}
3398
+ {#if canEditBar && resizable && !s.continuesRight}
3377
3399
  <!-- svelte-ignore a11y_no_static_element_interactions -->
3378
3400
  <span
3379
3401
  class="sv-sched-chip-resize sv-sched-chip-resize-end"
@@ -3569,14 +3591,14 @@
3569
3591
  onmouseleave={onEventLeave}
3570
3592
  title={it.event.title}
3571
3593
  >
3572
- {#if canEdit && !g.continuesLeft}
3594
+ {#if canEdit && resizable && !g.continuesLeft}
3573
3595
  <!-- svelte-ignore a11y_no_static_element_interactions -->
3574
3596
  <span class="sv-sched-chip-resize sv-sched-chip-resize-start" aria-hidden="true" onpointerdown={(e) => startTlDrag(e, it.event, "resize-start")}></span>
3575
3597
  {/if}
3576
3598
  {#if wpx >= 22}
3577
3599
  {#if scheduler.event}{@render scheduler.event(it.event.row)}{:else}{#if view === "timelineDay" && !it.event.allDay && !g.continuesLeft}<span class="sv-sched-bar-time">{fmtTime(it.event.start)}</span>{/if}<span class="sv-sched-bar-title">{it.event.title}</span>{/if}
3578
3600
  {/if}
3579
- {#if canEdit && !g.continuesRight}
3601
+ {#if canEdit && resizable && !g.continuesRight}
3580
3602
  <!-- svelte-ignore a11y_no_static_element_interactions -->
3581
3603
  <span class="sv-sched-chip-resize sv-sched-chip-resize-end" aria-hidden="true" onpointerdown={(e) => startTlDrag(e, it.event, "resize-end")}></span>
3582
3604
  {/if}
@@ -3709,7 +3731,7 @@
3709
3731
  onmouseleave={onEventLeave}
3710
3732
  title={s.event.title}
3711
3733
  >
3712
- {#if canEditBar && !s.continuesLeft}
3734
+ {#if canEditBar && resizable && !s.continuesLeft}
3713
3735
  <!-- svelte-ignore a11y_no_static_element_interactions -->
3714
3736
  <span
3715
3737
  class="sv-sched-chip-resize sv-sched-chip-resize-start"
@@ -3718,7 +3740,7 @@
3718
3740
  ></span>
3719
3741
  {/if}
3720
3742
  {#if scheduler.event}{@render scheduler.event(s.event.row)}{:else}<span class="sv-sched-bar-title">{s.event.title}</span>{/if}
3721
- {#if canEditBar && !s.continuesRight}
3743
+ {#if canEditBar && resizable && !s.continuesRight}
3722
3744
  <!-- svelte-ignore a11y_no_static_element_interactions -->
3723
3745
  <span
3724
3746
  class="sv-sched-chip-resize sv-sched-chip-resize-end"
@@ -3825,7 +3847,7 @@
3825
3847
  onmouseenter={(e) => onEventEnter(e, p.event)}
3826
3848
  onmouseleave={onEventLeave}
3827
3849
  >
3828
- {#if canEdit}
3850
+ {#if canEdit && resizable}
3829
3851
  <!-- svelte-ignore a11y_no_static_element_interactions -->
3830
3852
  <span
3831
3853
  class="sv-sched-resize sv-sched-resize-top"
@@ -3834,7 +3856,7 @@
3834
3856
  ></span>
3835
3857
  {/if}
3836
3858
  {#if scheduler.event}{@render scheduler.event(p.event.row)}{:else}<span class="sv-sched-event-time">{fmtTime(isResize ? drag!.previewStart : p.event.start)}{isResize ? ` - ${fmtTime(drag!.previewEnd)}` : ""}</span><span class="sv-sched-event-title">{p.event.title}</span>{/if}
3837
- {#if canEdit}
3859
+ {#if canEdit && resizable}
3838
3860
  <!-- svelte-ignore a11y_no_static_element_interactions -->
3839
3861
  <span
3840
3862
  class="sv-sched-resize sv-sched-resize-bottom"
@@ -45,6 +45,23 @@
45
45
  const ICON = {
46
46
  selectAll: 'M9 11l3 3L22 4M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11',
47
47
  editFields: 'M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7M18.5 2.5a2.1 2.1 0 0 1 3 3L12 15l-4 1 1-4Z',
48
+ deleteRows: 'M3 6h18M8 6V4h8v2M19 6l-1 14H6L5 6M10 11v6M14 11v6',
49
+ }
50
+ // Delete asks first, on the bar itself: "Delete 3 rows?" Delete / Cancel.
51
+ let confirming = $state(false)
52
+ let confirmButton = $state<HTMLButtonElement | null>(null)
53
+ $effect(() => {
54
+ if (confirming) confirmButton?.focus()
55
+ })
56
+ function deleteSelected() {
57
+ const rows = target.rows
58
+ const ids = target.ids
59
+ const drop = new Set(rows)
60
+ const data = (ctrl.internalData as unknown[]).filter((r) => !drop.has(r))
61
+ confirming = false
62
+ clearSelection()
63
+ ctrl.internalData = data
64
+ ctrl.props?.onRowsDelete?.({ rows, ids, data })
48
65
  }
49
66
 
50
67
  /** Turn the built-in string keys into real actions. */
@@ -69,6 +86,16 @@
69
86
  action: () => (bulkEditOpen = true),
70
87
  }
71
88
  }
89
+ if (entry === 'deleteRows') {
90
+ return {
91
+ key: 'deleteRows',
92
+ label: messages.selectionBarDelete,
93
+ icon: ICON.deleteRows,
94
+ // Rows a server row model never loaded cannot be deleted here.
95
+ hidden: () => !!ctrl.props?.rowModel,
96
+ action: () => (confirming = true),
97
+ }
98
+ }
72
99
  return null
73
100
  }
74
101
 
@@ -107,6 +134,11 @@
107
134
  */
108
135
  function onKeydown(event: KeyboardEvent) {
109
136
  if (event.key === 'Escape') {
137
+ if (confirming) {
138
+ confirming = false
139
+ event.stopPropagation()
140
+ return
141
+ }
110
142
  if (overflowOpen) {
111
143
  overflowOpen = false
112
144
  event.stopPropagation()
@@ -154,6 +186,16 @@
154
186
  <span class="sv-selbar-count-label">{messages.selectionBarCount}</span>
155
187
  </span>
156
188
 
189
+ {#if confirming}
190
+ <span class="sv-selbar-sep" aria-hidden="true"></span>
191
+ <span class="sv-selbar-confirm" role="alert">{fill(messages.selectionBarDeleteConfirm, count)}</span>
192
+ <button type="button" class="sv-selbar-btn is-danger is-solid" bind:this={confirmButton} onclick={deleteSelected}>
193
+ <span>{messages.selectionBarDelete}</span>
194
+ </button>
195
+ <button type="button" class="sv-selbar-btn" onclick={() => (confirming = false)}>
196
+ <span>{messages.selectionBarCancel}</span>
197
+ </button>
198
+ {:else}
157
199
  {#if inline.length}
158
200
  <span class="sv-selbar-sep" aria-hidden="true"></span>
159
201
  {/if}
@@ -222,6 +264,7 @@
222
264
  {/if}
223
265
  </div>
224
266
  {/if}
267
+ {/if}
225
268
 
226
269
  {#if !hideClear}
227
270
  <span class="sv-selbar-sep" aria-hidden="true"></span>
@@ -366,6 +409,10 @@
366
409
  .sv-selbar-btn.is-danger:hover:not(:disabled) {
367
410
  background: color-mix(in srgb, var(--sg-danger, #dc2626) 12%, transparent 88%);
368
411
  }
412
+ /* The confirm is the one red, solid button: the choice that cannot be undone. */
413
+ .sv-selbar-btn.is-solid { background: var(--sg-danger, #dc2626); color: #fff; }
414
+ .sv-selbar-btn.is-solid:hover:not(:disabled) { background: color-mix(in srgb, var(--sg-danger, #dc2626) 88%, #000 12%); }
415
+ .sv-selbar-confirm { flex: none; padding: 0 4px; font-weight: 600; white-space: nowrap; }
369
416
  .sv-selbar-more-btn { padding: 5px 7px; flex: none; }
370
417
  .sv-selbar-btn > span {
371
418
  overflow: hidden;
@@ -11,6 +11,7 @@ type GridColumnInfo = {
11
11
  field?: string;
12
12
  header: string;
13
13
  visible: boolean;
14
+ cellDataType?: string;
14
15
  editorType?: string;
15
16
  };
16
17
  export type ExprColumnsOptions = {
@@ -3,16 +3,20 @@
3
3
  * structural (a checkbox gutter, a row-number gutter) rather than data.
4
4
  */
5
5
  const NON_DATA_IDS = new Set(['__select', '__selection', '__rowNumber', '__autoGroup', '__actions']);
6
- /** Map a grid editorType onto the coarse type the operator catalogue uses. */
7
- function toExprType(editorType) {
8
- switch (editorType) {
6
+ /**
7
+ * The coarse type the operator catalogue uses, from the column's data type
8
+ * (whatever edits it). A datetime editor keeps the time in the filter.
9
+ */
10
+ function toExprType(col) {
11
+ if (col.editorType === 'datetime')
12
+ return 'datetime';
13
+ switch (col.cellDataType) {
9
14
  case 'number':
10
15
  return 'number';
11
16
  case 'date':
17
+ case 'dateString':
12
18
  return 'date';
13
- case 'datetime':
14
- return 'datetime';
15
- case 'checkbox':
19
+ case 'boolean':
16
20
  return 'boolean';
17
21
  default:
18
22
  return 'text';
@@ -37,7 +41,7 @@ export function exprColumnsFromGrid(api, options = {}) {
37
41
  // Fall back to the id so a column with no header is still addressable
38
42
  // in the `[Bracketed Name]` reference syntax.
39
43
  name: col.header || col.id,
40
- type: toExprType(col.editorType),
44
+ type: toExprType(col),
41
45
  });
42
46
  }
43
47
  return out;
@@ -1,3 +1,9 @@
1
+ /** Compiles an expression kind of another Enterprise module (the fields view bar's `fieldFilter`). */
2
+ export type FilterKindCompiler = (expr: any, ctx: {
3
+ getValue: (row: any, columnId: string) => unknown;
4
+ }) => ((row: any) => boolean) | null;
5
+ /** Teach the advanced filter an expression kind of its own (one per kind). */
6
+ export declare function registerFilterKind(kind: string, compile: FilterKindCompiler): void;
1
7
  /**
2
8
  * Enable the advanced filter. Call once (installEnterprise does it for you),
3
9
  * after which `api.setAdvancedFilter(expr)` actually filters rows.
@@ -10,11 +10,19 @@ import { hasValidLicense } from './license.js';
10
10
  import { emitUnlicensedNudge } from './watermark.js';
11
11
  import { compilePredicate } from './expressions/compile.js';
12
12
  let enabled = false;
13
+ const kinds = new Map();
14
+ /** Teach the advanced filter an expression kind of its own (one per kind). */
15
+ export function registerFilterKind(kind, compile) {
16
+ kinds.set(kind, compile);
17
+ }
13
18
  const advancedFilterEngine = (expr, ctx) => {
14
19
  // The grid treats null as "do not filter" and never surfaces a partially
15
20
  // applied predicate, so swallowing here is safe and is the fail-open half of
16
21
  // the contract documented on AdvancedFilterEngine.
17
22
  try {
23
+ const own = kinds.get(expr.kind ?? '');
24
+ if (own)
25
+ return own(expr, ctx);
18
26
  return compilePredicate(expr, ctx);
19
27
  }
20
28
  catch {
@@ -5,6 +5,12 @@ export type AlertEngineOptions<TData> = {
5
5
  /** Resolve a column id to a value (defaults to `row[id]`). */
6
6
  getValue?: (row: TData, columnId: string) => unknown;
7
7
  locale?: string | ReadonlyArray<string>;
8
+ /**
9
+ * A message token the built-in ones do not cover, as text: SvGrid Base reads
10
+ * `{Due date}` as the field of that name, formatted as its cell shows it.
11
+ * Undefined leaves the token as it was.
12
+ */
13
+ token?: (row: TData, name: string) => string | undefined;
8
14
  /** Clock for `firedAt` (injectable for deterministic tests). */
9
15
  now?: () => number;
10
16
  };
@@ -44,5 +50,6 @@ export declare function renderTemplate(template: string, ctx: {
44
50
  row?: Record<string, unknown>;
45
51
  columnId?: string;
46
52
  value?: unknown;
53
+ token?: (row: Record<string, unknown>, name: string) => string | undefined;
47
54
  }): string;
48
55
  export declare function createAlertEngine<TData = Record<string, unknown>>(options: AlertEngineOptions<TData>): AlertEngine<TData>;
@@ -9,14 +9,16 @@ import { collectColumnRefs } from '../expressions/parse.js';
9
9
  const AGG_ROW_KEY = '*';
10
10
  /** Fill message-template tokens from the firing context. */
11
11
  export function renderTemplate(template, ctx) {
12
- const { rule, row, columnId, value } = ctx;
13
- return template
12
+ const { rule, row, columnId, value, token } = ctx;
13
+ const out = template
14
14
  .replace(/\{rule\}/g, rule.name)
15
15
  .replace(/\{severity\}/g, rule.severity)
16
16
  .replace(/\{column\}/g, columnId ?? '')
17
17
  .replace(/\{value\}/g, value == null ? '' : String(value))
18
18
  .replace(/\{row\.([\w$]+)\}/g, (_m, key) => fmt(row?.[key]))
19
19
  .replace(/\{([\w$]+)\}/g, (m, key) => (row && key in row ? fmt(row[key]) : m));
20
+ // Names with spaces ("{Due date}") only mean something to a resolver.
21
+ return token && row ? out.replace(/\{([^{}\n]+)\}/g, (m, name) => token(row, name.trim()) ?? m) : out;
20
22
  }
21
23
  function fmt(v) {
22
24
  return v == null ? '' : String(v);
@@ -55,6 +57,7 @@ export function createAlertEngine(options) {
55
57
  row: opts.row,
56
58
  columnId: opts.columnId,
57
59
  value: opts.value,
60
+ token: options.token,
58
61
  });
59
62
  return {
60
63
  ruleId: rule.id,
@@ -0,0 +1,26 @@
1
+ /**
2
+ * The condition editor an alert rule shows, when a module brings its own.
3
+ *
4
+ * `SvAlertRuleEditor` edits a rule's predicate with the expression editor.
5
+ * SvGrid Base sets this context around its grid so a rule there is written
6
+ * with the view bar's filter ("Where Status is Done and Due date is before
7
+ * today"), stored as an `ext` node, and read with the field types' meaning.
8
+ */
9
+ import { type Component } from 'svelte';
10
+ import type { PredicateExpr } from '../expressions/expression-types.js';
11
+ export type AlertConditionEditor = {
12
+ /** Draws a predicate and reports each change. */
13
+ component: Component<{
14
+ value: PredicateExpr;
15
+ onChange: (next: PredicateExpr) => void;
16
+ }>;
17
+ /** The predicate a new rule starts with. */
18
+ initial: () => PredicateExpr;
19
+ /** Whether it can show this predicate; one it cannot goes to the expression editor. */
20
+ accepts: (expr: PredicateExpr) => boolean;
21
+ /** The tokens a message can name, for the hint under the message box. */
22
+ tokens?: () => string[];
23
+ };
24
+ /** Call during a component's init: rules authored under it use this editor. */
25
+ export declare function setAlertConditionEditor(editor: AlertConditionEditor): void;
26
+ export declare function getAlertConditionEditor(): AlertConditionEditor | undefined;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * The condition editor an alert rule shows, when a module brings its own.
3
+ *
4
+ * `SvAlertRuleEditor` edits a rule's predicate with the expression editor.
5
+ * SvGrid Base sets this context around its grid so a rule there is written
6
+ * with the view bar's filter ("Where Status is Done and Due date is before
7
+ * today"), stored as an `ext` node, and read with the field types' meaning.
8
+ */
9
+ import { getContext, setContext } from 'svelte';
10
+ const KEY = Symbol('sv-alert-condition-editor');
11
+ /** Call during a component's init: rules authored under it use this editor. */
12
+ export function setAlertConditionEditor(editor) {
13
+ setContext(KEY, editor);
14
+ }
15
+ export function getAlertConditionEditor() {
16
+ return getContext(KEY);
17
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @svgrid/enterprise/base - SvGrid Base: a table database in the browser, the
3
+ * way a team runs a project tracker, a CRM or a content calendar. Fields of
4
+ * many types, saved views (grid, Kanban, calendar, gallery, form), filters,
5
+ * groups, colors, linked records and expanded records with comments.
6
+ *
7
+ * ```svelte
8
+ * <script lang="ts">
9
+ * import { SvBase, enableBase } from '@svgrid/enterprise/base'
10
+ * enableBase()
11
+ * </script>
12
+ *
13
+ * <SvBase {data} {columns} primaryField="name" bind:views editable />
14
+ * ```
15
+ *
16
+ * A Suite product. It is the fields module (`@svgrid/enterprise/fields`) with
17
+ * the product's own entry: everything that module exports is here too.
18
+ */
19
+ export * from '../fields/index.js';
20
+ export { enableFields as enableBase } from '../fields/index.js';
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @svgrid/enterprise/base - SvGrid Base: a table database in the browser, the
3
+ * way a team runs a project tracker, a CRM or a content calendar. Fields of
4
+ * many types, saved views (grid, Kanban, calendar, gallery, form), filters,
5
+ * groups, colors, linked records and expanded records with comments.
6
+ *
7
+ * ```svelte
8
+ * <script lang="ts">
9
+ * import { SvBase, enableBase } from '@svgrid/enterprise/base'
10
+ * enableBase()
11
+ * </script>
12
+ *
13
+ * <SvBase {data} {columns} primaryField="name" bind:views editable />
14
+ * ```
15
+ *
16
+ * A Suite product. It is the fields module (`@svgrid/enterprise/fields`) with
17
+ * the product's own entry: everything that module exports is here too.
18
+ */
19
+ export * from '../fields/index.js';
20
+ export { enableFields as enableBase } from '../fields/index.js';
@@ -19,6 +19,17 @@ export type BulkEditField = {
19
19
  value: unknown;
20
20
  label: string;
21
21
  }>;
22
+ /** A field column's type (`@svgrid/enterprise/fields`), for its form control. */
23
+ fieldType?: string;
24
+ /** The column holds several values (a multiple select, several people). */
25
+ multiple?: boolean;
26
+ /** A rating's maximum. */
27
+ max?: number;
28
+ /**
29
+ * The column's own reading of a typed value (its `valueParser`): "$1,200"
30
+ * to 1200 for an amount, "42" to 0.42 for a percent of fractions.
31
+ */
32
+ parse?: (raw: unknown) => unknown;
22
33
  };
23
34
  /**
24
35
  * The columns a bulk edit can target.
package/dist/bulk-edit.js CHANGED
@@ -33,7 +33,24 @@ export function bulkEditableFields(ctx) {
33
33
  ? { value: o.value, label: String(o.label ?? o.value) }
34
34
  : { value: o, label: String(o) })
35
35
  : undefined;
36
- out.push({ id: column.id, field: String(def.field), label, editorType: String(def.editorType ?? 'text'), options });
36
+ // A file list or a link to other records is not one value to set on
37
+ // every row from a form field.
38
+ if (def.editorType === 'attachment' || def.editorType === 'fieldLink')
39
+ continue;
40
+ const parser = typeof def.valueParser === 'function' ? def.valueParser : null;
41
+ out.push({
42
+ id: column.id,
43
+ field: String(def.field),
44
+ label,
45
+ editorType: String(def.editorType ?? 'text'),
46
+ options,
47
+ ...(def.fieldType ? { fieldType: String(def.fieldType) } : {}),
48
+ ...(def.editorMultiple ? { multiple: true } : {}),
49
+ ...(def.fieldType === 'rating' ? { max: Number(def.fieldProps?.max) || 5 } : {}),
50
+ ...(parser
51
+ ? { parse: (raw) => parser({ newValue: raw, rawInput: typeof raw === 'string' ? raw : undefined, oldValue: undefined }) }
52
+ : {}),
53
+ });
37
54
  }
38
55
  return out;
39
56
  }