@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.
Files changed (235) hide show
  1. package/README.md +95 -95
  2. package/dist/ExpressionEditorHarness.svelte.d.ts +2 -2
  3. package/dist/SvAdvancedFilter.svelte.d.ts +2 -2
  4. package/dist/SvAlertRuleEditor.svelte.d.ts +2 -2
  5. package/dist/SvAlertsManager.svelte.d.ts +3 -3
  6. package/dist/SvAlertsPanel.svelte.d.ts +1 -1
  7. package/dist/SvAuthGate.svelte +115 -115
  8. package/dist/SvAuthGate.svelte.d.ts +1 -1
  9. package/dist/SvBoard.svelte.d.ts +1 -1
  10. package/dist/SvExportMenu.svelte +553 -553
  11. package/dist/SvExportMenu.svelte.d.ts +2 -2
  12. package/dist/SvExpressionEditor.svelte.d.ts +2 -2
  13. package/dist/SvFileInput.svelte +113 -113
  14. package/dist/SvGridAlerts.svelte.d.ts +2 -2
  15. package/dist/SvGridBoard.svelte +2358 -2358
  16. package/dist/SvGridBulkEditDrawer.svelte.d.ts +1 -1
  17. package/dist/SvGridEditPanel.svelte +1157 -1157
  18. package/dist/SvGridEditPanel.svelte.d.ts +3 -3
  19. package/dist/SvGridMasterDetail.svelte +116 -116
  20. package/dist/SvGridMasterDetail.svelte.d.ts +1 -1
  21. package/dist/SvGridScheduler.svelte +5358 -5358
  22. package/dist/SvImportDialog.svelte +1020 -1020
  23. package/dist/SvImportDialog.svelte.d.ts +2 -2
  24. package/dist/SvLookupInput.svelte +180 -180
  25. package/dist/SvLookupInput.svelte.d.ts +1 -1
  26. package/dist/SvPivotDesigner.svelte +1990 -1990
  27. package/dist/SvPivotDesigner.svelte.d.ts +2 -2
  28. package/dist/SvRecordDetail.svelte.d.ts +1 -1
  29. package/dist/SvSchedule.svelte.d.ts +1 -1
  30. package/dist/SvSchemaChart.svelte +234 -234
  31. package/dist/SvSchemaChart.svelte.d.ts +2 -2
  32. package/dist/SvSchemaDashboard.svelte +130 -130
  33. package/dist/SvSchemaDashboard.svelte.d.ts +3 -3
  34. package/dist/advanced-filter/expr-columns-from-grid.d.ts +1 -1
  35. package/dist/advanced-filter-enable.js +3 -3
  36. package/dist/alerts/alert-engine-attach.d.ts +2 -2
  37. package/dist/alerts/alert-engine-attach.js +3 -3
  38. package/dist/alerts/alert-engine.d.ts +1 -1
  39. package/dist/alerts/alert-engine.js +2 -2
  40. package/dist/alerts/alert-formats.d.ts +1 -1
  41. package/dist/alerts/alert-formats.js +1 -1
  42. package/dist/alerts/alert-observer.d.ts +3 -3
  43. package/dist/alerts/alert-observer.js +1 -1
  44. package/dist/alerts/alert-storage.d.ts +1 -1
  45. package/dist/alerts/alert-store.svelte.d.ts +1 -1
  46. package/dist/alerts/alert-types.d.ts +2 -2
  47. package/dist/alerts.js +2 -2
  48. package/dist/board.js +2 -2
  49. package/dist/cdn/svgrid-enterprise.svelte-external.js +1161 -1144
  50. package/dist/designer/assets/GridMenus-B1JtIN21.js +8 -0
  51. package/dist/designer/assets/SvDateRangeInput-C0iCCZ8o.css +1 -0
  52. package/dist/designer/assets/{SvDateRangeInput-CVn-yqrQ.js → SvDateRangeInput-CjO7nn_x.js} +1 -1
  53. package/dist/designer/assets/SvDateTimePicker-ByBD_ov6.js +1 -0
  54. package/dist/designer/assets/SvDateTimePicker-DPv09DIT.css +1 -0
  55. package/dist/designer/assets/SvField-YDLipR6O.css +1 -0
  56. package/dist/designer/assets/{SvField-BsqiA5me.js → SvField-cj1PFNgZ.js} +1 -1
  57. package/dist/designer/assets/{preload-helper-CG0n22O7.js → SvGrid.helpers-BgT-gnCo.js} +1 -1
  58. package/dist/designer/assets/SvGridCellEditor-0W1L2hJ1.js +2 -0
  59. package/dist/designer/assets/SvGridChart-DBOR4xcz.js +2 -0
  60. package/dist/designer/assets/SvGridChart-fkMWeh1J.css +1 -0
  61. package/dist/designer/assets/SvGridChartPanel-symrhNnR.js +11 -0
  62. package/dist/designer/assets/SvGridChartView-BmRxq6mU.js +1 -0
  63. package/dist/designer/assets/SvGridChartView-DUc-1RUf.css +1 -0
  64. package/dist/designer/assets/SvGridDropdown-Bb3HH2Aj.js +1 -0
  65. package/dist/designer/assets/SvGridDropdown-CcidB3rm.css +1 -0
  66. package/dist/designer/assets/SvListBox-1oUF6Iav.js +110 -0
  67. package/dist/designer/assets/SvListBox-BXfyqy4a.css +1 -0
  68. package/dist/designer/assets/cell-formatting-wr5wm7US.js +1 -0
  69. package/dist/designer/assets/chart-DXFganU8.js +1 -0
  70. package/dist/designer/assets/date-format-DGagAqRc.css +1 -0
  71. package/dist/designer/assets/{date-format-4DJvNtG2.js → date-format-onlYDsrY.js} +1 -1
  72. package/dist/designer/assets/export-format-D-eP4b2l.js +6 -0
  73. package/dist/designer/assets/{index-zUBix-JQ.js → index-C_a9Cj8Y.js} +2984 -141
  74. package/dist/designer/assets/index-k2stW6L8.css +1 -0
  75. package/dist/designer/assets/preload-helper-HclGiUj8.js +1 -0
  76. package/dist/designer/assets/src-D9p27OGC.js +58 -0
  77. package/dist/designer/index.html +22 -22
  78. package/dist/export-conditional.d.ts +1 -1
  79. package/dist/export-print.js +19 -19
  80. package/dist/export-xls.d.ts +2 -2
  81. package/dist/export.d.ts +2 -2
  82. package/dist/export.js +7 -7
  83. package/dist/expressions/builder-tree.d.ts +2 -2
  84. package/dist/expressions/builder-tree.js +1 -1
  85. package/dist/expressions/compile.d.ts +1 -1
  86. package/dist/import.js +1 -1
  87. package/dist/index.d.ts +53 -53
  88. package/dist/index.js +50 -50
  89. package/dist/install.d.ts +4 -4
  90. package/dist/install.js +11 -11
  91. package/dist/license.d.ts +3 -2
  92. package/dist/license.js +9 -4
  93. package/dist/node/studio.js +123 -114
  94. package/dist/pivot-chart.d.ts +1 -1
  95. package/dist/pivot-designer.d.ts +1 -1
  96. package/dist/pivot-enable.js +3 -3
  97. package/dist/print.d.ts +1 -1
  98. package/dist/print.js +4 -4
  99. package/dist/scheduler-config.d.ts +5 -5
  100. package/dist/scheduler-freebusy.d.ts +1 -1
  101. package/dist/scheduler-freebusy.js +1 -1
  102. package/dist/scheduler.js +2 -2
  103. package/dist/schema-designer.d.ts +1 -1
  104. package/dist/schema-designer.js +2 -2
  105. package/dist/selection-bar.js +2 -2
  106. package/dist/sources/aggregate.d.ts +1 -1
  107. package/dist/sources/auth-supabase.js +1 -1
  108. package/dist/sources/dashboard.d.ts +2 -2
  109. package/dist/sources/dashboard.js +1 -1
  110. package/dist/sources/index.d.ts +13 -13
  111. package/dist/sources/index.js +13 -13
  112. package/dist/sources/realtime-supabase.js +1 -1
  113. package/dist/sources/relation-lookup.d.ts +1 -1
  114. package/dist/sources/relation-lookup.js +1 -1
  115. package/dist/sources/rest-adapters.d.ts +1 -1
  116. package/dist/sources/rest-adapters.js +1 -1
  117. package/dist/sources/rest.d.ts +2 -2
  118. package/dist/sources/rest.js +3 -3
  119. package/dist/sources/supabase.d.ts +2 -2
  120. package/dist/sources/supabase.js +3 -3
  121. package/dist/sources/with-entity-rules.d.ts +1 -1
  122. package/dist/sources/with-entity-rules.js +1 -1
  123. package/dist/sources/with-relation-labels.d.ts +1 -1
  124. package/dist/studio/emit-project.js +2161 -2127
  125. package/dist/studio/emit-schema.js +369 -369
  126. package/dist/studio/index.d.ts +1 -1
  127. package/dist/studio/index.js +1 -1
  128. package/dist/studio/introspect-db.js +45 -45
  129. package/dist/studio/project.d.ts +10 -0
  130. package/dist/studio/samples/crm.js +6 -6
  131. package/dist/studio/samples/fleet.js +7 -7
  132. package/dist/studio/samples/insurance.js +9 -9
  133. package/dist/studio/samples/inventory.js +12 -12
  134. package/dist/studio/samples/projects.js +5 -5
  135. package/dist/studio/samples/support.js +8 -8
  136. package/dist/studio/scaffold-app.js +104 -104
  137. package/dist/studio/scaffold.js +151 -151
  138. package/dist/studio/ui-components.d.ts +7 -0
  139. package/dist/studio/ui-components.js +35 -0
  140. package/dist/sveltekit/in-memory.d.ts +3 -3
  141. package/dist/sveltekit/in-memory.js +4 -4
  142. package/dist/sveltekit/index.d.ts +6 -6
  143. package/dist/sveltekit/index.js +5 -5
  144. package/dist/sveltekit/query-plan.d.ts +1 -1
  145. package/dist/sveltekit/sql-source.d.ts +4 -4
  146. package/dist/sveltekit/sql-source.js +4 -4
  147. package/dist/sveltekit/sql.d.ts +1 -1
  148. package/dist/sveltekit/transport.d.ts +2 -2
  149. package/dist/sveltekit/transport.js +1 -1
  150. package/dist/upgrade-prompt.js +25 -25
  151. package/package.json +6 -3
  152. package/dist/designer/assets/GridMenus-Cgilexpk.js +0 -8
  153. package/dist/designer/assets/SvDateRangeInput-BV5OXYQ2.css +0 -1
  154. package/dist/designer/assets/SvDateTimePicker-BdioTrJQ.js +0 -1
  155. package/dist/designer/assets/SvDateTimePicker-CY8TK4BT.css +0 -1
  156. package/dist/designer/assets/SvField-BF-9TJSd.css +0 -1
  157. package/dist/designer/assets/SvGridCellEditor-dLY7_kk9.js +0 -2
  158. package/dist/designer/assets/SvGridChart-BEDNTdc5.js +0 -2
  159. package/dist/designer/assets/SvGridChart-Vu4Nvjiv.css +0 -1
  160. package/dist/designer/assets/SvGridChartPanel-x3lzSxuf.js +0 -10
  161. package/dist/designer/assets/SvGridChartView-CAKhPELi.js +0 -1
  162. package/dist/designer/assets/SvGridChartView-DX9HfkBR.css +0 -1
  163. package/dist/designer/assets/SvGridDropdown-CAYG7Y-O.js +0 -1
  164. package/dist/designer/assets/SvGridDropdown-Crwb2P3Q.css +0 -1
  165. package/dist/designer/assets/SvListBox-CVYQcLX9.js +0 -1
  166. package/dist/designer/assets/SvListBox-DgN8kvjt.css +0 -1
  167. package/dist/designer/assets/chart-DHEgt4lN.js +0 -1
  168. package/dist/designer/assets/date-format-Dzy4mTGh.css +0 -1
  169. package/dist/designer/assets/export-format-DwjuTfrQ.js +0 -6
  170. package/dist/designer/assets/index-Cp7fDJ3b.css +0 -1
  171. package/dist/designer/assets/js-scroller.svelte-Bhxqb3-c.js +0 -110
  172. package/dist/designer/assets/src-B7DNcoQK.css +0 -1
  173. package/dist/designer/assets/src-BoYyigAC.js +0 -2896
  174. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/_svelte_metadata.json +0 -1
  175. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/_metadata.json +0 -178
  176. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/attachments-BOv1rBKp.js +0 -3875
  177. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/attachments-BOv1rBKp.js.map +0 -1
  178. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/constants-B9vgIdCd.js +0 -21
  179. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/constants-B9vgIdCd.js.map +0 -1
  180. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/dev-T1qbW_qD.js +0 -1938
  181. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/dev-T1qbW_qD.js.map +0 -1
  182. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/events-Bo11SfVK.js +0 -205
  183. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/events-Bo11SfVK.js.map +0 -1
  184. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/flags-X7D4vfrZ.js +0 -18
  185. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/flags-X7D4vfrZ.js.map +0 -1
  186. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/hydration-oyUje5i1.js +0 -264
  187. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/hydration-oyUje5i1.js.map +0 -1
  188. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/legacy-client-DeSQgSFm.js +0 -697
  189. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/legacy-client-DeSQgSFm.js.map +0 -1
  190. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/package.json +0 -3
  191. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte.js +0 -134
  192. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte.js.map +0 -1
  193. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_animate.js +0 -55
  194. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_animate.js.map +0 -1
  195. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_attachments.js +0 -2
  196. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_compiler.js +0 -46843
  197. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_compiler.js.map +0 -1
  198. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_easing.js +0 -237
  199. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_easing.js.map +0 -1
  200. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_events.js +0 -2
  201. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal.js +0 -4
  202. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal.js.map +0 -1
  203. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_client.js +0 -7
  204. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_disclose-version.js +0 -4
  205. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_disclose-version.js.map +0 -1
  206. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_async.js +0 -5
  207. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_async.js.map +0 -1
  208. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_legacy.js +0 -5
  209. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_legacy.js.map +0 -1
  210. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_tracing.js +0 -5
  211. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_tracing.js.map +0 -1
  212. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_server.js +0 -6
  213. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_legacy.js +0 -83
  214. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_legacy.js.map +0 -1
  215. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_motion.js +0 -559
  216. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_motion.js.map +0 -1
  217. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_reactivity.js +0 -24
  218. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_reactivity.js.map +0 -1
  219. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_reactivity_window.js +0 -122
  220. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_reactivity_window.js.map +0 -1
  221. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_server.js +0 -2
  222. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_store.js +0 -89
  223. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_store.js.map +0 -1
  224. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_transition.js +0 -241
  225. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_transition.js.map +0 -1
  226. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/utils-BbWyXNk1.js +0 -4938
  227. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/utils-BbWyXNk1.js.map +0 -1
  228. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/utils-DI_fC7vt.js +0 -495
  229. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/utils-DI_fC7vt.js.map +0 -1
  230. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/validate-Dyr3lQv9.js +0 -190
  231. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/validate-Dyr3lQv9.js.map +0 -1
  232. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/version-_9FHH-LF.js +0 -8
  233. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/version-_9FHH-LF.js.map +0 -1
  234. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/warnings-CUbSPnyP.js +0 -138
  235. package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/warnings-CUbSPnyP.js.map +0 -1
@@ -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';
@@ -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
  }),
@@ -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
  }