smoodly 0.0.45 → 0.0.47

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 (245) hide show
  1. package/README.md +3 -3
  2. package/dist/addresses.d.ts +6 -7
  3. package/dist/addresses.js +6 -4
  4. package/dist/admin/PublicSans-LICENSE.txt +93 -0
  5. package/dist/admin/auth-config.d.ts +6 -0
  6. package/dist/admin/auth-config.js +1 -0
  7. package/dist/admin/browser/fetch-op.d.ts +10 -0
  8. package/dist/admin/browser/fetch-op.js +44 -0
  9. package/dist/admin/browser/main.d.ts +1 -0
  10. package/dist/admin/browser/main.js +21 -0
  11. package/dist/admin/custom-section.d.ts +1 -1
  12. package/dist/admin/drift.d.ts +1 -1
  13. package/dist/admin/editor/EditorView.js +14 -14
  14. package/dist/admin/editor/autosave.js +1 -1
  15. package/dist/admin/editor/canvas-address.d.ts +2 -0
  16. package/dist/admin/editor/canvas-address.js +8 -0
  17. package/dist/admin/editor/overlay-geometry.d.ts +1 -1
  18. package/dist/admin/editor/protocol.d.ts +18 -4
  19. package/dist/admin/editor/protocol.js +15 -1
  20. package/dist/admin/editor/useCanvasBridge.d.ts +1 -1
  21. package/dist/admin/editor/useCanvasBridge.js +5 -6
  22. package/dist/admin/editor/useInlineSession.js +4 -2
  23. package/dist/admin/files.d.ts +11 -0
  24. package/dist/admin/files.generated.js +2 -0
  25. package/dist/admin/files.js +8 -0
  26. package/dist/admin/forms/useRefOptions.d.ts +2 -2
  27. package/dist/admin/forms/useRefOptions.js +2 -2
  28. package/dist/admin/forms/useRichtextEditor.js +4 -4
  29. package/dist/admin/handler.d.ts +40 -0
  30. package/dist/admin/handler.js +151 -0
  31. package/dist/admin/health.d.ts +4 -0
  32. package/dist/admin/index.d.ts +1 -1
  33. package/dist/admin/ops-impl.d.ts +7 -1
  34. package/dist/admin/ops-impl.js +112 -35
  35. package/dist/admin/ops.d.ts +3 -2
  36. package/dist/admin/page-data.d.ts +21 -0
  37. package/dist/admin/page-data.js +4 -0
  38. package/dist/admin/page.d.ts +6 -0
  39. package/dist/admin/page.js +35 -0
  40. package/dist/admin/serialize.js +7 -7
  41. package/dist/admin/shell/AdminApp.js +2 -2
  42. package/dist/admin/shell/ContentHealthPage.js +3 -1
  43. package/dist/admin/shell/EntryForm.js +1 -1
  44. package/dist/admin/shell/router.d.ts +3 -16
  45. package/dist/admin/shell/router.js +3 -39
  46. package/dist/admin/shell/session.d.ts +2 -5
  47. package/dist/admin/supabase-auth.js +1 -1
  48. package/dist/admin/tree-ops.d.ts +1 -1
  49. package/dist/admin/ui/fonts.d.ts +12 -0
  50. package/dist/admin/ui/fonts.js +22 -0
  51. package/dist/admin/ui/theme.d.ts +13 -4
  52. package/dist/admin/ui/theme.js +28 -157
  53. package/dist/assemble.d.ts +60 -0
  54. package/dist/assemble.js +359 -0
  55. package/dist/astro/cache.d.ts +34 -0
  56. package/dist/astro/cache.js +69 -0
  57. package/dist/astro/components/Custom.astro +21 -0
  58. package/dist/astro/components/Guarded.astro +24 -0
  59. package/dist/astro/components/Head.astro +26 -0
  60. package/dist/astro/components/Image.astro +20 -0
  61. package/dist/astro/components/RichText.astro +23 -0
  62. package/dist/astro/components/Section.astro +20 -0
  63. package/dist/astro/components/Video.astro +5 -0
  64. package/dist/astro/components/Zone.astro +19 -0
  65. package/dist/astro/components.d.ts +6 -0
  66. package/dist/astro/components.js +7 -0
  67. package/dist/astro/content-loaders.d.ts +40 -0
  68. package/dist/astro/content-loaders.js +100 -0
  69. package/dist/astro/content.d.ts +9 -0
  70. package/dist/astro/content.js +17 -0
  71. package/dist/astro/custom.d.ts +1 -0
  72. package/dist/astro/custom.js +3 -0
  73. package/dist/astro/defaults.d.ts +20 -0
  74. package/dist/astro/defaults.js +21 -0
  75. package/dist/astro/env-files.d.ts +1 -0
  76. package/dist/astro/env-files.js +21 -0
  77. package/dist/astro/head.d.ts +13 -0
  78. package/dist/astro/head.js +19 -0
  79. package/dist/astro/image.d.ts +27 -0
  80. package/dist/astro/image.js +29 -0
  81. package/dist/astro/index.d.ts +43 -0
  82. package/dist/astro/index.js +111 -0
  83. package/dist/astro/locale-paths.d.ts +30 -0
  84. package/dist/astro/locale-paths.js +38 -0
  85. package/dist/astro/middleware.d.ts +1 -0
  86. package/dist/astro/middleware.js +83 -0
  87. package/dist/astro/preview-document.d.ts +1 -0
  88. package/dist/astro/preview-document.js +18 -0
  89. package/dist/astro/preview.d.ts +10 -0
  90. package/dist/astro/preview.js +72 -0
  91. package/dist/astro/richtext.d.ts +15 -0
  92. package/dist/astro/richtext.js +78 -0
  93. package/dist/astro/routes/admin.d.ts +3 -0
  94. package/dist/astro/routes/admin.js +41 -0
  95. package/dist/astro/routes/page.astro +17 -0
  96. package/dist/astro/routes/preview.astro +11 -0
  97. package/dist/astro/runtime.d.ts +32 -0
  98. package/dist/astro/runtime.js +46 -0
  99. package/dist/astro/scope.d.ts +45 -0
  100. package/dist/astro/scope.js +103 -0
  101. package/dist/astro/server.d.ts +14 -0
  102. package/dist/astro/server.js +45 -0
  103. package/dist/astro/shell.d.ts +67 -0
  104. package/dist/astro/shell.js +63 -0
  105. package/dist/astro/style.d.ts +1 -0
  106. package/dist/astro/style.js +11 -0
  107. package/dist/astro/views-check.d.ts +3 -0
  108. package/dist/astro/views-check.js +19 -0
  109. package/dist/astro/zone.d.ts +39 -0
  110. package/dist/astro/zone.js +33 -0
  111. package/dist/bind.d.ts +19 -0
  112. package/dist/bind.js +34 -0
  113. package/dist/bridge/bridge.d.ts +9 -0
  114. package/dist/bridge/bridge.js +107 -0
  115. package/dist/bridge/entry.d.ts +1 -0
  116. package/dist/bridge/entry.js +5 -0
  117. package/dist/bridge/preview-pill.d.ts +18 -0
  118. package/dist/bridge/preview-pill.js +115 -0
  119. package/dist/cli/import.d.ts +3 -0
  120. package/dist/cli/import.js +10 -1
  121. package/dist/cli/load-collections.js +4 -3
  122. package/dist/cli/load-config.d.ts +4 -0
  123. package/dist/cli/load-config.js +26 -0
  124. package/dist/cli/main.d.ts +5 -1
  125. package/dist/cli/main.js +24 -6
  126. package/dist/cli/migrate.d.ts +13 -0
  127. package/dist/cli/migrate.js +30 -2
  128. package/dist/cli/rebuild.d.ts +23 -0
  129. package/dist/cli/rebuild.js +22 -0
  130. package/dist/cli/space-io.d.ts +15 -1
  131. package/dist/cli/space-io.js +14 -0
  132. package/dist/client.js +5 -0
  133. package/dist/config.d.ts +28 -20
  134. package/dist/config.js +71 -75
  135. package/dist/content/content-api.d.ts +1 -1
  136. package/dist/content/node.d.ts +2 -3
  137. package/dist/content/node.js +2 -1
  138. package/dist/crash-message.d.ts +1 -0
  139. package/dist/crash-message.js +8 -0
  140. package/dist/css.d.ts +4 -0
  141. package/dist/css.js +5 -2
  142. package/dist/custom/CustomSection.d.ts +1 -1
  143. package/dist/custom/CustomSection.js +4 -8
  144. package/dist/custom/css.js +2 -2
  145. package/dist/custom/index.d.ts +6 -10
  146. package/dist/custom/index.js +1 -2
  147. package/dist/custom/layout.d.ts +5 -0
  148. package/dist/custom/layout.js +14 -0
  149. package/dist/document-stamp.d.ts +7 -0
  150. package/dist/document-stamp.js +48 -0
  151. package/dist/entry-page.d.ts +3 -18
  152. package/dist/env.js +1 -1
  153. package/dist/global-id.js +2 -2
  154. package/dist/global.d.ts +5 -2
  155. package/dist/global.js +8 -5
  156. package/dist/image/next-config.d.ts +3 -0
  157. package/dist/image/next-config.js +12 -7
  158. package/dist/image/remote-pattern.d.ts +1 -0
  159. package/dist/image/remote-pattern.js +5 -0
  160. package/dist/index.d.ts +15 -17
  161. package/dist/index.js +10 -19
  162. package/dist/marks.d.ts +7 -0
  163. package/dist/marks.js +7 -0
  164. package/dist/next/admin-route.d.ts +7 -0
  165. package/dist/next/admin-route.js +28 -0
  166. package/dist/next/bridge.d.ts +1 -0
  167. package/dist/next/bridge.js +26 -0
  168. package/dist/next/canvas-boundary.d.ts +1 -1
  169. package/dist/next/canvas-slot.d.ts +1 -0
  170. package/dist/next/canvas-slot.js +4 -3
  171. package/dist/next/index.d.ts +2 -0
  172. package/dist/next/index.js +1 -0
  173. package/dist/next/page-renderer.d.ts +5 -1
  174. package/dist/next/page-renderer.js +19 -33
  175. package/dist/next/preview-pill-define.d.ts +1 -0
  176. package/dist/next/preview-pill-define.js +10 -0
  177. package/dist/next/preview-pill.d.ts +0 -3
  178. package/dist/next/preview-pill.js +7 -50
  179. package/dist/next/queries.d.ts +3 -28
  180. package/dist/next/queries.js +3 -90
  181. package/dist/next/reads.d.ts +2 -0
  182. package/dist/next/reads.js +18 -0
  183. package/dist/page-context.d.ts +89 -0
  184. package/dist/page-context.js +8 -0
  185. package/dist/pairing.d.ts +2 -22
  186. package/dist/project.d.ts +85 -0
  187. package/dist/project.js +228 -0
  188. package/dist/published.d.ts +115 -0
  189. package/dist/published.js +136 -0
  190. package/dist/react.d.ts +61 -0
  191. package/dist/react.js +17 -0
  192. package/dist/read-shapes.d.ts +1 -1
  193. package/dist/reads.d.ts +80 -0
  194. package/dist/reads.js +142 -0
  195. package/dist/refs.d.ts +1 -1
  196. package/dist/registration.d.ts +8 -0
  197. package/dist/registration.js +17 -0
  198. package/dist/render.d.ts +5 -83
  199. package/dist/render.js +5 -10
  200. package/dist/resolve.d.ts +1 -1
  201. package/dist/richtext/index.d.ts +6 -2
  202. package/dist/richtext/index.js +3 -2
  203. package/dist/richtext-href.d.ts +4 -0
  204. package/dist/richtext-href.js +17 -0
  205. package/dist/richtext-render.js +1 -14
  206. package/dist/schema-version.d.ts +1 -1
  207. package/dist/schema-version.js +1 -1
  208. package/dist/section-crash.d.ts +2 -2
  209. package/dist/section-crash.js +2 -7
  210. package/dist/section-wrapper.d.ts +3 -10
  211. package/dist/section-wrapper.js +3 -2
  212. package/dist/site.d.ts +40 -14
  213. package/dist/site.js +199 -284
  214. package/dist/smd-key.d.ts +9 -0
  215. package/dist/smd-key.js +1 -0
  216. package/dist/sql-space.d.ts +5 -0
  217. package/dist/sql-space.js +11 -5
  218. package/dist/sql.d.ts +2 -0
  219. package/dist/sql.js +127 -1
  220. package/dist/store.d.ts +1 -1
  221. package/dist/supabase-published-store.d.ts +45 -0
  222. package/dist/supabase-published-store.js +247 -0
  223. package/dist/supabase-store.d.ts +1 -1
  224. package/dist/toolset.d.ts +2 -4
  225. package/dist/toolset.js +6 -4
  226. package/dist/version.d.ts +1 -1
  227. package/dist/version.js +1 -1
  228. package/dist/view-props.d.ts +40 -0
  229. package/dist/view-props.js +1 -0
  230. package/dist/views.d.ts +36 -0
  231. package/dist/views.js +52 -0
  232. package/dist/zones.d.ts +7 -7
  233. package/dist/zones.js +7 -6
  234. package/migrations/20261007120000_smoodly_v8.sql +154 -0
  235. package/migrations/20261007200000_smoodly_v9.sql +30 -0
  236. package/migrations/20261008120000_smoodly_v10.sql +47 -0
  237. package/package.json +46 -19
  238. package/dist/admin/next/bridge.d.ts +0 -2
  239. package/dist/admin/next/bridge.js +0 -129
  240. package/dist/admin/next/create-admin.d.ts +0 -19
  241. package/dist/admin/next/create-admin.js +0 -44
  242. package/dist/admin/next/index.d.ts +0 -8
  243. package/dist/admin/next/index.js +0 -8
  244. package/dist/admin/next/op-handler.d.ts +0 -18
  245. package/dist/admin/next/op-handler.js +0 -31
