@svgrid/enterprise 2.7.0 → 3.0.1
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 +95 -95
- package/dist/ExpressionEditorHarness.svelte.d.ts +2 -2
- package/dist/SvAdvancedFilter.svelte.d.ts +2 -2
- package/dist/SvAlertRuleEditor.svelte.d.ts +2 -2
- package/dist/SvAlertsManager.svelte.d.ts +3 -3
- package/dist/SvAlertsPanel.svelte.d.ts +1 -1
- package/dist/SvAuthGate.svelte +115 -115
- package/dist/SvAuthGate.svelte.d.ts +1 -1
- package/dist/SvBoard.svelte.d.ts +1 -1
- package/dist/SvExportMenu.svelte +553 -553
- package/dist/SvExportMenu.svelte.d.ts +2 -2
- package/dist/SvExpressionEditor.svelte.d.ts +2 -2
- package/dist/SvFileInput.svelte +113 -113
- package/dist/SvGridAlerts.svelte.d.ts +2 -2
- package/dist/SvGridBoard.svelte +2358 -2358
- package/dist/SvGridBulkEditDrawer.svelte.d.ts +1 -1
- package/dist/SvGridEditPanel.svelte +1157 -1157
- package/dist/SvGridEditPanel.svelte.d.ts +3 -3
- package/dist/SvGridMasterDetail.svelte +116 -116
- package/dist/SvGridMasterDetail.svelte.d.ts +1 -1
- package/dist/SvGridScheduler.svelte +5358 -5358
- package/dist/SvImportDialog.svelte +1020 -1020
- package/dist/SvImportDialog.svelte.d.ts +2 -2
- package/dist/SvLookupInput.svelte +180 -180
- package/dist/SvLookupInput.svelte.d.ts +1 -1
- package/dist/SvPivotDesigner.svelte +1990 -1990
- package/dist/SvPivotDesigner.svelte.d.ts +2 -2
- package/dist/SvRecordDetail.svelte.d.ts +1 -1
- package/dist/SvSchedule.svelte.d.ts +1 -1
- package/dist/SvSchemaChart.svelte +234 -234
- package/dist/SvSchemaChart.svelte.d.ts +2 -2
- package/dist/SvSchemaDashboard.svelte +130 -130
- package/dist/SvSchemaDashboard.svelte.d.ts +3 -3
- package/dist/advanced-filter/expr-columns-from-grid.d.ts +1 -1
- package/dist/advanced-filter-enable.js +3 -3
- package/dist/alerts/alert-engine-attach.d.ts +2 -2
- package/dist/alerts/alert-engine-attach.js +3 -3
- package/dist/alerts/alert-engine.d.ts +1 -1
- package/dist/alerts/alert-engine.js +2 -2
- package/dist/alerts/alert-formats.d.ts +1 -1
- package/dist/alerts/alert-formats.js +1 -1
- package/dist/alerts/alert-observer.d.ts +3 -3
- package/dist/alerts/alert-observer.js +1 -1
- package/dist/alerts/alert-storage.d.ts +1 -1
- package/dist/alerts/alert-store.svelte.d.ts +1 -1
- package/dist/alerts/alert-types.d.ts +2 -2
- package/dist/alerts.js +2 -2
- package/dist/board.js +2 -2
- package/dist/cdn/svgrid-enterprise.svelte-external.js +1162 -1145
- package/dist/designer/assets/GridMenus-B1JtIN21.js +8 -0
- package/dist/designer/assets/SvDateRangeInput-C0iCCZ8o.css +1 -0
- package/dist/designer/assets/{SvDateRangeInput-CVn-yqrQ.js → SvDateRangeInput-CjO7nn_x.js} +1 -1
- package/dist/designer/assets/SvDateTimePicker-ByBD_ov6.js +1 -0
- package/dist/designer/assets/SvDateTimePicker-DPv09DIT.css +1 -0
- package/dist/designer/assets/SvField-YDLipR6O.css +1 -0
- package/dist/designer/assets/{SvField-BsqiA5me.js → SvField-cj1PFNgZ.js} +1 -1
- package/dist/designer/assets/{preload-helper-CG0n22O7.js → SvGrid.helpers-BgT-gnCo.js} +1 -1
- package/dist/designer/assets/SvGridCellEditor-0W1L2hJ1.js +2 -0
- package/dist/designer/assets/SvGridChart-DBOR4xcz.js +2 -0
- package/dist/designer/assets/SvGridChart-fkMWeh1J.css +1 -0
- package/dist/designer/assets/SvGridChartPanel-symrhNnR.js +11 -0
- package/dist/designer/assets/SvGridChartView-BmRxq6mU.js +1 -0
- package/dist/designer/assets/SvGridChartView-DUc-1RUf.css +1 -0
- package/dist/designer/assets/SvGridDropdown-Bb3HH2Aj.js +1 -0
- package/dist/designer/assets/SvGridDropdown-CcidB3rm.css +1 -0
- package/dist/designer/assets/SvListBox-1oUF6Iav.js +110 -0
- package/dist/designer/assets/SvListBox-BXfyqy4a.css +1 -0
- package/dist/designer/assets/cell-formatting-wr5wm7US.js +1 -0
- package/dist/designer/assets/chart-DXFganU8.js +1 -0
- package/dist/designer/assets/date-format-DGagAqRc.css +1 -0
- package/dist/designer/assets/{date-format-4DJvNtG2.js → date-format-onlYDsrY.js} +1 -1
- package/dist/designer/assets/export-format-D-eP4b2l.js +6 -0
- package/dist/designer/assets/{index-BvaLmQSd.js → index-C_a9Cj8Y.js} +2984 -141
- package/dist/designer/assets/index-k2stW6L8.css +1 -0
- package/dist/designer/assets/preload-helper-HclGiUj8.js +1 -0
- package/dist/designer/assets/{row-drag-touch-IuJPEt0z.js → row-drag-touch-BdknxBNL.js} +1 -1
- package/dist/designer/assets/src-D9p27OGC.js +58 -0
- package/dist/designer/index.html +22 -22
- package/dist/export-conditional.d.ts +1 -1
- package/dist/export-print.js +19 -19
- package/dist/export-xls.d.ts +2 -2
- package/dist/export.d.ts +2 -2
- package/dist/export.js +7 -7
- package/dist/expressions/builder-tree.d.ts +2 -2
- package/dist/expressions/builder-tree.js +1 -1
- package/dist/expressions/compile.d.ts +1 -1
- package/dist/import.js +1 -1
- package/dist/index.d.ts +53 -53
- package/dist/index.js +50 -50
- package/dist/install.d.ts +4 -4
- package/dist/install.js +11 -11
- package/dist/license.d.ts +3 -2
- package/dist/license.js +9 -4
- package/dist/node/studio.js +124 -115
- package/dist/pivot-chart.d.ts +1 -1
- package/dist/pivot-designer.d.ts +1 -1
- package/dist/pivot-enable.js +3 -3
- package/dist/print.d.ts +1 -1
- package/dist/print.js +4 -4
- package/dist/scheduler-config.d.ts +5 -5
- package/dist/scheduler-freebusy.d.ts +1 -1
- package/dist/scheduler-freebusy.js +1 -1
- package/dist/scheduler.js +2 -2
- package/dist/schema-designer.d.ts +1 -1
- package/dist/schema-designer.js +2 -2
- package/dist/selection-bar.js +2 -2
- package/dist/sources/aggregate.d.ts +1 -1
- package/dist/sources/auth-supabase.js +1 -1
- package/dist/sources/dashboard.d.ts +2 -2
- package/dist/sources/dashboard.js +1 -1
- package/dist/sources/index.d.ts +13 -13
- package/dist/sources/index.js +13 -13
- package/dist/sources/realtime-supabase.js +1 -1
- package/dist/sources/relation-lookup.d.ts +1 -1
- package/dist/sources/relation-lookup.js +1 -1
- package/dist/sources/rest-adapters.d.ts +1 -1
- package/dist/sources/rest-adapters.js +1 -1
- package/dist/sources/rest.d.ts +2 -2
- package/dist/sources/rest.js +3 -3
- package/dist/sources/supabase.d.ts +2 -2
- package/dist/sources/supabase.js +3 -3
- package/dist/sources/with-entity-rules.d.ts +1 -1
- package/dist/sources/with-entity-rules.js +1 -1
- package/dist/sources/with-relation-labels.d.ts +1 -1
- package/dist/studio/emit-project.js +2161 -2127
- package/dist/studio/emit-schema.js +369 -369
- package/dist/studio/index.d.ts +1 -1
- package/dist/studio/index.js +1 -1
- package/dist/studio/introspect-db.js +45 -45
- package/dist/studio/project.d.ts +10 -0
- package/dist/studio/samples/crm.js +6 -6
- package/dist/studio/samples/fleet.js +7 -7
- package/dist/studio/samples/insurance.js +9 -9
- package/dist/studio/samples/inventory.js +12 -12
- package/dist/studio/samples/projects.js +5 -5
- package/dist/studio/samples/support.js +8 -8
- package/dist/studio/scaffold-app.js +104 -104
- package/dist/studio/scaffold.js +151 -151
- package/dist/studio/ui-components.d.ts +7 -0
- package/dist/studio/ui-components.js +35 -0
- package/dist/sveltekit/in-memory.d.ts +3 -3
- package/dist/sveltekit/in-memory.js +4 -4
- package/dist/sveltekit/index.d.ts +6 -6
- package/dist/sveltekit/index.js +5 -5
- package/dist/sveltekit/query-plan.d.ts +1 -1
- package/dist/sveltekit/sql-source.d.ts +4 -4
- package/dist/sveltekit/sql-source.js +4 -4
- package/dist/sveltekit/sql.d.ts +1 -1
- package/dist/sveltekit/transport.d.ts +2 -2
- package/dist/sveltekit/transport.js +1 -1
- package/dist/upgrade-prompt.js +25 -25
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +6 -3
- package/dist/designer/assets/GridMenus-Cgilexpk.js +0 -8
- package/dist/designer/assets/SvDateRangeInput-BV5OXYQ2.css +0 -1
- package/dist/designer/assets/SvDateTimePicker-BdioTrJQ.js +0 -1
- package/dist/designer/assets/SvDateTimePicker-CY8TK4BT.css +0 -1
- package/dist/designer/assets/SvField-BF-9TJSd.css +0 -1
- package/dist/designer/assets/SvGridCellEditor-dLY7_kk9.js +0 -2
- package/dist/designer/assets/SvGridChart-BEDNTdc5.js +0 -2
- package/dist/designer/assets/SvGridChart-Vu4Nvjiv.css +0 -1
- package/dist/designer/assets/SvGridChartPanel-x3lzSxuf.js +0 -10
- package/dist/designer/assets/SvGridChartView-CAKhPELi.js +0 -1
- package/dist/designer/assets/SvGridChartView-DX9HfkBR.css +0 -1
- package/dist/designer/assets/SvGridDropdown-CAYG7Y-O.js +0 -1
- package/dist/designer/assets/SvGridDropdown-Crwb2P3Q.css +0 -1
- package/dist/designer/assets/SvListBox-CVYQcLX9.js +0 -1
- package/dist/designer/assets/SvListBox-DgN8kvjt.css +0 -1
- package/dist/designer/assets/chart-DHEgt4lN.js +0 -1
- package/dist/designer/assets/date-format-Dzy4mTGh.css +0 -1
- package/dist/designer/assets/export-format-DwjuTfrQ.js +0 -6
- package/dist/designer/assets/index-Cp7fDJ3b.css +0 -1
- package/dist/designer/assets/js-scroller.svelte-Bhxqb3-c.js +0 -110
- package/dist/designer/assets/src-7qOYsBug.js +0 -2896
- package/dist/designer/assets/src-B7DNcoQK.css +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/_svelte_metadata.json +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/_metadata.json +0 -178
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/attachments-BOv1rBKp.js +0 -3875
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/attachments-BOv1rBKp.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/constants-B9vgIdCd.js +0 -21
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/constants-B9vgIdCd.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/dev-T1qbW_qD.js +0 -1938
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/dev-T1qbW_qD.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/events-Bo11SfVK.js +0 -205
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/events-Bo11SfVK.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/flags-X7D4vfrZ.js +0 -18
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/flags-X7D4vfrZ.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/hydration-oyUje5i1.js +0 -264
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/hydration-oyUje5i1.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/legacy-client-DeSQgSFm.js +0 -697
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/legacy-client-DeSQgSFm.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/package.json +0 -3
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte.js +0 -134
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_animate.js +0 -55
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_animate.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_attachments.js +0 -2
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_compiler.js +0 -46843
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_compiler.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_easing.js +0 -237
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_easing.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_events.js +0 -2
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal.js +0 -4
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_client.js +0 -7
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_disclose-version.js +0 -4
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_disclose-version.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_async.js +0 -5
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_async.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_legacy.js +0 -5
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_legacy.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_tracing.js +0 -5
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_tracing.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_server.js +0 -6
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_legacy.js +0 -83
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_legacy.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_motion.js +0 -559
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_motion.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_reactivity.js +0 -24
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_reactivity.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_reactivity_window.js +0 -122
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_reactivity_window.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_server.js +0 -2
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_store.js +0 -89
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_store.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_transition.js +0 -241
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_transition.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/utils-BbWyXNk1.js +0 -4938
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/utils-BbWyXNk1.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/utils-DI_fC7vt.js +0 -495
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/utils-DI_fC7vt.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/validate-Dyr3lQv9.js +0 -190
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/validate-Dyr3lQv9.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/version-_9FHH-LF.js +0 -8
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/version-_9FHH-LF.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/warnings-CUbSPnyP.js +0 -138
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/warnings-CUbSPnyP.js.map +0 -1
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
* rest of the suite.
|
|
18
18
|
*/
|
|
19
19
|
import type { RowData, TableFeatures } from '@svgrid/grid';
|
|
20
|
-
import type { EnterpriseGridApi } from './install';
|
|
21
|
-
import { type ImportResult, type ImportValidator } from './import';
|
|
20
|
+
import type { EnterpriseGridApi } from './install.js';
|
|
21
|
+
import { type ImportResult, type ImportValidator } from './import.js';
|
|
22
22
|
declare function $$render<TFeatures extends TableFeatures, TData extends RowData>(): {
|
|
23
23
|
props: {
|
|
24
24
|
api: EnterpriseGridApi<TFeatures, TData> | null | undefined;
|
|
@@ -1,180 +1,180 @@
|
|
|
1
|
-
<script module lang="ts">
|
|
2
|
-
let lookupUid = 0
|
|
3
|
-
</script>
|
|
4
|
-
|
|
5
|
-
<script lang="ts">
|
|
6
|
-
/**
|
|
7
|
-
* SvLookupInput - a searchable single-select for a foreign-key ("lookup")
|
|
8
|
-
* field. It searches the related entity through a `RelationLookup`, shows human
|
|
9
|
-
* labels, and stores the selected key. Used by SvGridEditPanel for `relation`
|
|
10
|
-
* fields, and usable on its own.
|
|
11
|
-
*/
|
|
12
|
-
import type { RelationLookup, RelationOption } from './sources/relation-lookup'
|
|
13
|
-
|
|
14
|
-
type Props = {
|
|
15
|
-
value: unknown
|
|
16
|
-
lookup: RelationLookup
|
|
17
|
-
onSelect: (value: string) => void
|
|
18
|
-
id?: string
|
|
19
|
-
placeholder?: string
|
|
20
|
-
disabled?: boolean
|
|
21
|
-
required?: boolean
|
|
22
|
-
/** Debounce for the search query, ms. Default 200. */
|
|
23
|
-
debounceMs?: number
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
let {
|
|
27
|
-
value,
|
|
28
|
-
lookup,
|
|
29
|
-
onSelect,
|
|
30
|
-
id,
|
|
31
|
-
placeholder = 'Search…',
|
|
32
|
-
disabled = false,
|
|
33
|
-
required = false,
|
|
34
|
-
debounceMs = 200,
|
|
35
|
-
}: Props = $props()
|
|
36
|
-
|
|
37
|
-
// Stable listbox id so the combobox input can reference it via aria-controls.
|
|
38
|
-
const listboxId = `sv-lookup-list-${++lookupUid}`
|
|
39
|
-
let open = $state(false)
|
|
40
|
-
let query = $state('')
|
|
41
|
-
let options = $state<RelationOption[]>([])
|
|
42
|
-
let loading = $state(false)
|
|
43
|
-
let active = $state(-1)
|
|
44
|
-
let label = $state('')
|
|
45
|
-
let rootEl: HTMLDivElement | undefined = $state()
|
|
46
|
-
|
|
47
|
-
let searchTimer: ReturnType<typeof setTimeout> | undefined
|
|
48
|
-
let labelToken = 0
|
|
49
|
-
let searchToken = 0
|
|
50
|
-
|
|
51
|
-
// Resolve the current value's label whenever it changes (and we're not typing).
|
|
52
|
-
$effect(() => {
|
|
53
|
-
const v = value
|
|
54
|
-
if (v == null || v === '') { label = ''; return }
|
|
55
|
-
const token = ++labelToken
|
|
56
|
-
lookup.labelFor(v).then((l) => {
|
|
57
|
-
if (token === labelToken) label = l ?? String(v)
|
|
58
|
-
})
|
|
59
|
-
})
|
|
60
|
-
|
|
61
|
-
async function runSearch(q: string) {
|
|
62
|
-
const token = ++searchToken
|
|
63
|
-
loading = true
|
|
64
|
-
try {
|
|
65
|
-
const res = await lookup.search(q)
|
|
66
|
-
if (token === searchToken) { options = res; active = res.length ? 0 : -1 }
|
|
67
|
-
} finally {
|
|
68
|
-
if (token === searchToken) loading = false
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
function openList() {
|
|
73
|
-
if (disabled) return
|
|
74
|
-
open = true
|
|
75
|
-
query = ''
|
|
76
|
-
runSearch('')
|
|
77
|
-
}
|
|
78
|
-
function closeList() {
|
|
79
|
-
open = false
|
|
80
|
-
query = ''
|
|
81
|
-
if (searchTimer) clearTimeout(searchTimer)
|
|
82
|
-
}
|
|
83
|
-
function onInput(e: Event) {
|
|
84
|
-
query = (e.currentTarget as HTMLInputElement).value
|
|
85
|
-
open = true
|
|
86
|
-
if (searchTimer) clearTimeout(searchTimer)
|
|
87
|
-
searchTimer = setTimeout(() => runSearch(query), debounceMs)
|
|
88
|
-
}
|
|
89
|
-
function choose(opt: RelationOption) {
|
|
90
|
-
label = opt.label
|
|
91
|
-
onSelect(opt.value)
|
|
92
|
-
closeList()
|
|
93
|
-
}
|
|
94
|
-
function clear() {
|
|
95
|
-
onSelect('')
|
|
96
|
-
label = ''
|
|
97
|
-
closeList()
|
|
98
|
-
}
|
|
99
|
-
function onKeydown(e: KeyboardEvent) {
|
|
100
|
-
if (!open && (e.key === 'ArrowDown' || e.key === 'Enter')) { openList(); return }
|
|
101
|
-
if (e.key === 'ArrowDown') { e.preventDefault(); active = Math.min(active + 1, options.length - 1) }
|
|
102
|
-
else if (e.key === 'ArrowUp') { e.preventDefault(); active = Math.max(active - 1, 0) }
|
|
103
|
-
else if (e.key === 'Enter') { if (open && options[active]) { e.preventDefault(); choose(options[active]) } }
|
|
104
|
-
else if (e.key === 'Escape') { if (open) { e.preventDefault(); closeList() } }
|
|
105
|
-
}
|
|
106
|
-
function onDocClick(e: MouseEvent) {
|
|
107
|
-
if (open && rootEl && !rootEl.contains(e.target as Node)) closeList()
|
|
108
|
-
}
|
|
109
|
-
</script>
|
|
110
|
-
|
|
111
|
-
<svelte:document onclick={onDocClick} />
|
|
112
|
-
|
|
113
|
-
<div class="sv-lookup" bind:this={rootEl}>
|
|
114
|
-
<div class="sv-lookup__control">
|
|
115
|
-
<input
|
|
116
|
-
{id}
|
|
117
|
-
class="sv-lookup__input"
|
|
118
|
-
type="text"
|
|
119
|
-
role="combobox"
|
|
120
|
-
aria-expanded={open}
|
|
121
|
-
aria-controls={listboxId}
|
|
122
|
-
aria-autocomplete="list"
|
|
123
|
-
autocomplete="off"
|
|
124
|
-
{placeholder}
|
|
125
|
-
{disabled}
|
|
126
|
-
{required}
|
|
127
|
-
value={open ? query : label}
|
|
128
|
-
onfocus={openList}
|
|
129
|
-
oninput={onInput}
|
|
130
|
-
onkeydown={onKeydown}
|
|
131
|
-
/>
|
|
132
|
-
{#if value != null && value !== '' && !required && !disabled}
|
|
133
|
-
<button type="button" class="sv-lookup__clear" title="Clear" aria-label="Clear" onclick={clear}>×</button>
|
|
134
|
-
{/if}
|
|
135
|
-
</div>
|
|
136
|
-
|
|
137
|
-
<ul class="sv-lookup__menu" role="listbox" id={listboxId} hidden={!open}>
|
|
138
|
-
{#if loading}
|
|
139
|
-
<li class="sv-lookup__msg">Searching…</li>
|
|
140
|
-
{:else if options.length === 0}
|
|
141
|
-
<li class="sv-lookup__msg">No matches</li>
|
|
142
|
-
{:else}
|
|
143
|
-
{#each options as opt, i (opt.value)}
|
|
144
|
-
<li>
|
|
145
|
-
<button
|
|
146
|
-
type="button"
|
|
147
|
-
role="option"
|
|
148
|
-
aria-selected={i === active}
|
|
149
|
-
class="sv-lookup__opt"
|
|
150
|
-
class:is-active={i === active}
|
|
151
|
-
onmouseenter={() => (active = i)}
|
|
152
|
-
onclick={() => choose(opt)}
|
|
153
|
-
>{opt.label}</button>
|
|
154
|
-
</li>
|
|
155
|
-
{/each}
|
|
156
|
-
{/if}
|
|
157
|
-
</ul>
|
|
158
|
-
</div>
|
|
159
|
-
|
|
160
|
-
<style>
|
|
161
|
-
.sv-lookup { position: relative; }
|
|
162
|
-
.sv-lookup__control { position: relative; display: flex; align-items: center; }
|
|
163
|
-
.sv-lookup__input { width: 100%; }
|
|
164
|
-
.sv-lookup__clear {
|
|
165
|
-
position: absolute; right: 6px; border: none; background: none; cursor: pointer;
|
|
166
|
-
font-size: 16px; line-height: 1; color: var(--sg-muted, #888); padding: 2px 4px;
|
|
167
|
-
}
|
|
168
|
-
.sv-lookup__menu {
|
|
169
|
-
position: absolute; z-index: 30; top: calc(100% + 2px); left: 0; right: 0; margin: 0; padding: 4px;
|
|
170
|
-
list-style: none; max-height: 220px; overflow: auto;
|
|
171
|
-
background: var(--sg-bg, #fff); border: 1px solid var(--sg-border, #ddd); border-radius: 8px;
|
|
172
|
-
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
|
|
173
|
-
}
|
|
174
|
-
.sv-lookup__opt {
|
|
175
|
-
display: block; width: 100%; text-align: left; padding: 7px 10px; border: none; border-radius: 6px;
|
|
176
|
-
background: none; cursor: pointer; font: inherit; color: var(--sg-fg, inherit);
|
|
177
|
-
}
|
|
178
|
-
.sv-lookup__opt.is-active { background: var(--sg-accent, #2563eb); color: #fff; }
|
|
179
|
-
.sv-lookup__msg { padding: 8px 10px; color: var(--sg-muted, #888); font-size: 13px; }
|
|
180
|
-
</style>
|
|
1
|
+
<script module lang="ts">
|
|
2
|
+
let lookupUid = 0
|
|
3
|
+
</script>
|
|
4
|
+
|
|
5
|
+
<script lang="ts">
|
|
6
|
+
/**
|
|
7
|
+
* SvLookupInput - a searchable single-select for a foreign-key ("lookup")
|
|
8
|
+
* field. It searches the related entity through a `RelationLookup`, shows human
|
|
9
|
+
* labels, and stores the selected key. Used by SvGridEditPanel for `relation`
|
|
10
|
+
* fields, and usable on its own.
|
|
11
|
+
*/
|
|
12
|
+
import type { RelationLookup, RelationOption } from './sources/relation-lookup'
|
|
13
|
+
|
|
14
|
+
type Props = {
|
|
15
|
+
value: unknown
|
|
16
|
+
lookup: RelationLookup
|
|
17
|
+
onSelect: (value: string) => void
|
|
18
|
+
id?: string
|
|
19
|
+
placeholder?: string
|
|
20
|
+
disabled?: boolean
|
|
21
|
+
required?: boolean
|
|
22
|
+
/** Debounce for the search query, ms. Default 200. */
|
|
23
|
+
debounceMs?: number
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
let {
|
|
27
|
+
value,
|
|
28
|
+
lookup,
|
|
29
|
+
onSelect,
|
|
30
|
+
id,
|
|
31
|
+
placeholder = 'Search…',
|
|
32
|
+
disabled = false,
|
|
33
|
+
required = false,
|
|
34
|
+
debounceMs = 200,
|
|
35
|
+
}: Props = $props()
|
|
36
|
+
|
|
37
|
+
// Stable listbox id so the combobox input can reference it via aria-controls.
|
|
38
|
+
const listboxId = `sv-lookup-list-${++lookupUid}`
|
|
39
|
+
let open = $state(false)
|
|
40
|
+
let query = $state('')
|
|
41
|
+
let options = $state<RelationOption[]>([])
|
|
42
|
+
let loading = $state(false)
|
|
43
|
+
let active = $state(-1)
|
|
44
|
+
let label = $state('')
|
|
45
|
+
let rootEl: HTMLDivElement | undefined = $state()
|
|
46
|
+
|
|
47
|
+
let searchTimer: ReturnType<typeof setTimeout> | undefined
|
|
48
|
+
let labelToken = 0
|
|
49
|
+
let searchToken = 0
|
|
50
|
+
|
|
51
|
+
// Resolve the current value's label whenever it changes (and we're not typing).
|
|
52
|
+
$effect(() => {
|
|
53
|
+
const v = value
|
|
54
|
+
if (v == null || v === '') { label = ''; return }
|
|
55
|
+
const token = ++labelToken
|
|
56
|
+
lookup.labelFor(v).then((l) => {
|
|
57
|
+
if (token === labelToken) label = l ?? String(v)
|
|
58
|
+
})
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
async function runSearch(q: string) {
|
|
62
|
+
const token = ++searchToken
|
|
63
|
+
loading = true
|
|
64
|
+
try {
|
|
65
|
+
const res = await lookup.search(q)
|
|
66
|
+
if (token === searchToken) { options = res; active = res.length ? 0 : -1 }
|
|
67
|
+
} finally {
|
|
68
|
+
if (token === searchToken) loading = false
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function openList() {
|
|
73
|
+
if (disabled) return
|
|
74
|
+
open = true
|
|
75
|
+
query = ''
|
|
76
|
+
runSearch('')
|
|
77
|
+
}
|
|
78
|
+
function closeList() {
|
|
79
|
+
open = false
|
|
80
|
+
query = ''
|
|
81
|
+
if (searchTimer) clearTimeout(searchTimer)
|
|
82
|
+
}
|
|
83
|
+
function onInput(e: Event) {
|
|
84
|
+
query = (e.currentTarget as HTMLInputElement).value
|
|
85
|
+
open = true
|
|
86
|
+
if (searchTimer) clearTimeout(searchTimer)
|
|
87
|
+
searchTimer = setTimeout(() => runSearch(query), debounceMs)
|
|
88
|
+
}
|
|
89
|
+
function choose(opt: RelationOption) {
|
|
90
|
+
label = opt.label
|
|
91
|
+
onSelect(opt.value)
|
|
92
|
+
closeList()
|
|
93
|
+
}
|
|
94
|
+
function clear() {
|
|
95
|
+
onSelect('')
|
|
96
|
+
label = ''
|
|
97
|
+
closeList()
|
|
98
|
+
}
|
|
99
|
+
function onKeydown(e: KeyboardEvent) {
|
|
100
|
+
if (!open && (e.key === 'ArrowDown' || e.key === 'Enter')) { openList(); return }
|
|
101
|
+
if (e.key === 'ArrowDown') { e.preventDefault(); active = Math.min(active + 1, options.length - 1) }
|
|
102
|
+
else if (e.key === 'ArrowUp') { e.preventDefault(); active = Math.max(active - 1, 0) }
|
|
103
|
+
else if (e.key === 'Enter') { if (open && options[active]) { e.preventDefault(); choose(options[active]) } }
|
|
104
|
+
else if (e.key === 'Escape') { if (open) { e.preventDefault(); closeList() } }
|
|
105
|
+
}
|
|
106
|
+
function onDocClick(e: MouseEvent) {
|
|
107
|
+
if (open && rootEl && !rootEl.contains(e.target as Node)) closeList()
|
|
108
|
+
}
|
|
109
|
+
</script>
|
|
110
|
+
|
|
111
|
+
<svelte:document onclick={onDocClick} />
|
|
112
|
+
|
|
113
|
+
<div class="sv-lookup" bind:this={rootEl}>
|
|
114
|
+
<div class="sv-lookup__control">
|
|
115
|
+
<input
|
|
116
|
+
{id}
|
|
117
|
+
class="sv-lookup__input"
|
|
118
|
+
type="text"
|
|
119
|
+
role="combobox"
|
|
120
|
+
aria-expanded={open}
|
|
121
|
+
aria-controls={listboxId}
|
|
122
|
+
aria-autocomplete="list"
|
|
123
|
+
autocomplete="off"
|
|
124
|
+
{placeholder}
|
|
125
|
+
{disabled}
|
|
126
|
+
{required}
|
|
127
|
+
value={open ? query : label}
|
|
128
|
+
onfocus={openList}
|
|
129
|
+
oninput={onInput}
|
|
130
|
+
onkeydown={onKeydown}
|
|
131
|
+
/>
|
|
132
|
+
{#if value != null && value !== '' && !required && !disabled}
|
|
133
|
+
<button type="button" class="sv-lookup__clear" title="Clear" aria-label="Clear" onclick={clear}>×</button>
|
|
134
|
+
{/if}
|
|
135
|
+
</div>
|
|
136
|
+
|
|
137
|
+
<ul class="sv-lookup__menu" role="listbox" id={listboxId} hidden={!open}>
|
|
138
|
+
{#if loading}
|
|
139
|
+
<li class="sv-lookup__msg">Searching…</li>
|
|
140
|
+
{:else if options.length === 0}
|
|
141
|
+
<li class="sv-lookup__msg">No matches</li>
|
|
142
|
+
{:else}
|
|
143
|
+
{#each options as opt, i (opt.value)}
|
|
144
|
+
<li>
|
|
145
|
+
<button
|
|
146
|
+
type="button"
|
|
147
|
+
role="option"
|
|
148
|
+
aria-selected={i === active}
|
|
149
|
+
class="sv-lookup__opt"
|
|
150
|
+
class:is-active={i === active}
|
|
151
|
+
onmouseenter={() => (active = i)}
|
|
152
|
+
onclick={() => choose(opt)}
|
|
153
|
+
>{opt.label}</button>
|
|
154
|
+
</li>
|
|
155
|
+
{/each}
|
|
156
|
+
{/if}
|
|
157
|
+
</ul>
|
|
158
|
+
</div>
|
|
159
|
+
|
|
160
|
+
<style>
|
|
161
|
+
.sv-lookup { position: relative; }
|
|
162
|
+
.sv-lookup__control { position: relative; display: flex; align-items: center; }
|
|
163
|
+
.sv-lookup__input { width: 100%; }
|
|
164
|
+
.sv-lookup__clear {
|
|
165
|
+
position: absolute; right: 6px; border: none; background: none; cursor: pointer;
|
|
166
|
+
font-size: 16px; line-height: 1; color: var(--sg-muted, #888); padding: 2px 4px;
|
|
167
|
+
}
|
|
168
|
+
.sv-lookup__menu {
|
|
169
|
+
position: absolute; z-index: 30; top: calc(100% + 2px); left: 0; right: 0; margin: 0; padding: 4px;
|
|
170
|
+
list-style: none; max-height: 220px; overflow: auto;
|
|
171
|
+
background: var(--sg-bg, #fff); border: 1px solid var(--sg-border, #ddd); border-radius: 8px;
|
|
172
|
+
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
|
|
173
|
+
}
|
|
174
|
+
.sv-lookup__opt {
|
|
175
|
+
display: block; width: 100%; text-align: left; padding: 7px 10px; border: none; border-radius: 6px;
|
|
176
|
+
background: none; cursor: pointer; font: inherit; color: var(--sg-fg, inherit);
|
|
177
|
+
}
|
|
178
|
+
.sv-lookup__opt.is-active { background: var(--sg-accent, #2563eb); color: #fff; }
|
|
179
|
+
.sv-lookup__msg { padding: 8px 10px; color: var(--sg-muted, #888); font-size: 13px; }
|
|
180
|
+
</style>
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* labels, and stores the selected key. Used by SvGridEditPanel for `relation`
|
|
5
5
|
* fields, and usable on its own.
|
|
6
6
|
*/
|
|
7
|
-
import type { RelationLookup } from './sources/relation-lookup';
|
|
7
|
+
import type { RelationLookup } from './sources/relation-lookup.js';
|
|
8
8
|
type Props = {
|
|
9
9
|
value: unknown;
|
|
10
10
|
lookup: RelationLookup;
|