@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.
- package/README.md +1 -0
- package/dist/SvAlertRuleEditor.svelte +16 -5
- package/dist/SvGridAlerts.svelte +8 -0
- package/dist/SvGridAlerts.svelte.d.ts +4 -0
- package/dist/SvGridBoard.svelte +69 -10
- package/dist/SvGridBulkEditDrawer.svelte +13 -5
- package/dist/SvGridGallery.svelte +286 -0
- package/dist/SvGridGallery.svelte.d.ts +30 -0
- package/dist/SvGridScheduler.svelte +33 -11
- package/dist/SvGridSelectionBar.svelte +47 -0
- package/dist/advanced-filter/expr-columns-from-grid.d.ts +1 -0
- package/dist/advanced-filter/expr-columns-from-grid.js +11 -7
- package/dist/advanced-filter-enable.d.ts +6 -0
- package/dist/advanced-filter-enable.js +8 -0
- package/dist/alerts/alert-engine.d.ts +7 -0
- package/dist/alerts/alert-engine.js +5 -2
- package/dist/alerts/condition-editor.d.ts +26 -0
- package/dist/alerts/condition-editor.js +17 -0
- package/dist/base/index.d.ts +20 -0
- package/dist/base/index.js +20 -0
- package/dist/bulk-edit.d.ts +11 -0
- package/dist/bulk-edit.js +18 -1
- package/dist/cdn/svgrid-enterprise.svelte-external.js +11197 -10639
- package/dist/designer/assets/GridFooter-Cu8_yBlQ.js +2 -0
- package/dist/designer/assets/GridMenus-BUjkkAU2.js +6 -0
- package/dist/designer/assets/PinSplitter-BgTpgh1d.css +1 -0
- package/dist/designer/assets/PinSplitter-C5AwA1xV.js +1 -0
- package/dist/designer/assets/SvGrid.helpers-CIrmIo9U.js +1 -0
- package/dist/designer/assets/SvGridCellEditor-CJxThKL_.js +4 -0
- package/dist/designer/assets/SvListBox-CS7oUAiX.js +2 -0
- package/dist/designer/assets/conditional-formatting-MDWbF8_Y.js +1 -0
- package/dist/designer/assets/grid-extension.svelte-BZ7AqyJI.js +1 -0
- package/dist/designer/assets/index-BmvG99kR.css +1 -0
- package/dist/designer/assets/{index-Obk8sI77.js → index-CJodU3tU.js} +307 -307
- package/dist/designer/assets/sparkline-C-NcnB2i.js +1 -0
- package/dist/designer/assets/src-C_U1NKOY.js +58 -0
- package/dist/designer/assets/sv-grid-scrollbar-B9N6Wuj0.js +109 -0
- package/dist/designer/assets/validate-H5u2HEQh.js +1 -0
- package/dist/designer/index.html +11 -7
- package/dist/expressions/compile.js +10 -0
- package/dist/expressions/evaluate.js +18 -0
- package/dist/expressions/expression-types.d.ts +10 -0
- package/dist/expressions/kinds.d.ts +28 -0
- package/dist/expressions/kinds.js +19 -0
- package/dist/expressions/parse.js +9 -1
- package/dist/fields/AttachmentCell.svelte +242 -0
- package/dist/fields/AttachmentCell.svelte.d.ts +5 -0
- package/dist/fields/AttachmentDialog.svelte +357 -0
- package/dist/fields/AttachmentDialog.svelte.d.ts +13 -0
- package/dist/fields/AttachmentEditor.svelte +41 -0
- package/dist/fields/AttachmentEditor.svelte.d.ts +11 -0
- package/dist/fields/AttachmentPreview.svelte +72 -0
- package/dist/fields/AttachmentPreview.svelte.d.ts +8 -0
- package/dist/fields/BarcodeCell.svelte +20 -0
- package/dist/fields/BarcodeCell.svelte.d.ts +5 -0
- package/dist/fields/BaseAutomations.svelte +558 -0
- package/dist/fields/BaseAutomations.svelte.d.ts +18 -0
- package/dist/fields/BaseChartView.svelte +47 -0
- package/dist/fields/BaseChartView.svelte.d.ts +8 -0
- package/dist/fields/BaseTableView.svelte +185 -0
- package/dist/fields/BaseTableView.svelte.d.ts +37 -0
- package/dist/fields/BaseTabs.svelte +308 -0
- package/dist/fields/BaseTabs.svelte.d.ts +21 -0
- package/dist/fields/ButtonCell.svelte +47 -0
- package/dist/fields/ButtonCell.svelte.d.ts +20 -0
- package/dist/fields/CheckboxCell.svelte +46 -0
- package/dist/fields/CheckboxCell.svelte.d.ts +14 -0
- package/dist/fields/DeleteFieldConfirm.svelte +80 -0
- package/dist/fields/DeleteFieldConfirm.svelte.d.ts +8 -0
- package/dist/fields/DeleteRecordConfirm.svelte +48 -0
- package/dist/fields/DeleteRecordConfirm.svelte.d.ts +9 -0
- package/dist/fields/FieldCell.svelte +80 -0
- package/dist/fields/FieldCell.svelte.d.ts +9 -0
- package/dist/fields/FieldEditor.svelte +321 -0
- package/dist/fields/FieldEditor.svelte.d.ts +10 -0
- package/dist/fields/FieldInput.svelte +188 -0
- package/dist/fields/FieldInput.svelte.d.ts +29 -0
- package/dist/fields/FieldsHeaderEnd.svelte +146 -0
- package/dist/fields/FieldsHeaderEnd.svelte.d.ts +6 -0
- package/dist/fields/FootRowAdder.svelte +8 -0
- package/dist/fields/FootRowAdder.svelte.d.ts +6 -0
- package/dist/fields/GroupHeader.svelte +127 -0
- package/dist/fields/GroupHeader.svelte.d.ts +24 -0
- package/dist/fields/LinkCell.svelte +46 -0
- package/dist/fields/LinkCell.svelte.d.ts +9 -0
- package/dist/fields/LinkPickerEditor.svelte +172 -0
- package/dist/fields/LinkPickerEditor.svelte.d.ts +9 -0
- package/dist/fields/LinkPreview.svelte +60 -0
- package/dist/fields/LinkPreview.svelte.d.ts +7 -0
- package/dist/fields/LinkedRecordView.svelte +94 -0
- package/dist/fields/LinkedRecordView.svelte.d.ts +9 -0
- package/dist/fields/LinkedRecordsCell.svelte +59 -0
- package/dist/fields/LinkedRecordsCell.svelte.d.ts +11 -0
- package/dist/fields/LongTextEditor.svelte +157 -0
- package/dist/fields/LongTextEditor.svelte.d.ts +11 -0
- package/dist/fields/NumberEditor.svelte +309 -0
- package/dist/fields/NumberEditor.svelte.d.ts +12 -0
- package/dist/fields/OptionsEditor.svelte +117 -0
- package/dist/fields/OptionsEditor.svelte.d.ts +11 -0
- package/dist/fields/PercentCell.svelte +21 -0
- package/dist/fields/PercentCell.svelte.d.ts +8 -0
- package/dist/fields/PropertyInput.svelte +204 -0
- package/dist/fields/PropertyInput.svelte.d.ts +11 -0
- package/dist/fields/RatingCell.svelte +75 -0
- package/dist/fields/RatingCell.svelte.d.ts +16 -0
- package/dist/fields/RatingEditor.svelte +82 -0
- package/dist/fields/RatingEditor.svelte.d.ts +9 -0
- package/dist/fields/RecordView.svelte +310 -0
- package/dist/fields/RecordView.svelte.d.ts +11 -0
- package/dist/fields/RichTextCell.svelte +30 -0
- package/dist/fields/RichTextCell.svelte.d.ts +5 -0
- package/dist/fields/RowAdder.svelte +93 -0
- package/dist/fields/RowAdder.svelte.d.ts +7 -0
- package/dist/fields/RowHeader.svelte +99 -0
- package/dist/fields/RowHeader.svelte.d.ts +11 -0
- package/dist/fields/SelectCell.svelte +35 -0
- package/dist/fields/SelectCell.svelte.d.ts +15 -0
- package/dist/fields/SelectEditor.svelte +350 -0
- package/dist/fields/SelectEditor.svelte.d.ts +17 -0
- package/dist/fields/SummaryCell.svelte +160 -0
- package/dist/fields/SummaryCell.svelte.d.ts +11 -0
- package/dist/fields/SvBase.svelte +545 -0
- package/dist/fields/SvBase.svelte.d.ts +30 -0
- package/dist/fields/SvBaseForm.svelte +295 -0
- package/dist/fields/SvBaseForm.svelte.d.ts +22 -0
- package/dist/fields/SvBaseViewBar.svelte +644 -0
- package/dist/fields/SvBaseViewBar.svelte.d.ts +26 -0
- package/dist/fields/UserCell.svelte +39 -0
- package/dist/fields/UserCell.svelte.d.ts +9 -0
- package/dist/fields/UserFace.svelte +30 -0
- package/dist/fields/UserFace.svelte.d.ts +12 -0
- package/dist/fields/activity.svelte.d.ts +50 -0
- package/dist/fields/activity.svelte.js +110 -0
- package/dist/fields/attachments.d.ts +95 -0
- package/dist/fields/attachments.js +145 -0
- package/dist/fields/automation-outbound.d.ts +46 -0
- package/dist/fields/automation-outbound.js +61 -0
- package/dist/fields/automation-server.d.ts +53 -0
- package/dist/fields/automation-server.js +333 -0
- package/dist/fields/automations.svelte.d.ts +208 -0
- package/dist/fields/automations.svelte.js +437 -0
- package/dist/fields/bar-request.svelte.d.ts +16 -0
- package/dist/fields/bar-request.svelte.js +15 -0
- package/dist/fields/base-alerts.d.ts +24 -0
- package/dist/fields/base-alerts.js +64 -0
- package/dist/fields/base-connect.d.ts +82 -0
- package/dist/fields/base-connect.js +271 -0
- package/dist/fields/base-schema.d.ts +104 -0
- package/dist/fields/base-schema.js +266 -0
- package/dist/fields/base-sql.d.ts +62 -0
- package/dist/fields/base-sql.js +251 -0
- package/dist/fields/base-sync.d.ts +142 -0
- package/dist/fields/base-sync.js +499 -0
- package/dist/fields/base-tables.d.ts +89 -0
- package/dist/fields/base-tables.js +349 -0
- package/dist/fields/builtin-types.d.ts +13 -0
- package/dist/fields/builtin-types.js +773 -0
- package/dist/fields/button.d.ts +2 -0
- package/dist/fields/button.js +17 -0
- package/dist/fields/chart-view.d.ts +35 -0
- package/dist/fields/chart-view.js +154 -0
- package/dist/fields/column-order.d.ts +6 -0
- package/dist/fields/column-order.js +12 -0
- package/dist/fields/convert.d.ts +16 -0
- package/dist/fields/convert.js +176 -0
- package/dist/fields/copy-text.d.ts +13 -0
- package/dist/fields/copy-text.js +45 -0
- package/dist/fields/editor-request.svelte.d.ts +71 -0
- package/dist/fields/editor-request.svelte.js +52 -0
- package/dist/fields/field-ops.d.ts +72 -0
- package/dist/fields/field-ops.js +334 -0
- package/dist/fields/filter-model.d.ts +84 -0
- package/dist/fields/filter-model.js +446 -0
- package/dist/fields/format.d.ts +109 -0
- package/dist/fields/format.js +288 -0
- package/dist/fields/formula.d.ts +50 -0
- package/dist/fields/formula.js +530 -0
- package/dist/fields/grid-access.d.ts +60 -0
- package/dist/fields/grid-access.js +120 -0
- package/dist/fields/index.d.ts +34 -0
- package/dist/fields/index.js +312 -0
- package/dist/fields/linked-fields.d.ts +8 -0
- package/dist/fields/linked-fields.js +40 -0
- package/dist/fields/links.d.ts +10 -0
- package/dist/fields/links.js +46 -0
- package/dist/fields/name-list.d.ts +16 -0
- package/dist/fields/name-list.js +49 -0
- package/dist/fields/palette.d.ts +47 -0
- package/dist/fields/palette.js +69 -0
- package/dist/fields/record-delete.svelte.d.ts +12 -0
- package/dist/fields/record-delete.svelte.js +5 -0
- package/dist/fields/record-menu.d.ts +9 -0
- package/dist/fields/record-menu.js +78 -0
- package/dist/fields/registry.svelte.d.ts +176 -0
- package/dist/fields/registry.svelte.js +51 -0
- package/dist/fields/rich-text.d.ts +23 -0
- package/dist/fields/rich-text.js +48 -0
- package/dist/fields/row-color-choice.svelte.d.ts +31 -0
- package/dist/fields/row-color-choice.svelte.js +25 -0
- package/dist/fields/row-colors.d.ts +36 -0
- package/dist/fields/row-colors.js +90 -0
- package/dist/fields/row-height.d.ts +28 -0
- package/dist/fields/row-height.js +50 -0
- package/dist/fields/sources.svelte.d.ts +80 -0
- package/dist/fields/sources.svelte.js +131 -0
- package/dist/fields/summaries.d.ts +18 -0
- package/dist/fields/summaries.js +138 -0
- package/dist/fields/view-model.d.ts +129 -0
- package/dist/fields/view-model.js +492 -0
- package/dist/fields/viewbar/ChartPanel.svelte +61 -0
- package/dist/fields/viewbar/ChartPanel.svelte.d.ts +9 -0
- package/dist/fields/viewbar/ColorPanel.svelte +112 -0
- package/dist/fields/viewbar/ColorPanel.svelte.d.ts +9 -0
- package/dist/fields/viewbar/ConditionValue.svelte +153 -0
- package/dist/fields/viewbar/ConditionValue.svelte.d.ts +15 -0
- package/dist/fields/viewbar/FieldIcon.svelte +18 -0
- package/dist/fields/viewbar/FieldIcon.svelte.d.ts +9 -0
- package/dist/fields/viewbar/FilterPanel.svelte +192 -0
- package/dist/fields/viewbar/FilterPanel.svelte.d.ts +13 -0
- package/dist/fields/viewbar/GanttPanel.svelte +60 -0
- package/dist/fields/viewbar/GanttPanel.svelte.d.ts +10 -0
- package/dist/fields/viewbar/HideFieldsPanel.svelte +104 -0
- package/dist/fields/viewbar/HideFieldsPanel.svelte.d.ts +7 -0
- package/dist/fields/viewbar/SortPanel.svelte +85 -0
- package/dist/fields/viewbar/SortPanel.svelte.d.ts +8 -0
- package/dist/fields/viewbar/ViewsMenu.svelte +250 -0
- package/dist/fields/viewbar/ViewsMenu.svelte.d.ts +15 -0
- package/dist/fields/viewbar/panel-focus.d.ts +3 -0
- package/dist/fields/viewbar/panel-focus.js +22 -0
- package/dist/fields/viewbar/sort-state.d.ts +20 -0
- package/dist/fields/viewbar/sort-state.js +24 -0
- package/dist/gallery.d.ts +7 -0
- package/dist/gallery.js +36 -0
- package/dist/gantt/SvGridGantt.svelte +88 -16
- package/dist/gantt/gantt-config.d.ts +28 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +6 -0
- package/dist/install.js +3 -0
- package/dist/license-core.d.ts +3 -3
- package/dist/license.js +1 -0
- package/dist/node/studio.js +105 -4
- package/dist/scheduler-config.d.ts +11 -0
- package/dist/sources/introspect-supabase.js +4 -1
- package/dist/sources/rest.js +6 -2
- package/dist/studio/ui-components.generated.js +93 -1
- package/dist/upgrade-prompt.d.ts +1 -1
- package/dist/version.d.ts +2 -2
- package/dist/version.js +2 -2
- package/dist/wc/GridFooter-f5K0aLe_.js +145 -0
- package/dist/wc/GridMenus-FtSN_8t9.js +1369 -0
- package/dist/wc/PinSplitter-D-qtDhSM.js +132 -0
- package/dist/wc/{SvGrid.helpers-zBkDTryR.js → SvGrid.helpers-B2GEKrxS.js} +84 -36
- package/dist/wc/{SvGridCellEditor-CzUKEbkI.js → SvGridCellEditor-B_cLJrsp.js} +20 -9
- package/dist/wc/conditional-formatting-BXis_oP1.js +189 -0
- package/dist/wc/grid-extension.svelte-Bufq4B4C.js +20 -0
- package/dist/wc/sv-sheet-element.js +7556 -7617
- package/dist/wc/svelte-virtualizer.svelte-ehwOupl-.js +360 -0
- package/dist/wc/{validate-43C03DLP.js → validate-BaMO8UPE.js} +1 -1
- package/package.json +14 -3
- package/dist/designer/assets/GridMenus-CvcASlKv.js +0 -8
- package/dist/designer/assets/SvGrid.helpers-DE5mmORW.js +0 -1
- package/dist/designer/assets/SvGridCellEditor-C7NWcnNC.js +0 -4
- package/dist/designer/assets/SvListBox-BlmmzYcU.js +0 -110
- package/dist/designer/assets/index-KmSEY7Lb.css +0 -1
- package/dist/designer/assets/src-DqHCqori.js +0 -58
- package/dist/designer/assets/validate-B71dE1Cs.js +0 -1
- package/dist/wc/GridMenus-fWbBUiRH.js +0 -1088
- package/dist/wc/svelte-virtualizer.svelte-Dntdh8Ms.js +0 -581
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* One field's value outside the grid (the expanded record, the form view):
|
|
4
|
+
* drawn as its cell draws it, and on a click the editor its cell uses (the
|
|
5
|
+
* number box, the select panel, the date picker...) or a plain box. A
|
|
6
|
+
* checkbox toggles at once. The parent writes the value (`onCommit`) and
|
|
7
|
+
* decides which field is being edited, so Tab can move between them.
|
|
8
|
+
*/
|
|
9
|
+
import { SvDateTimePicker, getCellEditor, resolveEditorProps } from '@svgrid/grid'
|
|
10
|
+
import FieldCell from './FieldCell.svelte'
|
|
11
|
+
import { typeDrawsCell } from './registry.svelte'
|
|
12
|
+
|
|
13
|
+
type Col = { id: string; columnDef: Record<string, any> }
|
|
14
|
+
let {
|
|
15
|
+
ctrl,
|
|
16
|
+
column,
|
|
17
|
+
value,
|
|
18
|
+
row,
|
|
19
|
+
rowId = '',
|
|
20
|
+
label,
|
|
21
|
+
editable,
|
|
22
|
+
editing,
|
|
23
|
+
placeholder = 'Empty',
|
|
24
|
+
onStart,
|
|
25
|
+
onStop,
|
|
26
|
+
onCommit,
|
|
27
|
+
onTab,
|
|
28
|
+
addOptions = true,
|
|
29
|
+
}: {
|
|
30
|
+
ctrl: any
|
|
31
|
+
column: Col
|
|
32
|
+
value: unknown
|
|
33
|
+
/** The row the value belongs to (none in a form). */
|
|
34
|
+
row?: { id: string; original: unknown } | null
|
|
35
|
+
rowId?: string
|
|
36
|
+
label: string
|
|
37
|
+
editable: boolean
|
|
38
|
+
editing: boolean
|
|
39
|
+
placeholder?: string
|
|
40
|
+
onStart: () => void
|
|
41
|
+
onStop: () => void
|
|
42
|
+
onCommit: (value: unknown) => void
|
|
43
|
+
/** Tab or Shift+Tab out of the editor, after its value was committed. */
|
|
44
|
+
onTab?: (dir: 1 | -1) => void
|
|
45
|
+
/** False in a form: a select offers only the field's options, never "Add option". */
|
|
46
|
+
addOptions?: boolean
|
|
47
|
+
} = $props()
|
|
48
|
+
|
|
49
|
+
let draft: unknown = undefined
|
|
50
|
+
const reg = $derived(getCellEditor(String(column.columnDef.editorType ?? 'text')))
|
|
51
|
+
const drawsCell = $derived(!!column.columnDef.fieldType && column.columnDef.cell == null && typeDrawsCell(column.columnDef))
|
|
52
|
+
// Stars and a checkbox say what an empty value is; other cells would draw nothing.
|
|
53
|
+
const drawnEmpty = $derived(column.columnDef.fieldType === 'rating' || column.columnDef.fieldType === 'checkbox')
|
|
54
|
+
// An empty value shows the placeholder, not an empty drawing.
|
|
55
|
+
const blank = $derived(value == null || value === '' || (Array.isArray(value) && value.length === 0))
|
|
56
|
+
const text = $derived.by(() => {
|
|
57
|
+
const f = column.columnDef.formatter as ((x: { value: unknown; row: unknown; column: unknown }) => unknown) | undefined
|
|
58
|
+
// `{ id, original }`, the shape a grid row has: in a form, the draft with id ''.
|
|
59
|
+
if (f) return String(f({ value, row: row ?? null, column }) ?? '')
|
|
60
|
+
if (Array.isArray(value)) return value.join(', ')
|
|
61
|
+
return value == null ? '' : String(value)
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
function start() {
|
|
65
|
+
if (!editable) return
|
|
66
|
+
if (column.columnDef.editorType === 'checkbox') return onCommit(!value)
|
|
67
|
+
draft = value
|
|
68
|
+
onStart()
|
|
69
|
+
}
|
|
70
|
+
const commit = (v: unknown) => {
|
|
71
|
+
onStop()
|
|
72
|
+
if (v !== undefined) onCommit(v)
|
|
73
|
+
}
|
|
74
|
+
function editorProps(r: NonNullable<ReturnType<typeof getCellEditor>>) {
|
|
75
|
+
const props = resolveEditorProps(r, {
|
|
76
|
+
value,
|
|
77
|
+
rowId,
|
|
78
|
+
columnId: column.id,
|
|
79
|
+
columnDef: column.columnDef,
|
|
80
|
+
row: row?.original,
|
|
81
|
+
grid: ctrl,
|
|
82
|
+
typed: false,
|
|
83
|
+
inCell: false,
|
|
84
|
+
onChange: (v: unknown) => (draft = v),
|
|
85
|
+
onCommit: (v?: unknown) => commit(v === undefined ? draft : v),
|
|
86
|
+
onCancel: onStop,
|
|
87
|
+
onRequestClose: onStop,
|
|
88
|
+
onCommitAndMove: (v: unknown, dir: 1 | -1) => {
|
|
89
|
+
commit(v === undefined ? draft : v)
|
|
90
|
+
onTab?.(dir)
|
|
91
|
+
},
|
|
92
|
+
onCommitAndMoveDown: (v?: unknown) => commit(v === undefined ? draft : v),
|
|
93
|
+
})
|
|
94
|
+
// Editors that do not read it ignore it.
|
|
95
|
+
return addOptions ? props : { ...props, addOptions: false }
|
|
96
|
+
}
|
|
97
|
+
function plainKey(e: KeyboardEvent, multiline: boolean) {
|
|
98
|
+
const el = e.currentTarget as HTMLInputElement | HTMLTextAreaElement
|
|
99
|
+
if (e.key === 'Escape') {
|
|
100
|
+
e.preventDefault()
|
|
101
|
+
e.stopPropagation()
|
|
102
|
+
onStop()
|
|
103
|
+
} else if (e.key === 'Enter' && (!multiline || e.ctrlKey || e.metaKey)) {
|
|
104
|
+
e.preventDefault()
|
|
105
|
+
commit(el.value)
|
|
106
|
+
} else if (e.key === 'Tab') {
|
|
107
|
+
e.preventDefault()
|
|
108
|
+
commit(el.value)
|
|
109
|
+
onTab?.(e.shiftKey ? -1 : 1)
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
function focusOnMount(el: HTMLInputElement | HTMLTextAreaElement) {
|
|
113
|
+
queueMicrotask(() => {
|
|
114
|
+
el.focus()
|
|
115
|
+
el.select()
|
|
116
|
+
})
|
|
117
|
+
}
|
|
118
|
+
const blurCommit = (e: Event) => {
|
|
119
|
+
if (editing) commit((e.currentTarget as HTMLInputElement).value)
|
|
120
|
+
}
|
|
121
|
+
</script>
|
|
122
|
+
|
|
123
|
+
{#if editing}
|
|
124
|
+
<div class="sv-frv-box is-editing">
|
|
125
|
+
{#if reg}
|
|
126
|
+
<reg.component {...editorProps(reg)} />
|
|
127
|
+
{:else if column.columnDef.editorType === 'date' || column.columnDef.editorType === 'datetime'}
|
|
128
|
+
<SvDateTimePicker
|
|
129
|
+
value={value as string | number | Date | null}
|
|
130
|
+
formatString={column.columnDef.editorFormatString ?? (column.columnDef.editorType === 'date' ? 'yyyy-MM-dd' : 'yyyy-MM-dd HH:mm')}
|
|
131
|
+
dropDownDisplayMode={column.columnDef.editorType === 'date' ? 'calendar' : 'both'}
|
|
132
|
+
autoOpen
|
|
133
|
+
block
|
|
134
|
+
onChange={(d) => (draft = d)}
|
|
135
|
+
onCommit={() => commit(draft)}
|
|
136
|
+
onCancel={onStop}
|
|
137
|
+
/>
|
|
138
|
+
{:else if column.columnDef.editorType === 'textarea'}
|
|
139
|
+
<textarea class="sv-frv-input" rows="4" value={String(value ?? '')} use:focusOnMount onkeydown={(e) => plainKey(e, true)} onblur={blurCommit}></textarea>
|
|
140
|
+
{:else}
|
|
141
|
+
<input class="sv-frv-input" value={String(value ?? '')} use:focusOnMount onkeydown={(e) => plainKey(e, false)} onblur={blurCommit} />
|
|
142
|
+
{/if}
|
|
143
|
+
</div>
|
|
144
|
+
{:else}
|
|
145
|
+
<!-- A box acting as a button, not a <button>: a cell drawn in it can hold
|
|
146
|
+
buttons of its own (a linked record's chip), and buttons do not nest. -->
|
|
147
|
+
<div
|
|
148
|
+
class="sv-frv-box"
|
|
149
|
+
class:is-readonly={!editable}
|
|
150
|
+
role="button"
|
|
151
|
+
tabindex={editable ? 0 : -1}
|
|
152
|
+
aria-disabled={!editable}
|
|
153
|
+
aria-label={`${label}: ${text || 'empty'}${editable ? ', edit' : ''}`}
|
|
154
|
+
onclick={start}
|
|
155
|
+
onkeydown={(e) => {
|
|
156
|
+
if (e.target !== e.currentTarget || (e.key !== 'Enter' && e.key !== ' ')) return
|
|
157
|
+
e.preventDefault()
|
|
158
|
+
start()
|
|
159
|
+
}}
|
|
160
|
+
>
|
|
161
|
+
{#if drawsCell && (!blank || drawnEmpty)}
|
|
162
|
+
<FieldCell {ctrl} row={row ?? { id: rowId, original: {} }} column={column as never} {value} />
|
|
163
|
+
{:else if text}
|
|
164
|
+
<span class="sv-frv-text">{text}</span>
|
|
165
|
+
{:else}
|
|
166
|
+
<span class="sv-frv-empty">{editable ? placeholder : ''}</span>
|
|
167
|
+
{/if}
|
|
168
|
+
</div>
|
|
169
|
+
{/if}
|
|
170
|
+
|
|
171
|
+
<style>
|
|
172
|
+
.sv-frv-box {
|
|
173
|
+
position: relative; display: flex; align-items: center; min-height: 36px; width: 100%; box-sizing: border-box;
|
|
174
|
+
padding: 0 10px; text-align: start; font: inherit; font-size: 14px; color: var(--sg-fg, #0f172a);
|
|
175
|
+
border: 1px solid var(--sg-border, #e2e8f0); border-radius: var(--sg-radius, 6px); background: var(--sg-input-bg, var(--sg-bg, #fff));
|
|
176
|
+
cursor: pointer;
|
|
177
|
+
}
|
|
178
|
+
.sv-frv-box:hover:not(.is-readonly) { border-color: var(--sg-input-border, var(--sg-border, #cbd5e1)); }
|
|
179
|
+
.sv-frv-box:focus-visible { outline: 2px solid var(--sg-accent, #2563eb); outline-offset: 1px; }
|
|
180
|
+
.sv-frv-box.is-readonly { cursor: default; background: var(--sg-header-bg, #f8fafc); }
|
|
181
|
+
.sv-frv-box.is-editing { padding: 0; border-color: var(--sg-accent, #2563eb); cursor: auto; }
|
|
182
|
+
.sv-frv-text { white-space: pre-wrap; padding: 8px 0; }
|
|
183
|
+
.sv-frv-empty { color: var(--sg-muted, #94a3b8); font-size: 13px; }
|
|
184
|
+
.sv-frv-input {
|
|
185
|
+
width: 100%; box-sizing: border-box; min-height: 34px; padding: 8px 10px; border: 0; outline: none; resize: vertical;
|
|
186
|
+
font: inherit; font-size: 14px; background: none; color: var(--sg-fg, #0f172a);
|
|
187
|
+
}
|
|
188
|
+
</style>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
type Col = {
|
|
2
|
+
id: string;
|
|
3
|
+
columnDef: Record<string, any>;
|
|
4
|
+
};
|
|
5
|
+
type $$ComponentProps = {
|
|
6
|
+
ctrl: any;
|
|
7
|
+
column: Col;
|
|
8
|
+
value: unknown;
|
|
9
|
+
/** The row the value belongs to (none in a form). */
|
|
10
|
+
row?: {
|
|
11
|
+
id: string;
|
|
12
|
+
original: unknown;
|
|
13
|
+
} | null;
|
|
14
|
+
rowId?: string;
|
|
15
|
+
label: string;
|
|
16
|
+
editable: boolean;
|
|
17
|
+
editing: boolean;
|
|
18
|
+
placeholder?: string;
|
|
19
|
+
onStart: () => void;
|
|
20
|
+
onStop: () => void;
|
|
21
|
+
onCommit: (value: unknown) => void;
|
|
22
|
+
/** Tab or Shift+Tab out of the editor, after its value was committed. */
|
|
23
|
+
onTab?: (dir: 1 | -1) => void;
|
|
24
|
+
/** False in a form: a select offers only the field's options, never "Add option". */
|
|
25
|
+
addOptions?: boolean;
|
|
26
|
+
};
|
|
27
|
+
declare const FieldInput: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
28
|
+
type FieldInput = ReturnType<typeof FieldInput>;
|
|
29
|
+
export default FieldInput;
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* The last child of a grid's header row (registerGridExtension's `headerEnd`):
|
|
4
|
+
* the "+" cell of the `columnAdder` prop, and the host of this grid's field
|
|
5
|
+
* editor (opened by the "+" and the column-menu field actions) and record
|
|
6
|
+
* view (opened by a row header's expand button).
|
|
7
|
+
*/
|
|
8
|
+
import { untrack } from 'svelte'
|
|
9
|
+
import FieldEditor from './FieldEditor.svelte'
|
|
10
|
+
import { primaryIdOf } from './grid-access'
|
|
11
|
+
import RecordView from './RecordView.svelte'
|
|
12
|
+
import LinkedRecordView from './LinkedRecordView.svelte'
|
|
13
|
+
import DeleteFieldConfirm from './DeleteFieldConfirm.svelte'
|
|
14
|
+
import DeleteRecordConfirm from './DeleteRecordConfirm.svelte'
|
|
15
|
+
import { askDeleteRecord, getDeleteRecordRequest } from './record-delete.svelte'
|
|
16
|
+
import LinkPreview from './LinkPreview.svelte'
|
|
17
|
+
import {
|
|
18
|
+
closeFieldEditor,
|
|
19
|
+
closeLinkedRecord,
|
|
20
|
+
closeRecord,
|
|
21
|
+
getFieldEditorRequest,
|
|
22
|
+
getDeleteFieldRequest,
|
|
23
|
+
askDeleteField,
|
|
24
|
+
getLinkPreview,
|
|
25
|
+
getLinkedRecords,
|
|
26
|
+
getRecordRequest,
|
|
27
|
+
openFieldEditor,
|
|
28
|
+
} from './editor-request.svelte'
|
|
29
|
+
|
|
30
|
+
let { ctrl }: { ctrl: any } = $props()
|
|
31
|
+
|
|
32
|
+
const request = $derived(getFieldEditorRequest())
|
|
33
|
+
const mine = $derived(request && request.ctrl === ctrl ? request : null)
|
|
34
|
+
const deleting = $derived.by(() => {
|
|
35
|
+
const d = getDeleteFieldRequest()
|
|
36
|
+
return d && d.ctrl === ctrl ? d : null
|
|
37
|
+
})
|
|
38
|
+
const adder = $derived(!!ctrl.props.columnAdder)
|
|
39
|
+
const record = $derived(getRecordRequest())
|
|
40
|
+
const myRecord = $derived(record && record.ctrl === ctrl ? record : null)
|
|
41
|
+
// Linked records opened from this grid's chips, stacked, and the chip preview.
|
|
42
|
+
const linked = $derived(getLinkedRecords().filter((r) => r.ctrl === ctrl))
|
|
43
|
+
const preview = $derived.by(() => {
|
|
44
|
+
const p = getLinkPreview()
|
|
45
|
+
return p && p.ctrl === ctrl ? p : null
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
// Rows drag into a new order (`rowDragManaged`) only while nothing sorts or
|
|
49
|
+
// groups them: in a sorted table the order is the sort's.
|
|
50
|
+
$effect(() => {
|
|
51
|
+
// Only a grid whose app turned dragging on (our override is set only then).
|
|
52
|
+
const overridden = 'rowDragManaged' in (ctrl.optionOverrides ?? {})
|
|
53
|
+
if (!overridden && ctrl.props.rowDragManaged !== true) return
|
|
54
|
+
void ctrl.gridStateVersion
|
|
55
|
+
const s = ctrl.grid?.getState?.() ?? {}
|
|
56
|
+
const ordered = (s.sorting?.length ?? 0) > 0 || (s.grouping?.length ?? 0) > 0
|
|
57
|
+
const want = ordered ? false : undefined
|
|
58
|
+
untrack(() => {
|
|
59
|
+
if (ctrl.optionOverrides?.rowDragManaged !== want) ctrl.buildApi?.().setOption('rowDragManaged', want)
|
|
60
|
+
})
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
// `primaryField`: first, pinned and shown, whatever the column menu or a
|
|
64
|
+
// restored view did.
|
|
65
|
+
const primary = $derived(primaryIdOf(ctrl))
|
|
66
|
+
$effect(() => {
|
|
67
|
+
if (!primary) return
|
|
68
|
+
const pin = ctrl.columnPinning as { left: string[]; right: string[] }
|
|
69
|
+
const hidden = !!ctrl.hiddenColumns[primary]
|
|
70
|
+
untrack(() => {
|
|
71
|
+
if (hidden) {
|
|
72
|
+
const next = { ...ctrl.hiddenColumns }
|
|
73
|
+
delete next[primary]
|
|
74
|
+
ctrl.hiddenColumns = next
|
|
75
|
+
}
|
|
76
|
+
if (pin.left[0] !== primary || pin.right.includes(primary)) {
|
|
77
|
+
ctrl.columnPinning = { left: [primary, ...pin.left.filter((id) => id !== primary)], right: pin.right.filter((id) => id !== primary) }
|
|
78
|
+
}
|
|
79
|
+
})
|
|
80
|
+
})
|
|
81
|
+
</script>
|
|
82
|
+
|
|
83
|
+
{#if adder}
|
|
84
|
+
<th class="sv-grid-column sv-field-column-adder" role="columnheader" aria-label="Add a field">
|
|
85
|
+
<button
|
|
86
|
+
type="button"
|
|
87
|
+
class="sv-field-column-adder-button"
|
|
88
|
+
aria-label="Add a field"
|
|
89
|
+
title="Add a field"
|
|
90
|
+
onclick={() => openFieldEditor({ ctrl, mode: 'add', index: 'end' })}
|
|
91
|
+
>
|
|
92
|
+
<svg viewBox="0 0 24 24" width="16" height="16" aria-hidden="true"><path d="M12 5v14M5 12h14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" /></svg>
|
|
93
|
+
</button>
|
|
94
|
+
</th>
|
|
95
|
+
{/if}
|
|
96
|
+
{#if mine}
|
|
97
|
+
{#key mine}
|
|
98
|
+
<FieldEditor {ctrl} mode={mine.mode} columnId={mine.columnId} index={mine.index} onClose={closeFieldEditor} />
|
|
99
|
+
{/key}
|
|
100
|
+
{/if}
|
|
101
|
+
{#if deleting}
|
|
102
|
+
{#key deleting}
|
|
103
|
+
<DeleteFieldConfirm {ctrl} columnId={deleting.columnId} onClose={() => askDeleteField(null)} />
|
|
104
|
+
{/key}
|
|
105
|
+
{/if}
|
|
106
|
+
{#if getDeleteRecordRequest()?.ctrl === ctrl}
|
|
107
|
+
{@const r = getDeleteRecordRequest()!}
|
|
108
|
+
{#key r}
|
|
109
|
+
<DeleteRecordConfirm {ctrl} api={r.api} row={r.row} onClose={() => askDeleteRecord(null)} />
|
|
110
|
+
{/key}
|
|
111
|
+
{/if}
|
|
112
|
+
{#if myRecord}
|
|
113
|
+
{#key myRecord}
|
|
114
|
+
<RecordView {ctrl} rowId={myRecord.rowId} editPrimary={myRecord.editPrimary} onClose={closeRecord} />
|
|
115
|
+
{/key}
|
|
116
|
+
{/if}
|
|
117
|
+
{#each linked as r, i (`${i}:${r.table}:${r.rowId}`)}
|
|
118
|
+
<LinkedRecordView {ctrl} table={r.table} rowId={r.rowId} onClose={closeLinkedRecord} />
|
|
119
|
+
{/each}
|
|
120
|
+
{#if preview}
|
|
121
|
+
<LinkPreview request={preview} />
|
|
122
|
+
{/if}
|
|
123
|
+
|
|
124
|
+
<style>
|
|
125
|
+
.sv-field-column-adder {
|
|
126
|
+
flex: none;
|
|
127
|
+
width: 44px;
|
|
128
|
+
min-width: 44px;
|
|
129
|
+
max-width: 44px;
|
|
130
|
+
padding: 0;
|
|
131
|
+
}
|
|
132
|
+
.sv-field-column-adder-button {
|
|
133
|
+
display: inline-flex;
|
|
134
|
+
align-items: center;
|
|
135
|
+
justify-content: center;
|
|
136
|
+
width: 100%;
|
|
137
|
+
height: 100%;
|
|
138
|
+
min-height: 32px;
|
|
139
|
+
border: 0;
|
|
140
|
+
background: transparent;
|
|
141
|
+
color: var(--sg-muted, #64748b);
|
|
142
|
+
cursor: pointer;
|
|
143
|
+
}
|
|
144
|
+
.sv-field-column-adder-button:hover { color: var(--sg-fg, #0f172a); background: var(--sg-row-hover-bg, #f1f5f9); }
|
|
145
|
+
.sv-field-column-adder-button:focus-visible { outline: 2px solid var(--sg-accent, #2563eb); outline-offset: -2px; }
|
|
146
|
+
</style>
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* A group's header in a table grouped by fields: the field's name over its
|
|
4
|
+
* value, drawn as the cell draws it (a select's pill, a person's avatar),
|
|
5
|
+
* the number of records, the summaries the fields picked for this group
|
|
6
|
+
* ("Budget Sum $4,300"), and "+" to add a record that is already in it.
|
|
7
|
+
*/
|
|
8
|
+
import { tick } from 'svelte'
|
|
9
|
+
import FieldCell from './FieldCell.svelte'
|
|
10
|
+
import { newRowValues } from './field-ops'
|
|
11
|
+
import { typeDrawsCell } from './registry.svelte'
|
|
12
|
+
import { groupLeaves, leafFilter } from './grid-access'
|
|
13
|
+
|
|
14
|
+
type Row = {
|
|
15
|
+
id: string
|
|
16
|
+
depth: number
|
|
17
|
+
original: Record<string, unknown>
|
|
18
|
+
subRows?: Row[]
|
|
19
|
+
getCanExpand?: () => boolean
|
|
20
|
+
getIsExpanded?: () => boolean
|
|
21
|
+
toggleExpanded?: () => void
|
|
22
|
+
__treeRow?: boolean
|
|
23
|
+
}
|
|
24
|
+
type Col = { id: string; columnDef: Record<string, any> }
|
|
25
|
+
let { ctrl, row, column, value }: { ctrl: any; row: Row; column: Col | undefined; value: unknown; count: number } = $props()
|
|
26
|
+
|
|
27
|
+
// The group's records the view's filter keeps (the grid groups before it filters).
|
|
28
|
+
const records = $derived(groupLeaves(row, leafFilter(ctrl)))
|
|
29
|
+
// The first record's own value: the group key is text, the record has the value (an array, a number).
|
|
30
|
+
const raw = $derived(column?.columnDef.field ? (records[0]?.original?.[column.columnDef.field] ?? value) : value)
|
|
31
|
+
const draws = $derived(!!column?.columnDef.fieldType && column.columnDef.cell == null && typeDrawsCell(column.columnDef))
|
|
32
|
+
const empty = $derived(raw == null || raw === '' || (Array.isArray(raw) && raw.length === 0))
|
|
33
|
+
const label = $derived(column ? (typeof column.columnDef.header === 'string' ? column.columnDef.header : column.id) : '')
|
|
34
|
+
|
|
35
|
+
// The fields with a summary chosen, computed over this group's records.
|
|
36
|
+
const summaries = $derived.by(() => {
|
|
37
|
+
const out: Array<{ id: string; label: string; text: string }> = []
|
|
38
|
+
for (const c of (ctrl.allColumns ?? []) as Col[]) {
|
|
39
|
+
const fn = c.columnDef.summary
|
|
40
|
+
if (typeof fn !== 'function' || c.id === column?.id) continue
|
|
41
|
+
const text = String(fn([], records.map((r) => r.original)) ?? '')
|
|
42
|
+
if (text) out.push({ id: c.id, label: typeof c.columnDef.header === 'string' ? c.columnDef.header : c.id, text })
|
|
43
|
+
}
|
|
44
|
+
return out
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
/** A new record with this group's values (and its parent groups'), as "+ Add row" makes one. */
|
|
48
|
+
async function add() {
|
|
49
|
+
const api = ctrl.buildApi?.()
|
|
50
|
+
const first = records[0]
|
|
51
|
+
if (!api || !first) return
|
|
52
|
+
const grouped: string[] = ctrl.grid?.getState?.().grouping ?? []
|
|
53
|
+
const values: Record<string, unknown> = {}
|
|
54
|
+
for (const id of grouped.slice(0, row.depth + 1)) {
|
|
55
|
+
const def = ((ctrl.allColumns ?? []) as Col[]).find((c) => c.id === id)?.columnDef ?? ((ctrl.internalColumns ?? []) as Array<Record<string, any>>).find((d) => String(d.id ?? d.field) === id)
|
|
56
|
+
const field = def?.field
|
|
57
|
+
if (field && !def?.fieldFn) values[field] = copy(first.original[field])
|
|
58
|
+
}
|
|
59
|
+
const cfg = ctrl.props.rowAdder
|
|
60
|
+
const defaults = cfg && typeof cfg === 'object' && typeof cfg.defaults === 'function' ? cfg.defaults() : {}
|
|
61
|
+
const next: Record<string, unknown> = newRowValues(ctrl, { ...defaults, ...values })
|
|
62
|
+
api.addRow(next, 'bottom')
|
|
63
|
+
// Open the group, so the new record shows.
|
|
64
|
+
if (!row.getIsExpanded?.()) row.toggleExpanded?.()
|
|
65
|
+
await tick()
|
|
66
|
+
const index = (ctrl.allRows as Array<{ original: unknown }>).findIndex((r) => r.original === next)
|
|
67
|
+
if (index >= 0) {
|
|
68
|
+
api.scrollToRow(index)
|
|
69
|
+
await tick()
|
|
70
|
+
for (const c of ctrl.allColumns as Array<{ id: string }>) {
|
|
71
|
+
if (api.startEditing(index, c.id)) break
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
ctrl.props.onRowAdd?.({ row: next })
|
|
75
|
+
}
|
|
76
|
+
/** A list value (tags) is copied, not shared with the record it came from. */
|
|
77
|
+
const copy = (v: unknown): unknown => (Array.isArray(v) ? [...v] : v)
|
|
78
|
+
</script>
|
|
79
|
+
|
|
80
|
+
<span class="sv-fgh">
|
|
81
|
+
<span class="sv-fgh-key">
|
|
82
|
+
<span class="sv-fgh-name">{label}</span>
|
|
83
|
+
<span class="sv-fgh-value">
|
|
84
|
+
{#if empty}
|
|
85
|
+
<span class="sv-fgh-empty">Empty</span>
|
|
86
|
+
{:else if draws && column}
|
|
87
|
+
<FieldCell {ctrl} row={{ id: row.id, original: records[0]?.original ?? {} }} {column} value={raw} />
|
|
88
|
+
{:else}
|
|
89
|
+
{column?.columnDef.formatter ? String(column.columnDef.formatter({ value: raw, row: records[0] ?? null, column }) ?? '') : String(raw)}
|
|
90
|
+
{/if}
|
|
91
|
+
</span>
|
|
92
|
+
</span>
|
|
93
|
+
<span class="sv-fgh-count">{records.length} {records.length === 1 ? 'record' : 'records'}</span>
|
|
94
|
+
{#each summaries as s (s.id)}
|
|
95
|
+
<span class="sv-fgh-sum"><span class="sv-fgh-sum-label">{s.label}</span>{s.text}</span>
|
|
96
|
+
{/each}
|
|
97
|
+
{#if ctrl.props.rowAdder && ctrl.editingEnabled}
|
|
98
|
+
<button
|
|
99
|
+
type="button"
|
|
100
|
+
class="sv-fgh-add"
|
|
101
|
+
aria-label={`Add a record to ${label} ${empty ? 'Empty' : String(value ?? '')}`}
|
|
102
|
+
title="Add a record to this group"
|
|
103
|
+
onclick={(e) => {
|
|
104
|
+
e.stopPropagation()
|
|
105
|
+
void add()
|
|
106
|
+
}}
|
|
107
|
+
>
|
|
108
|
+
<svg viewBox="0 0 24 24" width="14" height="14" aria-hidden="true"><path d="M12 5v14M5 12h14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" /></svg>
|
|
109
|
+
</button>
|
|
110
|
+
{/if}
|
|
111
|
+
</span>
|
|
112
|
+
|
|
113
|
+
<style>
|
|
114
|
+
.sv-fgh { display: inline-flex; align-items: center; gap: 14px; min-width: 0; }
|
|
115
|
+
.sv-fgh-key { display: inline-flex; flex-direction: column; justify-content: center; gap: 4px; line-height: 1.2; min-width: 0; }
|
|
116
|
+
.sv-fgh-name { font-size: 11px; color: var(--sg-muted, #64748b); }
|
|
117
|
+
.sv-fgh-value { display: inline-flex; align-items: center; font-weight: 600; min-height: 20px; }
|
|
118
|
+
.sv-fgh-empty { color: var(--sg-muted, #64748b); font-weight: 400; font-style: italic; }
|
|
119
|
+
.sv-fgh-count { font-size: 12px; color: var(--sg-muted, #64748b); }
|
|
120
|
+
.sv-fgh-sum { font-size: 12px; font-variant-numeric: tabular-nums; }
|
|
121
|
+
.sv-fgh-sum-label { color: var(--sg-muted, #64748b); margin-inline-end: 4px; }
|
|
122
|
+
.sv-fgh-add {
|
|
123
|
+
display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; padding: 0;
|
|
124
|
+
border: 0; border-radius: 6px; background: none; color: var(--sg-muted, #64748b); cursor: pointer;
|
|
125
|
+
}
|
|
126
|
+
.sv-fgh-add:hover { background: var(--sg-row-hover-bg, #f1f5f9); color: var(--sg-fg, #0f172a); }
|
|
127
|
+
</style>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
type Row = {
|
|
2
|
+
id: string;
|
|
3
|
+
depth: number;
|
|
4
|
+
original: Record<string, unknown>;
|
|
5
|
+
subRows?: Row[];
|
|
6
|
+
getCanExpand?: () => boolean;
|
|
7
|
+
getIsExpanded?: () => boolean;
|
|
8
|
+
toggleExpanded?: () => void;
|
|
9
|
+
__treeRow?: boolean;
|
|
10
|
+
};
|
|
11
|
+
type Col = {
|
|
12
|
+
id: string;
|
|
13
|
+
columnDef: Record<string, any>;
|
|
14
|
+
};
|
|
15
|
+
type $$ComponentProps = {
|
|
16
|
+
ctrl: any;
|
|
17
|
+
row: Row;
|
|
18
|
+
column: Col | undefined;
|
|
19
|
+
value: unknown;
|
|
20
|
+
count: number;
|
|
21
|
+
};
|
|
22
|
+
declare const GroupHeader: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
23
|
+
type GroupHeader = ReturnType<typeof GroupHeader>;
|
|
24
|
+
export default GroupHeader;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* URL, email and phone cells: the value as a link when it is a valid one of
|
|
4
|
+
* its kind (see links.ts), plain text otherwise. A plain click on the link
|
|
5
|
+
* follows it; clicking elsewhere in the cell selects it as usual.
|
|
6
|
+
*/
|
|
7
|
+
import type { FieldCellProps } from './registry.svelte'
|
|
8
|
+
import { linkHref, linkText, type LinkKind } from './links'
|
|
9
|
+
|
|
10
|
+
let { value, column }: FieldCellProps = $props()
|
|
11
|
+
const kind = $derived((column.columnDef.fieldType as LinkKind) ?? 'url')
|
|
12
|
+
const href = $derived(linkHref(kind, value))
|
|
13
|
+
const text = $derived(linkText(kind, value))
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
{#if href}
|
|
17
|
+
<a
|
|
18
|
+
class="sv-field-link"
|
|
19
|
+
{href}
|
|
20
|
+
target={kind === 'url' ? '_blank' : undefined}
|
|
21
|
+
rel={kind === 'url' ? 'noopener noreferrer' : undefined}
|
|
22
|
+
onpointerdown={(e) => e.stopPropagation()}
|
|
23
|
+
>{text}</a>
|
|
24
|
+
{:else}
|
|
25
|
+
<span class="sv-field-link-text">{text}</span>
|
|
26
|
+
{/if}
|
|
27
|
+
|
|
28
|
+
<style>
|
|
29
|
+
/* Text colour with an underline, not the accent: on themes where the accent
|
|
30
|
+
marks selection (Ember), a column of accent links reads as selected. */
|
|
31
|
+
.sv-field-link {
|
|
32
|
+
color: inherit;
|
|
33
|
+
text-decoration: underline;
|
|
34
|
+
text-decoration-color: var(--sg-muted, #94a3b8);
|
|
35
|
+
text-underline-offset: 2px;
|
|
36
|
+
overflow: hidden;
|
|
37
|
+
text-overflow: ellipsis;
|
|
38
|
+
white-space: nowrap;
|
|
39
|
+
}
|
|
40
|
+
.sv-field-link:hover { text-decoration-color: currentColor; }
|
|
41
|
+
.sv-field-link-text {
|
|
42
|
+
overflow: hidden;
|
|
43
|
+
text-overflow: ellipsis;
|
|
44
|
+
white-space: nowrap;
|
|
45
|
+
}
|
|
46
|
+
</style>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* URL, email and phone cells: the value as a link when it is a valid one of
|
|
3
|
+
* its kind (see links.ts), plain text otherwise. A plain click on the link
|
|
4
|
+
* follows it; clicking elsewhere in the cell selects it as usual.
|
|
5
|
+
*/
|
|
6
|
+
import type { FieldCellProps } from './registry.svelte.js';
|
|
7
|
+
declare const LinkCell: import("svelte").Component<FieldCellProps, {}, "">;
|
|
8
|
+
type LinkCell = ReturnType<typeof LinkCell>;
|
|
9
|
+
export default LinkCell;
|