@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
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Checkbox cells with the field's icon and color. The default icon is a
3
+ * box with a check; star, heart and the rest show filled when checked and as
4
+ * a faint outline when not. Clicking and Space still toggle through the grid
5
+ * (the column's editor is 'checkbox'); this only draws.
6
+ */
7
+ import type { FieldCellProps } from './registry.svelte.js';
8
+ import { type IconName } from './palette.js';
9
+ declare const CheckboxCell: import("svelte").Component<FieldCellProps<{
10
+ icon?: IconName;
11
+ color?: string;
12
+ }>, {}, "">;
13
+ type CheckboxCell = ReturnType<typeof CheckboxCell>;
14
+ export default CheckboxCell;
@@ -0,0 +1,80 @@
1
+ <script lang="ts">
2
+ /**
3
+ * "Delete field?" for a link field with a field that links back from the
4
+ * other table, or with lookups, rollups and counts that read it: they are
5
+ * all deleted with it, so it says so before it does. Any field that
6
+ * formulas read asks too: they stay, and show #ERROR.
7
+ */
8
+ import { SvModal } from '@svgrid/grid'
9
+ import { linkReaders } from './base-tables'
10
+ import { defId, removeField } from './field-ops'
11
+ import { formulaReaders } from './formula'
12
+ import { getLinkedTable } from './sources.svelte'
13
+
14
+ let { ctrl, columnId, onClose }: { ctrl: any; columnId: string; onClose: () => void } = $props()
15
+
16
+ let open = $state(true)
17
+ // svelte-ignore state_referenced_locally
18
+ const def = (ctrl.internalColumns as Array<Record<string, any>>).find((d) => defId(d) === columnId)
19
+ // svelte-ignore state_referenced_locally
20
+ const name = String(def?.header ?? columnId)
21
+ const table = getLinkedTable(def?.fieldProps?.table)
22
+ const back = table?.fields?.find((f) => f.field === def?.fieldProps?.inverse)?.header
23
+ // Lookups, rollups and counts that read either field: they go with it. The
24
+ // ones here are removed from this grid; a base removes the ones in the
25
+ // other table with the field back.
26
+ // svelte-ignore state_referenced_locally
27
+ const own = def ? linkReaders({ columns: ctrl.internalColumns as Array<Record<string, any>> }, def) : []
28
+ const theirs = def?.fieldProps?.inverse ? (table?.fields ?? []).filter((f) => f.fieldProps?.linkField === def.fieldProps.inverse && ['lookup', 'rollup', 'count'].includes(String(f.fieldType))) : []
29
+ const readers = [...own.map((d) => String(d.header ?? d.field)), ...theirs.map((f) => `${f.header} (${table!.name})`)]
30
+ const isLink = def?.fieldType === 'link'
31
+ // Formulas that read it, or a lookup deleted with it: they stay and show #ERROR.
32
+ // svelte-ignore state_referenced_locally
33
+ const columns = ctrl.internalColumns as Array<Record<string, any>>
34
+ const formulas = def ? [...new Set([def, ...own].flatMap((d) => formulaReaders(columns, d)))].map((d) => String(d.header ?? d.field)) : []
35
+
36
+ function close() {
37
+ open = false
38
+ onClose()
39
+ }
40
+ function remove() {
41
+ for (const d of own) removeField(ctrl, defId(d))
42
+ removeField(ctrl, columnId)
43
+ close()
44
+ }
45
+ </script>
46
+
47
+ <SvModal bind:open title={`Delete ${name}?`} width={440} onClose={close}>
48
+ {#if isLink}
49
+ <p class="sv-fdel-text">
50
+ {name} links to {table?.name ?? 'another table'}.
51
+ {#if back}The field there that links back, <strong>{back}</strong>, is deleted with it.{/if}
52
+ The links between the records go too.
53
+ </p>
54
+ {#if readers.length}
55
+ <p class="sv-fdel-text sv-fdel-note">These fields read it and are deleted too: {readers.join(', ')}.</p>
56
+ {/if}
57
+ {:else}
58
+ <p class="sv-fdel-text">{name} and its values are deleted.</p>
59
+ {/if}
60
+ {#if formulas.length}
61
+ <p class="sv-fdel-text sv-fdel-note sv-fdel-formulas">These formulas read it and will show #ERROR: {formulas.join(', ')}.</p>
62
+ {/if}
63
+ {#snippet footer()}
64
+ <div class="sv-fdel-foot">
65
+ <button type="button" class="sv-fdel-btn" onclick={close}>Cancel</button>
66
+ <button type="button" class="sv-fdel-btn is-danger" onclick={remove}>Delete field</button>
67
+ </div>
68
+ {/snippet}
69
+ </SvModal>
70
+
71
+ <style>
72
+ .sv-fdel-text { margin: 0; font-size: 14px; line-height: 1.5; color: var(--sg-fg, #0f172a); }
73
+ .sv-fdel-note { margin-top: 10px; font-size: 13px; color: var(--sg-muted, #64748b); }
74
+ .sv-fdel-foot { display: flex; justify-content: flex-end; gap: 8px; width: 100%; }
75
+ .sv-fdel-btn {
76
+ height: 32px; padding: 0 14px; font: inherit; font-size: 13px; cursor: pointer; border-radius: var(--sg-radius, 6px);
77
+ background: transparent; color: var(--sg-fg, #0f172a); border: 1px solid var(--sg-border, #e2e8f0);
78
+ }
79
+ .sv-fdel-btn.is-danger { background: var(--sg-danger, #dc2626); border-color: var(--sg-danger, #dc2626); color: #fff; }
80
+ </style>
@@ -0,0 +1,8 @@
1
+ type $$ComponentProps = {
2
+ ctrl: any;
3
+ columnId: string;
4
+ onClose: () => void;
5
+ };
6
+ declare const DeleteFieldConfirm: import("svelte").Component<$$ComponentProps, {}, "">;
7
+ type DeleteFieldConfirm = ReturnType<typeof DeleteFieldConfirm>;
8
+ export default DeleteFieldConfirm;
@@ -0,0 +1,48 @@
1
+ <script lang="ts">
2
+ /**
3
+ * "Delete record?" from a row's or a card's menu, as the selection bar asks
4
+ * before it deletes: the record goes, and its links from other records.
5
+ */
6
+ import { SvModal } from '@svgrid/grid'
7
+ import { primaryIdOf } from './grid-access'
8
+ import { deleteRecord } from './view-model'
9
+
10
+ let { ctrl, api, row, onClose }: { ctrl: any; api: any; row: unknown; onClose: () => void } = $props()
11
+
12
+ let open = $state(true)
13
+ // svelte-ignore state_referenced_locally
14
+ const primary = (ctrl.internalColumns as Array<Record<string, any>>).find((d) => String(d.id ?? d.field) === primaryIdOf(ctrl))
15
+ // svelte-ignore state_referenced_locally
16
+ const name = String((primary?.field ? (row as Record<string, unknown> | null)?.[primary.field] : '') ?? '').trim()
17
+
18
+ function close() {
19
+ open = false
20
+ onClose()
21
+ }
22
+ function remove() {
23
+ deleteRecord(ctrl, api, row)
24
+ close()
25
+ }
26
+ </script>
27
+
28
+ <SvModal bind:open title="Delete record?" width={420} onClose={close}>
29
+ <p class="sv-frdel-text">
30
+ {#if name}<strong>{name}</strong> is deleted{:else}This record is deleted{/if}, and its links from other records go with it.
31
+ </p>
32
+ {#snippet footer()}
33
+ <div class="sv-frdel-foot">
34
+ <button type="button" class="sv-frdel-btn" onclick={close}>Cancel</button>
35
+ <button type="button" class="sv-frdel-btn is-danger" onclick={remove}>Delete record</button>
36
+ </div>
37
+ {/snippet}
38
+ </SvModal>
39
+
40
+ <style>
41
+ .sv-frdel-text { margin: 0; font-size: 14px; line-height: 1.5; color: var(--sg-fg, #0f172a); }
42
+ .sv-frdel-foot { display: flex; justify-content: flex-end; gap: 8px; width: 100%; }
43
+ .sv-frdel-btn {
44
+ height: 32px; padding: 0 14px; font: inherit; font-size: 13px; cursor: pointer; border-radius: var(--sg-radius, 6px);
45
+ background: transparent; color: var(--sg-fg, #0f172a); border: 1px solid var(--sg-border, #e2e8f0);
46
+ }
47
+ .sv-frdel-btn.is-danger { background: var(--sg-danger, #dc2626); border-color: var(--sg-danger, #dc2626); color: #fff; }
48
+ </style>
@@ -0,0 +1,9 @@
1
+ type $$ComponentProps = {
2
+ ctrl: any;
3
+ api: any;
4
+ row: unknown;
5
+ onClose: () => void;
6
+ };
7
+ declare const DeleteRecordConfirm: import("svelte").Component<$$ComponentProps, {}, "">;
8
+ type DeleteRecordConfirm = ReturnType<typeof DeleteRecordConfirm>;
9
+ export default DeleteRecordConfirm;
@@ -0,0 +1,80 @@
1
+ <script lang="ts">
2
+ /**
3
+ * The grid mounts this for every cell of a column with a `fieldType` whose
4
+ * type draws its own cell (registerGridExtension's `cell` + `hasCell`). It
5
+ * hands the cell to that type with the column's merged properties.
6
+ */
7
+ import { fieldPropsOf, getFieldType, type FieldCellProps } from './registry.svelte'
8
+
9
+ let { ctrl, row, column, value }: Omit<FieldCellProps, 'props'> = $props()
10
+ const type = $derived(getFieldType(column.columnDef.fieldType))
11
+ const props = $derived(fieldPropsOf(column.columnDef as { fieldType?: unknown; fieldProps?: Record<string, unknown> }))
12
+ </script>
13
+
14
+ {#if type?.cell}
15
+ <type.cell {ctrl} {row} {column} {value} {props} />
16
+ {:else}
17
+ {value == null ? '' : String(value)}
18
+ {/if}
19
+
20
+ <style>
21
+ /* The view bar's filter (`fieldFilter`) shows on the bar's Filter button. */
22
+ :global(.sv-fields-own-filter .sv-grid-advf-chip) { display: none; }
23
+ :global(.sv-fields-own-filter .sv-grid-toolbar:not(:has(> :not(.sv-grid-advf-chip)))) { display: none; }
24
+ /* rowColor (row-colors.ts): the grid sets --sv-row-mark on each colored row
25
+ and a root class naming the target. Background-image layers, not
26
+ box-shadow: the grid draws the selection outline with box-shadow on
27
+ cells, and layers leave the cell's own background colour underneath. */
28
+ /* The header target is a 3px stripe on the row's leading edge: the color
29
+ says which group a row is in without tinting the row number under it. */
30
+ :global(.sv-fields-rowcolor-header tbody .sv-grid-row-number-cell) {
31
+ background-image: linear-gradient(to right, var(--sv-row-mark, transparent) 3px, transparent 3px);
32
+ }
33
+ :global(.sv-fields-rowcolor-header:dir(rtl) tbody .sv-grid-row-number-cell) {
34
+ background-image: linear-gradient(to left, var(--sv-row-mark, transparent) 3px, transparent 3px);
35
+ }
36
+ :global(.sv-fields-rowcolor-bar tbody tr > td:first-child) {
37
+ background-image: linear-gradient(to right, var(--sv-row-mark, transparent) 3px, transparent 3px);
38
+ }
39
+ :global(.sv-fields-rowcolor-bar:dir(rtl) tbody tr > td:first-child) {
40
+ background-image: linear-gradient(to left, var(--sv-row-mark, transparent) 3px, transparent 3px);
41
+ }
42
+ :global(.sv-fields-rowcolor-row tbody tr > td) {
43
+ background-image: linear-gradient(color-mix(in srgb, var(--sv-row-mark, transparent) 10%, transparent), color-mix(in srgb, var(--sv-row-mark, transparent) 10%, transparent));
44
+ }
45
+
46
+ /* Tall rows (row-colors.ts, tallRowClass): content starts at the top and
47
+ uses the height - text wraps to as many lines as fit, select pills wrap,
48
+ attachment thumbnails grow, a long text keeps its line breaks. */
49
+ :global(.sv-fields-lines-2) { --sv-lines: 2; --sv-thumb: 40px; }
50
+ :global(.sv-fields-lines-3) { --sv-lines: 3; --sv-thumb: 56px; }
51
+ :global(.sv-fields-lines-4) { --sv-lines: 4; --sv-thumb: 72px; }
52
+ :global(.sv-fields-lines-5) { --sv-lines: 5; --sv-thumb: 92px; }
53
+ :global(.sv-fields-lines-6) { --sv-lines: 6; --sv-thumb: 108px; }
54
+ :global(.sv-fields-tall tbody > tr > td.sv-grid-cell) {
55
+ align-items: flex-start;
56
+ padding-block: 6px;
57
+ }
58
+ :global(.sv-fields-tall tbody > tr > td > .sv-grid-cell-line) {
59
+ display: -webkit-box;
60
+ -webkit-box-orient: vertical;
61
+ -webkit-line-clamp: var(--sv-lines, 2);
62
+ line-clamp: var(--sv-lines, 2);
63
+ white-space: normal;
64
+ overflow-wrap: anywhere;
65
+ line-height: 20px;
66
+ }
67
+ :global(.sv-fields-tall .sv-fsl) {
68
+ flex-wrap: wrap;
69
+ align-content: flex-start;
70
+ }
71
+ /* tbody td: one more than the attachment cell's own scoped rule, so this wins. */
72
+ :global(.sv-fields-tall tbody td .sv-att-thumb) {
73
+ width: var(--sv-thumb, 26px);
74
+ height: var(--sv-thumb, 26px);
75
+ }
76
+ :global(.sv-fields-tall .sv-frx-sep) {
77
+ display: block;
78
+ height: 0;
79
+ }
80
+ </style>
@@ -0,0 +1,9 @@
1
+ /**
2
+ * The grid mounts this for every cell of a column with a `fieldType` whose
3
+ * type draws its own cell (registerGridExtension's `cell` + `hasCell`). It
4
+ * hands the cell to that type with the column's merged properties.
5
+ */
6
+ import { type FieldCellProps } from './registry.svelte.js';
7
+ declare const FieldCell: import("svelte").Component<Omit<FieldCellProps, "props">, {}, "">;
8
+ type FieldCell = ReturnType<typeof FieldCell>;
9
+ export default FieldCell;
@@ -0,0 +1,321 @@
1
+ <script lang="ts">
2
+ /**
3
+ * The field editor: name, type, the type's properties, a description. Adds
4
+ * a field (column adder, Insert left / right) or edits one (Edit field). On a
5
+ * type change it says how many cells would be cleared before applying.
6
+ */
7
+ import { SvModal } from '@svgrid/grid'
8
+ import PropertyInput from './PropertyInput.svelte'
9
+ import { listFieldTypes, getFieldType, originalColumn, type FieldEditorContext } from './registry.svelte'
10
+ import { addField, defId, nameTaken, plainDef, previewChange, updateField } from './field-ops'
11
+ import { columnResolver, formulaError } from './formula'
12
+
13
+ let {
14
+ ctrl,
15
+ mode,
16
+ columnId,
17
+ index = 'end',
18
+ onClose,
19
+ }: {
20
+ ctrl: any
21
+ mode: 'add' | 'edit'
22
+ columnId?: string
23
+ index?: number | 'end'
24
+ onClose: () => void
25
+ } = $props()
26
+
27
+ // svelte-ignore state_referenced_locally
28
+ const existing = mode === 'edit' && columnId ? ctrl.internalColumns.find((d: any) => defId(d) === columnId) : null
29
+ // svelte-ignore state_referenced_locally
30
+ const plain = existing ? plainDef(existing) : null
31
+
32
+ const allowed = $derived.by(() => {
33
+ const cfg = ctrl.props.columnAdder
34
+ const ids = cfg && typeof cfg === 'object' && Array.isArray(cfg.types) ? (cfg.types as string[]) : null
35
+ const types = listFieldTypes()
36
+ return ids ? ids.map((id) => types.find((t) => t.id === id)).filter((t) => !!t) : types.filter((t) => !t.editAs)
37
+ })
38
+
39
+ // A currency or percent column opens as a number field in that format.
40
+ // svelte-ignore state_referenced_locally
41
+ const alias = getFieldType(plain?.fieldType)?.editAs
42
+ let name = $state(String(plain?.header ?? ''))
43
+ let fieldType = $state(alias?.type ?? String(plain?.fieldType ?? 'text'))
44
+ let props = $state<Record<string, any>>({ ...((plain?.fieldProps as Record<string, unknown>) ?? {}), ...(alias?.props ?? {}) })
45
+ let description = $state(String(plain?.description ?? ''))
46
+ let search = $state('')
47
+ // The type list is open while choosing (a new field starts there) and folds
48
+ // into a selector once a type is picked, so its options sit near the top.
49
+ // svelte-ignore state_referenced_locally
50
+ let pickerOpen = $state(mode === 'add')
51
+ let open = $state(true)
52
+
53
+ const type = $derived(getFieldType(fieldType))
54
+ const shownTypes = $derived(allowed.filter((t) => !search || t.label.toLowerCase().includes(search.toLowerCase())))
55
+ // A field left unnamed is named after its type, numbered when taken
56
+ // ("Number", "Number 2"); an edited field keeps needing a name.
57
+ const fallbackName = $derived.by(() => {
58
+ const base = type?.label ?? 'Field'
59
+ let n = base
60
+ for (let i = 2; nameTaken(ctrl, n, columnId); i++) n = `${base} ${i}`
61
+ return n
62
+ })
63
+ const finalName = $derived(name.trim() || (mode === 'add' ? fallbackName : ''))
64
+ const nameError = $derived(!finalName ? 'A field needs a name' : nameTaken(ctrl, finalName, columnId) ? 'Another field has this name' : null)
65
+ const cleared = $derived(mode === 'edit' && columnId ? previewChange(ctrl, columnId, { name, fieldType, fieldProps: props }) : 0)
66
+ // The stored type: what updateField converts from on save, alias or not.
67
+ const fromType = plain?.fieldType ? String(plain.fieldType) : undefined
68
+ // An alias opened as its target (Currency as Number) converts on save too;
69
+ // say so only when that clears cells, or the type was changed on purpose.
70
+ const warn = $derived(mode === 'edit' && !!fromType && fromType !== fieldType && (fieldType !== alias?.type || cleared > 0))
71
+
72
+ // Event readers live here, not in the markup: AGENTS.md keeps `as` casts in <script>.
73
+ const inputValue = (e: Event) => (e.currentTarget as HTMLInputElement).value
74
+
75
+ function pickType(id: string) {
76
+ if (id === fieldType) return
77
+ fieldType = id
78
+ pickerOpen = false
79
+ search = ''
80
+ // Keep only the properties the new type has, starting from its defaults.
81
+ const next = getFieldType(id)
82
+ const keep: Record<string, any> = { ...(next?.defaults ?? {}) }
83
+ for (const p of next?.properties ?? []) if (props[p.key] !== undefined) keep[p.key] = props[p.key]
84
+ props = keep
85
+ }
86
+
87
+ // What a property's dynamic choices and the formula see: the draft and every other field.
88
+ const editorCtx = $derived<FieldEditorContext>({
89
+ ctrl,
90
+ props: { ...(type?.defaults ?? {}), ...props },
91
+ columns: (ctrl.internalColumns as Array<Record<string, any>>).map((c) => originalColumn(c)).filter((c) => defId(c) !== columnId),
92
+ // A formula may not read its own field, by any of its names.
93
+ self: [plain?.field, columnId, plain?.header, finalName],
94
+ })
95
+ const shownProps = $derived((type?.properties ?? []).filter((p) => !p.visible || p.visible(editorCtx.props)))
96
+ // A formula that does not compile cannot be saved; the box shows why. An
97
+ // empty one can: its cells stay empty until it is written.
98
+ const formulaProblem = $derived.by(() => {
99
+ for (const p of shownProps) {
100
+ if (p.kind !== 'formula') continue
101
+ const src = String(editorCtx.props[p.key] ?? '')
102
+ const message = src.trim() ? formulaError(src, columnResolver(editorCtx.columns, editorCtx.self)) : null
103
+ if (message) return message
104
+ }
105
+ return null
106
+ })
107
+ // Every group a type may name; an empty one is not drawn.
108
+ const GROUPS = [
109
+ { id: 'basic', label: 'Fields' },
110
+ { id: 'number', label: 'Numbers and time' },
111
+ { id: 'date', label: 'Dates' },
112
+ { id: 'people', label: 'People' },
113
+ { id: 'computed', label: 'Computed and automatic' },
114
+ { id: 'relation', label: 'Other tables' },
115
+ ] as const
116
+ // A group the list does not know (a typo in a registered type) shows under Fields.
117
+ const groupOf = (t: { group?: string }) => (GROUPS.some((g) => g.id === t.group) ? t.group : 'basic')
118
+ const grouped = $derived(
119
+ GROUPS.map((g) => ({ ...g, types: shownTypes.filter((t) => groupOf(t) === g.id) })).filter((g) => g.types.length),
120
+ )
121
+
122
+ function save() {
123
+ if (nameError || formulaProblem) return
124
+ const draft = { name: finalName, fieldType, fieldProps: $state.snapshot(props), description }
125
+ if (mode === 'edit' && columnId) updateField(ctrl, columnId, draft)
126
+ else addField(ctrl, draft, index)
127
+ close()
128
+ }
129
+
130
+ function close() {
131
+ open = false
132
+ onClose()
133
+ }
134
+ </script>
135
+
136
+ <SvModal bind:open title={mode === 'edit' ? 'Edit field' : 'Add field'} width={500} onClose={close}>
137
+ <form class="sv-fed" onsubmit={(e) => { e.preventDefault(); save() }}>
138
+ <div class="sv-fed-group">
139
+ <label class="sv-fed-label" for="sv-fed-name">Name</label>
140
+ <!-- svelte-ignore a11y_autofocus -->
141
+ <input
142
+ id="sv-fed-name"
143
+ class="sv-fed-input"
144
+ placeholder={mode === 'add' ? fallbackName : 'Field name'}
145
+ bind:value={name}
146
+ autofocus
147
+ autocomplete="off"
148
+ aria-invalid={!!nameError && name.length > 0}
149
+ aria-describedby="sv-fed-name-error"
150
+ />
151
+ {#if nameError && name.length > 0}<p id="sv-fed-name-error" class="sv-fed-error">{nameError}</p>{/if}
152
+ </div>
153
+
154
+ <div class="sv-fed-group">
155
+ <span class="sv-fed-label" id="sv-fed-type-label">Field type</span>
156
+ {#if !pickerOpen}
157
+ <button type="button" class="sv-fed-current" aria-expanded="false" aria-labelledby="sv-fed-type-label" onclick={() => (pickerOpen = true)}>
158
+ <span class="sv-fed-type-icon" aria-hidden="true">
159
+ {#if type?.icon}<svg viewBox="0 0 24 24" width="14" height="14"><path d={type.icon} fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round" /></svg>{/if}
160
+ </span>
161
+ <span class="sv-fed-type-label">{type?.label ?? fieldType}</span>
162
+ <svg class="sv-fed-chevron" viewBox="0 0 24 24" width="14" height="14" aria-hidden="true"><path d="M6 9l6 6 6-6" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" /></svg>
163
+ </button>
164
+ {:else}
165
+ {#if allowed.length > 8}
166
+ <div class="sv-fed-search">
167
+ <svg viewBox="0 0 24 24" width="14" height="14" aria-hidden="true"><path d="M11 4a7 7 0 1 0 0 14 7 7 0 0 0 0-14zM20 20l-4-4" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" /></svg>
168
+ <input class="sv-fed-input" placeholder="Find a type" aria-label="Find a field type" bind:value={search} />
169
+ </div>
170
+ {/if}
171
+ <div class="sv-fed-types-scroll" role="radiogroup" aria-labelledby="sv-fed-type-label">
172
+ {#each grouped as g (g.id)}
173
+ <div class="sv-fed-type-group">{g.label}</div>
174
+ <div class="sv-fed-types">
175
+ {#each g.types as t (t.id)}
176
+ <button
177
+ type="button"
178
+ class="sv-fed-type"
179
+ class:is-on={t.id === fieldType}
180
+ role="radio"
181
+ aria-checked={t.id === fieldType}
182
+ onclick={() => pickType(t.id)}
183
+ >
184
+ <span class="sv-fed-type-icon" aria-hidden="true">
185
+ {#if t.icon}
186
+ <svg viewBox="0 0 24 24" width="14" height="14"><path d={t.icon} fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round" /></svg>
187
+ {/if}
188
+ </span>
189
+ <span class="sv-fed-type-label">{t.label}</span>
190
+ </button>
191
+ {/each}
192
+ </div>
193
+ {:else}
194
+ <p class="sv-fed-none">No type matches "{search}".</p>
195
+ {/each}
196
+ </div>
197
+ {/if}
198
+ {#if type?.description}<p class="sv-fed-hint-line">{type.description}</p>{/if}
199
+ </div>
200
+
201
+ {#if shownProps.length}
202
+ <div class="sv-fed-group sv-fed-props">
203
+ {#each shownProps as p (p.key)}
204
+ <PropertyInput
205
+ def={p}
206
+ value={props[p.key] ?? type?.defaults?.[p.key]}
207
+ {fieldType}
208
+ ctx={editorCtx}
209
+ onChange={(v) => (props = { ...props, [p.key]: v, ...(p.alsoSets?.(v, editorCtx.props) ?? {}) })}
210
+ />
211
+ {/each}
212
+ </div>
213
+ {/if}
214
+
215
+ <div class="sv-fed-group">
216
+ <label class="sv-fed-label" for="sv-fed-desc">Description <span class="sv-fed-optional">optional</span></label>
217
+ <textarea id="sv-fed-desc" class="sv-fed-input sv-fed-desc" rows="2" placeholder="What goes in this field" bind:value={description}></textarea>
218
+ </div>
219
+
220
+ {#if warn && fromType}
221
+ <p class="sv-fed-warning" role="status">
222
+ <svg viewBox="0 0 24 24" width="15" height="15" aria-hidden="true"><path d="M12 4 2.5 20h19zM12 10v4M12 17h.01" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" /></svg>
223
+ <span>
224
+ {getFieldType(fromType)?.label ?? fromType} to {type?.label ?? fieldType} converts the values.
225
+ {cleared === 0 ? 'Every value converts.' : `${cleared} cell${cleared === 1 ? '' : 's'} will be cleared or cut short.`}
226
+ </span>
227
+ </p>
228
+ {/if}
229
+ </form>
230
+ {#snippet footer()}
231
+ <div class="sv-fed-footer">
232
+ <button type="button" class="sv-fed-btn" onclick={close}>Cancel</button>
233
+ <button type="button" class="sv-fed-btn is-primary" disabled={!!nameError || !!formulaProblem} title={formulaProblem ? `Fix the formula first: ${formulaProblem}` : undefined} onclick={save}>
234
+ {mode === 'edit' ? 'Save' : 'Create field'}
235
+ </button>
236
+ </div>
237
+ {/snippet}
238
+ </SvModal>
239
+
240
+ <style>
241
+ /* Only tokens every theme defines (bg, fg, border, muted, header-bg,
242
+ row-hover-bg, input-bg, input-border, accent, selection-bg, radius): the
243
+ dialog renders under <body>, outside the grid, and a missing token falls
244
+ back to its light default even in a dark theme. */
245
+ .sv-fed { display: flex; flex-direction: column; gap: 18px; }
246
+ .sv-fed-group { display: flex; flex-direction: column; gap: 6px; }
247
+ .sv-fed-props {
248
+ gap: 10px; padding: 12px; border-radius: var(--sg-radius, 6px);
249
+ background: var(--sg-header-bg, #f8fafc); border: 1px solid var(--sg-border, #e2e8f0);
250
+ }
251
+ .sv-fed-label { font-size: 12px; font-weight: 600; color: var(--sg-fg, #0f172a); }
252
+ .sv-fed-optional { font-weight: 400; color: var(--sg-muted, #64748b); }
253
+ .sv-fed-input {
254
+ width: 100%; box-sizing: border-box; height: 34px; padding: 0 10px; font: inherit; font-size: 14px;
255
+ border: 1px solid var(--sg-input-border, var(--sg-border, #e2e8f0)); border-radius: var(--sg-radius, 6px);
256
+ background: var(--sg-input-bg, var(--sg-bg, #fff)); color: var(--sg-fg, #0f172a);
257
+ transition: border-color 120ms ease, box-shadow 120ms ease;
258
+ }
259
+ .sv-fed-input::placeholder { color: var(--sg-muted, #94a3b8); }
260
+ .sv-fed-input:focus { outline: none; border-color: var(--sg-accent, #2563eb); box-shadow: 0 0 0 3px color-mix(in srgb, var(--sg-accent, #2563eb) 22%, transparent); }
261
+ .sv-fed-input[aria-invalid='true'] { border-color: var(--sg-danger, #dc2626); }
262
+ .sv-fed-desc { height: auto; min-height: 58px; padding: 8px 10px; resize: vertical; line-height: 1.4; }
263
+ .sv-fed-error { margin: 0; font-size: 12px; color: var(--sg-danger, #dc2626); }
264
+ .sv-fed-search { position: relative; display: flex; align-items: center; color: var(--sg-muted, #64748b); }
265
+ .sv-fed-search svg { position: absolute; inset-inline-start: 10px; pointer-events: none; }
266
+ .sv-fed-search .sv-fed-input { height: 30px; padding-inline-start: 30px; font-size: 13px; }
267
+ .sv-fed-current {
268
+ display: flex; align-items: center; gap: 10px; width: 100%; height: 38px; padding: 0 10px;
269
+ border: 1px solid var(--sg-input-border, var(--sg-border, #e2e8f0)); border-radius: var(--sg-radius, 6px);
270
+ background: var(--sg-input-bg, var(--sg-bg, #fff)); color: var(--sg-fg, #0f172a); font: inherit; font-size: 14px; text-align: start; cursor: pointer;
271
+ }
272
+ .sv-fed-current:hover { border-color: var(--sg-muted, #94a3b8); }
273
+ .sv-fed-current:focus-visible { outline: none; border-color: var(--sg-accent, #2563eb); box-shadow: 0 0 0 3px color-mix(in srgb, var(--sg-accent, #2563eb) 22%, transparent); }
274
+ .sv-fed-current .sv-fed-type-label { flex: 1; }
275
+ .sv-fed-chevron { flex: none; color: var(--sg-muted, #64748b); }
276
+ .sv-fed-types-scroll { max-height: 300px; overflow: auto; margin-top: 2px; padding-inline-end: 2px; }
277
+ .sv-fed-types { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 2px; }
278
+ .sv-fed-type-group {
279
+ margin: 10px 0 4px; font-size: 11px; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase;
280
+ color: var(--sg-muted, #64748b);
281
+ }
282
+ .sv-fed-type-group:first-child { margin-top: 2px; }
283
+ .sv-fed-type {
284
+ display: flex; align-items: center; gap: 10px; height: 34px; padding: 0 8px;
285
+ border: 1px solid transparent; border-radius: var(--sg-radius, 6px); background: none;
286
+ color: var(--sg-fg, #0f172a); font: inherit; font-size: 13px; text-align: start; cursor: pointer;
287
+ }
288
+ .sv-fed-type:hover { background: var(--sg-row-hover-bg, #f1f5f9); }
289
+ .sv-fed-type.is-on { background: var(--sg-selection-bg, #eef4ff); border-color: var(--sg-accent, #2563eb); }
290
+ .sv-fed-type:focus-visible { outline: 2px solid var(--sg-accent, #2563eb); outline-offset: 1px; }
291
+ .sv-fed-type-icon {
292
+ flex: none; display: inline-flex; align-items: center; justify-content: center;
293
+ width: 24px; height: 24px; border-radius: 6px;
294
+ background: var(--sg-header-bg, #f8fafc); border: 1px solid var(--sg-border, #e2e8f0);
295
+ color: var(--sg-muted, #64748b);
296
+ }
297
+ .sv-fed-type.is-on .sv-fed-type-icon { color: var(--sg-accent, #2563eb); border-color: color-mix(in srgb, var(--sg-accent, #2563eb) 40%, transparent); }
298
+ .sv-fed-type-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
299
+ .sv-fed-none { grid-column: 1 / -1; margin: 8px 0; font-size: 13px; color: var(--sg-muted, #64748b); }
300
+ .sv-fed-hint-line { margin: 2px 0 0; font-size: 12px; color: var(--sg-muted, #64748b); }
301
+ .sv-fed-warning {
302
+ display: flex; gap: 8px; align-items: flex-start; margin: 0; padding: 10px 12px;
303
+ border-radius: var(--sg-radius, 6px); font-size: 13px; line-height: 1.4; color: var(--sg-fg, #0f172a);
304
+ background: color-mix(in srgb, var(--sg-warning, #f59e0b) 14%, transparent);
305
+ border: 1px solid color-mix(in srgb, var(--sg-warning, #f59e0b) 35%, transparent);
306
+ }
307
+ .sv-fed-warning svg { flex: none; margin-top: 1px; color: var(--sg-warning, #d97706); }
308
+ .sv-fed-footer { display: flex; justify-content: flex-end; gap: 8px; width: 100%; }
309
+ .sv-fed-btn {
310
+ height: 34px; padding: 0 16px; font: inherit; font-size: 13px; font-weight: 500; cursor: pointer;
311
+ border: 1px solid var(--sg-border, #e2e8f0); border-radius: var(--sg-radius, 6px);
312
+ background: var(--sg-bg, #fff); color: var(--sg-fg, #0f172a);
313
+ }
314
+ .sv-fed-btn:hover { background: var(--sg-row-hover-bg, #f1f5f9); }
315
+ .sv-fed-btn:focus-visible { outline: 2px solid var(--sg-accent, #2563eb); outline-offset: 2px; }
316
+ /* Primary is the inverted pair (fg on bg), not the accent: on Ember the
317
+ accent means selection and focus. */
318
+ .sv-fed-btn.is-primary { background: var(--sg-fg, #0f172a); color: var(--sg-bg, #fff); border-color: var(--sg-fg, #0f172a); }
319
+ .sv-fed-btn.is-primary:hover { opacity: 0.9; }
320
+ .sv-fed-btn:disabled { opacity: 0.4; cursor: not-allowed; }
321
+ </style>
@@ -0,0 +1,10 @@
1
+ type $$ComponentProps = {
2
+ ctrl: any;
3
+ mode: 'add' | 'edit';
4
+ columnId?: string;
5
+ index?: number | 'end';
6
+ onClose: () => void;
7
+ };
8
+ declare const FieldEditor: import("svelte").Component<$$ComponentProps, {}, "">;
9
+ type FieldEditor = ReturnType<typeof FieldEditor>;
10
+ export default FieldEditor;