@@ -1,9 +1,8 @@
1
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
1
  // The design system, as one injected stylesheet.
3
2
  //
4
3
  // Smoodly ships as a library into someone else's Next app, so the admin
5
- // can't rely on the host importing CSS: `AdminLayout` renders <AdminStyles/>
6
- // once and every admin surface styles itself from these tokens. Everything
4
+ // can't rely on the host importing CSS: the prebuilt admin's entry writes it into
5
+ // the document once (browser/main.tsx) and every admin surface styles itself from these tokens. Everything
7
6
  // is scoped under `.sm-admin` — never `:root` — so the host's own custom
8
7
  // properties and class names can't collide with ours.
9
8
  //
@@ -11,11 +10,13 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
11
10
  // neutral look, 2026-09-25: a navy frame around a white sheet, soft grey
12
11
  // tiles instead of white cards, white fields on the tiles, Spruce accent,
13
12
  // sans only). Every rule below reads its colours, radii, sizes and letter
14
- // case from tokens, so a look is a token block: the previous warm look
15
- // survives as the `warm` block further down, on `data-look="warm"`.
13
+ // case from tokens.
16
14
  // Hover/focus/disabled live here rather than in inline styles, which is
17
15
  // the whole reason for the stylesheet.
18
16
  import { INSPECTOR_W_KEY, MIN_INSPECTOR_W } from "./resize.js";
