@svgrid/enterprise 3.1.8 → 3.1.9

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-Obk8sI77.js → index-BPU2KNc5.js} +307 -307
  34. package/dist/designer/assets/index-BmvG99kR.css +1 -0
  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,172 @@
1
+ <script lang="ts">
2
+ /**
3
+ * The link field's editor (registered as 'fieldLink'): the linked table's
4
+ * rows in a dialog with a search box over the primary field and the
5
+ * table's text fields; tick the ones to link (one when the
6
+ * field allows a single record). Done commits the ids, Cancel leaves the
7
+ * cell as it was. When the table can add records (`create`), a search that
8
+ * names no record offers "+ Create" for it, picked at once.
9
+ */
10
+ import { SvModal } from '@svgrid/grid'
11
+ import { fieldPropsOf } from './registry.svelte'
12
+ import { getLinkedTable, idOf, rowsOf } from './sources.svelte'
13
+
14
+ let {
15
+ value,
16
+ columnDef,
17
+ onCommit,
18
+ onCancel,
19
+ }: { value: unknown; columnDef?: Record<string, unknown>; onCommit: (v?: unknown) => void; onCancel: () => void } = $props()
20
+
21
+ const props = $derived(fieldPropsOf((columnDef ?? {}) as { fieldType?: unknown; fieldProps?: Record<string, unknown> }) as { table?: string; multiple?: boolean })
22
+ const table = $derived(getLinkedTable(props.table))
23
+ const multiple = $derived(props.multiple !== false)
24
+ // svelte-ignore state_referenced_locally
25
+ let picked = $state<string[]>(Array.isArray(value) ? value.map(String) : value == null || value === '' ? [] : [String(value)])
26
+ let search = $state('')
27
+ let open = $state(true)
28
+ let finished = false
29
+
30
+ // The list draws this many rows at most; the footer of the list says how many matched.
31
+ const LIMIT = 200
32
+ const TEXT_TYPES = new Set(['text', 'longText', 'email', 'url', 'phone', 'singleSelect', 'multiSelect'])
33
+ const rows = $derived(table ? rowsOf(table) : [])
34
+ // Besides the primary field, search reads the table's text fields (every
35
+ // text value of the record when the table declares no fields).
36
+ const others = $derived(
37
+ table?.fields?.length
38
+ ? table.fields.filter((f) => f.field !== table.primaryField && (!f.fieldType || TEXT_TYPES.has(f.fieldType))).map((f) => ({ field: f.field, header: f.header }))
39
+ : null,
40
+ )
41
+ const textOf = (v: unknown): string => (typeof v === 'string' ? v : Array.isArray(v) ? v.filter((x) => typeof x === 'string').join(', ') : '')
42
+ /** Where `q` is found in a record other than its primary field, as "Email: maya@...". */
43
+ function hintFor(r: Record<string, unknown>, q: string): string | null {
44
+ const fields = others ?? Object.keys(r).filter((k) => k !== 'id' && k !== table!.primaryField).map((k) => ({ field: k, header: k }))
45
+ for (const f of fields) {
46
+ const text = textOf(r[f.field])
47
+ if (text && text.toLowerCase().includes(q)) return `${f.header}: ${text}`
48
+ }
49
+ return null
50
+ }
51
+ const found = $derived.by(() => {
52
+ const q = search.trim().toLowerCase()
53
+ const out: Array<{ id: string; label: string; hint: string | null }> = []
54
+ let total = 0
55
+ let exact = false
56
+ for (const r of rows) {
57
+ const label = String(r[table!.primaryField] ?? '')
58
+ let hint: string | null = null
59
+ if (q && !label.toLowerCase().includes(q)) {
60
+ hint = hintFor(r, q)
61
+ if (hint == null) continue
62
+ }
63
+ if (q && label.toLowerCase() === q) exact = true
64
+ total += 1
65
+ if (out.length < LIMIT) out.push({ id: idOf(table!, r), label, hint })
66
+ }
67
+ return { rows: out, total, exact }
68
+ })
69
+ const shown = $derived(found.rows)
70
+
71
+ const term = $derived(search.trim())
72
+ const canCreate = $derived(!!table?.create && !!term && !found.exact)
73
+ let creating = $state(false)
74
+ async function create() {
75
+ if (!table?.create || creating) return
76
+ creating = true
77
+ try {
78
+ const row = await table.create(term)
79
+ const id = idOf(table, row)
80
+ picked = multiple ? [...picked.filter((x) => x !== id), id] : [id]
81
+ search = ''
82
+ } finally {
83
+ creating = false
84
+ }
85
+ }
86
+
87
+ function toggle(id: string) {
88
+ if (!multiple) picked = picked[0] === id ? [] : [id]
89
+ else picked = picked.includes(id) ? picked.filter((x) => x !== id) : [...picked, id]
90
+ }
91
+ function done() {
92
+ finished = true
93
+ open = false
94
+ onCommit([...picked])
95
+ }
96
+ function cancel() {
97
+ if (finished) return
98
+ finished = true
99
+ open = false
100
+ onCancel()
101
+ }
102
+ const inputValue = (e: Event) => (e.currentTarget as HTMLInputElement).value
103
+ </script>
104
+
105
+ <SvModal bind:open title={table ? `Link to ${table.name}` : 'Link to records'} width={460} onClose={cancel}>
106
+ {#if !table}
107
+ <p class="sv-flp-empty">The table this field links to is not available.</p>
108
+ {:else}
109
+ <input class="sv-flp-search" placeholder={`Search ${table.name}`} aria-label={`Search ${table.name}`} value={search} oninput={(e) => (search = inputValue(e))} />
110
+ <ul class="sv-flp-list" role="listbox" aria-multiselectable={multiple}>
111
+ {#each shown as r (r.id)}
112
+ <li>
113
+ <button type="button" class="sv-flp-row" class:is-on={picked.includes(r.id)} role="option" aria-selected={picked.includes(r.id)} onclick={() => toggle(r.id)}>
114
+ <span class="sv-flp-mark" aria-hidden="true">{picked.includes(r.id) ? '✓' : ''}</span>
115
+ <span class="sv-flp-label">{r.label || 'Unnamed'}</span>
116
+ {#if r.hint}<span class="sv-flp-hint">{r.hint}</span>{/if}
117
+ </button>
118
+ </li>
119
+ {:else}
120
+ {#if !canCreate}<li class="sv-flp-empty">No records match.</li>{/if}
121
+ {/each}
122
+ {#if canCreate}
123
+ <li>
124
+ <button type="button" class="sv-flp-row sv-flp-create" disabled={creating} onclick={create}>
125
+ <span class="sv-flp-mark" aria-hidden="true">+</span>
126
+ <span class="sv-flp-label">Create “{term}”</span>
127
+ </button>
128
+ </li>
129
+ {/if}
130
+ </ul>
131
+ {#if found.total > shown.length}
132
+ <p class="sv-flp-more" role="status">Showing {shown.length.toLocaleString()} of {found.total.toLocaleString()}. Type to narrow.</p>
133
+ {/if}
134
+ {/if}
135
+ {#snippet footer()}
136
+ <div class="sv-flp-footer">
137
+ <span class="sv-flp-count">{picked.length} linked</span>
138
+ <button type="button" class="sv-flp-btn" onclick={cancel}>Cancel</button>
139
+ <button type="button" class="sv-flp-btn is-primary" onclick={done}>Done</button>
140
+ </div>
141
+ {/snippet}
142
+ </SvModal>
143
+
144
+ <style>
145
+ .sv-flp-search {
146
+ width: 100%; box-sizing: border-box; height: 34px; padding: 0 10px; font: inherit; font-size: 14px;
147
+ border: 1px solid var(--sg-input-border, var(--sg-border, #e2e8f0)); border-radius: var(--sg-radius, 6px);
148
+ background: var(--sg-input-bg, var(--sg-bg, #fff)); color: var(--sg-fg, #0f172a);
149
+ }
150
+ .sv-flp-search:focus { outline: none; border-color: var(--sg-accent, #2563eb); }
151
+ .sv-flp-list { list-style: none; margin: 10px 0 0; padding: 0; max-height: 320px; overflow: auto; }
152
+ .sv-flp-row {
153
+ display: flex; align-items: center; gap: 8px; width: 100%; height: 34px; padding: 0 8px; border: 0;
154
+ border-radius: var(--sg-radius, 6px); background: none; color: var(--sg-fg, #0f172a); font: inherit; font-size: 14px; text-align: start; cursor: pointer;
155
+ }
156
+ .sv-flp-row:hover { background: var(--sg-row-hover-bg, #f1f5f9); }
157
+ .sv-flp-row.is-on { background: var(--sg-selection-bg, #eef4ff); }
158
+ .sv-flp-create { color: var(--sg-accent, #2563eb); }
159
+ .sv-flp-mark { width: 16px; color: var(--sg-accent, #2563eb); font-weight: 700; }
160
+ .sv-flp-label { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
161
+ .sv-flp-hint { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; color: var(--sg-muted, #64748b); }
162
+ .sv-flp-more { margin: 8px 0 0; padding: 0 8px; font-size: 12px; color: var(--sg-muted, #64748b); }
163
+ .sv-flp-empty { padding: 12px 8px; color: var(--sg-muted, #64748b); font-size: 13px; }
164
+ .sv-flp-footer { display: flex; align-items: center; gap: 8px; width: 100%; }
165
+ .sv-flp-count { flex: 1; font-size: 13px; color: var(--sg-muted, #64748b); }
166
+ .sv-flp-btn {
167
+ height: 34px; padding: 0 16px; font: inherit; font-size: 13px; cursor: pointer;
168
+ border: 1px solid var(--sg-border, #e2e8f0); border-radius: var(--sg-radius, 6px);
169
+ background: var(--sg-bg, #fff); color: var(--sg-fg, #0f172a);
170
+ }
171
+ .sv-flp-btn.is-primary { background: var(--sg-fg, #0f172a); color: var(--sg-bg, #fff); border-color: var(--sg-fg, #0f172a); }
172
+ </style>
@@ -0,0 +1,9 @@
1
+ type $$ComponentProps = {
2
+ value: unknown;
3
+ columnDef?: Record<string, unknown>;
4
+ onCommit: (v?: unknown) => void;
5
+ onCancel: () => void;
6
+ };
7
+ declare const LinkPickerEditor: import("svelte").Component<$$ComponentProps, {}, "">;
8
+ type LinkPickerEditor = ReturnType<typeof LinkPickerEditor>;
9
+ export default LinkPickerEditor;
@@ -0,0 +1,60 @@
1
+ <script lang="ts">
2
+ /**
3
+ * The card a linked record shows while the pointer rests on its chip: the
4
+ * record's name, its table and its first few fields. One per grid; the chip
5
+ * says where it is (showLinkPreview).
6
+ */
7
+ import { portalToBody } from '@svgrid/grid'
8
+ import { showLinkPreview, type LinkPreviewRequest } from './editor-request.svelte'
9
+ import { getLinkedTable } from './sources.svelte'
10
+ import { linkedFields, linkedRow, linkedText, linkedValue } from './linked-fields'
11
+
12
+ let { request }: { request: LinkPreviewRequest } = $props()
13
+
14
+ const MAX_FIELDS = 4
15
+ const table = $derived(getLinkedTable(request.table))
16
+ const row = $derived(table ? linkedRow(table, request.rowId) : undefined)
17
+ // The first four fields that have a value: an empty one does not use up a place.
18
+ const fields = $derived.by(() => {
19
+ if (!table || !row) return []
20
+ const out: Array<{ id: string; header: string; text: string }> = []
21
+ for (const f of linkedFields(table, row)) {
22
+ if (f.id === table.primaryField) continue
23
+ const text = linkedText(f, linkedValue(f, row), row)
24
+ if (text) out.push({ id: f.id, header: f.header, text })
25
+ if (out.length === MAX_FIELDS) break
26
+ }
27
+ return out
28
+ })
29
+ // Below the chip, kept inside the window.
30
+ const left = $derived(Math.max(8, Math.min(request.x, (typeof window !== 'undefined' ? window.innerWidth : 1200) - 268)))
31
+ </script>
32
+
33
+ {#if table && row}
34
+ <div
35
+ class="sv-flpv"
36
+ use:portalToBody
37
+ style:left={`${left}px`}
38
+ style:top={`${request.y + 6}px`}
39
+ role="tooltip"
40
+ onpointerleave={() => showLinkPreview(null)}
41
+ >
42
+ <div class="sv-flpv-title">{String(row[table.primaryField] ?? '') || 'Unnamed'}</div>
43
+ <div class="sv-flpv-table">{table.name}</div>
44
+ {#each fields as f (f.id)}
45
+ <div class="sv-flpv-field"><span class="sv-flpv-label">{f.header}</span>{f.text}</div>
46
+ {/each}
47
+ </div>
48
+ {/if}
49
+
50
+ <style>
51
+ .sv-flpv {
52
+ position: fixed; z-index: 2147483645; width: 260px; box-sizing: border-box; padding: 10px 12px;
53
+ background: var(--sg-bg, #fff); color: var(--sg-fg, #0f172a); font-size: 12px; line-height: 1.5;
54
+ border: 1px solid var(--sg-border, #e2e8f0); border-radius: 10px; box-shadow: 0 12px 32px -12px rgba(15, 23, 42, 0.4);
55
+ }
56
+ .sv-flpv-title { font-size: 14px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
57
+ .sv-flpv-table { color: var(--sg-muted, #64748b); margin-bottom: 6px; }
58
+ .sv-flpv-field { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
59
+ .sv-flpv-label { color: var(--sg-muted, #64748b); margin-inline-end: 6px; }
60
+ </style>
@@ -0,0 +1,7 @@
1
+ import { type LinkPreviewRequest } from './editor-request.svelte.js';
2
+ type $$ComponentProps = {
3
+ request: LinkPreviewRequest;
4
+ };
5
+ declare const LinkPreview: import("svelte").Component<$$ComponentProps, {}, "">;
6
+ type LinkPreview = ReturnType<typeof LinkPreview>;
7
+ export default LinkPreview;
@@ -0,0 +1,94 @@
1
+ <script lang="ts">
2
+ /**
3
+ * A record of a linked table, opened from a link chip: its fields with
4
+ * their names and values, drawn as their cells draw them. The table belongs
5
+ * to the app, so the record is read here, not edited; a table that can show
6
+ * its records (another tab of a base, `open`) offers "Open in {table}".
7
+ */
8
+ import { SvModal } from '@svgrid/grid'
9
+ import FieldCell from './FieldCell.svelte'
10
+ import { getLinkedTable } from './sources.svelte'
11
+ import { closeAllLinkedRecords } from './editor-request.svelte'
12
+ import { linkedFields, linkedRow, linkedText, linkedValue } from './linked-fields'
13
+ import { getFieldType, typeDrawsCell } from './registry.svelte'
14
+
15
+ let { ctrl, table: tableId, rowId, onClose }: { ctrl: any; table: string; rowId: string; onClose: () => void } = $props()
16
+
17
+ let open = $state(true)
18
+ const table = $derived(getLinkedTable(tableId))
19
+ const row = $derived(table ? linkedRow(table, rowId) : undefined)
20
+ const fields = $derived(table ? linkedFields(table, row) : [])
21
+ const title = $derived(table && row ? String(row[table.primaryField] ?? '') || 'Unnamed' : 'Record')
22
+ const draws = (def: Record<string, any>) => !!def.fieldType && def.cell == null && typeDrawsCell(def)
23
+ /** Show the record in its own table, and close every linked record over this grid. */
24
+ function openWhere() {
25
+ const go = table?.open
26
+ open = false
27
+ closeAllLinkedRecords()
28
+ go?.(rowId)
29
+ }
30
+ </script>
31
+
32
+ <SvModal bind:open {title} width={520} {onClose}>
33
+ {#if !table || !row}
34
+ <p class="sv-flrv-gone">This record is not in its table any more.</p>
35
+ {:else}
36
+ <p class="sv-flrv-table">{table.name}</p>
37
+ <div class="sv-flrv-fields">
38
+ {#each fields as f (f.id)}
39
+ {@const v = linkedValue(f, row)}
40
+ <div class="sv-flrv-field">
41
+ <div class="sv-flrv-label">
42
+ {#if f.def.fieldType && getFieldType(f.def.fieldType)?.icon}
43
+ <svg viewBox="0 0 24 24" width="14" height="14" aria-hidden="true"><path d={getFieldType(f.def.fieldType)?.icon} fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round" /></svg>
44
+ {/if}
45
+ {f.header}
46
+ </div>
47
+ <div class="sv-flrv-value">
48
+ {#if draws(f.def)}
49
+ <FieldCell {ctrl} row={{ id: rowId, original: row }} column={{ id: f.id, columnDef: f.def }} value={v} />
50
+ {:else}
51
+ {linkedText(f, v, row) || ' '}
52
+ {/if}
53
+ </div>
54
+ </div>
55
+ {/each}
56
+ </div>
57
+ {/if}
58
+ {#snippet footer()}
59
+ <div class="sv-flrv-footer">
60
+ {#if table?.open && row}
61
+ <button
62
+ type="button"
63
+ class="sv-flrv-btn sv-flrv-btn-quiet"
64
+ onclick={openWhere}>Open in {table.name}</button
65
+ >
66
+ {/if}
67
+ <button
68
+ type="button"
69
+ class="sv-flrv-btn"
70
+ onclick={() => {
71
+ open = false
72
+ onClose()
73
+ }}>Close</button
74
+ >
75
+ </div>
76
+ {/snippet}
77
+ </SvModal>
78
+
79
+ <style>
80
+ .sv-flrv-table { margin: -6px 0 12px; font-size: 12px; color: var(--sg-muted, #64748b); }
81
+ .sv-flrv-fields { display: flex; flex-direction: column; gap: 12px; }
82
+ .sv-flrv-label { display: flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 600; color: var(--sg-muted, #64748b); margin-bottom: 4px; }
83
+ .sv-flrv-value {
84
+ display: flex; align-items: center; min-height: 34px; padding: 0 10px; box-sizing: border-box; font-size: 14px;
85
+ border: 1px solid var(--sg-border, #e2e8f0); border-radius: var(--sg-radius, 6px); background: var(--sg-header-bg, #f8fafc);
86
+ }
87
+ .sv-flrv-gone { color: var(--sg-muted, #64748b); }
88
+ .sv-flrv-footer { display: flex; justify-content: flex-end; gap: 8px; width: 100%; }
89
+ .sv-flrv-btn {
90
+ height: 32px; padding: 0 14px; font: inherit; font-size: 13px; cursor: pointer; border-radius: var(--sg-radius, 6px);
91
+ background: var(--sg-fg, #0f172a); color: var(--sg-bg, #fff); border: 1px solid var(--sg-fg, #0f172a);
92
+ }
93
+ .sv-flrv-btn-quiet { background: transparent; color: var(--sg-fg, #0f172a); border-color: var(--sg-border, #e2e8f0); }
94
+ </style>
@@ -0,0 +1,9 @@
1
+ type $$ComponentProps = {
2
+ ctrl: any;
3
+ table: string;
4
+ rowId: string;
5
+ onClose: () => void;
6
+ };
7
+ declare const LinkedRecordView: import("svelte").Component<$$ComponentProps, {}, "">;
8
+ type LinkedRecordView = ReturnType<typeof LinkedRecordView>;
9
+ export default LinkedRecordView;
@@ -0,0 +1,59 @@
1
+ <script lang="ts">
2
+ /**
3
+ * Link-to-records cells: one chip per linked row, showing its primary
4
+ * field. A click on a chip opens that record; resting the pointer on one
5
+ * previews it.
6
+ */
7
+ import type { FieldCellProps } from './registry.svelte'
8
+ import { getLinkedTable, idOf, linkedRows } from './sources.svelte'
9
+ import { openLinkedRecord, showLinkPreview } from './editor-request.svelte'
10
+
11
+ let { ctrl, value, props }: FieldCellProps<{ table?: string }> = $props()
12
+ const table = $derived(getLinkedTable(props.table))
13
+ const chips = $derived(
14
+ linkedRows(table, value).map((r) => ({ id: table ? idOf(table, r) : '', name: String(r[table?.primaryField ?? 'name'] ?? '') })),
15
+ )
16
+
17
+ let timer: ReturnType<typeof setTimeout> | undefined
18
+ function enter(e: PointerEvent, id: string) {
19
+ if (!table || e.pointerType === 'touch') return
20
+ const rect = (e.currentTarget as HTMLElement).getBoundingClientRect()
21
+ clearTimeout(timer)
22
+ timer = setTimeout(() => showLinkPreview({ ctrl, table: table.id, rowId: id, x: rect.left, y: rect.bottom }), 350)
23
+ }
24
+ function leave(e: PointerEvent) {
25
+ clearTimeout(timer)
26
+ // Onto the card itself: it closes when the pointer leaves it.
27
+ const to = e.relatedTarget as Element | null
28
+ if (!to?.closest?.('.sv-flpv')) showLinkPreview(null)
29
+ }
30
+ </script>
31
+
32
+ <span class="sv-flr">
33
+ {#each chips as chip, i (i)}
34
+ <button
35
+ type="button"
36
+ class="sv-flr-chip"
37
+ tabindex="-1"
38
+ onpointerdown={(e) => e.stopPropagation()}
39
+ onpointerenter={(e) => enter(e, chip.id)}
40
+ onpointerleave={leave}
41
+ onclick={(e) => {
42
+ e.stopPropagation()
43
+ clearTimeout(timer)
44
+ if (table) openLinkedRecord({ ctrl, table: table.id, rowId: chip.id })
45
+ }}>{chip.name || 'Unnamed'}</button
46
+ >
47
+ {/each}
48
+ </span>
49
+
50
+ <style>
51
+ .sv-flr { display: inline-flex; gap: 4px; min-width: 0; overflow: hidden; }
52
+ .sv-flr-chip {
53
+ flex: none; max-width: 160px; padding: 1px 8px; border-radius: 4px; font: inherit; font-size: 12px; color: inherit; cursor: pointer;
54
+ background: color-mix(in srgb, #2d7ff9 12%, transparent);
55
+ border: 1px solid color-mix(in srgb, #2d7ff9 30%, transparent);
56
+ overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
57
+ }
58
+ .sv-flr-chip:hover { background: color-mix(in srgb, #2d7ff9 22%, transparent); }
59
+ </style>
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Link-to-records cells: one chip per linked row, showing its primary
3
+ * field. A click on a chip opens that record; resting the pointer on one
4
+ * previews it.
5
+ */
6
+ import type { FieldCellProps } from './registry.svelte.js';
7
+ declare const LinkedRecordsCell: import("svelte").Component<FieldCellProps<{
8
+ table?: string;
9
+ }>, {}, "">;
10
+ type LinkedRecordsCell = ReturnType<typeof LinkedRecordsCell>;
11
+ export default LinkedRecordsCell;
@@ -0,0 +1,157 @@
1
+ <script lang="ts">
2
+ /**
3
+ * The long text field's editor (registered as 'fieldLongText'): the cell
4
+ * grows into a panel over itself with room for paragraphs. Enter starts a
5
+ * new line, as in any document; Ctrl+Enter (Cmd+Enter), Tab or a click
6
+ * outside saves, and Escape leaves the cell as it was. With rich text on,
7
+ * the footer names the markup the cell draws.
8
+ */
9
+ import { portalToBody } from '@svgrid/grid'
10
+ import { onMount } from 'svelte'
11
+ import { fieldPropsOf } from './registry.svelte'
12
+
13
+ let {
14
+ value,
15
+ typed = false,
16
+ columnDef,
17
+ onCommit,
18
+ onCancel,
19
+ onCommitAndMove,
20
+ }: {
21
+ value: unknown
22
+ typed?: boolean
23
+ columnDef?: Record<string, unknown>
24
+ onCommit: (v?: unknown) => void
25
+ onCancel: () => void
26
+ onCommitAndMove?: (v: unknown, direction: 1 | -1) => void
27
+ } = $props()
28
+
29
+ const rich = $derived(!!fieldPropsOf((columnDef ?? {}) as { fieldType?: unknown; fieldProps?: Record<string, unknown> }).richText)
30
+ // svelte-ignore state_referenced_locally
31
+ let text = $state(value == null ? '' : String(value))
32
+ let finished = false
33
+
34
+ let anchor = $state<HTMLElement | null>(null)
35
+ let panel = $state<HTMLElement | null>(null)
36
+ let area = $state<HTMLTextAreaElement | null>(null)
37
+ let rect = $state<{ top: number; left: number; width: number; maxHeight: number } | null>(null)
38
+ function place() {
39
+ const cell = anchor?.closest('td') ?? anchor
40
+ if (!cell) return
41
+ const r = cell.getBoundingClientRect()
42
+ const width = Math.min(Math.max(r.width + 2, 340), window.innerWidth - 16)
43
+ const left = Math.max(8, Math.min(r.left - 1, window.innerWidth - width - 8))
44
+ const top = Math.max(8, Math.min(r.top - 1, window.innerHeight - 220))
45
+ rect = { top, left, width, maxHeight: window.innerHeight - top - 8 }
46
+ }
47
+ /** The box grows with its lines, up to the panel's room. */
48
+ function fit() {
49
+ if (!area) return
50
+ area.style.height = 'auto'
51
+ area.style.height = `${Math.min(area.scrollHeight + 2, Math.max(120, (rect?.maxHeight ?? 400) - 48))}px`
52
+ }
53
+
54
+ onMount(() => {
55
+ place()
56
+ const takeFocus = () => {
57
+ if (!area || document.activeElement === area) return
58
+ area.focus({ preventScroll: true })
59
+ // A typed key continues after itself; opening an existing text puts
60
+ // the caret at its end, where more usually goes.
61
+ area.setSelectionRange(text.length, text.length)
62
+ fit()
63
+ }
64
+ queueMicrotask(takeFocus)
65
+ const frame = requestAnimationFrame(takeFocus)
66
+ const onDown = (e: PointerEvent) => {
67
+ const t = e.target as Node
68
+ if (finished || panel?.contains(t) || anchor?.contains(t)) return
69
+ finish('commit')
70
+ }
71
+ const onScroll = (e: Event) => {
72
+ if (!panel?.contains(e.target as Node)) place()
73
+ }
74
+ window.addEventListener('resize', place)
75
+ window.addEventListener('scroll', onScroll, true)
76
+ document.addEventListener('pointerdown', onDown, true)
77
+ return () => {
78
+ cancelAnimationFrame(frame)
79
+ window.removeEventListener('resize', place)
80
+ window.removeEventListener('scroll', onScroll, true)
81
+ document.removeEventListener('pointerdown', onDown, true)
82
+ }
83
+ })
84
+
85
+ function finish(how: 'commit' | 'cancel' | 'next' | 'prev') {
86
+ if (finished) return
87
+ finished = true
88
+ if (how === 'cancel') return onCancel()
89
+ const v = text === '' ? null : text
90
+ if ((how === 'next' || how === 'prev') && onCommitAndMove) onCommitAndMove(v, how === 'next' ? 1 : -1)
91
+ else onCommit(v)
92
+ }
93
+ function onKey(e: KeyboardEvent) {
94
+ if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) finish('commit')
95
+ else if (e.key === 'Escape') finish('cancel')
96
+ else if (e.key === 'Tab') finish(e.shiftKey ? 'prev' : 'next')
97
+ else {
98
+ // Enter, arrows and the rest are the text box's own.
99
+ e.stopPropagation()
100
+ return
101
+ }
102
+ e.preventDefault()
103
+ e.stopPropagation()
104
+ }
105
+ const areaValue = (e: Event) => (e.currentTarget as HTMLTextAreaElement).value
106
+ const mod = typeof navigator !== 'undefined' && /Mac|iPhone|iPad/.test(navigator.platform) ? 'Cmd' : 'Ctrl'
107
+ </script>
108
+
109
+ <span class="sv-flt-cell" bind:this={anchor}>{text.split('\n')[0]}</span>
110
+
111
+ {#if rect}
112
+ <div
113
+ class="sv-flt-panel"
114
+ bind:this={panel}
115
+ use:portalToBody
116
+ style:top={`${rect.top}px`}
117
+ style:left={`${rect.left}px`}
118
+ style:width={`${rect.width}px`}
119
+ style:max-height={`${rect.maxHeight}px`}
120
+ >
121
+ <textarea
122
+ bind:this={area}
123
+ class="sv-flt-area"
124
+ aria-label={String((columnDef as { header?: unknown } | undefined)?.header ?? 'Long text')}
125
+ value={text}
126
+ oninput={(e) => {
127
+ text = areaValue(e)
128
+ fit()
129
+ }}
130
+ onkeydown={onKey}
131
+ ></textarea>
132
+ <div class="sv-flt-foot">
133
+ {#if rich}<span class="sv-flt-markup">**bold** *italic* `code` [link](https://...) - list</span>{/if}
134
+ <span class="sv-flt-keys"><kbd>{mod}+Enter</kbd> save <kbd>Esc</kbd> cancel</span>
135
+ </div>
136
+ </div>
137
+ {/if}
138
+
139
+ <style>
140
+ .sv-flt-cell { display: block; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; padding: 0 8px; }
141
+ .sv-flt-panel {
142
+ position: fixed; z-index: 2147483646; display: flex; flex-direction: column; gap: 6px; box-sizing: border-box; padding: 6px;
143
+ border: 1px solid var(--sg-border, #e2e8f0); border-radius: var(--sg-radius, 6px);
144
+ background: var(--sg-bg, #fff); color: var(--sg-fg, #0f172a); box-shadow: 0 8px 24px rgb(0 0 0 / 0.16);
145
+ }
146
+ .sv-flt-area {
147
+ display: block; box-sizing: border-box; width: 100%; min-height: 120px; resize: none; overflow: auto;
148
+ padding: 8px 10px; font: inherit; font-size: 14px; line-height: 1.5;
149
+ border: 1px solid var(--sg-input-border, var(--sg-border, #e2e8f0)); border-radius: var(--sg-radius, 6px);
150
+ background: var(--sg-input-bg, var(--sg-bg, #fff)); color: var(--sg-fg, #0f172a);
151
+ }
152
+ .sv-flt-area:focus { outline: none; border-color: var(--sg-accent, #2563eb); }
153
+ .sv-flt-foot { display: flex; align-items: center; gap: 12px; padding: 0 2px; font-size: 12px; color: var(--sg-muted, #64748b); }
154
+ .sv-flt-markup { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-family: ui-monospace, monospace; }
155
+ .sv-flt-keys { margin-inline-start: auto; flex: none; }
156
+ .sv-flt-keys kbd { padding: 0 4px; border: 1px solid var(--sg-border, #e2e8f0); border-radius: 3px; font: inherit; font-size: 11px; }
157
+ </style>
@@ -0,0 +1,11 @@
1
+ type $$ComponentProps = {
2
+ value: unknown;
3
+ typed?: boolean;
4
+ columnDef?: Record<string, unknown>;
5
+ onCommit: (v?: unknown) => void;
6
+ onCancel: () => void;
7
+ onCommitAndMove?: (v: unknown, direction: 1 | -1) => void;
8
+ };
9
+ declare const LongTextEditor: import("svelte").Component<$$ComponentProps, {}, "">;
10
+ type LongTextEditor = ReturnType<typeof LongTextEditor>;
11
+ export default LongTextEditor;