@drawnagency/primitives 0.1.118 → 0.1.119

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 (258) 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-CEFFP3CH.js → chunk-G6O3TYPJ.js} +297 -83
  4. package/dist/{chunk-4NSOKEA7.js → chunk-HFHM4MNK.js} +12 -7
  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-YKKGVSJH.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/PagesModal.d.ts +0 -2
  19. package/dist/components/editor/PagesModal.d.ts.map +1 -1
  20. package/dist/components/editor/index.js +15 -19
  21. package/dist/components/primitives/index.js +11 -15
  22. package/dist/components/sections/brand-guide.js +10 -13
  23. package/dist/components/sections/register-schemas.js +16 -21
  24. package/dist/components/sections/register.js +16 -21
  25. package/dist/components/shell/AudienceChips.d.ts +1 -3
  26. package/dist/components/shell/AudienceChips.d.ts.map +1 -1
  27. package/dist/components/shell/EditorShell.d.ts +0 -34
  28. package/dist/components/shell/EditorShell.d.ts.map +1 -1
  29. package/dist/components/shell/SiteSettingsModal.d.ts.map +1 -1
  30. package/dist/hooks/useSortableNavRow.d.ts +1 -1
  31. package/dist/hooks/useSortableRow.d.ts +1 -1
  32. package/dist/index.js +83 -90
  33. package/dist/lib/index-ops.js +5 -6
  34. package/dist/lib/index.js +27 -32
  35. package/dist/lib/pages.d.ts +0 -2
  36. package/dist/lib/pages.d.ts.map +1 -1
  37. package/dist/lib/sidecars.js +2 -2
  38. package/dist/lib/site-validation.js +13 -14
  39. package/dist/lib/storage-tier.js +4 -4
  40. package/dist/schemas/index.js +42 -45
  41. package/dist/schemas/site-config.d.ts +1 -277
  42. package/dist/schemas/site-config.d.ts.map +1 -1
  43. package/package.json +2 -42
  44. package/src/components/chat/ChatComposer.tsx +0 -4
  45. package/src/components/chat/ChatPanel.tsx +2 -3
  46. package/src/components/chat/markdown.ts +2 -3
  47. package/src/components/editor/PagesModal.tsx +1 -15
  48. package/src/components/editor/StatusIndicator.tsx +4 -4
  49. package/src/components/shell/AudienceChips.tsx +1 -3
  50. package/src/components/shell/EditorShell.tsx +5 -113
  51. package/src/components/shell/SiteSettingsModal.tsx +0 -11
  52. package/src/lib/pages.ts +0 -22
  53. package/src/schemas/index.ts +0 -4
  54. package/src/schemas/site-config.ts +4 -32
  55. package/dist/chunk-4TZJZU2T.js +0 -92
  56. package/dist/chunk-DIMDRBFK.js +0 -11
  57. package/dist/chunk-FV7JQRCN.js +0 -94
  58. package/dist/chunk-IIDKW7AV.js +0 -41
  59. package/dist/chunk-JCDZAFX2.js +0 -224
  60. package/dist/chunk-MM7KZS5C.js +0 -30
  61. package/dist/chunk-QQ3S3P5P.js +0 -38
  62. package/dist/chunk-TEOAKGZA.js +0 -784
  63. package/dist/chunk-VAYZJKVR.js +0 -209
  64. package/dist/components/shell/DocInspector.d.ts +0 -18
  65. package/dist/components/shell/DocInspector.d.ts.map +0 -1
  66. package/dist/components/shell/DocumentEditorOverlay.d.ts +0 -29
  67. package/dist/components/shell/DocumentEditorOverlay.d.ts.map +0 -1
  68. package/dist/components/shell/DocumentPresentOverlay.d.ts +0 -30
  69. package/dist/components/shell/DocumentPresentOverlay.d.ts.map +0 -1
  70. package/dist/components/shell/SiteSettingsDecks.d.ts +0 -13
  71. package/dist/components/shell/SiteSettingsDecks.d.ts.map +0 -1
  72. package/dist/deck/DeckComponentView.d.ts +0 -13
  73. package/dist/deck/DeckComponentView.d.ts.map +0 -1
  74. package/dist/deck/DeckPlayer.d.ts +0 -26
  75. package/dist/deck/DeckPlayer.d.ts.map +0 -1
  76. package/dist/deck/DeckSlideView.d.ts +0 -17
  77. package/dist/deck/DeckSlideView.d.ts.map +0 -1
  78. package/dist/deck/DeckStage.d.ts +0 -16
  79. package/dist/deck/DeckStage.d.ts.map +0 -1
  80. package/dist/deck/components/DeckImage.d.ts +0 -14
  81. package/dist/deck/components/DeckImage.d.ts.map +0 -1
  82. package/dist/deck/components/DeckImageGrid.d.ts +0 -27
  83. package/dist/deck/components/DeckImageGrid.d.ts.map +0 -1
  84. package/dist/deck/components/DeckRichText.d.ts +0 -22
  85. package/dist/deck/components/DeckRichText.d.ts.map +0 -1
  86. package/dist/deck/components/DeckVideo.d.ts +0 -15
  87. package/dist/deck/components/DeckVideo.d.ts.map +0 -1
  88. package/dist/deck/editing.d.ts +0 -50
  89. package/dist/deck/editing.d.ts.map +0 -1
  90. package/dist/deck/flip.d.ts +0 -11
  91. package/dist/deck/flip.d.ts.map +0 -1
  92. package/dist/deck/index.d.ts +0 -24
  93. package/dist/deck/index.d.ts.map +0 -1
  94. package/dist/deck/index.js +0 -51
  95. package/dist/deck/layouts/CenteredTextLayout.d.ts +0 -12
  96. package/dist/deck/layouts/CenteredTextLayout.d.ts.map +0 -1
  97. package/dist/deck/layouts/ColumnSplitLayout.d.ts +0 -14
  98. package/dist/deck/layouts/ColumnSplitLayout.d.ts.map +0 -1
  99. package/dist/deck/layouts/FullBleedImageLayout.d.ts +0 -14
  100. package/dist/deck/layouts/FullBleedImageLayout.d.ts.map +0 -1
  101. package/dist/deck/media.d.ts +0 -33
  102. package/dist/deck/media.d.ts.map +0 -1
  103. package/dist/deck/tokens.d.ts +0 -22
  104. package/dist/deck/tokens.d.ts.map +0 -1
  105. package/dist/deck/useStageScale.d.ts +0 -10
  106. package/dist/deck/useStageScale.d.ts.map +0 -1
  107. package/dist/deck-builder/DeckBuilderApp.d.ts +0 -30
  108. package/dist/deck-builder/DeckBuilderApp.d.ts.map +0 -1
  109. package/dist/deck-builder/DeckBuilderTopBar.d.ts +0 -24
  110. package/dist/deck-builder/DeckBuilderTopBar.d.ts.map +0 -1
  111. package/dist/deck-builder/DeckChatPanel.d.ts +0 -45
  112. package/dist/deck-builder/DeckChatPanel.d.ts.map +0 -1
  113. package/dist/deck-builder/DeckEditor.d.ts +0 -37
  114. package/dist/deck-builder/DeckEditor.d.ts.map +0 -1
  115. package/dist/deck-builder/DeckLibrary.d.ts +0 -22
  116. package/dist/deck-builder/DeckLibrary.d.ts.map +0 -1
  117. package/dist/deck-builder/DeckSlideSurface.d.ts +0 -31
  118. package/dist/deck-builder/DeckSlideSurface.d.ts.map +0 -1
  119. package/dist/deck-builder/deck-api.d.ts +0 -76
  120. package/dist/deck-builder/deck-api.d.ts.map +0 -1
  121. package/dist/deck-builder/deck-chat-client.d.ts +0 -44
  122. package/dist/deck-builder/deck-chat-client.d.ts.map +0 -1
  123. package/dist/deck-builder/deck-chat-history.d.ts +0 -10
  124. package/dist/deck-builder/deck-chat-history.d.ts.map +0 -1
  125. package/dist/deck-builder/index.d.ts +0 -13
  126. package/dist/deck-builder/index.d.ts.map +0 -1
  127. package/dist/deck-builder/index.js +0 -1498
  128. package/dist/deck-builder/starter-deck.d.ts +0 -23
  129. package/dist/deck-builder/starter-deck.d.ts.map +0 -1
  130. package/dist/deck-builder/types.d.ts +0 -29
  131. package/dist/deck-builder/types.d.ts.map +0 -1
  132. package/dist/deck-builder/useSortableSlide.d.ts +0 -29
  133. package/dist/deck-builder/useSortableSlide.d.ts.map +0 -1
  134. package/dist/document/assets/fonts/albra-grotesk-bold.woff +0 -0
  135. package/dist/document/assets/fonts/albra-grotesk-regular.woff +0 -0
  136. package/dist/document/assets/fonts/kapra-neue-expanded-medium.woff +0 -0
  137. package/dist/document/assets/fonts/kapra-neue-expanded-regular.woff +0 -0
  138. package/dist/document/components/DocCoverPage.d.ts +0 -11
  139. package/dist/document/components/DocCoverPage.d.ts.map +0 -1
  140. package/dist/document/components/DocPage.d.ts +0 -10
  141. package/dist/document/components/DocPage.d.ts.map +0 -1
  142. package/dist/document/components/DocRail.d.ts +0 -28
  143. package/dist/document/components/DocRail.d.ts.map +0 -1
  144. package/dist/document/components/DocSectionPage.d.ts +0 -12
  145. package/dist/document/components/DocSectionPage.d.ts.map +0 -1
  146. package/dist/document/components/DocViewer.d.ts +0 -21
  147. package/dist/document/components/DocViewer.d.ts.map +0 -1
  148. package/dist/document/components/Wordmark.d.ts +0 -4
  149. package/dist/document/components/Wordmark.d.ts.map +0 -1
  150. package/dist/document/components/measure.d.ts +0 -7
  151. package/dist/document/components/measure.d.ts.map +0 -1
  152. package/dist/document/components/useDocPages.d.ts +0 -12
  153. package/dist/document/components/useDocPages.d.ts.map +0 -1
  154. package/dist/document/engine/blocks.d.ts +0 -2
  155. package/dist/document/engine/blocks.d.ts.map +0 -1
  156. package/dist/document/engine/harvest.d.ts +0 -3
  157. package/dist/document/engine/harvest.d.ts.map +0 -1
  158. package/dist/document/engine/masonry.d.ts +0 -26
  159. package/dist/document/engine/masonry.d.ts.map +0 -1
  160. package/dist/document/engine/paginate.d.ts +0 -43
  161. package/dist/document/engine/paginate.d.ts.map +0 -1
  162. package/dist/document/engine/settings.d.ts +0 -91
  163. package/dist/document/engine/settings.d.ts.map +0 -1
  164. package/dist/document/engine/types.d.ts +0 -44
  165. package/dist/document/engine/types.d.ts.map +0 -1
  166. package/dist/document/index.d.ts +0 -13
  167. package/dist/document/index.d.ts.map +0 -1
  168. package/dist/document/index.js +0 -1030
  169. package/dist/document/styles/document.css +0 -217
  170. package/dist/lib/deck-access.d.ts +0 -86
  171. package/dist/lib/deck-access.d.ts.map +0 -1
  172. package/dist/lib/deck-access.js +0 -58
  173. package/dist/lib/deck-dexie.d.ts +0 -88
  174. package/dist/lib/deck-dexie.d.ts.map +0 -1
  175. package/dist/lib/deck-dexie.js +0 -22
  176. package/dist/lib/deck-edit.d.ts +0 -67
  177. package/dist/lib/deck-edit.d.ts.map +0 -1
  178. package/dist/lib/deck-media-assets.d.ts +0 -27
  179. package/dist/lib/deck-media-assets.d.ts.map +0 -1
  180. package/dist/lib/deck-media-assets.js +0 -25
  181. package/dist/lib/deck-media-refs.d.ts +0 -35
  182. package/dist/lib/deck-media-refs.d.ts.map +0 -1
  183. package/dist/lib/deck-media-refs.js +0 -36
  184. package/dist/lib/deck-tool.d.ts +0 -25
  185. package/dist/lib/deck-tool.d.ts.map +0 -1
  186. package/dist/lib/deck-tool.js +0 -58
  187. package/dist/lib/document-input.d.ts +0 -25
  188. package/dist/lib/document-input.d.ts.map +0 -1
  189. package/dist/schemas/deck-meta.d.ts +0 -85
  190. package/dist/schemas/deck-meta.d.ts.map +0 -1
  191. package/dist/schemas/deck-meta.js +0 -64
  192. package/dist/schemas/deck.d.ts +0 -954
  193. package/dist/schemas/deck.d.ts.map +0 -1
  194. package/dist/schemas/deck.js +0 -65
  195. package/src/components/shell/DocInspector.tsx +0 -314
  196. package/src/components/shell/DocumentEditorOverlay.tsx +0 -179
  197. package/src/components/shell/DocumentPresentOverlay.tsx +0 -87
  198. package/src/components/shell/SiteSettingsDecks.tsx +0 -41
  199. package/src/deck/DeckComponentView.tsx +0 -28
  200. package/src/deck/DeckPlayer.tsx +0 -166
  201. package/src/deck/DeckSlideView.tsx +0 -38
  202. package/src/deck/DeckStage.tsx +0 -39
  203. package/src/deck/components/DeckImage.tsx +0 -38
  204. package/src/deck/components/DeckImageGrid.tsx +0 -254
  205. package/src/deck/components/DeckRichText.tsx +0 -111
  206. package/src/deck/components/DeckVideo.tsx +0 -81
  207. package/src/deck/editing.tsx +0 -201
  208. package/src/deck/flip.ts +0 -70
  209. package/src/deck/index.ts +0 -30
  210. package/src/deck/layouts/CenteredTextLayout.tsx +0 -29
  211. package/src/deck/layouts/ColumnSplitLayout.tsx +0 -69
  212. package/src/deck/layouts/FullBleedImageLayout.tsx +0 -58
  213. package/src/deck/media.tsx +0 -46
  214. package/src/deck/tokens.ts +0 -57
  215. package/src/deck/useStageScale.ts +0 -44
  216. package/src/deck-builder/DeckBuilderApp.tsx +0 -572
  217. package/src/deck-builder/DeckBuilderTopBar.tsx +0 -62
  218. package/src/deck-builder/DeckChatPanel.tsx +0 -334
  219. package/src/deck-builder/DeckEditor.tsx +0 -258
  220. package/src/deck-builder/DeckLibrary.tsx +0 -195
  221. package/src/deck-builder/DeckSlideSurface.tsx +0 -55
  222. package/src/deck-builder/deck-api.ts +0 -177
  223. package/src/deck-builder/deck-chat-client.ts +0 -129
  224. package/src/deck-builder/deck-chat-history.ts +0 -62
  225. package/src/deck-builder/index.ts +0 -12
  226. package/src/deck-builder/starter-deck.ts +0 -86
  227. package/src/deck-builder/types.ts +0 -24
  228. package/src/deck-builder/useSortableSlide.ts +0 -102
  229. package/src/document/assets/fonts/albra-grotesk-bold.woff +0 -0
  230. package/src/document/assets/fonts/albra-grotesk-regular.woff +0 -0
  231. package/src/document/assets/fonts/kapra-neue-expanded-medium.woff +0 -0
  232. package/src/document/assets/fonts/kapra-neue-expanded-regular.woff +0 -0
  233. package/src/document/components/DocCoverPage.tsx +0 -45
  234. package/src/document/components/DocPage.tsx +0 -40
  235. package/src/document/components/DocRail.tsx +0 -189
  236. package/src/document/components/DocSectionPage.tsx +0 -48
  237. package/src/document/components/DocViewer.tsx +0 -313
  238. package/src/document/components/Wordmark.tsx +0 -18
  239. package/src/document/components/measure.tsx +0 -133
  240. package/src/document/components/useDocPages.ts +0 -95
  241. package/src/document/engine/blocks.ts +0 -116
  242. package/src/document/engine/harvest.ts +0 -95
  243. package/src/document/engine/masonry.ts +0 -158
  244. package/src/document/engine/paginate.ts +0 -232
  245. package/src/document/engine/settings.ts +0 -125
  246. package/src/document/engine/types.ts +0 -64
  247. package/src/document/index.ts +0 -18
  248. package/src/document/styles/document.css +0 -217
  249. package/src/lib/deck-access.ts +0 -132
  250. package/src/lib/deck-dexie.ts +0 -190
  251. package/src/lib/deck-edit.ts +0 -196
  252. package/src/lib/deck-media-assets.ts +0 -57
  253. package/src/lib/deck-media-refs.ts +0 -67
  254. package/src/lib/deck-tool.ts +0 -95
  255. package/src/lib/document-input.ts +0 -57
  256. package/src/schemas/deck-meta.ts +0 -88
  257. package/src/schemas/deck.ts +0 -478
  258. package/dist/{chunk-DJABADOO.js → chunk-AJ2QOAZI.js} +3 -3