17
+ /** The sheet colours, named so the page's pre-script background (BOOT_CSS) cannot drift from the tokens. */
18
+ export const SHEET_LIGHT = "#FFFFFF";
19
+ export const SHEET_DARK = "#1B1E30";
19
20
  const TOKENS_LIGHT = `
20
21
  --accent:#1C6E5B; --accent-hover:#175C4C; --accent-soft:#DDEBE4; --accent-line:#9CC9B8; --on-accent:#FFFFFF;
21
22
  --green-700:#1F7A46; --green-50:#E3F3EA; --green-300:#6FD39A; --green-500:#2E9E5B;
@@ -23,7 +24,7 @@ const TOKENS_LIGHT = `
23
24
  --red-700:#C4372E; --red-50:#FBE9E7; --red-300:#F5A5A0;
24
25
 
25
26
  /* The shell: navy frame, white sheet, grey tiles on the sheet, white fields on the tiles. */
26
- --frame:#151727; --sheet:#FFFFFF;
27
+ --frame:#151727; --sheet:${SHEET_LIGHT};
27
28
  --bg:var(--sheet); --canvas:#ECEDF1; --surface:#F6F6F6; --surface-form:#F6F6F6; --surface-inset:#FFFFFF;
28
29
  --menu-bg:#FFFFFF;
