@drawnagency/primitives 0.1.111 → 0.1.113

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 (203) hide show
  1. package/dist/auth/types.d.ts +1 -0
  2. package/dist/auth/types.d.ts.map +1 -1
  3. package/dist/chunk-4I5OO5UB.js +785 -0
  4. package/dist/{chunk-7WQJ57XG.js → chunk-6BZ2KNTP.js} +68 -260
  5. package/dist/{chunk-UVIYI4J6.js → chunk-AHALSCQH.js} +19 -3
  6. package/dist/{chunk-7MI3HCOF.js → chunk-BDFTMGCL.js} +10 -6
  7. package/dist/chunk-CXZ5YJG4.js +85 -0
  8. package/dist/{chunk-RA5IOFPY.js → chunk-DNY72JZN.js} +16 -38
  9. package/dist/{chunk-3GAG6ZXB.js → chunk-DS4GCYV2.js} +8 -4
  10. package/dist/{chunk-XQMDWXD6.js → chunk-FRE2CCLV.js} +3 -2
  11. package/dist/chunk-FV7JQRCN.js +94 -0
  12. package/dist/chunk-IIDKW7AV.js +41 -0
  13. package/dist/chunk-IINIZBQB.js +204 -0
  14. package/dist/{chunk-ELQ4C677.js → chunk-JH762VUH.js} +9 -44
  15. package/dist/{chunk-OUYB2GCW.js → chunk-K7DYZXVU.js} +1 -57
  16. package/dist/{chunk-NXGIHSL5.js → chunk-KR2MHTNJ.js} +11 -91
  17. package/dist/chunk-MM7KZS5C.js +30 -0
  18. package/dist/{chunk-OTDA6KWL.js → chunk-NHN2LSIU.js} +1 -1
  19. package/dist/chunk-QQ3S3P5P.js +38 -0
  20. package/dist/chunk-VAYZJKVR.js +209 -0
  21. package/dist/{chunk-VCCNKTFD.js → chunk-VWWY5TL5.js} +3 -31
  22. package/dist/chunk-WUJ3XNFI.js +62 -0
  23. package/dist/{chunk-ALMEC3XN.js → chunk-Z7W3DQTR.js} +22 -18
  24. package/dist/collab/rebase.js +1 -1
  25. package/dist/components/chat/ChatComposer.d.ts +25 -0
  26. package/dist/components/chat/ChatComposer.d.ts.map +1 -0
  27. package/dist/components/chat/ChatPanel.d.ts +5 -4
  28. package/dist/components/chat/ChatPanel.d.ts.map +1 -1
  29. package/dist/components/chat/ChatWidget.d.ts.map +1 -1
  30. package/dist/components/chat/markdown.d.ts +14 -0
  31. package/dist/components/chat/markdown.d.ts.map +1 -0
  32. package/dist/components/editor/index.js +16 -11
  33. package/dist/components/primitives/EditablePlainText.d.ts.map +1 -1
  34. package/dist/components/primitives/index.js +15 -10
  35. package/dist/components/sections/brand-guide.js +11 -9
  36. package/dist/components/sections/register-schemas.js +19 -14
  37. package/dist/components/sections/register.js +19 -14
  38. package/dist/components/shared/Navigation.d.ts +1 -0
  39. package/dist/components/shared/Navigation.d.ts.map +1 -1
  40. package/dist/components/shell/AudienceChips.d.ts +10 -0
  41. package/dist/components/shell/AudienceChips.d.ts.map +1 -0
  42. package/dist/components/shell/EditorShell.d.ts.map +1 -1
  43. package/dist/components/shell/SiteSettingsChatbot.d.ts.map +1 -1
  44. package/dist/components/shell/SiteSettingsDecks.d.ts +13 -0
  45. package/dist/components/shell/SiteSettingsDecks.d.ts.map +1 -0
  46. package/dist/components/shell/SiteSettingsDisplay.d.ts.map +1 -1
  47. package/dist/components/shell/SiteSettingsModal.d.ts.map +1 -1
  48. package/dist/components/shell/SiteSettingsUsers.d.ts.map +1 -1
  49. package/dist/deck/DeckComponentView.d.ts +13 -0
  50. package/dist/deck/DeckComponentView.d.ts.map +1 -0
  51. package/dist/deck/DeckPlayer.d.ts +26 -0
  52. package/dist/deck/DeckPlayer.d.ts.map +1 -0
  53. package/dist/deck/DeckSlideView.d.ts +17 -0
  54. package/dist/deck/DeckSlideView.d.ts.map +1 -0
  55. package/dist/deck/DeckStage.d.ts +16 -0
  56. package/dist/deck/DeckStage.d.ts.map +1 -0
  57. package/dist/deck/components/DeckImage.d.ts +14 -0
  58. package/dist/deck/components/DeckImage.d.ts.map +1 -0
  59. package/dist/deck/components/DeckImageGrid.d.ts +27 -0
  60. package/dist/deck/components/DeckImageGrid.d.ts.map +1 -0
  61. package/dist/deck/components/DeckRichText.d.ts +22 -0
  62. package/dist/deck/components/DeckRichText.d.ts.map +1 -0
  63. package/dist/deck/components/DeckVideo.d.ts +15 -0
  64. package/dist/deck/components/DeckVideo.d.ts.map +1 -0
  65. package/dist/deck/editing.d.ts +50 -0
  66. package/dist/deck/editing.d.ts.map +1 -0
  67. package/dist/deck/flip.d.ts +11 -0
  68. package/dist/deck/flip.d.ts.map +1 -0
  69. package/dist/deck/index.d.ts +24 -0
  70. package/dist/deck/index.d.ts.map +1 -0
  71. package/dist/deck/index.js +53 -0
  72. package/dist/deck/layouts/CenteredTextLayout.d.ts +12 -0
  73. package/dist/deck/layouts/CenteredTextLayout.d.ts.map +1 -0
  74. package/dist/deck/layouts/ColumnSplitLayout.d.ts +14 -0
  75. package/dist/deck/layouts/ColumnSplitLayout.d.ts.map +1 -0
  76. package/dist/deck/layouts/FullBleedImageLayout.d.ts +14 -0
  77. package/dist/deck/layouts/FullBleedImageLayout.d.ts.map +1 -0
  78. package/dist/deck/media.d.ts +33 -0
  79. package/dist/deck/media.d.ts.map +1 -0
  80. package/dist/deck/tokens.d.ts +22 -0
  81. package/dist/deck/tokens.d.ts.map +1 -0
  82. package/dist/deck/useStageScale.d.ts +10 -0
  83. package/dist/deck/useStageScale.d.ts.map +1 -0
  84. package/dist/deck-builder/DeckBuilderApp.d.ts +30 -0
  85. package/dist/deck-builder/DeckBuilderApp.d.ts.map +1 -0
  86. package/dist/deck-builder/DeckBuilderTopBar.d.ts +24 -0
  87. package/dist/deck-builder/DeckBuilderTopBar.d.ts.map +1 -0
  88. package/dist/deck-builder/DeckChatPanel.d.ts +45 -0
  89. package/dist/deck-builder/DeckChatPanel.d.ts.map +1 -0
  90. package/dist/deck-builder/DeckEditor.d.ts +37 -0
  91. package/dist/deck-builder/DeckEditor.d.ts.map +1 -0
  92. package/dist/deck-builder/DeckLibrary.d.ts +22 -0
  93. package/dist/deck-builder/DeckLibrary.d.ts.map +1 -0
  94. package/dist/deck-builder/DeckSlideSurface.d.ts +31 -0
  95. package/dist/deck-builder/DeckSlideSurface.d.ts.map +1 -0
  96. package/dist/deck-builder/deck-api.d.ts +76 -0
  97. package/dist/deck-builder/deck-api.d.ts.map +1 -0
  98. package/dist/deck-builder/deck-chat-client.d.ts +44 -0
  99. package/dist/deck-builder/deck-chat-client.d.ts.map +1 -0
  100. package/dist/deck-builder/deck-chat-history.d.ts +10 -0
  101. package/dist/deck-builder/deck-chat-history.d.ts.map +1 -0
  102. package/dist/deck-builder/index.d.ts +13 -0
  103. package/dist/deck-builder/index.d.ts.map +1 -0
  104. package/dist/deck-builder/index.js +1505 -0
  105. package/dist/deck-builder/starter-deck.d.ts +23 -0
  106. package/dist/deck-builder/starter-deck.d.ts.map +1 -0
  107. package/dist/deck-builder/types.d.ts +29 -0
  108. package/dist/deck-builder/types.d.ts.map +1 -0
  109. package/dist/deck-builder/useSortableSlide.d.ts +29 -0
  110. package/dist/deck-builder/useSortableSlide.d.ts.map +1 -0
  111. package/dist/index.js +70 -63
  112. package/dist/lib/deck-access.d.ts +86 -0
  113. package/dist/lib/deck-access.d.ts.map +1 -0
  114. package/dist/lib/deck-access.js +58 -0
  115. package/dist/lib/deck-dexie.d.ts +88 -0
  116. package/dist/lib/deck-dexie.d.ts.map +1 -0
  117. package/dist/lib/deck-dexie.js +22 -0
  118. package/dist/lib/deck-edit.d.ts +67 -0
  119. package/dist/lib/deck-edit.d.ts.map +1 -0
  120. package/dist/lib/deck-media-assets.d.ts +27 -0
  121. package/dist/lib/deck-media-assets.d.ts.map +1 -0
  122. package/dist/lib/deck-media-assets.js +25 -0
  123. package/dist/lib/deck-media-refs.d.ts +35 -0
  124. package/dist/lib/deck-media-refs.d.ts.map +1 -0
  125. package/dist/lib/deck-media-refs.js +36 -0
  126. package/dist/lib/deck-tool.d.ts +25 -0
  127. package/dist/lib/deck-tool.d.ts.map +1 -0
  128. package/dist/lib/deck-tool.js +58 -0
  129. package/dist/lib/index-ops.js +2 -2
  130. package/dist/lib/index.js +17 -12
  131. package/dist/lib/nav.d.ts.map +1 -1
  132. package/dist/media/index.js +3 -3
  133. package/dist/media/resolve.d.ts +2 -0
  134. package/dist/media/resolve.d.ts.map +1 -1
  135. package/dist/schemas/deck-meta.d.ts +85 -0
  136. package/dist/schemas/deck-meta.d.ts.map +1 -0
  137. package/dist/schemas/deck-meta.js +64 -0
  138. package/dist/schemas/deck.d.ts +954 -0
  139. package/dist/schemas/deck.d.ts.map +1 -0
  140. package/dist/schemas/deck.js +65 -0
  141. package/dist/schemas/index.js +39 -37
  142. package/dist/schemas/site-config.d.ts +14 -1
  143. package/dist/schemas/site-config.d.ts.map +1 -1
  144. package/dist/types/database.d.ts +8 -0
  145. package/dist/types/database.d.ts.map +1 -1
  146. package/package.json +37 -1
  147. package/src/auth/types.ts +1 -0
  148. package/src/components/chat/ChatComposer.tsx +100 -0
  149. package/src/components/chat/ChatPanel.tsx +20 -69
  150. package/src/components/chat/ChatWidget.tsx +5 -4
  151. package/src/components/chat/markdown.ts +32 -0
  152. package/src/components/primitives/EditablePlainText.tsx +11 -1
  153. package/src/components/shared/Navigation.tsx +26 -18
  154. package/src/components/shell/AudienceChips.tsx +30 -0
  155. package/src/components/shell/EditorShell.tsx +12 -0
  156. package/src/components/shell/SiteSettingsChatbot.tsx +1 -18
  157. package/src/components/shell/SiteSettingsDecks.tsx +41 -0
  158. package/src/components/shell/SiteSettingsDisplay.tsx +10 -1
  159. package/src/components/shell/SiteSettingsModal.tsx +11 -0
  160. package/src/components/shell/SiteSettingsUsers.tsx +49 -2
  161. package/src/deck/DeckComponentView.tsx +28 -0
  162. package/src/deck/DeckPlayer.tsx +166 -0
  163. package/src/deck/DeckSlideView.tsx +38 -0
  164. package/src/deck/DeckStage.tsx +39 -0
  165. package/src/deck/components/DeckImage.tsx +38 -0
  166. package/src/deck/components/DeckImageGrid.tsx +254 -0
  167. package/src/deck/components/DeckRichText.tsx +111 -0
  168. package/src/deck/components/DeckVideo.tsx +81 -0
  169. package/src/deck/editing.tsx +201 -0
  170. package/src/deck/flip.ts +70 -0
  171. package/src/deck/index.ts +30 -0
  172. package/src/deck/layouts/CenteredTextLayout.tsx +29 -0
  173. package/src/deck/layouts/ColumnSplitLayout.tsx +69 -0
  174. package/src/deck/layouts/FullBleedImageLayout.tsx +58 -0
  175. package/src/deck/media.tsx +46 -0
  176. package/src/deck/tokens.ts +57 -0
  177. package/src/deck/useStageScale.ts +44 -0
  178. package/src/deck-builder/DeckBuilderApp.tsx +572 -0
  179. package/src/deck-builder/DeckBuilderTopBar.tsx +62 -0
  180. package/src/deck-builder/DeckChatPanel.tsx +334 -0
  181. package/src/deck-builder/DeckEditor.tsx +258 -0
  182. package/src/deck-builder/DeckLibrary.tsx +195 -0
  183. package/src/deck-builder/DeckSlideSurface.tsx +55 -0
  184. package/src/deck-builder/deck-api.ts +177 -0
  185. package/src/deck-builder/deck-chat-client.ts +129 -0
  186. package/src/deck-builder/deck-chat-history.ts +62 -0
  187. package/src/deck-builder/index.ts +12 -0
  188. package/src/deck-builder/starter-deck.ts +86 -0
  189. package/src/deck-builder/types.ts +24 -0
  190. package/src/deck-builder/useSortableSlide.ts +102 -0
  191. package/src/lib/deck-access.ts +132 -0
  192. package/src/lib/deck-dexie.ts +190 -0
  193. package/src/lib/deck-edit.ts +196 -0
  194. package/src/lib/deck-media-assets.ts +57 -0
  195. package/src/lib/deck-media-refs.ts +67 -0
  196. package/src/lib/deck-tool.ts +95 -0
  197. package/src/lib/nav.ts +21 -1
  198. package/src/media/resolve.ts +3 -1
  199. package/src/schemas/deck-meta.ts +88 -0
  200. package/src/schemas/deck.ts +478 -0
  201. package/src/schemas/index.ts +4 -0
  202. package/src/schemas/site-config.ts +27 -1
  203. package/src/types/database.ts +4 -0