@@ -1,784 +0,0 @@
1
- import {
2
- cn
3
- } from "./chunk-7EOSDFS3.js";
4
- import {
5
- DECK_STAGE_HEIGHT,
6
- DECK_STAGE_WIDTH
7
- } from "./chunk-VAYZJKVR.js";
8
-
9
- // src/deck/DeckPlayer.tsx
10
- import { ChevronLeft, ChevronRight } from "lucide-react";
11
- import { useCallback as useCallback2, useEffect as useEffect4, useMemo as useMemo2, useState as useState5 } from "react";
12
-
13
- // src/deck/media.tsx
14
- import { createContext, useContext } from "react";
15
- import { jsx } from "react/jsx-runtime";
16
- var NO_MEDIA = () => null;
17
- var DeckMediaContext = createContext(NO_MEDIA);
18
- function DeckMediaProvider({ resolve, children }) {
19
- return /* @__PURE__ */ jsx(DeckMediaContext.Provider, { value: resolve, children });
20
- }
21
- function useDeckMedia(ref) {
22
- return useContext(DeckMediaContext)(ref);
23
- }
24
- function useDeckMediaResolver() {
25
- return useContext(DeckMediaContext);
26
- }
27
- function DeckMissingMedia({ className }) {
28
- return /* @__PURE__ */ jsx("span", { "data-deck-media": "missing", "aria-hidden": "true", className: cn("block size-full bg-base-200", className) });
29
- }
30
-
31
- // src/deck/DeckStage.tsx
32
- import { useRef } from "react";
33
-
34
- // src/deck/useStageScale.ts
35
- import { useEffect, useLayoutEffect, useState } from "react";
36
- var useIsomorphicLayoutEffect = typeof window === "undefined" ? useEffect : useLayoutEffect;
37
- function useStageScale(fitRef) {
38
- const [scale, setScale] = useState(null);
39
- useIsomorphicLayoutEffect(() => {
40
- const el = fitRef.current;
41
- if (!el) return;
42
- const measure = () => {
43
- const { clientWidth, clientHeight } = el;
44
- if (!clientWidth || !clientHeight) return;
45
- setScale(Math.min(clientWidth / DECK_STAGE_WIDTH, clientHeight / DECK_STAGE_HEIGHT));
46
- };
47
- measure();
48
- if (typeof ResizeObserver === "undefined") {
49
- window.addEventListener("resize", measure);
50
- return () => window.removeEventListener("resize", measure);
51
- }
52
- const observer = new ResizeObserver(measure);
53
- observer.observe(el);
54
- return () => observer.disconnect();
55
- }, [fitRef]);
56
- return scale;
57
- }
58
-
59
- // src/deck/DeckStage.tsx
60
- import { jsx as jsx2 } from "react/jsx-runtime";
61
- function DeckStage({ children, className }) {
62
- const fitRef = useRef(null);
63
- const scale = useStageScale(fitRef);
64
- return /* @__PURE__ */ jsx2("div", { ref: fitRef, className: cn("relative min-h-0 w-full overflow-hidden", className), "data-deck-fit": "", children: /* @__PURE__ */ jsx2(
65
- "div",
66
- {
67
- "data-deck-stage": "",
68
- "data-deck-scale": scale === null ? void 0 : scale.toFixed(4),
69
- className: "absolute top-1/2 left-1/2 origin-center overflow-hidden rounded-[var(--radius-outer)] font-body",
70
- style: {
71
- width: DECK_STAGE_WIDTH,
72
- height: DECK_STAGE_HEIGHT,
73
- transform: scale === null ? "translate(-50%, -50%)" : `translate(-50%, -50%) scale(${scale})`
74
- },
75
- children
76
- }
77
- ) });
78
- }
79
-
80
- // src/deck/tokens.ts
81
- var SURFACE_INK = {
82
- base: {
83
- "--deck-ink": "var(--color-base-contrast)",
84
- "--deck-ink-muted": "var(--color-base-contrast-light)",
85
- "--deck-accent": "var(--color-primary)"
86
- },
87
- brand: {
88
- "--deck-ink": "var(--color-on-primary)",
89
- "--deck-ink-muted": "color-mix(in srgb, var(--color-on-primary) 72%, transparent)",
90
- "--deck-accent": "var(--color-primary-contrast)"
91
- }
92
- };
93
- function surfaceInk(surface) {
94
- return SURFACE_INK[surface];
95
- }
96
- var SURFACE_BACKGROUND = {
97
- base: "bg-base-accent",
98
- brand: "bg-primary"
99
- };
100
- function deckAlign(align) {
101
- return { "--deck-align": align };
102
- }
103
- var DECK_ELEVATION = {
104
- "--deck-lift": "0 26px 46px -18px color-mix(in srgb, var(--color-base-contrast) 45%, transparent)",
105
- "--deck-lift-strong": "0 30px 60px -22px color-mix(in srgb, var(--color-base-contrast) 58%, transparent)"
106
- };
107
-
108
- // src/deck/components/DeckImage.tsx
109
- import { jsx as jsx3, jsxs } from "react/jsx-runtime";
110
- function DeckImage({ content }) {
111
- const asset = useDeckMedia(content.media);
112
- return /* @__PURE__ */ jsxs("figure", { "data-deck-component": "image", className: "relative size-full overflow-hidden bg-base-200", children: [
113
- asset === null ? /* @__PURE__ */ jsx3(DeckMissingMedia, {}) : /* @__PURE__ */ jsx3("img", { src: asset.src, alt: asset.alt, className: "size-full object-cover" }),
114
- content.caption !== void 0 && /* @__PURE__ */ jsx3(
115
- "figcaption",
116
- {
117
- "data-deck-surface": "brand",
118
- style: surfaceInk("brand"),
119
- className: "absolute right-0 bottom-0 left-0 bg-primary px-[28px] py-[18px] text-[18px] tracking-[0.06em] text-[var(--deck-ink)] [text-transform:var(--nav-text-transform)]",
120
- children: content.caption
121
- }
122
- )
123
- ] });
124
- }
125
-
126
- // src/deck/components/DeckImageGrid.tsx
127
- import { useCallback, useEffect as useEffect2, useLayoutEffect as useLayoutEffect2, useMemo, useRef as useRef2, useState as useState2 } from "react";
128
-
129
- // src/deck/flip.ts
130
- var TILE_SELECTOR = "[data-deck-tile]";
131
- function captureTileRects(grid) {
132
- const rects = /* @__PURE__ */ new Map();
133
- for (const tile of grid.querySelectorAll(TILE_SELECTOR)) rects.set(tile, tile.getBoundingClientRect());
134
- return rects;
135
- }
136
- function stageScale(el) {
137
- const raw = el.closest("[data-deck-stage]")?.getAttribute("data-deck-scale");
138
- const value = raw === null || raw === void 0 ? Number.NaN : Number(raw);
139
- return Number.isFinite(value) && value > 0 ? value : 1;
140
- }
141
- function playTileFlip(grid, before) {
142
- const scale = stageScale(grid);
143
- const moved = [];
144
- for (const tile of grid.querySelectorAll(TILE_SELECTOR)) {
145
- const first = before.get(tile);
146
- if (!first) continue;
147
- const last = tile.getBoundingClientRect();
148
- if (!first.width || !last.width) continue;
149
- const dx = (first.left + first.width / 2 - (last.left + last.width / 2)) / scale;
150
- const dy = (first.top + first.height / 2 - (last.top + last.height / 2)) / scale;
151
- const sx = first.width / last.width;
152
- const sy = first.height / last.height;
153
- if (Math.abs(dx) < 0.5 && Math.abs(dy) < 0.5 && Math.abs(sx - 1) < 2e-3) continue;
154
- tile.style.transition = "none";
155
- tile.style.transform = `translate(${dx}px, ${dy}px) scale(${sx}, ${sy})`;
156
- moved.push(tile);
157
- }
158
- if (moved.length === 0) return;
159
- void grid.offsetWidth;
160
- for (const tile of moved) {
161
- tile.style.transition = "";
162
- tile.style.transform = "";
163
- }
164
- }
165
-
166
- // src/deck/components/DeckImageGrid.tsx
167
- import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
168
- function columnsFor(count) {
169
- return count <= 4 ? 2 : 3;
170
- }
171
- function tileRatio(asset) {
172
- if (asset?.width === void 0 || asset.height === void 0 || asset.width <= 0) return 1;
173
- return asset.height / asset.width;
174
- }
175
- function packMasonry(ratios, columns) {
176
- const packed = Array.from({ length: columns }, () => []);
177
- const filled = new Array(columns).fill(0);
178
- ratios.forEach((ratio, index) => {
179
- let target = 0;
180
- for (let column = 1; column < columns; column++) {
181
- if (filled[column] < filled[target]) target = column;
182
- }
183
- packed[target].push(index);
184
- filled[target] += ratio;
185
- });
186
- return packed;
187
- }
188
- var TILE_BASE = "group relative block shrink-0 overflow-hidden bg-base-200 will-change-transform transition-[transform,box-shadow,opacity] duration-[380ms] ease-[cubic-bezier(0.2,0.75,0.2,1)] focus-visible:outline-2 focus-visible:outline-offset-[-6px] focus-visible:outline-[var(--color-primary)]";
189
- function DeckImageGrid({ content }) {
190
- const [active, setActive] = useState2(null);
191
- const gridRef = useRef2(null);
192
- const pendingRects = useRef2(null);
193
- const expanded = active !== null;
194
- const resolve = useDeckMediaResolver();
195
- const count = content.items.length;
196
- const assets = useMemo(() => content.items.map((item) => resolve(item.media)), [content.items, resolve]);
197
- const columns = columnsFor(count);
198
- const packed = useMemo(() => packMasonry(assets.map(tileRatio), columns), [assets, columns]);
199
- const transitionTo = useCallback((next) => {
200
- const grid = gridRef.current;
201
- if (grid) pendingRects.current = captureTileRects(grid);
202
- setActive(next);
203
- }, []);
204
- useLayoutEffect2(() => {
205
- const grid = gridRef.current;
206
- const before = pendingRects.current;
207
- pendingRects.current = null;
208
- if (grid && before) playTileFlip(grid, before);
209
- }, [active]);
210
- useEffect2(() => {
211
- setActive((prev) => prev === null || prev < count ? prev : null);
212
- }, [count]);
213
- useEffect2(() => {
214
- if (!expanded) return;
215
- const onKeyDown = (event) => {
216
- if (event.key !== "Escape") return;
217
- event.stopPropagation();
218
- transitionTo(null);
219
- };
220
- window.addEventListener("keydown", onKeyDown);
221
- return () => window.removeEventListener("keydown", onKeyDown);
222
- }, [expanded, transitionTo]);
223
- const close = useCallback(() => {
224
- gridRef.current?.querySelector(`[data-deck-tile="${active}"]`)?.focus({ preventScroll: true });
225
- transitionTo(null);
226
- }, [active, transitionTo]);
227
- return /* @__PURE__ */ jsxs2(
228
- "div",
229
- {
230
- ref: gridRef,
231
- "data-deck-component": "imageGrid",
232
- "data-deck-grid-expanded": expanded ? "true" : "false",
233
- "data-deck-grid-columns": columns,
234
- style: DECK_ELEVATION,
235
- className: "relative flex size-full gap-[14px] overflow-hidden",
236
- children: [
237
- packed.map((indices, column) => (
238
- // `flex-1` rather than a width fraction: the columns have to share the
239
- // gap between them, and equal flex bases divide what is left over.
240
- /* @__PURE__ */ jsx4("div", { "data-deck-grid-column": column, className: "flex min-w-0 flex-1 flex-col gap-[14px]", children: indices.map((index) => /* @__PURE__ */ jsx4(
241
- Tile,
242
- {
243
- item: content.items[index],
244
- asset: assets[index],
245
- index,
246
- expanded,
247
- active: index === active,
248
- onActivate: () => transitionTo(index === active ? null : index)
249
- },
250
- index
251
- )) }, column)
252
- )),
253
- expanded && /* @__PURE__ */ jsx4(
254
- "button",
255
- {
256
- type: "button",
257
- "data-deck-grid-close": "",
258
- onClick: close,
259
- "data-deck-surface": "brand",
260
- style: surfaceInk("brand"),
261
- className: "absolute top-[14px] right-[14px] z-[4] bg-primary px-[18px] py-[10px] text-[15px] font-semibold tracking-[0.12em] text-[var(--deck-ink)] uppercase",
262
- children: "Close"
263
- }
264
- )
265
- ]
266
- }
267
- );
268
- }
269
- function Tile({ item, asset, index, expanded, active, onActivate }) {
270
- const label = item.caption ?? asset?.alt ?? `Image ${index + 1}`;
271
- return /* @__PURE__ */ jsxs2(
272
- "button",
273
- {
274
- type: "button",
275
- "data-deck-tile": index,
276
- "data-deck-tile-active": active ? "true" : "false",
277
- "aria-expanded": active,
278
- "aria-label": active ? `Close ${label}` : `Expand ${label}`,
279
- tabIndex: expanded && !active ? -1 : 0,
280
- onClick: onActivate,
281
- className: cn(
282
- TILE_BASE,
283
- // Every tile leaves the column flow when one is expanded, not only the
284
- // active one: leaving the siblings in place would let the columns
285
- // re-pack around the gap, which both reflows the tiles the lightbox is
286
- // covering and moves the ones the FLIP is animating.
287
- expanded ? "absolute inset-0 flex items-center justify-center" : "w-full",
288
- expanded && !active && "pointer-events-none opacity-0",
289
- // Transparent, not the tile's loading plate: an expanded frame is
290
- // letterboxed inside the slot, and the field around it should read as
291
- // the slide showing through rather than as a grey box drawn on top.
292
- expanded && active && "z-[3] bg-transparent opacity-100",
293
- !expanded && "cursor-pointer hover:z-[2] hover:scale-[1.035] hover:shadow-[var(--deck-lift)]"
294
- ),
295
- children: [
296
- asset === null ? /* @__PURE__ */ jsx4(DeckMissingMedia, { className: active ? "size-full" : "aspect-square h-auto w-full" }) : /* @__PURE__ */ jsx4(
297
- "img",
298
- {
299
- src: asset.src,
300
- alt: "",
301
- width: asset.width,
302
- height: asset.height,
303
- className: active ? "max-h-full max-w-full object-contain shadow-[var(--deck-lift-strong)]" : "block h-auto w-full"
304
- }
305
- ),
306
- /* @__PURE__ */ jsx4(
307
- "span",
308
- {
309
- "aria-hidden": "true",
310
- "data-deck-surface": "brand",
311
- style: surfaceInk("brand"),
312
- className: "absolute top-0 left-0 bg-primary px-[12px] py-[6px] text-[15px] font-bold tracking-[0.1em] text-[var(--deck-ink)] tabular-nums",
313
- children: String(index + 1).padStart(2, "0")
314
- }
315
- ),
316
- item.caption !== void 0 && /* @__PURE__ */ jsx4(
317
- "span",
318
- {
319
- "data-deck-surface": "brand",
320
- style: surfaceInk("brand"),
321
- className: cn(
322
- "absolute right-0 bottom-0 left-0 bg-primary text-left tracking-[0.04em] text-[var(--deck-ink)] transition-opacity duration-200",
323
- active ? "px-[30px] py-[22px] text-[24px] opacity-100" : "px-[18px] py-[14px] text-[18px] opacity-0 group-hover:opacity-100"
324
- ),
325
- children: item.caption
326
- }
327
- )
328
- ]
329
- }
330
- );
331
- }
332
-
333
- // src/deck/components/DeckRichText.tsx
334
- import { Fragment as Fragment2 } from "react";
335
-
336
- // src/deck/editing.tsx
337
- import { createContext as createContext2, useContext as useContext2, useEffect as useEffect3, useRef as useRef3, useState as useState3 } from "react";
338
- import { Fragment, jsx as jsx5 } from "react/jsx-runtime";
339
- var DeckTextEditContext = createContext2(null);
340
- function DeckTextEditProvider({ editor, children }) {
341
- return /* @__PURE__ */ jsx5(DeckTextEditContext.Provider, { value: editor, children });
342
- }
343
- function useDeckTextEditor() {
344
- return useContext2(DeckTextEditContext);
345
- }
346
- function EditableText({ path, children }) {
347
- const editor = useDeckTextEditor();
348
- const [editing, setEditing] = useState3(false);
349
- const enabled = editor !== null && path !== void 0 && editor.disabled !== true;
350
- useEffect3(() => {
351
- if (!enabled && editing) setEditing(false);
352
- }, [enabled, editing]);
353
- if (editor === null || path === void 0) return /* @__PURE__ */ jsx5(Fragment, { children });
354
- if (editing && enabled) {
355
- return /* @__PURE__ */ jsx5(
356
- EditableField,
357
- {
358
- initial: children,
359
- onCommit: (text) => {
360
- setEditing(false);
361
- const trimmed = text.trim();
362
- if (trimmed !== "" && trimmed !== children) editor.onEditText(path, trimmed);
363
- },
364
- onCancel: () => setEditing(false)
365
- }
366
- );
367
- }
368
- return /* @__PURE__ */ jsx5(
369
- "span",
370
- {
371
- role: "button",
372
- tabIndex: enabled ? 0 : -1,
373
- "aria-disabled": enabled ? void 0 : true,
374
- "data-deck-editable": "",
375
- onClick: enabled ? () => setEditing(true) : void 0,
376
- onKeyDown: enabled ? (event) => {
377
- if (event.key !== "Enter" && event.key !== " ") return;
378
- event.preventDefault();
379
- setEditing(true);
380
- } : void 0,
381
- className: enabled ? "cursor-text rounded-[var(--radius-inner)] decoration-dotted underline-offset-[6px] outline-none hover:underline focus-visible:underline" : "opacity-70",
382
- children
383
- }
384
- );
385
- }
386
- function EditableField({
387
- initial,
388
- onCommit,
389
- onCancel
390
- }) {
391
- const ref = useRef3(null);
392
- const cancelled = useRef3(false);
393
- useEffect3(() => {
394
- const element = ref.current;
395
- if (!element) return;
396
- element.textContent = initial;
397
- element.focus();
398
- const selection = window.getSelection?.();
399
- if (selection) {
400
- const range = document.createRange();
401
- range.selectNodeContents(element);
402
- selection.removeAllRanges();
403
- selection.addRange(range);
404
- }
405
- }, [initial]);
406
- return /* @__PURE__ */ jsx5(
407
- "span",
408
- {
409
- ref,
410
- contentEditable: true,
411
- suppressContentEditableWarning: true,
412
- role: "textbox",
413
- "aria-label": "Edit text",
414
- spellCheck: true,
415
- "data-deck-editing": "",
416
- onKeyDown: (event) => {
417
- if (event.nativeEvent.isComposing) return;
418
- if (event.key === "Enter") {
419
- event.preventDefault();
420
- event.currentTarget.blur();
421
- return;
422
- }
423
- if (event.key === "Escape") {
424
- event.preventDefault();
425
- cancelled.current = true;
426
- event.currentTarget.blur();
427
- }
428
- },
429
- onPaste: (event) => {
430
- event.preventDefault();
431
- const text = event.clipboardData.getData("text/plain").replace(/\s+/g, " ").trim();
432
- const doc = event.currentTarget.ownerDocument;
433
- if (text !== "" && typeof doc.execCommand === "function") doc.execCommand("insertText", false, text);
434
- },
435
- onBlur: (event) => {
436
- if (cancelled.current) {
437
- cancelled.current = false;
438
- onCancel();
439
- return;
440
- }
441
- onCommit(event.currentTarget.textContent ?? "");
442
- },
443
- className: "rounded-[var(--radius-inner)] outline-2 outline-offset-2 outline-[var(--deck-accent)]"
444
- }
445
- );
446
- }
447
-
448
- // src/deck/components/DeckRichText.tsx
449
- import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
450
- function InlineText({ value, path }) {
451
- if (typeof value === "string") return /* @__PURE__ */ jsx6(EditableText, { path, children: value });
452
- return /* @__PURE__ */ jsx6(Fragment3, { children: value.map((span, i) => {
453
- let node = /* @__PURE__ */ jsx6(EditableText, { path: path && { ...path, span: i }, children: span.text });
454
- if (span.italic) node = /* @__PURE__ */ jsx6("em", { className: "italic", children: node });
455
- if (span.bold) node = /* @__PURE__ */ jsx6("strong", { className: "font-semibold text-[var(--deck-ink)]", children: node });
456
- return /* @__PURE__ */ jsx6(Fragment2, { children: node }, i);
457
- }) });
458
- }
459
- function DeckRichText({ content, slot }) {
460
- const { kicker, heading, subheading, paragraphs, bullets } = content;
461
- const at = (field, line) => slot === void 0 ? void 0 : { slot, field, line };
462
- return /* @__PURE__ */ jsxs3("div", { "data-deck-component": "richText", className: "flex flex-col gap-[28px]", children: [
463
- kicker !== void 0 && /* @__PURE__ */ jsxs3("div", { className: "flex flex-col gap-[18px]", children: [
464
- /* @__PURE__ */ jsx6("p", { className: "text-[22px] font-semibold tracking-[0.2em] text-[var(--deck-accent)] [text-transform:var(--nav-text-transform)]", children: /* @__PURE__ */ jsx6(EditableText, { path: at("kicker"), children: kicker }) }),
465
- /* @__PURE__ */ jsx6(
466
- "span",
467
- {
468
- "aria-hidden": "true",
469
- style: { alignSelf: "var(--deck-align, start)" },
470
- className: "h-[4px] w-[84px] rounded-[var(--radius-inner)] bg-[var(--deck-accent)]"
471
- }
472
- )
473
- ] }),
474
- heading !== void 0 && /* @__PURE__ */ jsx6("h1", { className: "font-heading text-[88px] leading-[1.06] font-medium tracking-[-0.015em] text-[var(--deck-ink)] [text-transform:var(--heading-text-transform)]", children: /* @__PURE__ */ jsx6(EditableText, { path: at("heading"), children: heading }) }),
475
- subheading !== void 0 && /* @__PURE__ */ jsx6("h2", { className: "font-heading text-[38px] leading-[1.25] font-normal text-[var(--deck-ink-muted)] [text-transform:var(--subheading-text-transform)]", children: /* @__PURE__ */ jsx6(EditableText, { path: at("subheading"), children: subheading }) }),
476
- paragraphs !== void 0 && paragraphs.length > 0 && /* @__PURE__ */ jsx6("div", { className: "flex max-w-[1000px] flex-col gap-[18px] self-[var(--deck-align,start)]", children: paragraphs.map((paragraph, i) => /* @__PURE__ */ jsx6("p", { className: "text-[26px] leading-[1.6] text-[var(--deck-ink-muted)]", children: /* @__PURE__ */ jsx6(InlineText, { value: paragraph, path: at("paragraphs", i) }) }, i)) }),
477
- bullets !== void 0 && bullets.length > 0 && /* @__PURE__ */ jsx6("ul", { className: "flex flex-col gap-[16px] self-[var(--deck-align,start)] text-left", children: bullets.map((bullet, i) => /* @__PURE__ */ jsxs3("li", { className: "flex items-start gap-[18px] text-[26px] leading-[1.45] text-[var(--deck-ink)]", children: [
478
- /* @__PURE__ */ jsx6("span", { "aria-hidden": "true", className: "mt-[14px] size-[10px] shrink-0 rounded-full bg-[var(--deck-accent)]" }),
479
- /* @__PURE__ */ jsx6("span", { children: /* @__PURE__ */ jsx6(InlineText, { value: bullet, path: at("bullets", i) }) })
480
- ] }, i)) })
481
- ] });
482
- }
483
-
484
- // src/deck/components/DeckVideo.tsx
485
- import { Play } from "lucide-react";
486
- import { useRef as useRef4, useState as useState4 } from "react";
487
- import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
488
- function DeckVideo({ content }) {
489
- const asset = useDeckMedia(content.media);
490
- const videoRef = useRef4(null);
491
- const [playing, setPlaying] = useState4(false);
492
- const start = () => {
493
- setPlaying(true);
494
- videoRef.current?.play()?.catch(() => void 0);
495
- };
496
- return /* @__PURE__ */ jsxs4(
497
- "div",
498
- {
499
- "data-deck-component": "video",
500
- "data-deck-video-state": playing ? "playing" : "idle",
501
- style: DECK_ELEVATION,
502
- className: "relative size-full overflow-hidden bg-base-200",
503
- children: [
504
- asset === null ? /* @__PURE__ */ jsx7(DeckMissingMedia, {}) : /* @__PURE__ */ jsx7(
505
- "video",
506
- {
507
- ref: videoRef,
508
- src: asset.src,
509
- poster: asset.poster,
510
- preload: "none",
511
- playsInline: true,
512
- controls: playing,
513
- onEnded: () => setPlaying(false),
514
- className: "size-full object-cover"
515
- }
516
- ),
517
- !playing && asset !== null && /* @__PURE__ */ jsx7(
518
- "button",
519
- {
520
- type: "button",
521
- "data-deck-video-play": "",
522
- onClick: start,
523
- "aria-label": content.title === void 0 ? "Play video" : `Play ${content.title}`,
524
- className: "group absolute inset-0 grid cursor-pointer place-items-center",
525
- children: /* @__PURE__ */ jsx7("span", { className: "grid size-[108px] place-items-center rounded-full bg-primary text-[var(--color-on-primary)] shadow-[var(--deck-lift)] transition-transform duration-200 group-hover:scale-105", children: /* @__PURE__ */ jsx7(Play, { "aria-hidden": "true", className: "ml-[6px] size-[44px] fill-current" }) })
526
- }
527
- ),
528
- !playing && content.title !== void 0 && /* @__PURE__ */ jsx7(
529
- "span",
530
- {
531
- "data-deck-surface": "brand",
532
- style: surfaceInk("brand"),
533
- className: "pointer-events-none absolute right-0 bottom-0 left-0 bg-primary px-[28px] py-[18px] text-[18px] tracking-[0.06em] text-[var(--deck-ink)] [text-transform:var(--nav-text-transform)]",
534
- children: content.title
535
- }
536
- )
537
- ]
538
- }
539
- );
540
- }
541
-
542
- // src/deck/DeckComponentView.tsx
543
- import { jsx as jsx8 } from "react/jsx-runtime";
544
- function DeckComponentView({ component, slot }) {
545
- switch (component.type) {
546
- case "richText":
547
- return /* @__PURE__ */ jsx8(DeckRichText, { content: component, slot });
548
- case "image":
549
- return /* @__PURE__ */ jsx8(DeckImage, { content: component });
550
- case "imageGrid":
551
- return /* @__PURE__ */ jsx8(DeckImageGrid, { content: component });
552
- case "video":
553
- return /* @__PURE__ */ jsx8(DeckVideo, { content: component });
554
- }
555
- }
556
-
557
- // src/deck/layouts/CenteredTextLayout.tsx
558
- import { jsx as jsx9 } from "react/jsx-runtime";
559
- function CenteredTextLayout({ layout }) {
560
- return /* @__PURE__ */ jsx9(
561
- "div",
562
- {
563
- "data-deck-layout": "centeredText",
564
- "data-deck-surface": layout.background,
565
- style: { ...surfaceInk(layout.background), ...deckAlign("center") },
566
- className: cn(
567
- "flex size-full flex-col items-center justify-center px-[180px] py-[110px] text-center",
568
- SURFACE_BACKGROUND[layout.background]
569
- ),
570
- children: /* @__PURE__ */ jsx9(DeckComponentView, { component: layout.content, slot: "content" })
571
- }
572
- );
573
- }
574
-
575
- // src/deck/layouts/ColumnSplitLayout.tsx
576
- import { jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
577
- var RATIO = {
578
- "1-2": "grid-cols-[1fr_2fr]",
579
- "2-1": "grid-cols-[2fr_1fr]"
580
- };
581
- var COLUMN_PADDING = {
582
- richText: "flex flex-col justify-center px-[64px] py-[96px]",
583
- image: "",
584
- imageGrid: "p-[44px]",
585
- video: "p-[44px]"
586
- };
587
- function ColumnSplitLayout({ layout }) {
588
- const seam = layout.left.type === "richText" ? "left" : layout.right.type === "richText" ? "right" : null;
589
- return /* @__PURE__ */ jsxs5(
590
- "div",
591
- {
592
- "data-deck-layout": "columnSplit",
593
- "data-deck-ratio": layout.ratio,
594
- "data-deck-surface": "base",
595
- style: { ...surfaceInk("base"), ...deckAlign("start") },
596
- className: cn("grid size-full text-left", RATIO[layout.ratio], SURFACE_BACKGROUND.base),
597
- children: [
598
- /* @__PURE__ */ jsx10(Column, { component: layout.left, side: "left", rule: seam === "left" }),
599
- /* @__PURE__ */ jsx10(Column, { component: layout.right, side: "right", rule: seam === "right" })
600
- ]
601
- }
602
- );
603
- }
604
- function Column({ component, side, rule }) {
605
- return /* @__PURE__ */ jsx10(
606
- "div",
607
- {
608
- "data-deck-column": side,
609
- className: cn(
610
- "relative min-w-0 overflow-hidden",
611
- COLUMN_PADDING[component.type],
612
- rule && (side === "left" ? "border-r border-base-200" : "border-l border-base-200")
613
- ),
614
- children: /* @__PURE__ */ jsx10(DeckComponentView, { component, slot: side })
615
- }
616
- );
617
- }
618
-
619
- // src/deck/layouts/FullBleedImageLayout.tsx
620
- import { jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
621
- var PLACEMENT = {
622
- sideLeft: "top-0 bottom-0 left-0 w-[40%] justify-center px-[72px] py-[90px]",
623
- sideRight: "top-0 bottom-0 right-0 w-[40%] justify-center px-[72px] py-[90px]",
624
- bottomBand: "right-0 bottom-0 left-0 justify-end px-[96px] py-[56px]"
625
- };
626
- function FullBleedImageLayout({ layout }) {
627
- const asset = useDeckMedia(layout.media);
628
- const { overlay } = layout;
629
- return /* @__PURE__ */ jsxs6(
630
- "div",
631
- {
632
- "data-deck-layout": "fullBleedImage",
633
- "data-deck-surface": "base",
634
- style: { ...surfaceInk("base"), ...deckAlign("start") },
635
- className: cn("relative size-full overflow-hidden", SURFACE_BACKGROUND.base),
636
- children: [
637
- asset === null ? /* @__PURE__ */ jsx11(DeckMissingMedia, { className: "absolute inset-0" }) : /* @__PURE__ */ jsx11("img", { src: asset.src, alt: asset.alt, className: "absolute inset-0 size-full object-cover" }),
638
- overlay !== void 0 && /* @__PURE__ */ jsx11(
639
- "div",
640
- {
641
- "data-deck-overlay": overlay.placement,
642
- "data-deck-surface": "brand",
643
- style: surfaceInk("brand"),
644
- className: cn("absolute z-[2] flex flex-col text-left", SURFACE_BACKGROUND.brand, PLACEMENT[overlay.placement]),
645
- children: /* @__PURE__ */ jsx11(DeckRichText, { content: overlay.content, slot: "overlay" })
646
- }
647
- )
648
- ]
649
- }
650
- );
651
- }
652
-
653
- // src/deck/DeckSlideView.tsx
654
- import { jsx as jsx12 } from "react/jsx-runtime";
655
- function LayoutView({ slide }) {
656
- const { layout } = slide;
657
- switch (layout.type) {
658
- case "centeredText":
659
- return /* @__PURE__ */ jsx12(CenteredTextLayout, { layout });
660
- case "fullBleedImage":
661
- return /* @__PURE__ */ jsx12(FullBleedImageLayout, { layout });
662
- case "columnSplit":
663
- return /* @__PURE__ */ jsx12(ColumnSplitLayout, { layout });
664
- }
665
- }
666
- function DeckSlideView({ slide }) {
667
- return /* @__PURE__ */ jsx12("div", { "data-deck-slide": slide.id, className: "size-full", children: /* @__PURE__ */ jsx12(LayoutView, { slide }) }, slide.id);
668
- }
669
-
670
- // src/deck/DeckPlayer.tsx
671
- import { jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
672
- function clamp(index, length) {
673
- return Math.min(Math.max(index, 0), length - 1);
674
- }
675
- function isTypingTarget(target) {
676
- if (!(target instanceof HTMLElement)) return false;
677
- return target.isContentEditable || ["INPUT", "TEXTAREA", "SELECT"].includes(target.tagName);
678
- }
679
- function isActivatableTarget(target) {
680
- if (!(target instanceof HTMLElement)) return false;
681
- if (target.tagName === "BUTTON" || target.tagName === "SUMMARY") return true;
682
- if (target.tagName === "A" && target.hasAttribute("href")) return true;
683
- return target.getAttribute("role") === "button";
684
- }
685
- var NAV_BUTTON = "flex size-[38px] items-center justify-center rounded-[var(--radius-outer)] border border-base-200 text-base-contrast transition-colors hover:bg-base-accent disabled:cursor-not-allowed disabled:opacity-35 disabled:hover:bg-transparent";
686
- function DeckPlayer({ deck, initialSlide = 0, keyboard = true, resolveMedia, mediaAssets, className }) {
687
- const total = deck.slides.length;
688
- const [index, setIndex] = useState5(() => clamp(initialSlide, total));
689
- const resolve = useMemo2(
690
- () => resolveMedia ?? ((ref) => ref.kind === "portal" && mediaAssets !== void 0 && Object.hasOwn(mediaAssets, ref.id) ? mediaAssets[ref.id] : null),
691
- [resolveMedia, mediaAssets]
692
- );
693
- const current = clamp(index, total);
694
- const slide = deck.slides[current];
695
- const goTo = useCallback2((next) => setIndex(clamp(next, total)), [total]);
696
- const step = useCallback2(
697
- (delta) => setIndex((prev) => clamp(clamp(prev, total) + delta, total)),
698
- [total]
699
- );
700
- useEffect4(() => {
701
- if (!keyboard) return;
702
- const onKeyDown = (event) => {
703
- if (event.metaKey || event.ctrlKey || event.altKey) return;
704
- if (isTypingTarget(event.target)) return;
705
- switch (event.key) {
706
- case " ":
707
- if (isActivatableTarget(event.target)) return;
708
- event.preventDefault();
709
- step(1);
710
- break;
711
- case "ArrowRight":
712
- case "PageDown":
713
- event.preventDefault();
714
- step(1);
715
- break;
716
- case "ArrowLeft":
717
- case "PageUp":
718
- event.preventDefault();
719
- step(-1);
720
- break;
721
- case "Home":
722
- event.preventDefault();
723
- setIndex(0);
724
- break;
725
- case "End":
726
- event.preventDefault();
727
- setIndex(total - 1);
728
- break;
729
- }
730
- };
731
- window.addEventListener("keydown", onKeyDown);
732
- return () => window.removeEventListener("keydown", onKeyDown);
733
- }, [keyboard, step, total]);
734
- return /* @__PURE__ */ jsxs7("div", { "data-deck-player": deck.id, className: cn("flex h-full min-h-0 w-full flex-col gap-4 bg-base p-4", className), children: [
735
- /* @__PURE__ */ jsx13(DeckStage, { className: "flex-1", children: /* @__PURE__ */ jsx13(DeckMediaProvider, { resolve, children: /* @__PURE__ */ jsx13(DeckSlideView, { slide }) }) }),
736
- /* @__PURE__ */ jsxs7("nav", { "aria-label": `${deck.title} slides`, className: "flex shrink-0 items-center justify-center gap-4", children: [
737
- /* @__PURE__ */ jsx13("button", { type: "button", className: NAV_BUTTON, onClick: () => step(-1), disabled: current === 0, "aria-label": "Previous slide", children: /* @__PURE__ */ jsx13(ChevronLeft, { className: "size-5", "aria-hidden": "true" }) }),
738
- /* @__PURE__ */ jsx13("ol", { className: "flex items-center gap-2", children: deck.slides.map((s, i) => /* @__PURE__ */ jsx13("li", { children: /* @__PURE__ */ jsx13(
739
- "button",
740
- {
741
- type: "button",
742
- onClick: () => goTo(i),
743
- "aria-current": i === current ? "true" : void 0,
744
- "aria-label": s.title ? `Slide ${i + 1}: ${s.title}` : `Slide ${i + 1}`,
745
- className: cn(
746
- "size-[10px] rounded-full transition-colors",
747
- i === current ? "bg-primary" : "bg-base-300 hover:bg-base-contrast-light"
748
- )
749
- }
750
- ) }, s.id)) }),
751
- /* @__PURE__ */ jsx13("button", { type: "button", className: NAV_BUTTON, onClick: () => step(1), disabled: current === total - 1, "aria-label": "Next slide", children: /* @__PURE__ */ jsx13(ChevronRight, { className: "size-5", "aria-hidden": "true" }) }),
752
- /* @__PURE__ */ jsxs7("p", { "aria-live": "polite", className: "ml-2 text-sm tabular-nums text-base-contrast-light", children: [
753
- current + 1,
754
- " / ",
755
- total
756
- ] })
757
- ] })
758
- ] });
759
- }
760
-
761
- export {
762
- DeckMediaProvider,
763
- useDeckMedia,
764
- useDeckMediaResolver,
765
- DeckMissingMedia,
766
- useStageScale,
767
- DeckStage,
768
- surfaceInk,
769
- SURFACE_BACKGROUND,
770
- deckAlign,
771
- DECK_ELEVATION,
772
- DeckImage,
773
- DeckImageGrid,
774
- DeckTextEditProvider,
775
- EditableText,
776
- DeckRichText,
777
- DeckVideo,
778
- DeckComponentView,
779
- CenteredTextLayout,
780
- ColumnSplitLayout,
781
- FullBleedImageLayout,
782
- DeckSlideView,
783
- DeckPlayer
784
- };