29
30
  --input-bg:#FFFFFF; --input-hover-bg:#FFFFFF; --input-focus-bg:#FFFFFF; --input-border:transparent;
@@ -81,7 +82,7 @@ const TOKENS_LIGHT = `
81
82
  const TOKENS_DARK = `
82
83
  --accent:#6CC4A6; --accent-hover:#82D2B8; --accent-soft:rgba(108,196,166,.18); --accent-line:#6CC4A6; --on-accent:#151727;
83
84
  --selection-global:#F09A5C;
84
- --frame:#0F1120; --sheet:#1B1E30;
85
+ --frame:#0F1120; --sheet:${SHEET_DARK};
85
86
  --canvas:#131526; --surface:#242840; --surface-form:#242840; --surface-inset:#1B1E30;
86
87
  --menu-bg:#242840;
87
88
  --input-bg:#1B1E30; --input-hover-bg:#1B1E30; --input-focus-bg:#1B1E30;
@@ -142,129 +143,9 @@ const SCALE = `
142
143
  --outline-selection:2px solid var(--selection);
143
144
  --outline-selection-global:2px solid var(--selection-global);
144
145
  `;
145
- /* ── The warm look (design_handoff_smoodly_warm/, the default from
146
- 2026-09-08 to 2026-09-25), kept as a token block for comparison: frozen
147
- copies of the three strings as they were, plus WARM_EXTRA giving the
148
- tokens the neutral restyle added their warm values. Applied under
149
- `.sm-admin[data-look="warm"]`; switch from the console with
150
- localStorage.setItem("smoodly-look","warm") and reload, removeItem to go
151
- back. A token snapshot, not a pixel restore: shared class rules move
152
- with the default look. The earlier technical look is at tag
153
- `look-technical`. */
154
- const WARM_LIGHT = `
155
- --accent:#1C6E5B; --accent-hover:#175C4C; --accent-soft:#DDEBE4; --accent-line:#9CC9B8; --on-accent:#FFFFFF;
156
- --green-700:#1F7A46; --green-50:#E3F3EA; --green-300:#6FD39A; --green-500:#2E9E5B;
157
- --amber-700:#8A5A00; --amber-50:#FBF1DC; --amber-300:#E8B85A;
158
- --red-700:#B42318; --red-50:#FDECEC; --red-300:#F5A5A0;
159
-
160
- --bg:#F4F1EB; --canvas:#ECE8DF; --surface:#FFFFFF; --surface-form:#FDFCFA; --surface-inset:#F4F1EB;
161
- --input-bg:#FFFFFF; --input-hover-bg:#FFFFFF; --input-focus-bg:#FFFFFF; --input-border:var(--line);
162
- --line:#E8E3DA; --line-dashed:#D8D1C4; --line-soft:#EFEBE3;
163
- --text:#1F1D1A; --text-secondary:#4E4942; --text-muted:#7A746A; --text-subtle:#A39C90; --text-disabled:#C4BDB1;
164
- --selection:var(--accent); --nav-active-bg:var(--accent-soft); --nav-active-fg:var(--accent);
165
- --selection-global:#C4620C;
166
- --hover:rgba(31,29,26,.05); --press:rgba(31,29,26,.09); --control-hover:#F8F6F1;
167
- --btn-secondary-bg:var(--surface); --btn-secondary-hover:#F8F6F1; --tile-hover:var(--surface);
168
- --bar-bg:transparent; --bar-border:0; --menu-border:0; --card-divider:0;
169
- --card-title-size:var(--text-md); --card-title-color:var(--text);
170
- --tabs-bg:var(--surface-inset); --tab-active-bg:var(--surface); --tab-active-fg:var(--text); --tab-active-shadow:var(--shadow-seg);
171
- --seg-bg:var(--canvas);
172
- --toolbar-bg:#1F1D1A; --toolbar-fg:#F4F1EB;
173
- --plus-bg:#DDEBE4; --plus-hover:#D0E3D9; --plus-fg:#1C6E5B;
174
- --plus-icon-bg:#1C6E5B; --plus-icon-fg:#FFFFFF; --plus-shadow:none;
175
- --logo-color:var(--accent);
176
-
177
- --status-published-fg:var(--green-700); --status-published-bg:var(--green-50);
178
- --status-changes-fg:var(--amber-700); --status-changes-bg:var(--amber-50);
179
- --status-draft-fg:var(--text-muted); --status-draft-bg:var(--surface-inset);
180
- --status-scheduled-fg:var(--accent); --status-scheduled-bg:var(--accent-soft);
181
- --status-saved-dot:var(--green-500);
182
- --warn:var(--amber-700); --warn-soft:var(--amber-50);
183
- --danger:var(--red-700); --danger-soft:var(--red-50);
184
-
185
- --page-bg:#FFFFFF; --page-text:#1F1D1A;
186
- --shadow-page:0 1px 2px rgba(0,0,0,.06), 0 12px 32px rgba(0,0,0,.1);
187
- --shadow-float:0 2px 8px rgba(0,0,0,.2);
188
- --shadow-seg:0 1px 2px rgba(40,30,10,.08);
189
- --focus-ring:0 0 0 .5px var(--accent);
190
- --shadow-pop:0 4px 20px rgba(0,0,0,.14);
191
- --logo-filter:none;
192
- --when-light:inline-flex; --when-dark:none;
193
- `;
194
- const WARM_DARK = `
195
- --accent:#6CC4A6; --accent-hover:#82D2B8; --accent-soft:rgba(108,196,166,.18); --accent-line:#6CC4A6; --on-accent:#0B1F18;
196
- --selection-global:#F09A5C;
197
- --bg:#1C1A17; --canvas:#141210; --surface:#27241F; --surface-form:#27241F; --surface-inset:#1C1A17;
198
- --input-bg:#211E1A; --input-hover-bg:#211E1A; --input-focus-bg:#211E1A;
199
- --line:#3A3630; --line-dashed:#4A453D; --line-soft:#3A3630;
200
- --text:#F1EDE6; --text-secondary:#C9C2B7; --text-muted:#9A9388; --text-subtle:#7C7568; --text-disabled:#5A5449;
201
- --hover:rgba(241,237,230,.05); --press:rgba(241,237,230,.09); --control-hover:#2E2A25;
202
- --btn-secondary-bg:var(--surface); --btn-secondary-hover:#2E2A25;
203
- --toolbar-bg:#0F0E0C; --toolbar-fg:#F1EDE6;
204
-
205
- --status-published-fg:var(--green-300); --status-published-bg:rgba(111,211,154,.14);
206
- --status-changes-fg:var(--amber-300); --status-changes-bg:rgba(232,184,90,.14);
207
- --status-draft-fg:var(--text-muted); --status-draft-bg:var(--press);
208
- --warn:var(--amber-300); --warn-soft:rgba(232,184,90,.14);
209
- --danger:var(--red-300); --danger-soft:rgba(244,102,92,.14);
210
-
211
- --shadow-page:0 1px 2px rgba(0,0,0,.4), 0 12px 32px rgba(0,0,0,.35);
212
- --shadow-pop:0 4px 20px rgba(0,0,0,.5);
213
- --when-light:none; --when-dark:inline-flex;
214
- `;
215
- const WARM_SCALE = `
216
- --font-sans:'Public Sans',-apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;
217
- --font-serif:'Source Serif 4',Georgia,'Times New Roman',serif;
218
- --font-mono:ui-monospace,Menlo,Consolas,monospace;
219
- --text-2xs:10px; --text-xs:11px; --text-sm:12px; --text-md:14px;
220
- --text-lg:15px; --text-xl:16px; --text-2xl:20px; --text-3xl:22px; --text-4xl:30px;
221
- --tracking-tight:-0.02em; --tracking-label:0.1em; --tracking-tag:0.08em;
222
- --caps-transform:none; --caps-tracking:0;
223
- --label-size:12px; --label-weight:500; --label-transform:none; --label-tracking:0;
224
- --meta-font:var(--font-sans); --meta-size:13px;
225
- --title-font:var(--font-sans); --title-size:18px; --title-weight:600; --title-tracking:-0.01em;
226
- --doc-title-size:30px;
227
- --blocktag-font:var(--font-sans); --blocktag-size:11px; --blocktag-transform:none; --blocktag-tracking:0;
228
- --blocktag-radius:var(--radius-round); --blocktag-shift:translate(16px,-50%); --blocktag-shift-inside:translate(16px,8px);
229
- --badge-h:24px; --badge-dot:inline-block;
230
-
231
- --radius-xs:2px; --radius-sm:8px; --radius-md:10px; --radius-lg:12px;
232
- --radius-card:14px; --radius-card-lg:16px; --radius-btn:999px; --radius-round:999px;
233
- --page-radius:4px 4px 0 0; --selection-radius:4px;
234
- --control-h:40px; --control-h-sm:34px; --control-h-lg:48px; --button-h:36px; --button-h-sm:28px; --row-h:48px; --topbar-h:64px;
235
- --outline-row-h:36px; --seg-pad-y:7px; --tabs-pad:3px;
236
- --plus-h:32px; --plus-pad:0 14px 0 6px; --plus-label:inline;
237
- --nav-w:72px; --inspector-w:360px; --gutter:20px; --frame-pad:24px;
238
- --rail-pad:22px 6px 16px; --rail-logo:none; --topbar-pad:0; --back-size:32px; --back-bg:var(--surface);
239
- --table-pad:8px 12px; --table-top:80px; --canvas-pad:24px 40px 0; --card-pad:16px 18px; --card-gap:12px; --form-pad:32px 40px;
240
- --border:1px solid var(--line);
241
- --outline-selection:2px solid var(--selection);
242
- --outline-selection-global:2px solid var(--selection-global);
243
- `;
244
- /* The tokens the neutral restyle added, with the values the warm look
245
- implied: no frame or sheet (the ground is the shell's background and the
246
- main column sits on it), the rail on the ground in the text colour,
247
- menus and modals on the card surface, ruled table rows, hairlined
248
- outline rows, pill tabs and tags. */
249
- const WARM_EXTRA = `
250
- --frame:var(--bg); --sheet:transparent; --menu-bg:var(--surface);
251
- --rail-fg:var(--text); --rail-active-fg:var(--nav-active-fg); --rail-active-bg:var(--nav-active-bg); --rail-hover-bg:var(--tile-hover);
252
- --spanbar-bg:var(--seg-bg); --spanbar-col:var(--surface); --switch-bg:var(--seg-bg); --seg-active-bg:var(--surface);
253
- --table-rule:1px solid var(--line); --row-rule:1px solid var(--line-soft);
254
- --outline-row-bg:transparent; --outline-row-border:1px solid var(--line);
255
- --logo-outer:var(--accent); --logo-inner:#FFFFFF;
256
- --scrim:rgba(0,0,0,.45); --shadow-modal:var(--shadow-pop);
257
- --radius-modal:var(--radius-card); --outline-row-radius:var(--radius-md); --tabs-radius:var(--radius-btn); --tab-radius:var(--radius-btn);
258
- --row-radius:0; --tag-radius:var(--radius-sm); --plus-radius:var(--radius-round); --toolbar-radius:var(--radius-btn);
259
- --rtcard-bg:var(--input-bg); --rtcard-border:var(--input-border); --canvas-ground:var(--control-hover);
260
- --frame-pad-top:0px; --shell-gap:var(--gutter); --sheet-radius:0; --sheet-pad:0;
261
- --rail-logo-opacity:1; --rail-tile-w:42px; --rail-tile-h:34px; --rail-tile-radius:var(--radius-md);
262
- `;
263
146
  /** The light/dark cascade for one root selector. Order matters: the last
264
147
  * rule has the same specificity as the host-attribute rule, so an explicit
265
- * choice from the theme toggle wins over a dark <html> and over the OS.
266
- * Each look's root carries one more attribute than the default's, so a
267
- * look's rules beat the default's at every step of the same cascade. */
148
+ * choice from the theme toggle wins over a dark <html> and over the OS. */
268
149
  function cascade(root, scale, light, dark) {
269
150
  return `
270
151
  ${root}{${scale}${light}}
@@ -275,10 +156,7 @@ html[data-theme="dark"] ${root},${root}[data-theme="dark"]{${dark}}
275
156
  ${root}[data-theme="light"]{${light}}`;
276
157
  }
