@drawnagency/primitives 0.1.118 → 0.1.120

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 (279) hide show
  1. package/dist/{chunk-O37AV27P.js → chunk-5JYHTHVR.js} +28 -0
  2. package/dist/{chunk-W72BPGR3.js → chunk-BZKHHUIN.js} +44 -8
  3. package/dist/{chunk-4NSOKEA7.js → chunk-HFHM4MNK.js} +12 -7
  4. package/dist/{chunk-CEFFP3CH.js → chunk-HZTPF6OK.js} +304 -83
  5. package/dist/{chunk-RIITGTV3.js → chunk-LQHBC7C6.js} +37 -2
  6. package/dist/{chunk-VY3IFGE3.js → chunk-QAMAIDXZ.js} +1 -1
  7. package/dist/{chunk-HRX3XJBU.js → chunk-RIN2QCYJ.js} +9 -11
  8. package/dist/{chunk-ZOTRHHUB.js → chunk-UNFPATDE.js} +8 -10
  9. package/dist/{chunk-ERLIL4RU.js → chunk-UZBFVVTC.js} +35 -37
  10. package/dist/{chunk-67P34WNW.js → chunk-ZKVQMIMJ.js} +3 -20
  11. package/dist/collab/rebase.js +4 -5
  12. package/dist/components/chat/ChatComposer.d.ts +0 -4
  13. package/dist/components/chat/ChatComposer.d.ts.map +1 -1
  14. package/dist/components/chat/ChatPanel.d.ts +2 -3
  15. package/dist/components/chat/ChatPanel.d.ts.map +1 -1
  16. package/dist/components/chat/markdown.d.ts +2 -3
  17. package/dist/components/chat/markdown.d.ts.map +1 -1
  18. package/dist/components/editor/AudienceIndicator.d.ts +3 -1
  19. package/dist/components/editor/AudienceIndicator.d.ts.map +1 -1
  20. package/dist/components/editor/IndicatorPill.d.ts +3 -1
  21. package/dist/components/editor/IndicatorPill.d.ts.map +1 -1
  22. package/dist/components/editor/PagesModal.d.ts +0 -2
  23. package/dist/components/editor/PagesModal.d.ts.map +1 -1
  24. package/dist/components/editor/SectionBulkEditModal.d.ts +25 -0
  25. package/dist/components/editor/SectionBulkEditModal.d.ts.map +1 -0
  26. package/dist/components/editor/StatusIndicator.d.ts +3 -1
  27. package/dist/components/editor/StatusIndicator.d.ts.map +1 -1
  28. package/dist/components/editor/index.js +28 -26
  29. package/dist/components/primitives/index.js +11 -15
  30. package/dist/components/sections/brand-guide.js +10 -13
  31. package/dist/components/sections/register-schemas.js +16 -21
  32. package/dist/components/sections/register.js +16 -21
  33. package/dist/components/shared/Popover.d.ts +1 -1
  34. package/dist/components/shared/Popover.d.ts.map +1 -1
  35. package/dist/components/shared/SectionSummaryRow.d.ts +1 -1
  36. package/dist/components/shell/AudienceChips.d.ts +1 -3
  37. package/dist/components/shell/AudienceChips.d.ts.map +1 -1
  38. package/dist/components/shell/EditorModal.d.ts.map +1 -1
  39. package/dist/components/shell/EditorShell.d.ts +0 -34
  40. package/dist/components/shell/EditorShell.d.ts.map +1 -1
  41. package/dist/components/shell/SiteSettingsModal.d.ts.map +1 -1
  42. package/dist/hooks/useSortableNavRow.d.ts +1 -1
  43. package/dist/hooks/useSortableRow.d.ts +1 -1
  44. package/dist/index.js +83 -90
  45. package/dist/lib/index-ops.js +5 -6
  46. package/dist/lib/index.js +27 -32
  47. package/dist/lib/pages.d.ts +0 -2
  48. package/dist/lib/pages.d.ts.map +1 -1
  49. package/dist/lib/sidecars.js +2 -2
  50. package/dist/lib/site-validation.js +13 -14
  51. package/dist/lib/storage-tier.js +4 -4
  52. package/dist/schemas/index.js +42 -45
  53. package/dist/schemas/site-config.d.ts +1 -277
  54. package/dist/schemas/site-config.d.ts.map +1 -1
  55. package/package.json +2 -42
  56. package/src/components/chat/ChatComposer.tsx +0 -4
  57. package/src/components/chat/ChatPanel.tsx +2 -3
  58. package/src/components/chat/markdown.ts +2 -3
  59. package/src/components/editor/AudienceIndicator.tsx +8 -4
  60. package/src/components/editor/IndicatorPill.tsx +4 -0
  61. package/src/components/editor/PagesModal.tsx +1 -15
  62. package/src/components/editor/SectionBulkEditModal.tsx +328 -0
  63. package/src/components/editor/StatusIndicator.tsx +7 -6
  64. package/src/components/shared/Popover.tsx +17 -4
  65. package/src/components/shared/SectionSummaryRow.tsx +1 -1
  66. package/src/components/shell/AudienceChips.tsx +1 -3
  67. package/src/components/shell/EditorModal.tsx +5 -2
  68. package/src/components/shell/EditorShell.tsx +15 -119
  69. package/src/components/shell/SiteSettingsModal.tsx +0 -11
  70. package/src/lib/pages.ts +0 -22
  71. package/src/schemas/index.ts +0 -4
  72. package/src/schemas/site-config.ts +4 -32
  73. package/dist/chunk-4TZJZU2T.js +0 -92
  74. package/dist/chunk-DIMDRBFK.js +0 -11
  75. package/dist/chunk-FV7JQRCN.js +0 -94
  76. package/dist/chunk-IIDKW7AV.js +0 -41
  77. package/dist/chunk-JCDZAFX2.js +0 -224
  78. package/dist/chunk-MM7KZS5C.js +0 -30
  79. package/dist/chunk-QQ3S3P5P.js +0 -38
  80. package/dist/chunk-TEOAKGZA.js +0 -784
  81. package/dist/chunk-VAYZJKVR.js +0 -209
  82. package/dist/components/editor/SectionOrderingModal.d.ts +0 -10
  83. package/dist/components/editor/SectionOrderingModal.d.ts.map +0 -1
  84. package/dist/components/shell/DocInspector.d.ts +0 -18
  85. package/dist/components/shell/DocInspector.d.ts.map +0 -1
  86. package/dist/components/shell/DocumentEditorOverlay.d.ts +0 -29
  87. package/dist/components/shell/DocumentEditorOverlay.d.ts.map +0 -1
  88. package/dist/components/shell/DocumentPresentOverlay.d.ts +0 -30
  89. package/dist/components/shell/DocumentPresentOverlay.d.ts.map +0 -1
  90. package/dist/components/shell/SiteSettingsDecks.d.ts +0 -13
  91. package/dist/components/shell/SiteSettingsDecks.d.ts.map +0 -1
  92. package/dist/deck/DeckComponentView.d.ts +0 -13
  93. package/dist/deck/DeckComponentView.d.ts.map +0 -1
  94. package/dist/deck/DeckPlayer.d.ts +0 -26
  95. package/dist/deck/DeckPlayer.d.ts.map +0 -1
  96. package/dist/deck/DeckSlideView.d.ts +0 -17
  97. package/dist/deck/DeckSlideView.d.ts.map +0 -1
  98. package/dist/deck/DeckStage.d.ts +0 -16
  99. package/dist/deck/DeckStage.d.ts.map +0 -1
  100. package/dist/deck/components/DeckImage.d.ts +0 -14
  101. package/dist/deck/components/DeckImage.d.ts.map +0 -1
  102. package/dist/deck/components/DeckImageGrid.d.ts +0 -27
  103. package/dist/deck/components/DeckImageGrid.d.ts.map +0 -1
  104. package/dist/deck/components/DeckRichText.d.ts +0 -22
  105. package/dist/deck/components/DeckRichText.d.ts.map +0 -1
  106. package/dist/deck/components/DeckVideo.d.ts +0 -15
  107. package/dist/deck/components/DeckVideo.d.ts.map +0 -1
  108. package/dist/deck/editing.d.ts +0 -50
  109. package/dist/deck/editing.d.ts.map +0 -1
  110. package/dist/deck/flip.d.ts +0 -11
  111. package/dist/deck/flip.d.ts.map +0 -1
  112. package/dist/deck/index.d.ts +0 -24
  113. package/dist/deck/index.d.ts.map +0 -1
  114. package/dist/deck/index.js +0 -51
  115. package/dist/deck/layouts/CenteredTextLayout.d.ts +0 -12
  116. package/dist/deck/layouts/CenteredTextLayout.d.ts.map +0 -1
  117. package/dist/deck/layouts/ColumnSplitLayout.d.ts +0 -14
  118. package/dist/deck/layouts/ColumnSplitLayout.d.ts.map +0 -1
  119. package/dist/deck/layouts/FullBleedImageLayout.d.ts +0 -14
  120. package/dist/deck/layouts/FullBleedImageLayout.d.ts.map +0 -1
  121. package/dist/deck/media.d.ts +0 -33
  122. package/dist/deck/media.d.ts.map +0 -1
  123. package/dist/deck/tokens.d.ts +0 -22
  124. package/dist/deck/tokens.d.ts.map +0 -1
  125. package/dist/deck/useStageScale.d.ts +0 -10
  126. package/dist/deck/useStageScale.d.ts.map +0 -1
  127. package/dist/deck-builder/DeckBuilderApp.d.ts +0 -30
  128. package/dist/deck-builder/DeckBuilderApp.d.ts.map +0 -1
  129. package/dist/deck-builder/DeckBuilderTopBar.d.ts +0 -24
  130. package/dist/deck-builder/DeckBuilderTopBar.d.ts.map +0 -1
  131. package/dist/deck-builder/DeckChatPanel.d.ts +0 -45
  132. package/dist/deck-builder/DeckChatPanel.d.ts.map +0 -1
  133. package/dist/deck-builder/DeckEditor.d.ts +0 -37
  134. package/dist/deck-builder/DeckEditor.d.ts.map +0 -1
  135. package/dist/deck-builder/DeckLibrary.d.ts +0 -22
  136. package/dist/deck-builder/DeckLibrary.d.ts.map +0 -1
  137. package/dist/deck-builder/DeckSlideSurface.d.ts +0 -31
  138. package/dist/deck-builder/DeckSlideSurface.d.ts.map +0 -1
  139. package/dist/deck-builder/deck-api.d.ts +0 -76
  140. package/dist/deck-builder/deck-api.d.ts.map +0 -1
  141. package/dist/deck-builder/deck-chat-client.d.ts +0 -44
  142. package/dist/deck-builder/deck-chat-client.d.ts.map +0 -1
  143. package/dist/deck-builder/deck-chat-history.d.ts +0 -10
  144. package/dist/deck-builder/deck-chat-history.d.ts.map +0 -1
  145. package/dist/deck-builder/index.d.ts +0 -13
  146. package/dist/deck-builder/index.d.ts.map +0 -1
  147. package/dist/deck-builder/index.js +0 -1498
  148. package/dist/deck-builder/starter-deck.d.ts +0 -23
  149. package/dist/deck-builder/starter-deck.d.ts.map +0 -1
  150. package/dist/deck-builder/types.d.ts +0 -29
  151. package/dist/deck-builder/types.d.ts.map +0 -1
  152. package/dist/deck-builder/useSortableSlide.d.ts +0 -29
  153. package/dist/deck-builder/useSortableSlide.d.ts.map +0 -1
  154. package/dist/document/assets/fonts/albra-grotesk-bold.woff +0 -0
  155. package/dist/document/assets/fonts/albra-grotesk-regular.woff +0 -0
  156. package/dist/document/assets/fonts/kapra-neue-expanded-medium.woff +0 -0
  157. package/dist/document/assets/fonts/kapra-neue-expanded-regular.woff +0 -0
  158. package/dist/document/components/DocCoverPage.d.ts +0 -11
  159. package/dist/document/components/DocCoverPage.d.ts.map +0 -1
  160. package/dist/document/components/DocPage.d.ts +0 -10
  161. package/dist/document/components/DocPage.d.ts.map +0 -1
  162. package/dist/document/components/DocRail.d.ts +0 -28
  163. package/dist/document/components/DocRail.d.ts.map +0 -1
  164. package/dist/document/components/DocSectionPage.d.ts +0 -12
  165. package/dist/document/components/DocSectionPage.d.ts.map +0 -1
  166. package/dist/document/components/DocViewer.d.ts +0 -21
  167. package/dist/document/components/DocViewer.d.ts.map +0 -1
  168. package/dist/document/components/Wordmark.d.ts +0 -4
  169. package/dist/document/components/Wordmark.d.ts.map +0 -1
  170. package/dist/document/components/measure.d.ts +0 -7
  171. package/dist/document/components/measure.d.ts.map +0 -1
  172. package/dist/document/components/useDocPages.d.ts +0 -12
  173. package/dist/document/components/useDocPages.d.ts.map +0 -1
  174. package/dist/document/engine/blocks.d.ts +0 -2
  175. package/dist/document/engine/blocks.d.ts.map +0 -1
  176. package/dist/document/engine/harvest.d.ts +0 -3
  177. package/dist/document/engine/harvest.d.ts.map +0 -1
  178. package/dist/document/engine/masonry.d.ts +0 -26
  179. package/dist/document/engine/masonry.d.ts.map +0 -1
  180. package/dist/document/engine/paginate.d.ts +0 -43
  181. package/dist/document/engine/paginate.d.ts.map +0 -1
  182. package/dist/document/engine/settings.d.ts +0 -91
  183. package/dist/document/engine/settings.d.ts.map +0 -1
  184. package/dist/document/engine/types.d.ts +0 -44
  185. package/dist/document/engine/types.d.ts.map +0 -1
  186. package/dist/document/index.d.ts +0 -13
  187. package/dist/document/index.d.ts.map +0 -1
  188. package/dist/document/index.js +0 -1030
  189. package/dist/document/styles/document.css +0 -217
  190. package/dist/lib/deck-access.d.ts +0 -86
  191. package/dist/lib/deck-access.d.ts.map +0 -1
  192. package/dist/lib/deck-access.js +0 -58
  193. package/dist/lib/deck-dexie.d.ts +0 -88
  194. package/dist/lib/deck-dexie.d.ts.map +0 -1
  195. package/dist/lib/deck-dexie.js +0 -22
  196. package/dist/lib/deck-edit.d.ts +0 -67
  197. package/dist/lib/deck-edit.d.ts.map +0 -1
  198. package/dist/lib/deck-media-assets.d.ts +0 -27
  199. package/dist/lib/deck-media-assets.d.ts.map +0 -1
  200. package/dist/lib/deck-media-assets.js +0 -25
  201. package/dist/lib/deck-media-refs.d.ts +0 -35
  202. package/dist/lib/deck-media-refs.d.ts.map +0 -1
  203. package/dist/lib/deck-media-refs.js +0 -36
  204. package/dist/lib/deck-tool.d.ts +0 -25
  205. package/dist/lib/deck-tool.d.ts.map +0 -1
  206. package/dist/lib/deck-tool.js +0 -58
  207. package/dist/lib/document-input.d.ts +0 -25
  208. package/dist/lib/document-input.d.ts.map +0 -1
  209. package/dist/schemas/deck-meta.d.ts +0 -85
  210. package/dist/schemas/deck-meta.d.ts.map +0 -1
  211. package/dist/schemas/deck-meta.js +0 -64
  212. package/dist/schemas/deck.d.ts +0 -954
  213. package/dist/schemas/deck.d.ts.map +0 -1
  214. package/dist/schemas/deck.js +0 -65
  215. package/src/components/editor/SectionOrderingModal.tsx +0 -80
  216. package/src/components/shell/DocInspector.tsx +0 -314
  217. package/src/components/shell/DocumentEditorOverlay.tsx +0 -179
  218. package/src/components/shell/DocumentPresentOverlay.tsx +0 -87
  219. package/src/components/shell/SiteSettingsDecks.tsx +0 -41
  220. package/src/deck/DeckComponentView.tsx +0 -28
  221. package/src/deck/DeckPlayer.tsx +0 -166
  222. package/src/deck/DeckSlideView.tsx +0 -38
  223. package/src/deck/DeckStage.tsx +0 -39
  224. package/src/deck/components/DeckImage.tsx +0 -38
  225. package/src/deck/components/DeckImageGrid.tsx +0 -254
  226. package/src/deck/components/DeckRichText.tsx +0 -111
  227. package/src/deck/components/DeckVideo.tsx +0 -81
  228. package/src/deck/editing.tsx +0 -201
  229. package/src/deck/flip.ts +0 -70
  230. package/src/deck/index.ts +0 -30
  231. package/src/deck/layouts/CenteredTextLayout.tsx +0 -29
  232. package/src/deck/layouts/ColumnSplitLayout.tsx +0 -69
  233. package/src/deck/layouts/FullBleedImageLayout.tsx +0 -58
  234. package/src/deck/media.tsx +0 -46
  235. package/src/deck/tokens.ts +0 -57
  236. package/src/deck/useStageScale.ts +0 -44
  237. package/src/deck-builder/DeckBuilderApp.tsx +0 -572
  238. package/src/deck-builder/DeckBuilderTopBar.tsx +0 -62
  239. package/src/deck-builder/DeckChatPanel.tsx +0 -334
  240. package/src/deck-builder/DeckEditor.tsx +0 -258
  241. package/src/deck-builder/DeckLibrary.tsx +0 -195
  242. package/src/deck-builder/DeckSlideSurface.tsx +0 -55
  243. package/src/deck-builder/deck-api.ts +0 -177
  244. package/src/deck-builder/deck-chat-client.ts +0 -129
  245. package/src/deck-builder/deck-chat-history.ts +0 -62
  246. package/src/deck-builder/index.ts +0 -12
  247. package/src/deck-builder/starter-deck.ts +0 -86
  248. package/src/deck-builder/types.ts +0 -24
  249. package/src/deck-builder/useSortableSlide.ts +0 -102
  250. package/src/document/assets/fonts/albra-grotesk-bold.woff +0 -0
  251. package/src/document/assets/fonts/albra-grotesk-regular.woff +0 -0
  252. package/src/document/assets/fonts/kapra-neue-expanded-medium.woff +0 -0
  253. package/src/document/assets/fonts/kapra-neue-expanded-regular.woff +0 -0
  254. package/src/document/components/DocCoverPage.tsx +0 -45
  255. package/src/document/components/DocPage.tsx +0 -40
  256. package/src/document/components/DocRail.tsx +0 -189
  257. package/src/document/components/DocSectionPage.tsx +0 -48
  258. package/src/document/components/DocViewer.tsx +0 -313
  259. package/src/document/components/Wordmark.tsx +0 -18
  260. package/src/document/components/measure.tsx +0 -133
  261. package/src/document/components/useDocPages.ts +0 -95
  262. package/src/document/engine/blocks.ts +0 -116
  263. package/src/document/engine/harvest.ts +0 -95
  264. package/src/document/engine/masonry.ts +0 -158
  265. package/src/document/engine/paginate.ts +0 -232
  266. package/src/document/engine/settings.ts +0 -125
  267. package/src/document/engine/types.ts +0 -64
  268. package/src/document/index.ts +0 -18
  269. package/src/document/styles/document.css +0 -217
  270. package/src/lib/deck-access.ts +0 -132
  271. package/src/lib/deck-dexie.ts +0 -190
  272. package/src/lib/deck-edit.ts +0 -196
  273. package/src/lib/deck-media-assets.ts +0 -57
  274. package/src/lib/deck-media-refs.ts +0 -67
  275. package/src/lib/deck-tool.ts +0 -95
  276. package/src/lib/document-input.ts +0 -57
  277. package/src/schemas/deck-meta.ts +0 -88
  278. package/src/schemas/deck.ts +0 -478
  279. package/dist/{chunk-DJABADOO.js → chunk-AJ2QOAZI.js} +3 -3
