@svgrid/enterprise 3.0.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 +1161 -1144
- 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-zUBix-JQ.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/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 +123 -114
- 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/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-B7DNcoQK.css +0 -1
- package/dist/designer/assets/src-BoYyigAC.js +0 -2896
- 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
package/dist/studio/index.d.ts
CHANGED
|
@@ -27,7 +27,7 @@ export { generateValue, generateRows } from './sample-data.js';
|
|
|
27
27
|
export { studioThemes, defaultStudioTheme, getStudioTheme, resolveThemeTokens, resolveThemeTokensFor, isDarkTheme, themeStyleString, type StudioTheme } from './themes.js';
|
|
28
28
|
export { createProject, defaultScreenFor, defaultBlockConfig, gridColumns, entityOf, blockPalette, addBlock, addBlockAt, addComponentBlock, removeBlock, duplicateBlock, moveBlock, reorderBlock, updateBlock, addEntity, removeEntity, updateEntity, formPlan, setEntityForm, setFormColumns, addFormSection, updateFormSection, removeFormSection, moveFormSection, moveFormField, moveFormFields, setFieldConditions, updateEntityField, setFieldInput, setFieldHidden, formControlsFor, formControlSettings, suggestFormSections, addScreen, addFreestandingScreen, addScreenAction, removeScreenAction, enableScreenCode, disableScreenCode, setScreenRenderGrid, screenLayoutOf, buildDockLayout, reconcileDock, syncDockPanes, setScreenLayout, isPaneLayout, PANE_LAYOUTS, buildCanvasLayout, canvasRectOf, setCanvasRect, CANVAS_COLS, CANVAS_ROW_PX, CANVAS_GAP_PX, type CanvasRect, applyGridPreset, gridPresetLabel, GRID_PRESETS, setScreenDock, reseedScreenDock, setDockPaneTitle, dockPaneTitleOf, dockPaneIds, setLayoutOpts, gridOpts, stackOpts, splitOpts, dockOpts, canvasOpts, type ScreenLayout, type GridPreset, type LayoutOpts, type GridLayoutOpts, type StackLayoutOpts, type SplitLayoutOpts, type DockLayoutOpts, type CanvasLayoutOpts, setHandlerBody, setScreenHandlersSource, setHandlerSteps, addHandlerStep, updateHandlerStep, moveHandlerStep, stepsToCode, compileStep, compileHandlerSteps, compileValue, compileCondition, compileTriggerStep, compileTriggerSteps, triggersOf, setTrigger, TRIGGER_EVENTS, type TriggerStep, type TriggerEvent, type EntityTriggers, setJob, type ScheduledJob, type ScheduledJobKind, setTenancy, tenantField, isTenantScoped, type TenancyConfig, clickSlot, ssrScreenShape, ssrEligible, withSsrDefaults, setScreenRenderMode, eventSlot, rowSelectSlot, changeSlot, FORM_SUBMIT, GRID_EVENTS, type GridEventDef, addStateVar, updateStateVar, removeStateVar, stateInitExpr, stateTsType, type ActionStep, type ActionStepType, type StateVar, type StateVarType, type LogicValue, type LogicOp, type Condition, type FieldValue, setComponentName, setComponentBinding, componentHasBindings, componentHandleName, ON_LOAD, removeScreen, updateScreen, duplicateScreen, reorderScreen, insertBlock, setDataSource, setDeployTarget, setAuth, setDataLayer, seedUsers, defaultEntitySource, flattenBlocks, TAB_CHILD_KINDS, CONTAINER_CHILD_KINDS, CONTAINER_DISPLAY_KINDS, addTab, removeTab, renameTab, addTabBlock, addTabComponent, removeTabBlock, addAccordionSection, removeAccordionSection, renameAccordionSection, setAccordionMultiple, addAccordionBlock, addAccordionComponent, removeAccordionBlock, setEntityDataSource, entityDataSource, setTheme, setThemePreset, setShell, sanitizeProject, screenFromTemplate, addScreenFromTemplate, serializeProject, parseProject, validateProject, isProjectValid, blockColumns, blockStyleCss, blockClassName, sanitizeClassName, mergeBlockStyle, type BlockStyle, roleCanScreen, roleCanAction, CRUD_ACTIONS, type CrudAction, type RoleAccess, type AccessControl, type AuthConfig, type OAuthProvider, type SeedUser, type I18nConfig, type DeployTarget, type StudioProject, type Screen, type ScreenNav, type Block, type BlockKind, type BlockConfig, type GridConfig, type GridColumnConfig, type ColumnFormat, type ColumnCellType, type GridExportConfig, type GridFilterUi, type TreeDataConfig, type SchedulerViewConfig, type SchedulerViewMode, type RowLink, type RowAction, type RowActionKind, type ActionConfig, type ComponentConfig, type ComponentBinding, type FormatOp, type FormatRule, type GridEditing, type GridDensity, type GridAlign, type PagerPosition, type FormConfig, type ChartConfig, type KpiConfig, type KpiFormat, type GaugeConfig, type TreeConfig, type TabsConfig, type StudioTab, type AccordionConfig, type AccordionSection, type DashboardConfig, type MasterDetailConfig, type LookupConfig, type PivotConfig, type FilterPanelConfig, type RecordConfig, type BoardConfig, type CalendarConfig, type DetailConfig, type DetailRelated, type Reduce, type DataSourceKind, type EntityDataSource, type MemorySource, type RestSource, type RestAdapterConfig, type SqlSource, type SupabaseSource, type PgliteSource, type RestMethod, type ParamLocation, type ParamType, type RequestParam, type SqlDialectKind, type ProjectTheme, type ShellConfig, type ShellStyle, type ScreenTemplate, type PaletteItem, type ProjectIssue, } from './project.js';
|
|
29
29
|
export { verifyScaffold, summarizeVerify, type VerifyResult, type VerifyIssue, type VerifySeverity, } from './verify.js';
|
|
30
|
-
export { UI_COMPONENT_REGISTRY, uiComponentSpec, gridPropSurface, gridApiSettableProps, GRID_CURATED_PROPS, STANDARD_UI_EVENTS, type UiPropType, type UiPropGroup, type UiComponentEvent, type UiComponentProp, type UiComponentSpec, } from './ui-components.js';
|
|
30
|
+
export { UI_COMPONENT_REGISTRY, uiComponentSpec, gridPropSurface, gridApiSettableProps, gridIconGroups, GRID_CURATED_PROPS, STANDARD_UI_EVENTS, type UiPropType, type UiPropGroup, type UiComponentEvent, type UiComponentProp, type UiComponentSpec, } from './ui-components.js';
|
|
31
31
|
export { buildCopilotMessages, projectFromModelText, type CopilotMessages } from './copilot-core.js';
|
|
32
32
|
export { resolveDeployTarget, deployCommands, missingEnvKeys, type DeployProvider, type DeployResolution, type DeployPlanCommands, } from './deploy-cli.js';
|
|
33
33
|
export { runStudioAdd, runStudioAddApp, resolveSchema, resolveSchemas, type StudioIO, type AddOptions, type AddResult, type AddAppResult, } from './cli.js';
|
package/dist/studio/index.js
CHANGED
|
@@ -30,7 +30,7 @@ export { createProject, defaultScreenFor, defaultBlockConfig, gridColumns, entit
|
|
|
30
30
|
// `form` so a built form travels with the entity rather than with one block.
|
|
31
31
|
formPlan, setEntityForm, setFormColumns, addFormSection, updateFormSection, removeFormSection, moveFormSection, moveFormField, moveFormFields, setFieldConditions, updateEntityField, setFieldInput, setFieldHidden, formControlsFor, formControlSettings, suggestFormSections, addScreen, addFreestandingScreen, addScreenAction, removeScreenAction, enableScreenCode, disableScreenCode, setScreenRenderGrid, screenLayoutOf, buildDockLayout, reconcileDock, syncDockPanes, setScreenLayout, isPaneLayout, PANE_LAYOUTS, buildCanvasLayout, canvasRectOf, setCanvasRect, CANVAS_COLS, CANVAS_ROW_PX, CANVAS_GAP_PX, applyGridPreset, gridPresetLabel, GRID_PRESETS, setScreenDock, reseedScreenDock, setDockPaneTitle, dockPaneTitleOf, dockPaneIds, setLayoutOpts, gridOpts, stackOpts, splitOpts, dockOpts, canvasOpts, setHandlerBody, setScreenHandlersSource, setHandlerSteps, addHandlerStep, updateHandlerStep, moveHandlerStep, stepsToCode, compileStep, compileHandlerSteps, compileValue, compileCondition, compileTriggerStep, compileTriggerSteps, triggersOf, setTrigger, TRIGGER_EVENTS, setJob, setTenancy, tenantField, isTenantScoped, clickSlot, ssrScreenShape, ssrEligible, withSsrDefaults, setScreenRenderMode, eventSlot, rowSelectSlot, changeSlot, FORM_SUBMIT, GRID_EVENTS, addStateVar, updateStateVar, removeStateVar, stateInitExpr, stateTsType, setComponentName, setComponentBinding, componentHasBindings, componentHandleName, ON_LOAD, removeScreen, updateScreen, duplicateScreen, reorderScreen, insertBlock, setDataSource, setDeployTarget, setAuth, setDataLayer, seedUsers, defaultEntitySource, flattenBlocks, TAB_CHILD_KINDS, CONTAINER_CHILD_KINDS, CONTAINER_DISPLAY_KINDS, addTab, removeTab, renameTab, addTabBlock, addTabComponent, removeTabBlock, addAccordionSection, removeAccordionSection, renameAccordionSection, setAccordionMultiple, addAccordionBlock, addAccordionComponent, removeAccordionBlock, setEntityDataSource, entityDataSource, setTheme, setThemePreset, setShell, sanitizeProject, screenFromTemplate, addScreenFromTemplate, serializeProject, parseProject, validateProject, isProjectValid, blockColumns, blockStyleCss, blockClassName, sanitizeClassName, mergeBlockStyle, roleCanScreen, roleCanAction, CRUD_ACTIONS, } from './project.js';
|
|
32
32
|
export { verifyScaffold, summarizeVerify, } from './verify.js';
|
|
33
|
-
export { UI_COMPONENT_REGISTRY, uiComponentSpec, gridPropSurface, gridApiSettableProps, GRID_CURATED_PROPS, STANDARD_UI_EVENTS, } from './ui-components.js';
|
|
33
|
+
export { UI_COMPONENT_REGISTRY, uiComponentSpec, gridPropSurface, gridApiSettableProps, gridIconGroups, GRID_CURATED_PROPS, STANDARD_UI_EVENTS, } from './ui-components.js';
|
|
34
34
|
export { buildCopilotMessages, projectFromModelText } from './copilot-core.js';
|
|
35
35
|
export { resolveDeployTarget, deployCommands, missingEnvKeys, } from './deploy-cli.js';
|
|
36
36
|
export { runStudioAdd, runStudioAddApp, resolveSchema, resolveSchemas, } from './cli.js';
|
|
@@ -59,34 +59,34 @@ function sqliteFks(rows) {
|
|
|
59
59
|
}
|
|
60
60
|
const POSTGRES = {
|
|
61
61
|
columns: (table) => ({
|
|
62
|
-
sql: `SELECT c.column_name AS name, c.data_type AS type,
|
|
63
|
-
CASE WHEN c.is_nullable = 'YES' THEN 1 ELSE 0 END AS nullable,
|
|
64
|
-
CASE WHEN pk.column_name IS NOT NULL THEN 1 ELSE 0 END AS pk
|
|
65
|
-
FROM information_schema.columns c
|
|
66
|
-
LEFT JOIN (
|
|
67
|
-
SELECT kcu.column_name
|
|
68
|
-
FROM information_schema.table_constraints tc
|
|
69
|
-
JOIN information_schema.key_column_usage kcu
|
|
70
|
-
ON kcu.constraint_name = tc.constraint_name AND kcu.table_name = tc.table_name
|
|
71
|
-
WHERE tc.constraint_type = 'PRIMARY KEY' AND tc.table_name = $1
|
|
72
|
-
) pk ON pk.column_name = c.column_name
|
|
73
|
-
WHERE c.table_name = $1
|
|
62
|
+
sql: `SELECT c.column_name AS name, c.data_type AS type,
|
|
63
|
+
CASE WHEN c.is_nullable = 'YES' THEN 1 ELSE 0 END AS nullable,
|
|
64
|
+
CASE WHEN pk.column_name IS NOT NULL THEN 1 ELSE 0 END AS pk
|
|
65
|
+
FROM information_schema.columns c
|
|
66
|
+
LEFT JOIN (
|
|
67
|
+
SELECT kcu.column_name
|
|
68
|
+
FROM information_schema.table_constraints tc
|
|
69
|
+
JOIN information_schema.key_column_usage kcu
|
|
70
|
+
ON kcu.constraint_name = tc.constraint_name AND kcu.table_name = tc.table_name
|
|
71
|
+
WHERE tc.constraint_type = 'PRIMARY KEY' AND tc.table_name = $1
|
|
72
|
+
) pk ON pk.column_name = c.column_name
|
|
73
|
+
WHERE c.table_name = $1
|
|
74
74
|
ORDER BY c.ordinal_position`,
|
|
75
75
|
params: [table],
|
|
76
76
|
}),
|
|
77
77
|
toFields: infoSchemaFields,
|
|
78
78
|
tables: {
|
|
79
|
-
sql: `SELECT table_name AS name FROM information_schema.tables
|
|
79
|
+
sql: `SELECT table_name AS name FROM information_schema.tables
|
|
80
80
|
WHERE table_schema = 'public' AND table_type = 'BASE TABLE' ORDER BY table_name`,
|
|
81
81
|
params: [],
|
|
82
82
|
},
|
|
83
83
|
foreignKeys: (table) => ({
|
|
84
|
-
sql: `SELECT kcu.column_name AS "column", ccu.table_name AS ref_table, ccu.column_name AS ref_column
|
|
85
|
-
FROM information_schema.table_constraints tc
|
|
86
|
-
JOIN information_schema.key_column_usage kcu
|
|
87
|
-
ON kcu.constraint_name = tc.constraint_name AND kcu.table_name = tc.table_name
|
|
88
|
-
JOIN information_schema.constraint_column_usage ccu
|
|
89
|
-
ON ccu.constraint_name = tc.constraint_name
|
|
84
|
+
sql: `SELECT kcu.column_name AS "column", ccu.table_name AS ref_table, ccu.column_name AS ref_column
|
|
85
|
+
FROM information_schema.table_constraints tc
|
|
86
|
+
JOIN information_schema.key_column_usage kcu
|
|
87
|
+
ON kcu.constraint_name = tc.constraint_name AND kcu.table_name = tc.table_name
|
|
88
|
+
JOIN information_schema.constraint_column_usage ccu
|
|
89
|
+
ON ccu.constraint_name = tc.constraint_name
|
|
90
90
|
WHERE tc.constraint_type = 'FOREIGN KEY' AND tc.table_name = $1`,
|
|
91
91
|
params: [table],
|
|
92
92
|
}),
|
|
@@ -94,23 +94,23 @@ WHERE tc.constraint_type = 'FOREIGN KEY' AND tc.table_name = $1`,
|
|
|
94
94
|
};
|
|
95
95
|
const MYSQL = {
|
|
96
96
|
columns: (table) => ({
|
|
97
|
-
sql: `SELECT COLUMN_NAME AS name, DATA_TYPE AS type,
|
|
98
|
-
CASE WHEN IS_NULLABLE = 'YES' THEN 1 ELSE 0 END AS nullable,
|
|
99
|
-
CASE WHEN COLUMN_KEY = 'PRI' THEN 1 ELSE 0 END AS pk
|
|
100
|
-
FROM information_schema.columns
|
|
101
|
-
WHERE TABLE_NAME = ? AND TABLE_SCHEMA = DATABASE()
|
|
97
|
+
sql: `SELECT COLUMN_NAME AS name, DATA_TYPE AS type,
|
|
98
|
+
CASE WHEN IS_NULLABLE = 'YES' THEN 1 ELSE 0 END AS nullable,
|
|
99
|
+
CASE WHEN COLUMN_KEY = 'PRI' THEN 1 ELSE 0 END AS pk
|
|
100
|
+
FROM information_schema.columns
|
|
101
|
+
WHERE TABLE_NAME = ? AND TABLE_SCHEMA = DATABASE()
|
|
102
102
|
ORDER BY ORDINAL_POSITION`,
|
|
103
103
|
params: [table],
|
|
104
104
|
}),
|
|
105
105
|
toFields: infoSchemaFields,
|
|
106
106
|
tables: {
|
|
107
|
-
sql: `SELECT TABLE_NAME AS name FROM information_schema.tables
|
|
107
|
+
sql: `SELECT TABLE_NAME AS name FROM information_schema.tables
|
|
108
108
|
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_TYPE = 'BASE TABLE' ORDER BY TABLE_NAME`,
|
|
109
109
|
params: [],
|
|
110
110
|
},
|
|
111
111
|
foreignKeys: (table) => ({
|
|
112
|
-
sql: `SELECT COLUMN_NAME AS \`column\`, REFERENCED_TABLE_NAME AS ref_table, REFERENCED_COLUMN_NAME AS ref_column
|
|
113
|
-
FROM information_schema.KEY_COLUMN_USAGE
|
|
112
|
+
sql: `SELECT COLUMN_NAME AS \`column\`, REFERENCED_TABLE_NAME AS ref_table, REFERENCED_COLUMN_NAME AS ref_column
|
|
113
|
+
FROM information_schema.KEY_COLUMN_USAGE
|
|
114
114
|
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ? AND REFERENCED_TABLE_NAME IS NOT NULL`,
|
|
115
115
|
params: [table],
|
|
116
116
|
}),
|
|
@@ -118,33 +118,33 @@ WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ? AND REFERENCED_TABLE_NAME IS
|
|
|
118
118
|
};
|
|
119
119
|
const MSSQL = {
|
|
120
120
|
columns: (table) => ({
|
|
121
|
-
sql: `SELECT c.COLUMN_NAME AS name, c.DATA_TYPE AS type,
|
|
122
|
-
CASE WHEN c.IS_NULLABLE = 'YES' THEN 1 ELSE 0 END AS nullable,
|
|
123
|
-
CASE WHEN pk.COLUMN_NAME IS NOT NULL THEN 1 ELSE 0 END AS pk
|
|
124
|
-
FROM INFORMATION_SCHEMA.COLUMNS c
|
|
125
|
-
LEFT JOIN (
|
|
126
|
-
SELECT ku.COLUMN_NAME
|
|
127
|
-
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc
|
|
128
|
-
JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE ku ON tc.CONSTRAINT_NAME = ku.CONSTRAINT_NAME
|
|
129
|
-
WHERE tc.CONSTRAINT_TYPE = 'PRIMARY KEY' AND tc.TABLE_NAME = @p1
|
|
130
|
-
) pk ON pk.COLUMN_NAME = c.COLUMN_NAME
|
|
131
|
-
WHERE c.TABLE_NAME = @p1
|
|
121
|
+
sql: `SELECT c.COLUMN_NAME AS name, c.DATA_TYPE AS type,
|
|
122
|
+
CASE WHEN c.IS_NULLABLE = 'YES' THEN 1 ELSE 0 END AS nullable,
|
|
123
|
+
CASE WHEN pk.COLUMN_NAME IS NOT NULL THEN 1 ELSE 0 END AS pk
|
|
124
|
+
FROM INFORMATION_SCHEMA.COLUMNS c
|
|
125
|
+
LEFT JOIN (
|
|
126
|
+
SELECT ku.COLUMN_NAME
|
|
127
|
+
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc
|
|
128
|
+
JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE ku ON tc.CONSTRAINT_NAME = ku.CONSTRAINT_NAME
|
|
129
|
+
WHERE tc.CONSTRAINT_TYPE = 'PRIMARY KEY' AND tc.TABLE_NAME = @p1
|
|
130
|
+
) pk ON pk.COLUMN_NAME = c.COLUMN_NAME
|
|
131
|
+
WHERE c.TABLE_NAME = @p1
|
|
132
132
|
ORDER BY c.ORDINAL_POSITION`,
|
|
133
133
|
params: [table],
|
|
134
134
|
}),
|
|
135
135
|
toFields: infoSchemaFields,
|
|
136
136
|
tables: {
|
|
137
|
-
sql: `SELECT TABLE_NAME AS name FROM INFORMATION_SCHEMA.TABLES
|
|
137
|
+
sql: `SELECT TABLE_NAME AS name FROM INFORMATION_SCHEMA.TABLES
|
|
138
138
|
WHERE TABLE_TYPE = 'BASE TABLE' ORDER BY TABLE_NAME`,
|
|
139
139
|
params: [],
|
|
140
140
|
},
|
|
141
141
|
foreignKeys: (table) => ({
|
|
142
|
-
sql: `SELECT cu.COLUMN_NAME AS [column], pk.TABLE_NAME AS ref_table, pt.COLUMN_NAME AS ref_column
|
|
143
|
-
FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc
|
|
144
|
-
JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE cu ON cu.CONSTRAINT_NAME = rc.CONSTRAINT_NAME
|
|
145
|
-
JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS pk ON pk.CONSTRAINT_NAME = rc.UNIQUE_CONSTRAINT_NAME
|
|
146
|
-
JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE pt
|
|
147
|
-
ON pt.CONSTRAINT_NAME = pk.CONSTRAINT_NAME AND pt.ORDINAL_POSITION = cu.ORDINAL_POSITION
|
|
142
|
+
sql: `SELECT cu.COLUMN_NAME AS [column], pk.TABLE_NAME AS ref_table, pt.COLUMN_NAME AS ref_column
|
|
143
|
+
FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc
|
|
144
|
+
JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE cu ON cu.CONSTRAINT_NAME = rc.CONSTRAINT_NAME
|
|
145
|
+
JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS pk ON pk.CONSTRAINT_NAME = rc.UNIQUE_CONSTRAINT_NAME
|
|
146
|
+
JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE pt
|
|
147
|
+
ON pt.CONSTRAINT_NAME = pk.CONSTRAINT_NAME AND pt.ORDINAL_POSITION = cu.ORDINAL_POSITION
|
|
148
148
|
WHERE cu.TABLE_NAME = @p1`,
|
|
149
149
|
params: [table],
|
|
150
150
|
}),
|
package/dist/studio/project.d.ts
CHANGED
|
@@ -209,6 +209,16 @@ export type GridConfig = {
|
|
|
209
209
|
* prop the curated controls don't manage. Passed straight through to `<SvGrid>`
|
|
210
210
|
* (deduped against the curated props at codegen time). */
|
|
211
211
|
props?: Record<string, unknown>;
|
|
212
|
+
/** No-code icon overrides: a `GridIconName` from the grid's catalogue -> the glyph
|
|
213
|
+
* that replaces the built-in one. Names left out keep their default, so a partial
|
|
214
|
+
* map is all this ever needs to hold.
|
|
215
|
+
*
|
|
216
|
+
* Deliberately NOT part of `props` above. SvGrid's `icons` prop takes a map of
|
|
217
|
+
* SNIPPETS, and `props` is emitted with `JSON.stringify`, so an entry there would
|
|
218
|
+
* generate `icons={{"sort-asc":"..."}}` and throw the moment the grid tried to
|
|
219
|
+
* render it. This compiles to one real snippet per entry instead - which is also
|
|
220
|
+
* why the extractor keeps `icons` out of the "All properties" panel. */
|
|
221
|
+
icons?: Record<string, string>;
|
|
212
222
|
};
|
|
213
223
|
/** Which calendar view the scheduler opens on / offers. */
|
|
214
224
|
export type SchedulerViewMode = 'month' | 'week' | 'day' | 'agenda' | 'timelineDay' | 'timelineWeek' | 'timelineMonth' | 'timelineYear';
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { screen, formScreen, boardScreen, schedulerScreen, workspaceScreen, detailScreen, project, dashScreen, statusPills, pad, ids, whenIs } from './shared.js';
|
|
2
2
|
// Salesforce Lightning-style chrome: a gradient blue brand rail, white rounded-pill
|
|
3
3
|
// nav with a solid-white active state, and a Lightning-blue rule under the toolbar.
|
|
4
|
-
const LIGHTNING_CSS = `.sv-app.theme-lightning .sv-app__side { background: linear-gradient(180deg, #032d60, #0176d3); border-right: 0; }
|
|
5
|
-
.sv-app.theme-lightning .sv-app__brandtext { color: #fff; font-weight: 800; letter-spacing: -0.01em; }
|
|
6
|
-
.sv-app.theme-lightning .sv-app__link { color: #d9edff; font-weight: 600; border-radius: 9999px; padding: 8px 14px; }
|
|
7
|
-
.sv-app.theme-lightning .sv-app__link:hover { background: rgba(255, 255, 255, 0.14); color: #fff; }
|
|
8
|
-
.sv-app.theme-lightning .sv-app__link.is-active { background: #fff; color: #032d60; }
|
|
9
|
-
.sv-app.theme-lightning .sv-app__collapse, .sv-app.theme-lightning .sv-app__foot { color: rgba(255, 255, 255, 0.72); }
|
|
4
|
+
const LIGHTNING_CSS = `.sv-app.theme-lightning .sv-app__side { background: linear-gradient(180deg, #032d60, #0176d3); border-right: 0; }
|
|
5
|
+
.sv-app.theme-lightning .sv-app__brandtext { color: #fff; font-weight: 800; letter-spacing: -0.01em; }
|
|
6
|
+
.sv-app.theme-lightning .sv-app__link { color: #d9edff; font-weight: 600; border-radius: 9999px; padding: 8px 14px; }
|
|
7
|
+
.sv-app.theme-lightning .sv-app__link:hover { background: rgba(255, 255, 255, 0.14); color: #fff; }
|
|
8
|
+
.sv-app.theme-lightning .sv-app__link.is-active { background: #fff; color: #032d60; }
|
|
9
|
+
.sv-app.theme-lightning .sv-app__collapse, .sv-app.theme-lightning .sv-app__foot { color: rgba(255, 255, 255, 0.72); }
|
|
10
10
|
.sv-app.theme-lightning .sv-app__toolbar { border-bottom: 2px solid #0176d3; }`;
|
|
11
11
|
// A fixed sales-rep pool, shared by deals + activities so leaderboards, pivots
|
|
12
12
|
// and owner pills stay clean (padded rows cycle these instead of random names).
|
|
@@ -2,13 +2,13 @@ import { screen, formScreen, schedulerScreen, detailScreen, project, dashScreen,
|
|
|
2
2
|
// Industrial control-console chrome (the look of a LabVIEW / SystemLink operations
|
|
3
3
|
// dashboard): a near-black rail, uppercase monospace nav labels, a cyan LED-style
|
|
4
4
|
// active indicator, and a faint measurement grid over the content.
|
|
5
|
-
const CONTROL_CSS = `.sv-app.theme-control .sv-app__side { background: #0a0e14; border-right: 1px solid #1b2430; }
|
|
6
|
-
.sv-app.theme-control .sv-app__brandtext { color: #e6f6ff; font-family: ui-monospace, "SFMono-Regular", Menlo, monospace; text-transform: uppercase; letter-spacing: 0.08em; font-size: 14px; }
|
|
7
|
-
.sv-app.theme-control .sv-app__link { color: #9fb3c8; font-family: ui-monospace, "SFMono-Regular", Menlo, monospace; font-size: 12px; letter-spacing: 0.04em; text-transform: uppercase; border-radius: 4px; padding: 7px 12px; }
|
|
8
|
-
.sv-app.theme-control .sv-app__link:hover { background: rgba(34, 211, 238, 0.08); color: #e6f6ff; }
|
|
9
|
-
.sv-app.theme-control .sv-app__link.is-active { background: rgba(34, 211, 238, 0.14); color: #67e8f9; box-shadow: inset 3px 0 0 #22d3ee; }
|
|
10
|
-
.sv-app.theme-control .sv-app__collapse, .sv-app.theme-control .sv-app__foot { color: #64798f; }
|
|
11
|
-
.sv-app.theme-control .sv-app__toolbar { border-bottom: 1px solid #1b2430; }
|
|
5
|
+
const CONTROL_CSS = `.sv-app.theme-control .sv-app__side { background: #0a0e14; border-right: 1px solid #1b2430; }
|
|
6
|
+
.sv-app.theme-control .sv-app__brandtext { color: #e6f6ff; font-family: ui-monospace, "SFMono-Regular", Menlo, monospace; text-transform: uppercase; letter-spacing: 0.08em; font-size: 14px; }
|
|
7
|
+
.sv-app.theme-control .sv-app__link { color: #9fb3c8; font-family: ui-monospace, "SFMono-Regular", Menlo, monospace; font-size: 12px; letter-spacing: 0.04em; text-transform: uppercase; border-radius: 4px; padding: 7px 12px; }
|
|
8
|
+
.sv-app.theme-control .sv-app__link:hover { background: rgba(34, 211, 238, 0.08); color: #e6f6ff; }
|
|
9
|
+
.sv-app.theme-control .sv-app__link.is-active { background: rgba(34, 211, 238, 0.14); color: #67e8f9; box-shadow: inset 3px 0 0 #22d3ee; }
|
|
10
|
+
.sv-app.theme-control .sv-app__collapse, .sv-app.theme-control .sv-app__foot { color: #64798f; }
|
|
11
|
+
.sv-app.theme-control .sv-app__toolbar { border-bottom: 1px solid #1b2430; }
|
|
12
12
|
.sv-app.theme-control .sv-app__content { background-image: linear-gradient(rgba(34, 211, 238, 0.045) 1px, transparent 1px), linear-gradient(90deg, rgba(34, 211, 238, 0.045) 1px, transparent 1px); background-size: 28px 28px; }`;
|
|
13
13
|
const drivers = {
|
|
14
14
|
name: 'drivers',
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { screen, formScreen, boardScreen, calendarScreen, detailScreen, project, dashScreen, statusPills, pad, ids, whenIs } from './shared.js';
|
|
2
2
|
// SAP Fiori-style chrome: a dark shell bar across the top (the toolbar), a white
|
|
3
3
|
// launchpad-style rail, and a blue left-bar on the active item (square corners).
|
|
4
|
-
const FIORI_CSS = `.sv-app.theme-fiori .sv-app__toolbar { background: #354a5f; border-bottom: 0; }
|
|
5
|
-
.sv-app.theme-fiori .sv-app__search { background: rgba(255, 255, 255, 0.12); border-color: rgba(255, 255, 255, 0.24); }
|
|
6
|
-
.sv-app.theme-fiori .sv-app__search-in { color: #fff; }
|
|
7
|
-
.sv-app.theme-fiori .sv-app__search-in::placeholder { color: rgba(255, 255, 255, 0.72); }
|
|
8
|
-
.sv-app.theme-fiori .sv-app__search-ic, .sv-app.theme-fiori .sv-app__kbd { color: #fff; }
|
|
9
|
-
.sv-app.theme-fiori .sv-app__side { background: #fff; border-right: 1px solid #e5e5e5; }
|
|
10
|
-
.sv-app.theme-fiori .sv-app__brandtext { color: #0a6ed1; font-weight: 700; }
|
|
11
|
-
.sv-app.theme-fiori .sv-app__link { border-radius: 0; padding: 9px 12px; border-left: 3px solid transparent; color: #32363a; }
|
|
12
|
-
.sv-app.theme-fiori .sv-app__link:hover { background: #f5f6f7; }
|
|
4
|
+
const FIORI_CSS = `.sv-app.theme-fiori .sv-app__toolbar { background: #354a5f; border-bottom: 0; }
|
|
5
|
+
.sv-app.theme-fiori .sv-app__search { background: rgba(255, 255, 255, 0.12); border-color: rgba(255, 255, 255, 0.24); }
|
|
6
|
+
.sv-app.theme-fiori .sv-app__search-in { color: #fff; }
|
|
7
|
+
.sv-app.theme-fiori .sv-app__search-in::placeholder { color: rgba(255, 255, 255, 0.72); }
|
|
8
|
+
.sv-app.theme-fiori .sv-app__search-ic, .sv-app.theme-fiori .sv-app__kbd { color: #fff; }
|
|
9
|
+
.sv-app.theme-fiori .sv-app__side { background: #fff; border-right: 1px solid #e5e5e5; }
|
|
10
|
+
.sv-app.theme-fiori .sv-app__brandtext { color: #0a6ed1; font-weight: 700; }
|
|
11
|
+
.sv-app.theme-fiori .sv-app__link { border-radius: 0; padding: 9px 12px; border-left: 3px solid transparent; color: #32363a; }
|
|
12
|
+
.sv-app.theme-fiori .sv-app__link:hover { background: #f5f6f7; }
|
|
13
13
|
.sv-app.theme-fiori .sv-app__link.is-active { background: #ebf5ff; color: #0a6ed1; border-left-color: #0a6ed1; font-weight: 600; }`;
|
|
14
14
|
const policies = {
|
|
15
15
|
name: 'policies',
|
|
@@ -2,18 +2,18 @@ import { screen, formScreen, boardScreen, detailScreen, project, dashScreen, sta
|
|
|
2
2
|
// Excel-style chrome: a green header band over the brand, a green command bar
|
|
3
3
|
// (the toolbar), square-cornered nav rows with a green left-marker on the active
|
|
4
4
|
// sheet. Pairs with the square-cornered `excel` preset.
|
|
5
|
-
const EXCEL_CSS = `.sv-app.theme-excel .sv-app__side { background: #f3f2f1; border-right: 1px solid #d0cfce; padding: 0 0 12px; }
|
|
6
|
-
.sv-app.theme-excel .sv-app__sidehead { background: #107c41; margin: 0 0 6px; padding: 13px 14px; }
|
|
7
|
-
.sv-app.theme-excel .sv-app__brandtext { color: #fff; font-weight: 700; }
|
|
8
|
-
.sv-app.theme-excel .sv-app__collapse { color: rgba(255, 255, 255, 0.85); }
|
|
9
|
-
.sv-app.theme-excel .sv-app__links { padding: 0 8px; }
|
|
10
|
-
.sv-app.theme-excel .sv-app__link { border-radius: 0; padding: 7px 12px; border-left: 3px solid transparent; }
|
|
11
|
-
.sv-app.theme-excel .sv-app__link.is-active { background: #e7f2ec; color: #0b5c31; border-left-color: #107c41; font-weight: 600; }
|
|
12
|
-
.sv-app.theme-excel .sv-app__foot { padding-left: 12px; }
|
|
13
|
-
.sv-app.theme-excel .sv-app__toolbar { background: #107c41; border-bottom: 1px solid #0b5c31; }
|
|
14
|
-
.sv-app.theme-excel .sv-app__search { background: rgba(255, 255, 255, 0.16); border-color: rgba(255, 255, 255, 0.3); }
|
|
15
|
-
.sv-app.theme-excel .sv-app__search-in { color: #fff; }
|
|
16
|
-
.sv-app.theme-excel .sv-app__search-in::placeholder { color: rgba(255, 255, 255, 0.78); }
|
|
5
|
+
const EXCEL_CSS = `.sv-app.theme-excel .sv-app__side { background: #f3f2f1; border-right: 1px solid #d0cfce; padding: 0 0 12px; }
|
|
6
|
+
.sv-app.theme-excel .sv-app__sidehead { background: #107c41; margin: 0 0 6px; padding: 13px 14px; }
|
|
7
|
+
.sv-app.theme-excel .sv-app__brandtext { color: #fff; font-weight: 700; }
|
|
8
|
+
.sv-app.theme-excel .sv-app__collapse { color: rgba(255, 255, 255, 0.85); }
|
|
9
|
+
.sv-app.theme-excel .sv-app__links { padding: 0 8px; }
|
|
10
|
+
.sv-app.theme-excel .sv-app__link { border-radius: 0; padding: 7px 12px; border-left: 3px solid transparent; }
|
|
11
|
+
.sv-app.theme-excel .sv-app__link.is-active { background: #e7f2ec; color: #0b5c31; border-left-color: #107c41; font-weight: 600; }
|
|
12
|
+
.sv-app.theme-excel .sv-app__foot { padding-left: 12px; }
|
|
13
|
+
.sv-app.theme-excel .sv-app__toolbar { background: #107c41; border-bottom: 1px solid #0b5c31; }
|
|
14
|
+
.sv-app.theme-excel .sv-app__search { background: rgba(255, 255, 255, 0.16); border-color: rgba(255, 255, 255, 0.3); }
|
|
15
|
+
.sv-app.theme-excel .sv-app__search-in { color: #fff; }
|
|
16
|
+
.sv-app.theme-excel .sv-app__search-in::placeholder { color: rgba(255, 255, 255, 0.78); }
|
|
17
17
|
.sv-app.theme-excel .sv-app__search-ic, .sv-app.theme-excel .sv-app__kbd { color: #fff; }`;
|
|
18
18
|
const suppliers = {
|
|
19
19
|
name: 'suppliers',
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { screen, formScreen, boardScreen, schedulerScreen, detailScreen, project, dashScreen, statusPills, pad, ids } from './shared.js';
|
|
2
2
|
// Jira-style chrome: a dark navy issue-tracker sidebar with muted labels and a
|
|
3
3
|
// blue active row (accent bar + tinted fill), the board front and centre.
|
|
4
|
-
const JIRA_CSS = `.sv-app.theme-jira .sv-app__side { background: #1d2125; border-right: 1px solid #2c333a; }
|
|
5
|
-
.sv-app.theme-jira .sv-app__brandtext { color: #fff; font-weight: 700; }
|
|
6
|
-
.sv-app.theme-jira .sv-app__link { color: #c7d1db; border-radius: 4px; padding: 7px 12px; }
|
|
7
|
-
.sv-app.theme-jira .sv-app__link:hover { background: rgba(255, 255, 255, 0.08); color: #fff; }
|
|
8
|
-
.sv-app.theme-jira .sv-app__link.is-active { background: color-mix(in srgb, #0c66e4 30%, #1d2125); color: #fff; box-shadow: inset 3px 0 0 #4c9aff; }
|
|
4
|
+
const JIRA_CSS = `.sv-app.theme-jira .sv-app__side { background: #1d2125; border-right: 1px solid #2c333a; }
|
|
5
|
+
.sv-app.theme-jira .sv-app__brandtext { color: #fff; font-weight: 700; }
|
|
6
|
+
.sv-app.theme-jira .sv-app__link { color: #c7d1db; border-radius: 4px; padding: 7px 12px; }
|
|
7
|
+
.sv-app.theme-jira .sv-app__link:hover { background: rgba(255, 255, 255, 0.08); color: #fff; }
|
|
8
|
+
.sv-app.theme-jira .sv-app__link.is-active { background: color-mix(in srgb, #0c66e4 30%, #1d2125); color: #fff; box-shadow: inset 3px 0 0 #4c9aff; }
|
|
9
9
|
.sv-app.theme-jira .sv-app__collapse, .sv-app.theme-jira .sv-app__foot { color: #8c9bab; }`;
|
|
10
10
|
const projectsEntity = {
|
|
11
11
|
name: 'projects',
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { screen, formScreen, boardScreen, workspaceScreen, detailScreen, project, dashScreen, statusPills, pad, ids, whenIsAny } from './shared.js';
|
|
2
2
|
// Outlook-style chrome: a solid blue command ribbon (the toolbar), a light "folder"
|
|
3
3
|
// rail with compact rows, and an accented left bar on the active folder.
|
|
4
|
-
const OUTLOOK_CSS = `.sv-app.theme-outlook .sv-app__toolbar { background: #0f6cbd; border-bottom: 0; }
|
|
5
|
-
.sv-app.theme-outlook .sv-app__toolbar, .sv-app.theme-outlook .sv-app__search-ic, .sv-app.theme-outlook .sv-app__kbd { color: #fff; }
|
|
6
|
-
.sv-app.theme-outlook .sv-app__search { background: rgba(255, 255, 255, 0.16); border-color: rgba(255, 255, 255, 0.28); }
|
|
7
|
-
.sv-app.theme-outlook .sv-app__search-in { color: #fff; }
|
|
8
|
-
.sv-app.theme-outlook .sv-app__search-in::placeholder { color: rgba(255, 255, 255, 0.75); }
|
|
9
|
-
.sv-app.theme-outlook .sv-app__side { background: #faf9f8; padding: 12px 8px; }
|
|
10
|
-
.sv-app.theme-outlook .sv-app__brandtext { color: #0f6cbd; font-weight: 700; }
|
|
11
|
-
.sv-app.theme-outlook .sv-app__link { border-radius: 4px; padding: 6px 12px; font-size: 13.5px; }
|
|
4
|
+
const OUTLOOK_CSS = `.sv-app.theme-outlook .sv-app__toolbar { background: #0f6cbd; border-bottom: 0; }
|
|
5
|
+
.sv-app.theme-outlook .sv-app__toolbar, .sv-app.theme-outlook .sv-app__search-ic, .sv-app.theme-outlook .sv-app__kbd { color: #fff; }
|
|
6
|
+
.sv-app.theme-outlook .sv-app__search { background: rgba(255, 255, 255, 0.16); border-color: rgba(255, 255, 255, 0.28); }
|
|
7
|
+
.sv-app.theme-outlook .sv-app__search-in { color: #fff; }
|
|
8
|
+
.sv-app.theme-outlook .sv-app__search-in::placeholder { color: rgba(255, 255, 255, 0.75); }
|
|
9
|
+
.sv-app.theme-outlook .sv-app__side { background: #faf9f8; padding: 12px 8px; }
|
|
10
|
+
.sv-app.theme-outlook .sv-app__brandtext { color: #0f6cbd; font-weight: 700; }
|
|
11
|
+
.sv-app.theme-outlook .sv-app__link { border-radius: 4px; padding: 6px 12px; font-size: 13.5px; }
|
|
12
12
|
.sv-app.theme-outlook .sv-app__link.is-active { background: color-mix(in srgb, #0f6cbd 12%, #fff); color: #0f6cbd; box-shadow: inset 3px 0 0 #0f6cbd; }`;
|
|
13
13
|
const customers = {
|
|
14
14
|
name: 'customers',
|
|
@@ -18,90 +18,90 @@ function layoutFile(nav, appTitle, theme) {
|
|
|
18
18
|
return {
|
|
19
19
|
path: 'src/routes/+layout.svelte',
|
|
20
20
|
description: 'App shell: a collapsible nav sidebar linking every entity screen (an off-canvas drawer on tablet/phone), with the routed page in the main area.',
|
|
21
|
-
contents: `<script lang="ts">
|
|
22
|
-
${managed(` let { children } = $props()
|
|
23
|
-
const appTitle = ${JSON.stringify(appTitle)}
|
|
24
|
-
const nav = ${JSON.stringify(nav)}
|
|
25
|
-
|
|
26
|
-
// The sidebar collapses to an off-canvas drawer either on user request or on
|
|
27
|
-
// tablet / phone (<= 1024px), where it also starts collapsed. The desktop
|
|
28
|
-
// collapse choice persists across visits.
|
|
29
|
-
let navOpen = $state(false)
|
|
30
|
-
let collapsed = $state(false)
|
|
31
|
-
let narrow = $state(false)
|
|
32
|
-
const drawer = $derived(collapsed || narrow)
|
|
33
|
-
function toggleNav() { collapsed = !collapsed; try { localStorage.setItem('svapp:nav', collapsed ? 'c' : 'e') } catch (_) { /* storage blocked */ } }
|
|
34
|
-
$effect(() => {
|
|
35
|
-
const mq = window.matchMedia('(max-width: 1024px)')
|
|
36
|
-
const sync = () => (narrow = mq.matches)
|
|
37
|
-
sync()
|
|
38
|
-
try { const s = localStorage.getItem('svapp:nav'); if (s) collapsed = s === 'c' } catch (_) { /* storage blocked */ }
|
|
39
|
-
mq.addEventListener('change', sync)
|
|
40
|
-
return () => mq.removeEventListener('change', sync)
|
|
41
|
-
})`)}
|
|
42
|
-
</script>
|
|
43
|
-
|
|
44
|
-
<svelte:head><style>
|
|
45
|
-
${themeTokenCss(theme, { layer: 'svgrid-studio' })}
|
|
46
|
-
</style></svelte:head>
|
|
47
|
-
|
|
48
|
-
<div class="app-shell" class:is-drawer={drawer} class:is-navopen={navOpen}>
|
|
49
|
-
<header class="app-shell__mobilebar">
|
|
50
|
-
<button type="button" class="app-shell__burger" aria-label="Toggle navigation" aria-expanded={navOpen} onclick={() => (navOpen = !navOpen)}>
|
|
51
|
-
<svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M3 6h18M3 12h18M3 18h18"/></svg>
|
|
52
|
-
</button>
|
|
53
|
-
<a class="app-shell__brand" href="/">{appTitle}</a>
|
|
54
|
-
{#if !narrow}<button type="button" class="app-shell__dock" aria-label="Dock sidebar" title="Dock sidebar" onclick={toggleNav}>
|
|
55
|
-
<svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 6l6 6-6 6"/></svg>
|
|
56
|
-
</button>{/if}
|
|
57
|
-
</header>
|
|
58
|
-
{#if navOpen}<button type="button" class="app-shell__backdrop" aria-label="Close navigation" onclick={() => (navOpen = false)}></button>{/if}
|
|
59
|
-
<aside class="app-shell__nav">
|
|
60
|
-
<div class="app-shell__navhead">
|
|
61
|
-
<a class="app-shell__brand" href="/">{appTitle}</a>
|
|
62
|
-
<button type="button" class="app-shell__collapse" aria-label="Collapse sidebar" title="Collapse sidebar" onclick={toggleNav}>
|
|
63
|
-
<svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 6l-6 6 6 6"/></svg>
|
|
64
|
-
</button>
|
|
65
|
-
</div>
|
|
66
|
-
<nav onclick={() => (navOpen = false)}>
|
|
67
|
-
{#each nav as item (item.href)}
|
|
68
|
-
<a class="app-shell__link" href={item.href}>{item.label}</a>
|
|
69
|
-
{/each}
|
|
70
|
-
</nav>
|
|
71
|
-
</aside>
|
|
72
|
-
<main class="app-shell__main">
|
|
73
|
-
{@render children?.()}
|
|
74
|
-
</main>
|
|
75
|
-
</div>
|
|
76
|
-
|
|
77
|
-
<style>
|
|
78
|
-
.app-shell { display: grid; grid-template-columns: 220px 1fr; min-height: 100vh; }
|
|
79
|
-
.app-shell__nav { display: flex; flex-direction: column; gap: 4px; padding: 16px 12px; border-right: 1px solid #e5e7eb; background: #f8fafc; }
|
|
80
|
-
.app-shell__navhead { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
|
|
81
|
-
.app-shell__brand { font-weight: 700; font-size: 16px; padding: 6px 10px 12px; color: inherit; text-decoration: none; }
|
|
82
|
-
.app-shell__navhead .app-shell__brand { padding-bottom: 6px; }
|
|
83
|
-
.app-shell__collapse, .app-shell__dock, .app-shell__burger { display: inline-flex; align-items: center; justify-content: center; padding: 6px; border: 0; border-radius: 8px; background: transparent; color: #64748b; cursor: pointer; }
|
|
84
|
-
.app-shell__collapse:hover, .app-shell__dock:hover, .app-shell__burger:hover { background: #e2e8f0; color: #0f172a; }
|
|
85
|
-
.app-shell__link { padding: 8px 10px; border-radius: 6px; color: #334155; text-decoration: none; }
|
|
86
|
-
.app-shell__link:hover { background: #e2e8f0; }
|
|
87
|
-
.app-shell nav { display: flex; flex-direction: column; gap: 4px; }
|
|
88
|
-
.app-shell__main { padding: 20px 24px; min-width: 0; }
|
|
89
|
-
.app-shell__mobilebar { display: none; align-items: center; gap: 12px; padding: 10px 14px; border-bottom: 1px solid #e5e7eb; background: #f8fafc; position: sticky; top: 0; z-index: 50; }
|
|
90
|
-
.app-shell__mobilebar .app-shell__dock { margin-left: auto; }
|
|
91
|
-
.app-shell__backdrop { display: none; position: fixed; inset: 0; z-index: 55; border: 0; padding: 0; background: rgba(15, 23, 42, 0.42); cursor: pointer; }
|
|
92
|
-
/* Drawer mode: tablet / phone (<= 1024px) or a user-collapsed desktop sidebar.
|
|
93
|
-
The sidebar becomes a fixed off-canvas panel that slides in when opened. */
|
|
94
|
-
.app-shell.is-drawer { display: block; }
|
|
95
|
-
.app-shell.is-drawer .app-shell__mobilebar { display: flex; }
|
|
96
|
-
.app-shell.is-drawer .app-shell__backdrop { display: block; }
|
|
97
|
-
.app-shell.is-drawer .app-shell__nav {
|
|
98
|
-
position: fixed; top: 0; bottom: 0; left: 0; z-index: 60; width: 264px; max-width: 82vw;
|
|
99
|
-
transform: translateX(-100%); transition: transform 0.24s ease; box-shadow: 0 0 40px rgba(15, 23, 42, 0.28);
|
|
100
|
-
}
|
|
101
|
-
.app-shell.is-drawer.is-navopen .app-shell__nav { transform: translateX(0); }
|
|
102
|
-
.app-shell.is-drawer .app-shell__navhead .app-shell__brand { display: none; } /* brand already in the top bar */
|
|
103
|
-
.app-shell.is-drawer .app-shell__collapse { display: none; } /* dock lives in the top bar when drawered */
|
|
104
|
-
</style>
|
|
21
|
+
contents: `<script lang="ts">
|
|
22
|
+
${managed(` let { children } = $props()
|
|
23
|
+
const appTitle = ${JSON.stringify(appTitle)}
|
|
24
|
+
const nav = ${JSON.stringify(nav)}
|
|
25
|
+
|
|
26
|
+
// The sidebar collapses to an off-canvas drawer either on user request or on
|
|
27
|
+
// tablet / phone (<= 1024px), where it also starts collapsed. The desktop
|
|
28
|
+
// collapse choice persists across visits.
|
|
29
|
+
let navOpen = $state(false)
|
|
30
|
+
let collapsed = $state(false)
|
|
31
|
+
let narrow = $state(false)
|
|
32
|
+
const drawer = $derived(collapsed || narrow)
|
|
33
|
+
function toggleNav() { collapsed = !collapsed; try { localStorage.setItem('svapp:nav', collapsed ? 'c' : 'e') } catch (_) { /* storage blocked */ } }
|
|
34
|
+
$effect(() => {
|
|
35
|
+
const mq = window.matchMedia('(max-width: 1024px)')
|
|
36
|
+
const sync = () => (narrow = mq.matches)
|
|
37
|
+
sync()
|
|
38
|
+
try { const s = localStorage.getItem('svapp:nav'); if (s) collapsed = s === 'c' } catch (_) { /* storage blocked */ }
|
|
39
|
+
mq.addEventListener('change', sync)
|
|
40
|
+
return () => mq.removeEventListener('change', sync)
|
|
41
|
+
})`)}
|
|
42
|
+
</script>
|
|
43
|
+
|
|
44
|
+
<svelte:head><style>
|
|
45
|
+
${themeTokenCss(theme, { layer: 'svgrid-studio' })}
|
|
46
|
+
</style></svelte:head>
|
|
47
|
+
|
|
48
|
+
<div class="app-shell" class:is-drawer={drawer} class:is-navopen={navOpen}>
|
|
49
|
+
<header class="app-shell__mobilebar">
|
|
50
|
+
<button type="button" class="app-shell__burger" aria-label="Toggle navigation" aria-expanded={navOpen} onclick={() => (navOpen = !navOpen)}>
|
|
51
|
+
<svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M3 6h18M3 12h18M3 18h18"/></svg>
|
|
52
|
+
</button>
|
|
53
|
+
<a class="app-shell__brand" href="/">{appTitle}</a>
|
|
54
|
+
{#if !narrow}<button type="button" class="app-shell__dock" aria-label="Dock sidebar" title="Dock sidebar" onclick={toggleNav}>
|
|
55
|
+
<svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 6l6 6-6 6"/></svg>
|
|
56
|
+
</button>{/if}
|
|
57
|
+
</header>
|
|
58
|
+
{#if navOpen}<button type="button" class="app-shell__backdrop" aria-label="Close navigation" onclick={() => (navOpen = false)}></button>{/if}
|
|
59
|
+
<aside class="app-shell__nav">
|
|
60
|
+
<div class="app-shell__navhead">
|
|
61
|
+
<a class="app-shell__brand" href="/">{appTitle}</a>
|
|
62
|
+
<button type="button" class="app-shell__collapse" aria-label="Collapse sidebar" title="Collapse sidebar" onclick={toggleNav}>
|
|
63
|
+
<svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 6l-6 6 6 6"/></svg>
|
|
64
|
+
</button>
|
|
65
|
+
</div>
|
|
66
|
+
<nav onclick={() => (navOpen = false)}>
|
|
67
|
+
{#each nav as item (item.href)}
|
|
68
|
+
<a class="app-shell__link" href={item.href}>{item.label}</a>
|
|
69
|
+
{/each}
|
|
70
|
+
</nav>
|
|
71
|
+
</aside>
|
|
72
|
+
<main class="app-shell__main">
|
|
73
|
+
{@render children?.()}
|
|
74
|
+
</main>
|
|
75
|
+
</div>
|
|
76
|
+
|
|
77
|
+
<style>
|
|
78
|
+
.app-shell { display: grid; grid-template-columns: 220px 1fr; min-height: 100vh; }
|
|
79
|
+
.app-shell__nav { display: flex; flex-direction: column; gap: 4px; padding: 16px 12px; border-right: 1px solid #e5e7eb; background: #f8fafc; }
|
|
80
|
+
.app-shell__navhead { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
|
|
81
|
+
.app-shell__brand { font-weight: 700; font-size: 16px; padding: 6px 10px 12px; color: inherit; text-decoration: none; }
|
|
82
|
+
.app-shell__navhead .app-shell__brand { padding-bottom: 6px; }
|
|
83
|
+
.app-shell__collapse, .app-shell__dock, .app-shell__burger { display: inline-flex; align-items: center; justify-content: center; padding: 6px; border: 0; border-radius: 8px; background: transparent; color: #64748b; cursor: pointer; }
|
|
84
|
+
.app-shell__collapse:hover, .app-shell__dock:hover, .app-shell__burger:hover { background: #e2e8f0; color: #0f172a; }
|
|
85
|
+
.app-shell__link { padding: 8px 10px; border-radius: 6px; color: #334155; text-decoration: none; }
|
|
86
|
+
.app-shell__link:hover { background: #e2e8f0; }
|
|
87
|
+
.app-shell nav { display: flex; flex-direction: column; gap: 4px; }
|
|
88
|
+
.app-shell__main { padding: 20px 24px; min-width: 0; }
|
|
89
|
+
.app-shell__mobilebar { display: none; align-items: center; gap: 12px; padding: 10px 14px; border-bottom: 1px solid #e5e7eb; background: #f8fafc; position: sticky; top: 0; z-index: 50; }
|
|
90
|
+
.app-shell__mobilebar .app-shell__dock { margin-left: auto; }
|
|
91
|
+
.app-shell__backdrop { display: none; position: fixed; inset: 0; z-index: 55; border: 0; padding: 0; background: rgba(15, 23, 42, 0.42); cursor: pointer; }
|
|
92
|
+
/* Drawer mode: tablet / phone (<= 1024px) or a user-collapsed desktop sidebar.
|
|
93
|
+
The sidebar becomes a fixed off-canvas panel that slides in when opened. */
|
|
94
|
+
.app-shell.is-drawer { display: block; }
|
|
95
|
+
.app-shell.is-drawer .app-shell__mobilebar { display: flex; }
|
|
96
|
+
.app-shell.is-drawer .app-shell__backdrop { display: block; }
|
|
97
|
+
.app-shell.is-drawer .app-shell__nav {
|
|
98
|
+
position: fixed; top: 0; bottom: 0; left: 0; z-index: 60; width: 264px; max-width: 82vw;
|
|
99
|
+
transform: translateX(-100%); transition: transform 0.24s ease; box-shadow: 0 0 40px rgba(15, 23, 42, 0.28);
|
|
100
|
+
}
|
|
101
|
+
.app-shell.is-drawer.is-navopen .app-shell__nav { transform: translateX(0); }
|
|
102
|
+
.app-shell.is-drawer .app-shell__navhead .app-shell__brand { display: none; } /* brand already in the top bar */
|
|
103
|
+
.app-shell.is-drawer .app-shell__collapse { display: none; } /* dock lives in the top bar when drawered */
|
|
104
|
+
</style>
|
|
105
105
|
`,
|
|
106
106
|
};
|
|
107
107
|
}
|
|
@@ -109,26 +109,26 @@ function homeFile(nav, appTitle) {
|
|
|
109
109
|
return {
|
|
110
110
|
path: 'src/routes/+page.svelte',
|
|
111
111
|
description: 'Home page: cards linking to each entity screen.',
|
|
112
|
-
contents: `<script lang="ts">
|
|
113
|
-
${managed(` const appTitle = ${JSON.stringify(appTitle)}
|
|
114
|
-
const entities = ${JSON.stringify(nav)}`)}
|
|
115
|
-
</script>
|
|
116
|
-
|
|
117
|
-
<section class="home">
|
|
118
|
-
<h2 class="home__title">{appTitle}</h2>
|
|
119
|
-
<div class="home__grid">
|
|
120
|
-
{#each entities as item (item.href)}
|
|
121
|
-
<a class="home__card" href={item.href}>{item.label}</a>
|
|
122
|
-
{/each}
|
|
123
|
-
</div>
|
|
124
|
-
</section>
|
|
125
|
-
|
|
126
|
-
<style>
|
|
127
|
-
.home__title { margin: 0 0 16px; font-size: 20px; font-weight: 600; }
|
|
128
|
-
.home__grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 12px; }
|
|
129
|
-
.home__card { display: block; padding: 18px 16px; border: 1px solid #e5e7eb; border-radius: 10px; color: inherit; text-decoration: none; font-weight: 600; }
|
|
130
|
-
.home__card:hover { border-color: #94a3b8; background: #f8fafc; }
|
|
131
|
-
</style>
|
|
112
|
+
contents: `<script lang="ts">
|
|
113
|
+
${managed(` const appTitle = ${JSON.stringify(appTitle)}
|
|
114
|
+
const entities = ${JSON.stringify(nav)}`)}
|
|
115
|
+
</script>
|
|
116
|
+
|
|
117
|
+
<section class="home">
|
|
118
|
+
<h2 class="home__title">{appTitle}</h2>
|
|
119
|
+
<div class="home__grid">
|
|
120
|
+
{#each entities as item (item.href)}
|
|
121
|
+
<a class="home__card" href={item.href}>{item.label}</a>
|
|
122
|
+
{/each}
|
|
123
|
+
</div>
|
|
124
|
+
</section>
|
|
125
|
+
|
|
126
|
+
<style>
|
|
127
|
+
.home__title { margin: 0 0 16px; font-size: 20px; font-weight: 600; }
|
|
128
|
+
.home__grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 12px; }
|
|
129
|
+
.home__card { display: block; padding: 18px 16px; border: 1px solid #e5e7eb; border-radius: 10px; color: inherit; text-decoration: none; font-weight: 600; }
|
|
130
|
+
.home__card:hover { border-color: #94a3b8; background: #f8fafc; }
|
|
131
|
+
</style>
|
|
132
132
|
`,
|
|
133
133
|
};
|
|
134
134
|
}
|