@@ -2,68 +2,47 @@ import {
2
2
  Checkbox
3
3
  } from "./chunk-F2LYQPXV.js";
4
4
  import {
5
- Button,
6
5
  LinkField,
7
6
  Select
8
- } from "./chunk-OUYB2GCW.js";
7
+ } from "./chunk-K7DYZXVU.js";
9
8
  import {
10
9
  DeleteIcon,
11
10
  DragHandle,
12
11
  FormLabel,
13
- IconButton,
14
12
  Input,
15
13
  SettingsIcon,
16
14
  useMediaLibrary,
17
15
  useResolvedMedia
18
- } from "./chunk-ELQ4C677.js";
16
+ } from "./chunk-JH762VUH.js";
17
+ import {
18
+ Kbd,
19
+ Tooltip
20
+ } from "./chunk-IINIZBQB.js";
21
+ import {
22
+ Button
23
+ } from "./chunk-WUJ3XNFI.js";
24
+ import {
25
+ IconButton
26
+ } from "./chunk-IIDKW7AV.js";
19
27
  import {
20
28
  formatFileSize
21
- } from "./chunk-XQMDWXD6.js";
29
+ } from "./chunk-FRE2CCLV.js";
22
30
  import {
23
31
  cn
24
32
  } from "./chunk-7EOSDFS3.js";