package/src/deck/flip.ts DELETED
@@ -1,70 +0,0 @@
1
- /**
2
- * FLIP for the image grid's expand/collapse.
3
- *
4
- * The grid changes layout via React state, so the "First" rects have to be
5
- * taken in the event handler (before `setState`) and the invert applied in a
6
- * layout effect (after the DOM has moved, before paint).
7
- */
8
-
9
- const TILE_SELECTOR = "[data-deck-tile]";
10
-
11
- export type TileRects = Map<Element, DOMRect>;
12
-
13
- export function captureTileRects(grid: HTMLElement): TileRects {
14
- const rects: TileRects = new Map();
15
- for (const tile of grid.querySelectorAll(TILE_SELECTOR)) rects.set(tile, tile.getBoundingClientRect());
16
- return rects;
17
- }
18
-
19
- /**
20
- * Rects are screen-space but the transform applies inside the stage, which is
21
- * itself scaled — so translations divide by that scale or the tile overshoots
22
- * by exactly the stage factor. `DeckStage` publishes it as `data-deck-scale`.
23
- */
24
- function stageScale(el: Element): number {
25
- const raw = el.closest("[data-deck-stage]")?.getAttribute("data-deck-scale");
26
- const value = raw === null || raw === undefined ? Number.NaN : Number(raw);
27
- return Number.isFinite(value) && value > 0 ? value : 1;
28
- }
29
-
30
- export function playTileFlip(grid: HTMLElement, before: TileRects): void {
31
- const scale = stageScale(grid);
32
- const moved: HTMLElement[] = [];
33
-
34
- for (const tile of grid.querySelectorAll<HTMLElement>(TILE_SELECTOR)) {
35
- const first = before.get(tile);
36
- if (!first) continue;
37
- const last = tile.getBoundingClientRect();
38
- // Unmeasurable boxes (jsdom, a hidden ancestor) invert to NaN; skip them
39
- // and the tile simply lands without an animation.
40
- if (!first.width || !last.width) continue;
41
-
42
- // Inverted about the element's CENTER, which is `transform-origin`'s
43
- // default — so this never sets the property and never has to clean it up.
44
- // A top-left origin would have to be cleared, and clearing it synchronously
45
- // jumps an in-flight animation while leaving it behind makes the tile's
46
- // next hover scale from its corner instead of its middle.
47
- const dx = (first.left + first.width / 2 - (last.left + last.width / 2)) / scale;
48
- const dy = (first.top + first.height / 2 - (last.top + last.height / 2)) / scale;
49
- const sx = first.width / last.width;
50
- const sy = first.height / last.height;
51
- if (Math.abs(dx) < 0.5 && Math.abs(dy) < 0.5 && Math.abs(sx - 1) < 0.002) continue;
52
-
53
- tile.style.transition = "none";
54
- tile.style.transform = `translate(${dx}px, ${dy}px) scale(${sx}, ${sy})`;
55
- moved.push(tile);
56
- }
57
-
58
- if (moved.length === 0) return;
59
-
60
- // Commit the inverted start state with a synchronous reflow, NOT
61
- // requestAnimationFrame: rAF does not run in a background tab, and a deck
62
- // left on an inactive tab would come back with every tile stranded under its
63
- // inverse transform.
64
- void grid.offsetWidth;
65
-
66
- for (const tile of moved) {
67
- tile.style.transition = "";
68
- tile.style.transform = "";
69
- }
70
- }
package/src/deck/index.ts DELETED
@@ -1,30 +0,0 @@
1
- /**
2
- * The deck runtime — a sealed subtree, like ./document.
3
- *
4
- * NOT re-exported from the primitives root barrel, and deliberately not a
5
- * section type: nothing on an ordinary viewer page may pull this graph in.
6
- * Only deck surfaces (the Deck Builder, in-portal deck views, the Public Link
7
- * route) import from here.
8
- */
9
- export { DeckPlayer } from "./DeckPlayer";
10
- export { DeckStage } from "./DeckStage";
11
- export { DeckSlideView } from "./DeckSlideView";
12
- export { DeckComponentView } from "./DeckComponentView";
13
- export { CenteredTextLayout } from "./layouts/CenteredTextLayout";
14
- export { ColumnSplitLayout } from "./layouts/ColumnSplitLayout";
15
- export { FullBleedImageLayout } from "./layouts/FullBleedImageLayout";
16
- export { DeckRichText } from "./components/DeckRichText";
17
- export { DeckImage } from "./components/DeckImage";
18
- export { DeckImageGrid } from "./components/DeckImageGrid";
19
- export { DeckVideo } from "./components/DeckVideo";
20
- export {
21
- DeckMediaProvider,
22
- DeckMissingMedia,
23
- useDeckMedia,
24
- useDeckMediaResolver,
25
- type DeckMediaAsset,
26
- type DeckMediaResolver,
27
- } from "./media";
28
- export { DeckTextEditProvider, EditableText, type DeckTextEditor } from "./editing";
29
- export { useStageScale } from "./useStageScale";
30
- export { deckAlign, surfaceInk, DECK_ELEVATION, SURFACE_BACKGROUND, type DeckSurface } from "./tokens";
@@ -1,29 +0,0 @@
1
- import { cn } from "../../lib/cn";
2
- import type { CenteredTextLayout as CenteredTextLayoutNode } from "../../schemas/deck";
3
- import { DeckComponentView } from "../DeckComponentView";
4
- import { deckAlign, SURFACE_BACKGROUND, surfaceInk } from "../tokens";
5
-
6
- interface Props {
7
- layout: CenteredTextLayoutNode;
8
- }
9
-
10
- /**
11
- * Layout — centered text. A full-slide title card holding one Deck Component,
12
- * centered on both axes. The Layout owns the surface (background + ink tokens)
13
- * and the stage-relative padding; the component owns nothing but its own type.
14
- */
15
- export function CenteredTextLayout({ layout }: Props) {
16
- return (
17
- <div
18
- data-deck-layout="centeredText"
19
- data-deck-surface={layout.background}
20
- style={{ ...surfaceInk(layout.background), ...deckAlign("center") }}
21
- className={cn(
22
- "flex size-full flex-col items-center justify-center px-[180px] py-[110px] text-center",
23
- SURFACE_BACKGROUND[layout.background],
24
- )}
25
- >
26
- <DeckComponentView component={layout.content} slot="content" />
27
- </div>
28
- );
29
- }
@@ -1,69 +0,0 @@
1
- import { cn } from "../../lib/cn";
2
- import type { ColumnSplitLayout as ColumnSplitLayoutNode, DeckComponent, DeckSplitRatio } from "../../schemas/deck";
3
- import { DeckComponentView } from "../DeckComponentView";
4
- import { deckAlign, SURFACE_BACKGROUND, surfaceInk } from "../tokens";
5
-
6
- interface Props {
7
- layout: ColumnSplitLayoutNode;
8
- }
9
-
10
- const RATIO: Record<DeckSplitRatio, string> = {
11
- "1-2": "grid-cols-[1fr_2fr]",
12
- "2-1": "grid-cols-[2fr_1fr]",
13
- };
14
-
15
- /**
16
- * How much air a column gives its component. Text needs generous margins; an
17
- * image is meant to run to the stage edge; a grid and a video need enough
18
- * breathing room for a tile to lift without clipping.
19
- */
20
- const COLUMN_PADDING: Record<DeckComponent["type"], string> = {
21
- richText: "flex flex-col justify-center px-[64px] py-[96px]",
22
- image: "",
23
- imageGrid: "p-[44px]",
24
- video: "p-[44px]",
25
- };
26
-
27
- /**
28
- * Layout — left/right column split.
29
- *
30
- * The hairline runs down the text column's inner edge, which is the editorial
31
- * treatment's only separator: the columns are set apart by the type and the
32
- * crop, not by a card or a shadow.
33
- */
34
- export function ColumnSplitLayout({ layout }: Props) {
35
- // The rule belongs to the seam, so exactly one column ever draws it. Asking
36
- // each text column for its own inner border drew a 2px rule whenever both
37
- // columns held text — the one case where the hairline is doing the most work.
38
- const seam = layout.left.type === "richText" ? "left" : layout.right.type === "richText" ? "right" : null;
39
-
40
- return (
41
- <div
42
- data-deck-layout="columnSplit"
43
- data-deck-ratio={layout.ratio}
44
- data-deck-surface="base"
45
- style={{ ...surfaceInk("base"), ...deckAlign("start") }}
46
- className={cn("grid size-full text-left", RATIO[layout.ratio], SURFACE_BACKGROUND.base)}
47
- >
48
- <Column component={layout.left} side="left" rule={seam === "left"} />
49
- <Column component={layout.right} side="right" rule={seam === "right"} />
50
- </div>
51
- );
52
- }
53
-
54
- // `side` doubles as the edit-seam slot name (see DeckTextPath) — the two are
55
- // the same coordinate, so keeping one avoids a mapping that could drift.
56
- function Column({ component, side, rule }: { component: DeckComponent; side: "left" | "right"; rule: boolean }) {
57
- return (
58
- <div
59
- data-deck-column={side}
60
- className={cn(
61
- "relative min-w-0 overflow-hidden",
62
- COLUMN_PADDING[component.type],
63
- rule && (side === "left" ? "border-r border-base-200" : "border-l border-base-200"),
64
- )}
65
- >
66
- <DeckComponentView component={component} slot={side} />
67
- </div>
68
- );
69
- }
@@ -1,58 +0,0 @@
1
- import { cn } from "../../lib/cn";
2
- import type { DeckOverlayPlacement, FullBleedImageLayout as FullBleedImageLayoutNode } from "../../schemas/deck";
3
- import { DeckRichText } from "../components/DeckRichText";
4
- import { DeckMissingMedia, useDeckMedia } from "../media";
5
- import { deckAlign, SURFACE_BACKGROUND, surfaceInk } from "../tokens";
6
-
7
- interface Props {
8
- layout: FullBleedImageLayoutNode;
9
- }
10
-
11
- /**
12
- * Panel geometry, stage-relative. Hard edges and full bleed to the stage sides
13
- * — the panel is a block of brand color laid over the picture, not a card
14
- * floating on it.
15
- */
16
- const PLACEMENT: Record<DeckOverlayPlacement, string> = {
17
- sideLeft: "top-0 bottom-0 left-0 w-[40%] justify-center px-[72px] py-[90px]",
18
- sideRight: "top-0 bottom-0 right-0 w-[40%] justify-center px-[72px] py-[90px]",
19
- bottomBand: "right-0 bottom-0 left-0 justify-end px-[96px] py-[56px]",
20
- };
21
-
22
- /**
23
- * Layout — full-bleed image with an optional text overlay panel.
24
- *
25
- * The Layout owns both surfaces: the slide is base (the image covers it), the
26
- * panel declares brand, so the rich text inside reads on-primary ink without
27
- * knowing it sits over a photograph.
28
- */
29
- export function FullBleedImageLayout({ layout }: Props) {
30
- const asset = useDeckMedia(layout.media);
31
- const { overlay } = layout;
32
-
33
- return (
34
- <div
35
- data-deck-layout="fullBleedImage"
36
- data-deck-surface="base"
37
- style={{ ...surfaceInk("base"), ...deckAlign("start") }}
38
- className={cn("relative size-full overflow-hidden", SURFACE_BACKGROUND.base)}
39
- >
40
- {asset === null ? (
41
- <DeckMissingMedia className="absolute inset-0" />
42
- ) : (
43
- <img src={asset.src} alt={asset.alt} className="absolute inset-0 size-full object-cover" />
44
- )}
45
-
46
- {overlay !== undefined && (
47
- <div
48
- data-deck-overlay={overlay.placement}
49
- data-deck-surface="brand"
50
- style={surfaceInk("brand")}
51
- className={cn("absolute z-[2] flex flex-col text-left", SURFACE_BACKGROUND.brand, PLACEMENT[overlay.placement])}
52
- >
53
- <DeckRichText content={overlay.content} slot="overlay" />
54
- </div>
55
- )}
56
- </div>
57
- );
58
- }
@@ -1,46 +0,0 @@
1
- import { createContext, useContext, type ReactNode } from "react";
2
- import { cn } from "../lib/cn";
3
- import type { DeckMediaAsset, DeckMediaRef, DeckMediaResolver } from "../schemas/deck";
4
-
5
- /**
6
- * The runtime's media seam.
7
- *
8
- * Deck JSON stores references, never URLs (ADR 0001), so something outside the
9
- * runtime has to turn `{ kind: "portal", id }` into bytes. That something is a
10
- * resolver injected through context: the Deck Builder passes the manifest-backed
11
- * one, the dev preview route passes placeholders, and the components below never
12
- * learn which. Absent a provider every reference resolves to `null`, which is
13
- * also what a deleted asset resolves to — one path, one rendering.
14
- */
15
-
16
- export type { DeckMediaAsset, DeckMediaResolver } from "../schemas/deck";
17
-
18
- const NO_MEDIA: DeckMediaResolver = () => null;
19
-
20
- const DeckMediaContext = createContext<DeckMediaResolver>(NO_MEDIA);
21
-
22
- export function DeckMediaProvider({ resolve, children }: { resolve: DeckMediaResolver; children: ReactNode }) {
23
- return <DeckMediaContext.Provider value={resolve}>{children}</DeckMediaContext.Provider>;
24
- }
25
-
26
- export function useDeckMedia(ref: DeckMediaRef): DeckMediaAsset | null {
27
- return useContext(DeckMediaContext)(ref);
28
- }
29
-
30
- /**
31
- * The resolver itself, for a component that has to resolve a whole set before
32
- * it can lay any of it out — the image grid packs its masonry columns from
33
- * every tile's aspect ratio, which it cannot learn one `useDeckMedia` at a time.
34
- */
35
- export function useDeckMediaResolver(): DeckMediaResolver {
36
- return useContext(DeckMediaContext);
37
- }
38
-
39
- /**
40
- * What an unresolvable reference renders. A published deck can outlive the
41
- * media it points at (ADR 0002 flags the GC hazard), and a torn alt string over
42
- * a presentation is worse than a quiet gap.
43
- */
44
- export function DeckMissingMedia({ className }: { className?: string }) {
45
- return <span data-deck-media="missing" aria-hidden="true" className={cn("block size-full bg-base-200", className)} />;
46
- }
@@ -1,57 +0,0 @@
1
- import type { CSSProperties } from "react";
2
- import type { DeckSurface } from "../schemas/deck";
3
-
4
- export type { DeckSurface } from "../schemas/deck";
5
-
6
- /**
7
- * Deck ink is indirected through three custom properties so a Deck Component
8
- * never has to know what it is sitting on: a Layout declares the palette for
9
- * its surface, components read `--deck-ink` / `--deck-ink-muted` /
10
- * `--deck-accent`. Every value resolves to a portal brand token — nothing in
11
- * the deck runtime carries a literal color.
12
- */
13
- const SURFACE_INK: Record<DeckSurface, CSSProperties> = {
14
- base: {
15
- "--deck-ink": "var(--color-base-contrast)",
16
- "--deck-ink-muted": "var(--color-base-contrast-light)",
17
- "--deck-accent": "var(--color-primary)",
18
- } as CSSProperties,
19
- brand: {
20
- "--deck-ink": "var(--color-on-primary)",
21
- "--deck-ink-muted": "color-mix(in srgb, var(--color-on-primary) 72%, transparent)",
22
- "--deck-accent": "var(--color-primary-contrast)",
23
- } as CSSProperties,
24
- };
25
-
26
- export function surfaceInk(surface: DeckSurface): CSSProperties {
27
- return SURFACE_INK[surface];
28
- }
29
-
30
- /** Tailwind background utility for a surface — both are brand tokens. */
31
- export const SURFACE_BACKGROUND: Record<DeckSurface, string> = {
32
- base: "bg-base-accent",
33
- brand: "bg-primary",
34
- };
35
-
36
- /**
37
- * Alignment travels the same way the ink does: a Layout declares how its slot
38
- * reads, components resolve `--deck-align` (an `align-self` value). Without it
39
- * a component would have to know whether it sits on a centered title card or in
40
- * a left-aligned column, which is precisely what the indirection prevents.
41
- */
42
- export type DeckAlign = "center" | "start";
43
-
44
- export function deckAlign(align: DeckAlign): CSSProperties {
45
- return { "--deck-align": align } as CSSProperties;
46
- }
47
-
48
- /**
49
- * Elevation for media that lifts off the slide — grid tiles on hover, the video
50
- * play affordance. Declared as `--deck-*` custom properties rather than as
51
- * arbitrary Tailwind values so the shadow can be mixed from the site's ink
52
- * token instead of a literal rgba, and so a hover variant can reference it.
53
- */
54
- export const DECK_ELEVATION: CSSProperties = {
55
- "--deck-lift": "0 26px 46px -18px color-mix(in srgb, var(--color-base-contrast) 45%, transparent)",
56
- "--deck-lift-strong": "0 30px 60px -22px color-mix(in srgb, var(--color-base-contrast) 58%, transparent)",
57
- } as CSSProperties;
@@ -1,44 +0,0 @@
1
- import { useEffect, useLayoutEffect, useState, type RefObject } from "react";
2
- import { DECK_STAGE_HEIGHT, DECK_STAGE_WIDTH } from "../schemas/deck";
3
-
4
- /**
5
- * The first measurement has to happen before paint or the stage shows one frame
6
- * unscaled — a full-bleed 1600x900 flash on a laptop viewport. useLayoutEffect
7
- * warns when React renders on the server (Astro SSRs this island), and there is
8
- * nothing to measure there anyway, so fall back to useEffect off the browser.
9
- */
10
- const useIsomorphicLayoutEffect = typeof window === "undefined" ? useEffect : useLayoutEffect;
11
-
12
- /**
13
- * The factor that fits the fixed 1600x900 stage inside `fitRef`'s box.
14
- *
15
- * `null` until the box has been measured — an unmeasured box (SSR, jsdom, a
16
- * hidden ancestor) reports 0x0, and scaling the stage to 0 would blank it. The
17
- * caller renders the stage unscaled until a real measurement arrives.
18
- */
19
- export function useStageScale(fitRef: RefObject<HTMLElement | null>): number | null {
20
- const [scale, setScale] = useState<number | null>(null);
21
-
22
- useIsomorphicLayoutEffect(() => {
23
- const el = fitRef.current;
24
- if (!el) return;
25
-
26
- const measure = () => {
27
- const { clientWidth, clientHeight } = el;
28
- if (!clientWidth || !clientHeight) return;
29
- setScale(Math.min(clientWidth / DECK_STAGE_WIDTH, clientHeight / DECK_STAGE_HEIGHT));
30
- };
31
-
32
- measure();
33
-
34
- if (typeof ResizeObserver === "undefined") {
35
- window.addEventListener("resize", measure);
36
- return () => window.removeEventListener("resize", measure);
37
- }
38
- const observer = new ResizeObserver(measure);
39
- observer.observe(el);
40
- return () => observer.disconnect();
41
- }, [fitRef]);
42
-
43
- return scale;
44
- }