277
158
  export const ADMIN_CSS = `
278
- @import url("https://fonts.googleapis.com/css2?family=Public+Sans:wght@400;500;600;700&family=Source+Serif+4:opsz,wght@8..60,500;8..60,600&display=swap");
279
-
280
159
  ${cascade(".sm-admin", SCALE, TOKENS_LIGHT, TOKENS_DARK)}
281
- ${cascade('.sm-admin[data-look="warm"]', WARM_SCALE + WARM_EXTRA, WARM_LIGHT, WARM_DARK)}
282
160
 
283
161
  /* The admin owns the viewport; a host <body> margin would push it into a
284
162
  page scrollbar. Scoped by :has, so only a page holding the admin is touched. */
@@ -305,8 +183,7 @@ body:has(.sm-admin){margin:0}
305
183
  /* Rail | main. The shell is the frame (design_handoff_smoodly_neutral/
306
184
  components/AppShell.html): navy, 6px above, right of and below the main
307
185
  column, which is the white sheet with a 20px radius and its own inner
308
- padding; the rail fills the frame's left edge. In the warm look the frame
309
- is the ground, the sheet transparent, and a gutter separates the columns.
186
+ padding; the rail fills the frame's left edge.
310
187
  The main column stacks the top bar over one tile-shaped region: list,
311
188
  form or editor. */
312
189
  .sm-shell{
@@ -479,7 +356,7 @@ body:has(.sm-admin){margin:0}
479
356
  }
480
357
  .sm-input,.sm-select{height:var(--control-h);padding:0 14px}
481
358
  .sm-textarea{padding:11px 14px;line-height:1.55;resize:vertical;min-height:72px}
482
- /* The document title at the doc-title size (serif in the warm look, sans in the neutral). */
359
+ /* The document title at the doc-title size. */
483
360
  .sm-input--lg{
484
361
  height:var(--control-h-lg);font:600 var(--doc-title-size)/1.2 var(--font-serif);letter-spacing:var(--title-tracking);
485
362
  }
@@ -537,7 +414,7 @@ body:has(.sm-admin){margin:0}
537
414
  .sm-richtext__content>.react-renderer{margin:18px 0}
538
415
  .sm-richtext__content>.react-renderer:first-child{margin-top:0}
539
416
  .sm-richtext__content>.react-renderer:last-child{margin-bottom:0}
540
- /* Headings inside content are editorial: serif in the warm look. */
417
+ /* Headings inside content take the heading font and weight. */
541
418
  .sm-richtext__content h1,.sm-richtext__content h2,.sm-richtext__content h3,
542
419
  .sm-richtext__content h4,.sm-richtext__content h5,.sm-richtext__content h6{
543
420
  font-family:var(--font-serif);font-weight:600;line-height:1.3;letter-spacing:var(--title-tracking);
@@ -564,8 +441,8 @@ body:has(.sm-admin){margin:0}
564
441
  .sm-richtext__insert-empty{padding:8px;color:var(--text-muted);font-size:var(--text-sm)}
565
442
  .sm-picker__item--active,.sm-picker__item[aria-selected="true"]{background:var(--nav-active-bg)}
566
443
  /* block-node cards (elements, images) inside a richtext field: the tile
567
- tone with a hairline in the neutral look, so a card stands off the white
568
- field it sits in (2026-09-25); white and hairlined in the warm one. The
444
+ tone with a hairline, so a card stands off the white field it sits in
445
+ (2026-09-25). The
569
446
  selected card takes the accent outline below. */
570
447
  .sm-rtcard{border:1px solid var(--rtcard-border);border-radius:var(--radius-md);background:var(--rtcard-bg);min-width:0}
571
448
  .sm-richtext__content .ProseMirror-selectednode .sm-rtcard,.sm-richtext__content .sm-rtcard.ProseMirror-selectednode{outline:2px solid var(--accent);outline-offset:1px}
@@ -653,8 +530,7 @@ body:has(.sm-admin){margin:0}
653
530
  font-size:var(--meta-size);letter-spacing:var(--caps-tracking);color:var(--text-muted);
654
531
  text-transform:var(--caps-transform);position:sticky;top:0;background:var(--surface-form);z-index:1;
655
532
  }
656
- /* Rows: a hairline under every row in both looks (the header's too in the
657
- warm look, 2026-09-09; none in the neutral, 2026-09-25). The rule is a
533
+ /* Rows: a hairline under every row, none under the header (2026-09-25). The rule is a
658
534
  pseudo-element, not a border: a border would follow the rounded corners
659
535
  the neutral hover fill has, and the line must stay straight. */
660
536
  .sm-table__body{display:flex;flex-direction:column}
@@ -730,8 +606,7 @@ body:has(.sm-admin){margin:0}
730
606
 
731
607
  /* ── navigation bits ───────────────────────────────────────────────── */
732
608
  /* Tabs read as an in-card segmented control: a white track with the chosen
733
- option in the tile grey and 10/6px corners in the neutral look, a pill
734
- track with a white shadowed option in the warm one — all tokens. */
609
+ option in the tile grey and 10/6px corners — all tokens. */
735
610
  .sm-tabs{
736
611
  display:flex;gap:2px;padding:var(--tabs-pad);background:var(--tabs-bg);border-radius:var(--tabs-radius);
737
612
  border-bottom:var(--card-divider);flex:none;
@@ -823,7 +698,7 @@ body:has(.sm-admin){margin:0}
823
698
 
824
699
  /* ── cards ─────────────────────────────────────────────────────────── */
825
700
  /* The inspector column (editor, entry and global forms) is a stack of
826
- cards (grey tiles in the neutral look, white cards in the warm). */
701
+ cards (grey tiles). */
827
702
  .sm-inspector{
828
703
  display:flex;flex-direction:column;gap:var(--card-gap);min-height:0;overflow:auto;
829
704
  background:var(--bar-bg);border-left:var(--bar-border);
@@ -852,8 +727,8 @@ body:has(.sm-admin){margin:0}
852
727
  .sm-form>*{width:100%;max-width:680px;align-self:center}
853
728
 
854
729
  /* ── editor ────────────────────────────────────────────────────────── */
855
- /* canvas · handle · inspector. The handle column is the gutter (8px in the
856
- warm look; 8px in the neutral, whose gutter is 0). The calc() is the
730
+ /* canvas · handle · inspector. The handle column is 8px (the gutter is 0).
731
+ The calc() is the
857
732
  maximum the drag maths (ui/resize.ts) also applies — the row less the
858
733
  handle and the canvas's 440px minimum — so a window that shrinks after a
859
734
  drag never leaves the canvas squeezed. */
@@ -885,8 +760,7 @@ body:has(.sm-admin){margin:0}
885
760
  font-size:var(--meta-size);letter-spacing:var(--caps-tracking);text-transform:var(--caps-transform);
886
761
  }
887
762
  .sm-blockglyph{width:14px;height:10px;border:1.5px solid var(--text-muted);border-radius:var(--radius-xs);flex:none}
888
- /* The selected block's label: a pill riding the outline in the warm look,
889
- a 4px-cornered chip in the neutral one. */
763
+ /* The selected block's label: a 4px-cornered chip. */
890
764
  .sm-blocktag{
891
765
  position:absolute;top:0;left:0;transform:var(--blocktag-shift);background:var(--selection);color:var(--on-accent);
892
766
  font-family:var(--blocktag-font);font-size:var(--blocktag-size);font-weight:600;line-height:1.3;
@@ -901,7 +775,7 @@ body:has(.sm-admin){margin:0}
901
775
  }
902
776
  .sm-blocktoolbar__note{font-family:var(--font-mono);font-size:var(--text-xs);color:var(--toolbar-fg);opacity:.7;padding:4px 8px}
903
777
  /* The insert affordance between sections: a labelled pill (the label is
904
- 8px-cornered in the neutral look, a pill in the warm). */
778
+ 8px-cornered). */
905
779
  .sm-plus{
906
780
  display:inline-flex;align-items:center;gap:8px;height:var(--plus-h);min-width:var(--plus-h);padding:var(--plus-pad);
907
781
  border-radius:var(--plus-radius);border:0;background:var(--plus-bg);color:var(--plus-fg);
@@ -917,7 +791,7 @@ body:has(.sm-admin){margin:0}
917
791
  }
918
792
  .sm-plus__label{display:var(--plus-label);font-size:var(--text-sm)}
919
793
  .sm-guide{height:1px;background:color-mix(in srgb,var(--selection) 35%,transparent)}
920
- /* Outline rows: white boxes on the tile in the neutral look, hairlined in the warm one. */
794
+ /* Outline rows: white boxes on the tile. */
921
795
  .sm-outline-row{
922
796
  display:flex;align-items:center;justify-content:space-between;gap:4px;
923
797
  height:var(--outline-row-h);border-radius:var(--outline-row-radius);padding:0 6px 0 12px;
@@ -1190,22 +1064,19 @@ body:has(.sm-admin){margin:0}
1190
1064
  `;