25
33
 
26
34
  // src/components/editor/DragHandle.tsx
27
35
  import { forwardRef } from "react";
28
-
29
- // src/components/shared/Tooltip.tsx
30
- import { jsx, jsxs } from "react/jsx-runtime";
31
- var sideClasses = {
32
- bottom: "left-1/2 top-full mt-1.5 -translate-x-1/2",
33
- right: "left-full top-1/2 ml-1.5 -translate-y-1/2",
34
- "bottom-clamp": "top-full mt-1.5 left-1/2 -translate-x-1/2 max-xl:left-auto max-xl:right-0 max-xl:translate-x-0"
35
- };
36
- function Tooltip({ content, children, className, side = "bottom" }) {
37
- return /* @__PURE__ */ jsxs("div", { className: cn("group/tooltip relative inline-flex", className), children: [
38
- children,
39
- /* @__PURE__ */ jsx(
40
- "span",
41
- {
42
- className: cn(
43
- "pointer-events-none absolute z-50 opacity-0 transition-opacity delay-300 group-hover/tooltip:opacity-100",
44
- sideClasses[side]
45
- ),
46
- role: "tooltip",
47
- children: /* @__PURE__ */ jsx("span", { className: "block whitespace-nowrap rounded bg-tooltip px-2 py-1 text-center text-xs leading-relaxed text-tooltip-muted", children: content })
48
- }
49
- )
50
- ] });
51
- }
52
- function Kbd({ children }) {
53
- return /* @__PURE__ */ jsx("strong", { className: "text-tooltip-contrast", children });
54
- }
55
-
56
- // src/components/editor/DragHandle.tsx
57
- import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
36
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
58
37
  var DragHandle2 = forwardRef(function DragHandle3({ tooltipSide }, ref) {
59
- return /* @__PURE__ */ jsx2(Tooltip, { side: tooltipSide, content: /* @__PURE__ */ jsxs2(Fragment, { children: [
60
- /* @__PURE__ */ jsx2(Kbd, { children: "Drag" }),
38
+ return /* @__PURE__ */ jsx(Tooltip, { side: tooltipSide, content: /* @__PURE__ */ jsxs(Fragment, { children: [
39
+ /* @__PURE__ */ jsx(Kbd, { children: "Drag" }),
61
40
  " to move"
62
- ] }), children: /* @__PURE__ */ jsx2(
41
+ ] }), children: /* @__PURE__ */ jsx(
63
42
  IconButton,
64
43
  {
65
44
  ref,
66
- icon: /* @__PURE__ */ jsx2(DragHandle, { size: 18 }),
45
+ icon: /* @__PURE__ */ jsx(DragHandle, { size: 18 }),
67
46
  label: "Drag to reorder section",
68
47
  className: "pointer-events-auto cursor-grab active:cursor-grabbing rounded-md text-base-contrast-light/80 hover:bg-base-contrast-light/10 hover:text-base-contrast",
69
48
  tabIndex: -1
@@ -72,12 +51,12 @@ var DragHandle2 = forwardRef(function DragHandle3({ tooltipSide }, ref) {
72
51
  });
73
52
 
74
53
  // src/components/editor/DeleteButton.tsx
75
- import { jsx as jsx3 } from "react/jsx-runtime";
54
+ import { jsx as jsx2 } from "react/jsx-runtime";
76
55
  function DeleteButton({ onDelete }) {
77
- return /* @__PURE__ */ jsx3(
56
+ return /* @__PURE__ */ jsx2(
78
57
  IconButton,
79
58
  {
80
- icon: /* @__PURE__ */ jsx3(DeleteIcon, { size: 16 }),
59
+ icon: /* @__PURE__ */ jsx2(DeleteIcon, { size: 16 }),
81
60
  label: "Delete section",
82
61
  intent: "destructive",
83
62
  onClick: onDelete,
@@ -87,12 +66,12 @@ function DeleteButton({ onDelete }) {
87
66
  }
88
67
 
89
68
  // src/components/editor/SettingsButton.tsx
90
- import { jsx as jsx4 } from "react/jsx-runtime";
69
+ import { jsx as jsx3 } from "react/jsx-runtime";
91
70
  function SettingsButton({ onClick }) {
92
- return /* @__PURE__ */ jsx4(
71
+ return /* @__PURE__ */ jsx3(
93
72
  IconButton,
94
73
  {
95
- icon: /* @__PURE__ */ jsx4(SettingsIcon, { size: 16 }),
74
+ icon: /* @__PURE__ */ jsx3(SettingsIcon, { size: 16 }),
96
75
  label: "Section settings",
97
76
  onClick,
98
77
  className: "pointer-events-auto"
@@ -105,7 +84,7 @@ import { useId, useState as useState3 } from "react";
105
84
 
106
85
  // src/components/shared/VideoSourceField.tsx
107
86
  import { useState } from "react";
108
- import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
87
+ import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
109
88
  var ASPECTS = [
110
89
  { label: "9:16", width: 9, height: 16 },
111
90
  { label: "4:5", width: 4, height: 5 },
@@ -154,9 +133,9 @@ function VideoSourceField({ value, onChange }) {
154
133
  setLoading(false);
155
134
  }
156
135
  }
157
- return /* @__PURE__ */ jsxs3("div", { className: "flex flex-col gap-3", children: [
158
- /* @__PURE__ */ jsx5(FormLabel, { children: "Source" }),
159
- /* @__PURE__ */ jsx5("div", { className: "flex gap-2", role: "tablist", children: ["library", "embed"].map((m) => /* @__PURE__ */ jsx5(
136
+ return /* @__PURE__ */ jsxs2("div", { className: "flex flex-col gap-3", children: [
137
+ /* @__PURE__ */ jsx4(FormLabel, { children: "Source" }),
138
+ /* @__PURE__ */ jsx4("div", { className: "flex gap-2", role: "tablist", children: ["library", "embed"].map((m) => /* @__PURE__ */ jsx4(
160
139
  "button",
161
140
  {
162
141
  type: "button",
@@ -171,9 +150,9 @@ function VideoSourceField({ value, onChange }) {
171
150
  },
172
151
  m
173
152
  )) }),
174
- mode === "library" ? /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-3", children: [
175
- libraryImageId ? resolved.poster ? /* @__PURE__ */ jsx5("img", { src: resolved.poster, alt: "", className: "h-12 w-20 rounded object-cover" }) : /* @__PURE__ */ jsx5("span", { className: "text-sm text-base-contrast-light", children: "Video selected" }) : /* @__PURE__ */ jsx5("span", { className: "text-sm text-base-contrast-light", children: "No video selected" }),
176
- /* @__PURE__ */ jsx5(
153
+ mode === "library" ? /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-3", children: [
154
+ libraryImageId ? resolved.poster ? /* @__PURE__ */ jsx4("img", { src: resolved.poster, alt: "", className: "h-12 w-20 rounded object-cover" }) : /* @__PURE__ */ jsx4("span", { className: "text-sm text-base-contrast-light", children: "Video selected" }) : /* @__PURE__ */ jsx4("span", { className: "text-sm text-base-contrast-light", children: "No video selected" }),
155
+ /* @__PURE__ */ jsx4(
177
156
  Button,
178
157
  {
179
158
  type: "button",
@@ -183,9 +162,9 @@ function VideoSourceField({ value, onChange }) {
183
162
  children: "Choose video"
184
163
  }
185
164
  )
186
- ] }) : /* @__PURE__ */ jsxs3("div", { className: "flex flex-col gap-2", children: [
187
- /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-2", children: [
188
- /* @__PURE__ */ jsx5(
165
+ ] }) : /* @__PURE__ */ jsxs2("div", { className: "flex flex-col gap-2", children: [
166
+ /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2", children: [
167
+ /* @__PURE__ */ jsx4(
189
168
  "input",
190
169
  {
191
170
  type: "text",
@@ -205,7 +184,7 @@ function VideoSourceField({ value, onChange }) {
205
184
  className: "flex-1 rounded border border-base-200 bg-base px-2 py-1 text-sm text-base-contrast placeholder:text-base-contrast-light focus:outline-none focus:ring-1 focus:ring-primary"
206
185
  }
207
186
  ),
208
- /* @__PURE__ */ jsx5(
187
+ /* @__PURE__ */ jsx4(
209
188
  Button,
210
189
  {
211
190
  type: "button",
@@ -217,13 +196,13 @@ function VideoSourceField({ value, onChange }) {
217
196
  }
218
197
  )
219
198
  ] }),
220
- error ? /* @__PURE__ */ jsx5("p", { className: "text-xs text-red-600", children: error }) : null,
221
- !error && fallback ? /* @__PURE__ */ jsx5("p", { className: "text-xs text-base-contrast-light/70", children: "Added \u2014 couldn't fetch exact dimensions, using 16:9." }) : null,
222
- value?.type === "external" && value.provider === "instagram" ? /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-2", children: [
223
- /* @__PURE__ */ jsx5("span", { className: "text-xs text-base-contrast-light", children: "Aspect" }),
199
+ error ? /* @__PURE__ */ jsx4("p", { className: "text-xs text-red-600", children: error }) : null,
200
+ !error && fallback ? /* @__PURE__ */ jsx4("p", { className: "text-xs text-base-contrast-light/70", children: "Added \u2014 couldn't fetch exact dimensions, using 16:9." }) : null,
201
+ value?.type === "external" && value.provider === "instagram" ? /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2", children: [
202
+ /* @__PURE__ */ jsx4("span", { className: "text-xs text-base-contrast-light", children: "Aspect" }),
224
203
  ASPECTS.map(({ label, width, height }) => {
225
204
  const active = value.width === width && value.height === height;
226
- return /* @__PURE__ */ jsx5(
205
+ return /* @__PURE__ */ jsx4(
227
206
  "button",
228
207
  {
229
208
  type: "button",
@@ -257,22 +236,22 @@ function useResolvedDocument(documentId) {
257
236
  }
258
237
 
259
238
  // src/components/shared/DocumentSourceField.tsx
260
- import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
239
+ import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
261
240
  function DocumentSourceField({ value, onChange }) {
262
241
  const mediaLibrary = useMediaLibrary();
263
242
  const documentId = value?.documentId || void 0;
264
243
  const { entry, missing } = useResolvedDocument(documentId);
265
- return /* @__PURE__ */ jsxs4("div", { className: "flex flex-col gap-3", children: [
266
- /* @__PURE__ */ jsx6(FormLabel, { children: "Document" }),
267
- /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-3", children: [
268
- entry ? /* @__PURE__ */ jsxs4("span", { className: "min-w-0 flex-1 truncate text-sm text-base-contrast", children: [
244
+ return /* @__PURE__ */ jsxs3("div", { className: "flex flex-col gap-3", children: [
245
+ /* @__PURE__ */ jsx5(FormLabel, { children: "Document" }),
246
+ /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-3", children: [
247
+ entry ? /* @__PURE__ */ jsxs3("span", { className: "min-w-0 flex-1 truncate text-sm text-base-contrast", children: [
269
248
  entry.filename,
270
- /* @__PURE__ */ jsxs4("span", { className: "text-base-contrast-light", children: [
249
+ /* @__PURE__ */ jsxs3("span", { className: "text-base-contrast-light", children: [
271
250
  " \xB7 ",
272
251
  formatFileSize(entry.size)
273
252
  ] })
274
- ] }) : /* @__PURE__ */ jsx6("span", { className: "flex-1 text-sm text-base-contrast-light", children: missing ? "File missing" : "No document selected" }),
275
- /* @__PURE__ */ jsx6(
253
+ ] }) : /* @__PURE__ */ jsx5("span", { className: "flex-1 text-sm text-base-contrast-light", children: missing ? "File missing" : "No document selected" }),
254
+ /* @__PURE__ */ jsx5(
276
255
  Button,
277
256
  {
278
257
  type: "button",
@@ -288,7 +267,7 @@ function DocumentSourceField({ value, onChange }) {
288
267
 
289
268
  // src/components/shared/Tabs.tsx
290
269
  import { useState as useState2 } from "react";
291
- import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
270
+ import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
292
271
  function Tabs({ tabs, defaultTabId, activeTabId, onTabChange, fullBleedTabBar }) {
293
272
  const [uncontrolledId, setUncontrolledId] = useState2(defaultTabId ?? tabs[0]?.id);
294
273
  const isControlled = activeTabId !== void 0;
@@ -298,8 +277,8 @@ function Tabs({ tabs, defaultTabId, activeTabId, onTabChange, fullBleedTabBar })
298
277
  if (!isControlled) setUncontrolledId(id);
299
278
  onTabChange?.(id);
300
279
  }
301
- return /* @__PURE__ */ jsxs5("div", { className: "flex flex-1 flex-col overflow-hidden", children: [
302
- /* @__PURE__ */ jsx7("div", { className: cn("border-b border-base-200", fullBleedTabBar && "-mx-6 px-6"), children: /* @__PURE__ */ jsx7("div", { className: "flex", role: "tablist", children: tabs.map((tab) => /* @__PURE__ */ jsx7(
280
+ return /* @__PURE__ */ jsxs4("div", { className: "flex flex-1 flex-col overflow-hidden", children: [
281
+ /* @__PURE__ */ jsx6("div", { className: cn("border-b border-base-200", fullBleedTabBar && "-mx-6 px-6"), children: /* @__PURE__ */ jsx6("div", { className: "flex", role: "tablist", children: tabs.map((tab) => /* @__PURE__ */ jsx6(
303
282
  "button",
304
283
  {
305
284
  type: "button",
@@ -314,12 +293,12 @@ function Tabs({ tabs, defaultTabId, activeTabId, onTabChange, fullBleedTabBar })
314
293
  },
315
294
  tab.id
316
295
  )) }) }),
317
- /* @__PURE__ */ jsx7("div", { role: "tabpanel", className: cn("flex min-h-0 flex-1 flex-col px-px", fullBleedTabBar && "pt-4"), children: activeTab?.content })
296
+ /* @__PURE__ */ jsx6("div", { role: "tabpanel", className: cn("flex min-h-0 flex-1 flex-col px-px", fullBleedTabBar && "pt-4"), children: activeTab?.content })
318
297
  ] });
319
298
  }
320
299
 
321
300
  // src/components/editor/SettingsForm.tsx
322
- import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
301
+ import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
323
302
  function resolveValues(schema, values) {
324
303
  const resolved = {};
325
304
  for (const [key, field] of Object.entries(schema)) {
@@ -359,9 +338,9 @@ function RangeField({
359
338
  onChange
360
339
  }) {
361
340
  const id = useId();
362
- return /* @__PURE__ */ jsxs6("div", { children: [
363
- /* @__PURE__ */ jsx8(FormLabel, { htmlFor: id, children: field.label }),
364
- /* @__PURE__ */ jsx8(
341
+ return /* @__PURE__ */ jsxs5("div", { children: [
342
+ /* @__PURE__ */ jsx7(FormLabel, { htmlFor: id, children: field.label }),
343
+ /* @__PURE__ */ jsx7(
365
344
  "input",
366
345
  {
367
346
  id,
@@ -381,7 +360,7 @@ function RangeField({
381
360
  function renderField(key, field, value, handleFieldChange) {
382
361
  switch (field.type) {
383
362
  case "text":
384
- return /* @__PURE__ */ jsx8(
363
+ return /* @__PURE__ */ jsx7(
385
364
  Input,
386
365
  {
387
366
  label: field.label,
@@ -392,7 +371,7 @@ function renderField(key, field, value, handleFieldChange) {
392
371
  key
393
372
  );
394
373
  case "number":
395
- return /* @__PURE__ */ jsx8(
374
+ return /* @__PURE__ */ jsx7(
396
375
  Input,
397
376
  {
398
377
  label: field.label,
@@ -403,7 +382,7 @@ function renderField(key, field, value, handleFieldChange) {
403
382
  key
404
383
  );
405
384
  case "checkbox":
406
- return /* @__PURE__ */ jsx8(
385
+ return /* @__PURE__ */ jsx7(
407
386
  Checkbox,
408
387
  {
409
388
  label: field.label,
@@ -413,7 +392,7 @@ function renderField(key, field, value, handleFieldChange) {
413
392
  key
414
393
  );
415
394
  case "select":
416
- return /* @__PURE__ */ jsx8(
395
+ return /* @__PURE__ */ jsx7(
417
396
  Select,
418
397
  {
419
398
  label: field.label,
@@ -424,7 +403,7 @@ function renderField(key, field, value, handleFieldChange) {
424
403
  key
425
404
  );
426
405
  case "range":
427
- return /* @__PURE__ */ jsx8(
406
+ return /* @__PURE__ */ jsx7(
428
407
  RangeField,
429
408
  {
430
409
  field,
@@ -434,7 +413,7 @@ function renderField(key, field, value, handleFieldChange) {
434
413
  key
435
414
  );
436
415
  case "link":
437
- return /* @__PURE__ */ jsx8(
416
+ return /* @__PURE__ */ jsx7(
438
417
  LinkField,
439
418
  {
440
419
  label: field.label,
@@ -444,7 +423,7 @@ function renderField(key, field, value, handleFieldChange) {
444
423
  key
445
424
  );
446
425
  case "video-source":
447
- return /* @__PURE__ */ jsx8(
426
+ return /* @__PURE__ */ jsx7(
448
427
  VideoSourceField,
449
428
  {
450
429
  value,
@@ -453,7 +432,7 @@ function renderField(key, field, value, handleFieldChange) {
453
432
  key
454
433
  );
455
434
  case "document-source":
456
- return /* @__PURE__ */ jsx8(
435
+ return /* @__PURE__ */ jsx7(
457
436
  DocumentSourceField,
458
437
  {
459
438
  value,
@@ -478,181 +457,14 @@ function SettingsForm({ schema, values, onChange, tabs }) {
478
457
  const otherKeys = Object.keys(schema).filter((key) => !listed.has(key));
479
458
  const panel = "flex min-h-0 flex-1 flex-col gap-4 overflow-y-auto px-px";
480
459
  const tabItems = [
481
- ...tabs.map((t) => ({ id: t.label, label: t.label, content: /* @__PURE__ */ jsx8("div", { className: panel, children: fields(t.fields) }) })),
482
- ...otherKeys.length > 0 ? [{ id: "__other__", label: "Other", content: /* @__PURE__ */ jsx8("div", { className: panel, children: fields(otherKeys) }) }] : []
460
+ ...tabs.map((t) => ({ id: t.label, label: t.label, content: /* @__PURE__ */ jsx7("div", { className: panel, children: fields(t.fields) }) })),
461
+ ...otherKeys.length > 0 ? [{ id: "__other__", label: "Other", content: /* @__PURE__ */ jsx7("div", { className: panel, children: fields(otherKeys) }) }] : []
483
462
  ];
484
- return /* @__PURE__ */ jsx8(Tabs, { tabs: tabItems, fullBleedTabBar: true });
463
+ return /* @__PURE__ */ jsx7(Tabs, { tabs: tabItems, fullBleedTabBar: true });
485
464
  }
486
- return /* @__PURE__ */ jsx8("div", { className: "flex flex-col gap-4", children: Object.entries(schema).map(([key, field]) => renderField(key, field, local[key], handleFieldChange)) });
465
+ return /* @__PURE__ */ jsx7("div", { className: "flex flex-col gap-4", children: Object.entries(schema).map(([key, field]) => renderField(key, field, local[key], handleFieldChange)) });
487
466
  }
488
467
 
489
- // src/components/shared/Popover.tsx
490
- import { useEffect as useEffect2, useLayoutEffect, useRef, useState as useState4 } from "react";
491
- import { createPortal } from "react-dom";
492
-
493
- // src/hooks/useFocusTrap.ts
494
- import { useEffect } from "react";
495
- var FOCUSABLE_SELECTOR = [
496
- "a[href]",
497
- "button:not([disabled])",
498
- "input:not([disabled])",
499
- "select:not([disabled])",
500
- "textarea:not([disabled])",
501
- '[tabindex]:not([tabindex="-1"])'
502
- ].join(", ");
503
- function useInitialFocus(ref, active) {
504
- useEffect(() => {
505
- if (!active || !ref.current) return;
506
- const previouslyFocused = document.activeElement;
507
- ref.current.querySelector(FOCUSABLE_SELECTOR)?.focus();
508
- return () => {
509
- if (previouslyFocused && document.body.contains(previouslyFocused)) {
510
- previouslyFocused.focus();
511
- }
512
- };
513
- }, [active, ref]);
514
- }
515
-
516
- // src/components/shared/Popover.tsx
517
- import { jsx as jsx9 } from "react/jsx-runtime";
518
- function Popover({
519
- isOpen,
520
- onClose,
521
- anchorRef,
522
- children,
523
- align = "auto",
524
- className,
525
- portal = false,
526
- placement = "bottom"
527
- }) {
528
- const panelRef = useRef(null);
529
- const [resolvedAlign, setResolvedAlign] = useState4("start");
530
- const [fixedPos, setFixedPos] = useState4(null);
531
- useInitialFocus(panelRef, isOpen && (!portal || fixedPos !== null));
532
- useLayoutEffect(() => {
533
- if (!portal) return;
534
- if (!isOpen) {
535
- setFixedPos(null);
536
- return;
537
- }
538
- const anchor = anchorRef.current;
539
- if (!anchor) return;
540
- const update = () => {
541
- const r = anchor.getBoundingClientRect();
542
- const next = placement === "top" ? { left: r.left, bottom: window.innerHeight - r.top + 4 } : { left: r.left, top: r.bottom + 4 };
543
- setFixedPos(
544
- (prev) => prev && prev.left === next.left && prev.top === next.top && prev.bottom === next.bottom ? prev : next
545
- );
546
- };
547
- update();
548
- window.addEventListener("resize", update);
549
- window.addEventListener("scroll", update, true);
550
- return () => {
551
- window.removeEventListener("resize", update);
552
- window.removeEventListener("scroll", update, true);
553
- };
554
- }, [isOpen, portal, placement, anchorRef]);
555
- useLayoutEffect(() => {
556
- if (portal) return;
557
- if (!isOpen || align !== "auto") {
558
- if (!isOpen) setResolvedAlign("start");
559
- return;
560
- }
561
- const panel = panelRef.current;
562
- if (!panel) return;
563
- panel.style.left = "0";
564
- panel.style.right = "auto";
565
- const rect = panel.getBoundingClientRect();
566
- if (rect.right > window.innerWidth) {
567
- setResolvedAlign("end");
568
- } else {
569
- setResolvedAlign("start");
570
- }
571
- panel.style.left = "";
572
- panel.style.right = "";
573
- }, [isOpen, align]);
574
- useEffect2(() => {
575
- if (!isOpen) return;
576
- function onKeyDown(e) {
577
- if (e.key !== "Escape") return;
578
- if (document.querySelector("[data-modal-layer]")) return;
579
- onClose();
580
- }
581
- function onMouseDown(e) {
582
- const target = e.target;
583
- if (panelRef.current?.contains(target)) return;
584
- if (anchorRef.current?.contains(target)) return;
585
- if (target instanceof Element && target.closest("[data-modal-layer]")) return;
586
- onClose();
587
- }
588
- document.addEventListener("keydown", onKeyDown);
589
- document.addEventListener("mousedown", onMouseDown);
590
- return () => {
591
- document.removeEventListener("keydown", onKeyDown);
592
- document.removeEventListener("mousedown", onMouseDown);
593
- };
594
- }, [isOpen, onClose, anchorRef]);
595
- if (!isOpen) return null;
596
- const effectiveAlign = align === "auto" ? resolvedAlign : align;
597
- if (portal) {
598
- if (!fixedPos) return null;
599
- return createPortal(
600
- /* @__PURE__ */ jsx9(
601
- "div",
602
- {
603
- ref: panelRef,
604
- role: "dialog",
605
- "aria-modal": "false",
606
- style: {
607
- position: "fixed",
608
- left: `${fixedPos.left}px`,
609
- ...fixedPos.top !== void 0 ? { top: `${fixedPos.top}px` } : {},
610
- ...fixedPos.bottom !== void 0 ? { bottom: `${fixedPos.bottom}px` } : {}
611
- },
612
- className: cn("z-50 rounded-md border border-base-200 bg-base shadow-lg", className),
613
- children
614
- }
615
- ),
616
- document.body
617
- );
618
- }
619
- return /* @__PURE__ */ jsx9(
620
- "div",
621
- {
622
- ref: panelRef,
623
- role: "dialog",
624
- "aria-modal": "false",
625
- className: cn(
626
- "absolute top-full z-50 mt-1 rounded-md border border-base-200 bg-base shadow-lg",
627
- effectiveAlign === "end" ? "right-0" : "left-0",
628
- className
629
- ),
630
- children
631
- }
632
- );
633
- }
634
-
635
- // src/components/shared/PopoverItem.tsx
636
- import { forwardRef as forwardRef2 } from "react";
637
- import { jsx as jsx10 } from "react/jsx-runtime";
638
- var PopoverItem = forwardRef2(
639
- function PopoverItem2({ className, children, ...rest }, ref) {
640
- return /* @__PURE__ */ jsx10(
641
- "button",
642
- {
643
- ref,
644
- type: "button",
645
- className: cn(
646
- "flex w-full cursor-pointer items-center gap-3 px-3 py-1.5 text-left text-xs hover:bg-base-accent",
647
- className
648
- ),
649
- ...rest,
650
- children
651
- }
652
- );
653
- }
654
- );
655
-
656
468
  // src/lib/block-dnd.ts
657
469
  var ROOT_CONTAINER_ID = "__root__";
658
470
  function buildBlockDragData(args) {
@@ -671,13 +483,9 @@ function canDropBlock(source, dropContainerId) {
671
483
  }
672
484
 
673
485
  export {
674
- Tooltip,
675
- Kbd,
676
486
  DragHandle2 as DragHandle,
677
487
  DeleteButton,
678
488
  SettingsButton,
679
- Popover,
680
- PopoverItem,
681
489
  SettingsForm,
682
490
  buildBlockDragData,
683
491
  buildBlockDropData,
@@ -74,7 +74,7 @@ var SectionMetaSchema = z2.object({
74
74
  status: StatusSchema,
75
75
  access: z2.array(z2.string())
76
76
  });
77
- var RESERVED_SLUGS = ["edit", "api", "login", "set-password", "404", "present", "print", "audiences"];
77
+ var RESERVED_SLUGS = ["edit", "api", "login", "set-password", "404", "present", "print", "audiences", "decks"];
78
78
  var PARSE_REJECTED_SLUGS = ["edit", "api", "login", "set-password", "404"];
79
79
  var PageStatusSchema = z2.enum(["live", "archived"]);
80
80
  var PageSchema = z2.object({
@@ -232,6 +232,15 @@ var ChatbotConfigSchema = z2.object({
232
232
  seen.add(t.id);
233
233
  }
234
234
  });
235
+ var DeckBuilderConfigSchema = z2.object({
236
+ // Audience names whose members may CREATE decks — a Deck Creator. Strict
237
+ // opt-in exactly like chatbot.audiences: [] = no viewer may build a deck.
238
+ // Editors are super-admins over decks and are never gated by this list.
239
+ // Gates: [...slug].astro's FAB, /decks, and POST /api/decks (canCreateDeck).
240
+ audiences: z2.array(z2.string()).default([]).describe(
241
+ "Audience names allowed to create decks in the Deck Builder. Strict opt-in \u2014 an empty list means no viewer can. Editors always can."
242
+ )
243
+ });
235
244
  var SiteConfigSchema = z2.object({
236
245
  siteName: z2.string().default("Brand Portal"),
237
246
  primaryColor: HexColorSchema.default("#009ca6"),
@@ -263,7 +272,10 @@ var SiteConfigSchema = z2.object({
263
272
  light: z2.object({ imageId: z2.string() }),
264
273
  dark: z2.object({ imageId: z2.string() }).nullable().default(null),
265
274
  invertInDark: z2.boolean().default(false),
266
- showInNav: z2.boolean().default(true)
275
+ showInNav: z2.boolean().default(true),
276
+ // A nav logo stands in for the site name by default; the toggle is for
277
+ // wordmark-less logos that still need the name spelled out.
278
+ hideTitle: z2.boolean().default(true)
267
279
  }).nullable().default(null),
268
280
  media: MediaConfigSchema.default(MediaConfigSchema.parse({})),
269
281
  // Composed social-preview raster, stored as a media-library reference so it
@@ -286,7 +298,10 @@ var SiteConfigSchema = z2.object({
286
298
  // Brand chatbot config (editor-owned; the platform kill switch lives in the
287
299
  // sites table, not here). Every field defaults so pre-existing
288
300
  // site-config.json files keep parsing.
289
- chatbot: ChatbotConfigSchema.default({ enabled: false, name: "Portal Assistant", audienceNames: {}, thinkingPhrases: [], systemPrompt: "", audiences: [], tasks: [], audiencePrompts: {} })
301
+ chatbot: ChatbotConfigSchema.default({ enabled: false, name: "Portal Assistant", audienceNames: {}, thinkingPhrases: [], systemPrompt: "", audiences: [], tasks: [], audiencePrompts: {} }),
302
+ // Deck Builder config (editor-owned). Defaults so pre-existing
303
+ // site-config.json files keep parsing — and the default is closed.
304
+ deckBuilder: DeckBuilderConfigSchema.default({ audiences: [] })
290
305
  });
291
306
 
292
307
  export {
@@ -305,5 +320,6 @@ export {
305
320
  normalizeSiteIndex,
306
321
  ChatbotTaskSchema,
307
322
  ChatbotConfigSchema,
323
+ DeckBuilderConfigSchema,
308
324
  SiteConfigSchema
309
325
  };
@@ -1,16 +1,20 @@
1
1
  import {
2
2
  EditablePlainText
3
- } from "./chunk-3GAG6ZXB.js";
3
+ } from "./chunk-DS4GCYV2.js";
4
4
  import {
5
- Button,
6
5
  usePages
7
- } from "./chunk-OUYB2GCW.js";
6
+ } from "./chunk-K7DYZXVU.js";
7
+ import {
8
+ Button
9
+ } from "./chunk-WUJ3XNFI.js";
10
+ import {
11
+ toSectionId
12
+ } from "./chunk-DNY72JZN.js";
8
13
  import {
9
14
  ensureSanitizer,
10
15
  isSanitizerReady,
11
- sanitizeHtml,
12
- toSectionId
13
- } from "./chunk-RA5IOFPY.js";
16
+ sanitizeHtml
17
+ } from "./chunk-QQ3S3P5P.js";
14
18
  import {
15
19
  cn
16
20
  } from "./chunk-7EOSDFS3.js";