1191
1065
  /** Where the theme toggle's choice is remembered, browser-side only. */
1192
1066
  export const THEME_KEY = "smoodly-theme";
1193
- /** Which look the developer is comparing (see the warm block): "warm" applies it, anything else is the default. */
1194
- export const LOOK_KEY = "smoodly-look";
1195
1067
  /** Applies a remembered choice before first paint, so a dark-mode editor never
1196
1068
  * gets a white flash, and the inspector never jumps to a dragged width. It
1197
1069
  * runs INSIDE the admin wrapper, so `currentScript.parentElement` is that
1198
1070
  * element — no id lookup, and the host document's <html> is left alone. The
1199
1071
  * width test repeats parseStoredWidth (ui/resize.ts) inline: an integer
1200
1072
  * string at or above the minimum, else ignored. */
1201
- const THEME_BOOT = `(function(){try{var e=document.currentScript.parentElement,` +
1073
+ export const THEME_BOOT = `(function(){try{var e=document.currentScript.parentElement,` +
1202
1074
  `t=localStorage.getItem(${JSON.stringify(THEME_KEY)}),` +
1203
- `l=localStorage.getItem(${JSON.stringify(LOOK_KEY)}),` +
1204
1075
  `w=localStorage.getItem(${JSON.stringify(INSPECTOR_W_KEY)});` +
1205
1076
  `if(t==="dark"||t==="light")e.setAttribute("data-theme",t);` +
1206
- `if(l==="warm")e.setAttribute("data-look",l);` +
1207
1077
  `if(w&&/^\\d+$/.test(w)&&+w>=${MIN_INSPECTOR_W})e.style.setProperty("--inspector-w",w+"px")}catch(e){}})()`;
1208
- /** One <style> element and the theme boot, rendered once by AdminLayout. */
1209
- export function AdminStyles() {
1210
- return (_jsxs(_Fragment, { children: [_jsx("style", { "data-smoodly-admin-styles": true, dangerouslySetInnerHTML: { __html: ADMIN_CSS } }), _jsx("script", { dangerouslySetInnerHTML: { __html: THEME_BOOT } })] }));
1211
- }
1078
+ /** The admin page's background until the script has injected the stylesheet: the sheet colour under the
1079
+ * tokens' own light and dark rules, so a dark-mode editor never gets a white flash (admin/page.ts). */
1080
+ export const BOOT_CSS = `body{margin:0}.sm-admin{min-height:100vh;background:${SHEET_LIGHT}}` +
1081
+ `@media (prefers-color-scheme:dark){.sm-admin:not([data-theme="light"]){background:${SHEET_DARK}}}` +
1082
+ `.sm-admin[data-theme="dark"]{background:${SHEET_DARK}}`;
@@ -0,0 +1,60 @@
1
+ import { type EntryRecord } from "./entry-store.ts";
2
+ import type { CollectionSchema } from "./collections.ts";
3
+ import { type PagePathOptions } from "./paths.ts";
4
+ import { type GlobalSchema } from "./global.ts";
5
+ import type { PageRecord } from "./store.ts";
6
+ import type { Descriptor } from "./fields.ts";
7
+ import { type Anchors } from "./anchors.ts";
8
+ import { type EntryItem } from "./read-shapes.ts";
9
+ import type { PublishedPageRow } from "./published.ts";
10
+ import type { EntryQuery, PageTreeItem, SiteEntry, SitePage, SiteOptions } from "./site.ts";
11
+ /** What the site computes from its options before any read: the registered shapes, the code-owned addresses and the resolved styles. */
12
+ export declare function siteShape(options: SiteOptions): {
13
+ locales: import("./paths.ts").LocaleSet;
14
+ pageSchemas: import("./site.ts").SitePageSchema[];
15
+ homePageSlug: string;
16
+ styles: import("./styles.ts").StyleValues;
17
+ custom: import("./index.ts").ResolvedCustom;
18
+ elements: import("./richtext-walk.ts").ElementSchemas;
19
+ codeOwned: import("./addresses.ts").CodeAddress[];
20
+ addresses: import("./addresses.ts").Addresses;
21
+ pathOpts: PagePathOptions;
22
+ anchors: Anchors;
23
+ };
24
+ export type SiteShape = ReturnType<typeof siteShape>;
25
+ /** A template's page-field descriptors (spec 2026-09-10 page fields §3); none for a folder. */
26
+ export declare function pageFieldsOf(shape: SiteShape, template: string | null): Record<string, Descriptor>;
27
+ /** The checks `getEntries` makes before any read, in draft mode and outside it: one function both paths call. */
28
+ export declare function checkEntryQuery(schema: CollectionSchema<any>, collection: string, o: EntryQuery): void;
29
+ /** One read row: the public item, and the record it was projected from (a tree and a bare slug need `parentId`). */
30
+ export type ReadRow = {
31
+ record: EntryRecord;
32
+ item: EntryItem;
33
+ };
34
+ export type Assembler = {
35
+ /** A page of the locale, draft or published, with a stored version in draft mode. */
36
+ page(id: string, locale: string, path: string, opts: {
37
+ draft: boolean;
38
+ version?: string;
39
+ }): Promise<SitePage | null>;
40
+ entry(id: string, locale: string, path: string, opts: {
41
+ draft: boolean;
42
+ }): Promise<SiteEntry | null>;
43
+ global<V>(item: GlobalSchema<V>, locale: string, opts: {
44
+ draft: boolean;
45
+ }): Promise<V | null>;
46
+ /** The pages tree over the editing tables. */
47
+ tree(locale: string, opts: {
48
+ draft: boolean;
49
+ }): Promise<PageTreeItem[]>;
50
+ /** Rows with the record and the projected item. */
51
+ entries(collection: string, q: EntryQuery): Promise<ReadRow[]>;
52
+ /** The light tree row of a node as the delivery table stores it (path null when hidden), for a locale. */
53
+ treeRow(record: PageRecord, all: PageRecord[], locale: string): Promise<Omit<PublishedPageRow, "document" | "tags" | "model" | "stale" | "publishedAt">>;
54
+ /** A memoizing copy for one projection call: listPages, getMany, pathsIn, fieldsOf and assets.getMany answer once per argument set.
55
+ * `pages`: the page list the caller already read, so the copy's listPages answers with it and never reads again. */
56
+ batch(primed?: {
57
+ pages?: PageRecord[];
58
+ }): Assembler;
59
+ };
60
+ export declare function createAssembler(options: SiteOptions, shape: SiteShape): Assembler;