@drawnagency/primitives 0.1.108 → 0.1.110

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 (216) hide show
  1. package/dist/auth/cookies.d.ts +8 -0
  2. package/dist/auth/cookies.d.ts.map +1 -1
  3. package/dist/auth/index.d.ts +1 -1
  4. package/dist/auth/index.d.ts.map +1 -1
  5. package/dist/auth/index.js +3 -1
  6. package/dist/auth/types.d.ts +11 -4
  7. package/dist/auth/types.d.ts.map +1 -1
  8. package/dist/{chunk-5IZ2KTMU.js → chunk-3GAG6ZXB.js} +55 -46
  9. package/dist/{chunk-PZJL2S3Z.js → chunk-3ZRQ4G5F.js} +1 -1
  10. package/dist/{chunk-FM4M4Q2W.js → chunk-4TZJZU2T.js} +23 -3
  11. package/dist/{chunk-LUAI5DWR.js → chunk-7MI3HCOF.js} +60 -23
  12. package/dist/{chunk-ZHHJVKU7.js → chunk-7WQJ57XG.js} +63 -204
  13. package/dist/{chunk-JIQBLG6Y.js → chunk-ALMEC3XN.js} +12 -13
  14. package/dist/{chunk-TZQPOR5A.js → chunk-DMCGN5AS.js} +10 -3
  15. package/dist/{chunk-D6TLUVOP.js → chunk-ELQ4C677.js} +48 -2
  16. package/dist/chunk-F2LYQPXV.js +77 -0
  17. package/dist/{chunk-5BM2Y3NJ.js → chunk-FRVO75DK.js} +14 -2
  18. package/dist/{chunk-VKAGMEKE.js → chunk-FTPETWXE.js} +1 -0
  19. package/dist/{chunk-3TO4RRHY.js → chunk-GPPVYLEI.js} +7 -0
  20. package/dist/{chunk-NLQ5F3RQ.js → chunk-HBULBDGP.js} +1 -1
  21. package/dist/{chunk-IPKZ5FU6.js → chunk-NXGIHSL5.js} +72 -55
  22. package/dist/{chunk-CPTFFLK2.js → chunk-OTDA6KWL.js} +10 -3
  23. package/dist/chunk-OUYB2GCW.js +194 -0
  24. package/dist/{chunk-72CG6AA2.js → chunk-RA5IOFPY.js} +10 -2
  25. package/dist/{chunk-GEENI3OC.js → chunk-SW6PCQQD.js} +4 -0
  26. package/dist/{chunk-BOZUEKWL.js → chunk-UVIYI4J6.js} +1 -1
  27. package/dist/{chunk-AB3XVXI3.js → chunk-VCCNKTFD.js} +37 -29
  28. package/dist/{chunk-XBYJQ5RS.js → chunk-XQMDWXD6.js} +21 -6
  29. package/dist/collab/rebase.d.ts +6 -0
  30. package/dist/collab/rebase.d.ts.map +1 -1
  31. package/dist/collab/rebase.js +12 -3
  32. package/dist/collab/recovery.d.ts +0 -20
  33. package/dist/collab/recovery.d.ts.map +1 -1
  34. package/dist/components/brandguide/ColorSwatchSettings.d.ts.map +1 -1
  35. package/dist/components/brandguide/ColorsView.d.ts.map +1 -1
  36. package/dist/components/brandguide/colors-shared.d.ts +10 -1
  37. package/dist/components/brandguide/colors-shared.d.ts.map +1 -1
  38. package/dist/components/chat/ChatPanel.d.ts.map +1 -1
  39. package/dist/components/docfile/DocFilePane.d.ts.map +1 -1
  40. package/dist/components/docfile/PdfCanvasViewer.d.ts.map +1 -1
  41. package/dist/components/docfile/doc-file-state.d.ts.map +1 -1
  42. package/dist/components/editor/IndicatorPill.d.ts.map +1 -1
  43. package/dist/components/editor/NavGroupRow.d.ts +7 -2
  44. package/dist/components/editor/NavGroupRow.d.ts.map +1 -1
  45. package/dist/components/editor/PagesModal.d.ts.map +1 -1
  46. package/dist/components/editor/index.js +14 -13
  47. package/dist/components/primitives/EditableRichText.d.ts.map +1 -1
  48. package/dist/components/primitives/LinkPopover.d.ts.map +1 -1
  49. package/dist/components/primitives/index.d.ts +2 -0
  50. package/dist/components/primitives/index.d.ts.map +1 -1
  51. package/dist/components/primitives/index.js +22 -13
  52. package/dist/components/primitives/useEditableCollection.d.ts.map +1 -1
  53. package/dist/components/primitives/useEditablePlainText.d.ts.map +1 -1
  54. package/dist/components/sections/IconList/index.d.ts.map +1 -1
  55. package/dist/components/sections/Prose/Prose.d.ts.map +1 -1
  56. package/dist/components/sections/brand-guide.js +10 -10
  57. package/dist/components/sections/register-schemas.js +16 -16
  58. package/dist/components/sections/register.js +16 -16
  59. package/dist/components/shared/FontPicker.d.ts.map +1 -1
  60. package/dist/components/shared/HistoryChangesModal.d.ts.map +1 -1
  61. package/dist/components/shared/HistoryPopover.d.ts.map +1 -1
  62. package/dist/components/shared/Navigation.d.ts.map +1 -1
  63. package/dist/components/shared/Popover.d.ts.map +1 -1
  64. package/dist/components/shell/AudienceAddForm.d.ts +1 -5
  65. package/dist/components/shell/AudienceAddForm.d.ts.map +1 -1
  66. package/dist/components/shell/AudienceRow.d.ts +2 -3
  67. package/dist/components/shell/AudienceRow.d.ts.map +1 -1
  68. package/dist/components/shell/BugReportFAB.d.ts.map +1 -1
  69. package/dist/components/shell/EditorShell.d.ts.map +1 -1
  70. package/dist/components/shell/MediaLibraryModal.d.ts.map +1 -1
  71. package/dist/components/shell/SiteSettingsUsers.d.ts.map +1 -1
  72. package/dist/components/shell/SiteSettingsViewerAccess.d.ts.map +1 -1
  73. package/dist/components/shell/view-branch.d.ts.map +1 -1
  74. package/dist/document/components/DocRail.d.ts.map +1 -1
  75. package/dist/document/components/DocViewer.d.ts.map +1 -1
  76. package/dist/document/components/measure.d.ts.map +1 -1
  77. package/dist/document/components/useDocPages.d.ts.map +1 -1
  78. package/dist/document/engine/blocks.d.ts.map +1 -1
  79. package/dist/document/engine/masonry.d.ts.map +1 -1
  80. package/dist/document/engine/paginate.d.ts.map +1 -1
  81. package/dist/document/engine/settings.d.ts +3 -0
  82. package/dist/document/engine/settings.d.ts.map +1 -1
  83. package/dist/document/index.js +79 -28
  84. package/dist/hooks/useBuildStatus.d.ts.map +1 -1
  85. package/dist/hooks/useDocumentUploads.d.ts +1 -0
  86. package/dist/hooks/useDocumentUploads.d.ts.map +1 -1
  87. package/dist/hooks/useEditorPersistence.d.ts.map +1 -1
  88. package/dist/hooks/useEditorPublish.d.ts.map +1 -1
  89. package/dist/hooks/useFocusTrap.d.ts +6 -0
  90. package/dist/hooks/useFocusTrap.d.ts.map +1 -1
  91. package/dist/hooks/useMediaPipeline.d.ts +3 -2
  92. package/dist/hooks/useMediaPipeline.d.ts.map +1 -1
  93. package/dist/hooks/useSanitizedHtml.d.ts +12 -0
  94. package/dist/hooks/useSanitizedHtml.d.ts.map +1 -0
  95. package/dist/index.js +20 -14
  96. package/dist/lib/block-move.d.ts.map +1 -1
  97. package/dist/lib/contrast.d.ts.map +1 -1
  98. package/dist/lib/dexie.d.ts +2 -8
  99. package/dist/lib/dexie.d.ts.map +1 -1
  100. package/dist/lib/dexie.js +21 -49
  101. package/dist/lib/index-ops.d.ts.map +1 -1
  102. package/dist/lib/index-ops.js +43 -23
  103. package/dist/lib/index.js +8 -8
  104. package/dist/lib/loader.d.ts.map +1 -1
  105. package/dist/lib/media-folders.d.ts +12 -4
  106. package/dist/lib/media-folders.d.ts.map +1 -1
  107. package/dist/lib/media-folders.js +12 -2
  108. package/dist/lib/migrate-sections-transform.js +1 -1
  109. package/dist/lib/nav-tree.d.ts.map +1 -1
  110. package/dist/lib/nav.d.ts.map +1 -1
  111. package/dist/lib/pages.d.ts.map +1 -1
  112. package/dist/lib/registry.d.ts.map +1 -1
  113. package/dist/lib/registry.js +1 -1
  114. package/dist/lib/sanitize.d.ts +6 -0
  115. package/dist/lib/sanitize.d.ts.map +1 -1
  116. package/dist/lib/timestamp.d.ts.map +1 -1
  117. package/dist/media/index.js +4 -4
  118. package/dist/media/queue.d.ts.map +1 -1
  119. package/dist/media/resolve.d.ts.map +1 -1
  120. package/dist/media/utils.d.ts.map +1 -1
  121. package/dist/media/videoPoster.d.ts.map +1 -1
  122. package/dist/schemas/audience.d.ts +5 -1
  123. package/dist/schemas/audience.d.ts.map +1 -1
  124. package/dist/schemas/audience.js +1 -1
  125. package/dist/schemas/index.js +9 -7
  126. package/dist/schemas/link.d.ts.map +1 -1
  127. package/dist/schemas/link.js +1 -1
  128. package/dist/schemas/sections.d.ts +12 -0
  129. package/dist/schemas/sections.d.ts.map +1 -1
  130. package/dist/storage/index.d.ts +1 -1
  131. package/dist/storage/index.d.ts.map +1 -1
  132. package/dist/storage/index.js +3 -1
  133. package/dist/storage/types.d.ts +9 -0
  134. package/dist/storage/types.d.ts.map +1 -1
  135. package/dist/types/database.d.ts +0 -3
  136. package/dist/types/database.d.ts.map +1 -1
  137. package/package.json +1 -1
  138. package/src/auth/cookies.ts +11 -0
  139. package/src/auth/index.ts +1 -1
  140. package/src/auth/types.ts +18 -4
  141. package/src/collab/rebase.ts +26 -1
  142. package/src/collab/recovery.ts +29 -3
  143. package/src/components/brandguide/ColorSwatchSettings.tsx +40 -13
  144. package/src/components/brandguide/ColorsEditable.tsx +7 -9
  145. package/src/components/brandguide/ColorsView.tsx +12 -11
  146. package/src/components/brandguide/colors-shared.ts +17 -1
  147. package/src/components/chat/ChatPanel.tsx +19 -0
  148. package/src/components/docfile/DocFilePane.tsx +11 -0
  149. package/src/components/docfile/PdfCanvasViewer.tsx +46 -5
  150. package/src/components/docfile/doc-file-state.ts +7 -0
  151. package/src/components/editor/IndicatorPill.tsx +5 -1
  152. package/src/components/editor/NavGroupRow.tsx +8 -3
  153. package/src/components/editor/PagesModal.tsx +10 -2
  154. package/src/components/primitives/EditableList.tsx +10 -2
  155. package/src/components/primitives/EditableRichText.tsx +4 -3
  156. package/src/components/primitives/LinkPopover.tsx +23 -1
  157. package/src/components/primitives/index.ts +5 -0
  158. package/src/components/primitives/useEditableCollection.ts +61 -41
  159. package/src/components/primitives/useEditablePlainText.ts +24 -3
  160. package/src/components/sections/IconList/index.tsx +8 -1
  161. package/src/components/sections/Prose/Prose.tsx +4 -2
  162. package/src/components/shared/FontPicker.tsx +16 -4
  163. package/src/components/shared/HistoryChangesModal.tsx +12 -1
  164. package/src/components/shared/HistoryPopover.tsx +18 -4
  165. package/src/components/shared/LinkField.tsx +1 -1
  166. package/src/components/shared/Navigation.tsx +20 -2
  167. package/src/components/shared/Popover.tsx +9 -5
  168. package/src/components/shell/AudienceAddForm.tsx +6 -26
  169. package/src/components/shell/AudienceRow.tsx +29 -39
  170. package/src/components/shell/BugReportFAB.tsx +20 -2
  171. package/src/components/shell/EditorShell.tsx +200 -50
  172. package/src/components/shell/MediaLibraryModal.tsx +52 -10
  173. package/src/components/shell/SiteSettingsUsers.tsx +3 -0
  174. package/src/components/shell/SiteSettingsViewerAccess.tsx +21 -16
  175. package/src/components/shell/view-branch.ts +4 -1
  176. package/src/document/components/DocRail.tsx +27 -2
  177. package/src/document/components/DocViewer.tsx +5 -1
  178. package/src/document/components/measure.tsx +22 -6
  179. package/src/document/components/useDocPages.ts +13 -3
  180. package/src/document/engine/blocks.ts +33 -4
  181. package/src/document/engine/masonry.ts +8 -2
  182. package/src/document/engine/paginate.ts +4 -1
  183. package/src/document/engine/settings.ts +40 -3
  184. package/src/hooks/useBuildStatus.ts +6 -0
  185. package/src/hooks/useDocumentUploads.ts +46 -3
  186. package/src/hooks/useEditorPersistence.ts +33 -19
  187. package/src/hooks/useEditorPublish.ts +83 -34
  188. package/src/hooks/useFocusTrap.ts +18 -0
  189. package/src/hooks/useMediaPipeline.ts +111 -38
  190. package/src/hooks/useSanitizedHtml.ts +29 -0
  191. package/src/lib/audience-secret.ts +1 -0
  192. package/src/lib/block-move.ts +13 -2
  193. package/src/lib/contrast.ts +14 -14
  194. package/src/lib/dexie.ts +46 -49
  195. package/src/lib/index-ops.ts +63 -20
  196. package/src/lib/loader.ts +41 -12
  197. package/src/lib/media-folders.ts +31 -5
  198. package/src/lib/migrate-sections-transform.ts +22 -2
  199. package/src/lib/nav-tree.ts +16 -2
  200. package/src/lib/nav.ts +10 -1
  201. package/src/lib/pages.ts +24 -6
  202. package/src/lib/registry.ts +3 -0
  203. package/src/lib/sanitize.ts +9 -0
  204. package/src/lib/timestamp.ts +5 -0
  205. package/src/media/queue.ts +4 -0
  206. package/src/media/resolve.ts +14 -1
  207. package/src/media/utils.ts +3 -1
  208. package/src/media/videoPoster.ts +14 -3
  209. package/src/schemas/audience.ts +10 -2
  210. package/src/schemas/link.ts +4 -1
  211. package/src/schemas/sections.ts +23 -1
  212. package/src/storage/index.ts +1 -1
  213. package/src/storage/types.ts +13 -0
  214. package/src/types/database.ts +0 -3
  215. package/dist/chunk-5THS4K5D.js +0 -123
  216. package/dist/chunk-ZSPCE6MZ.js +0 -70
@@ -1,23 +1,24 @@
1
1
  import {
2
- Checkbox,
3
- FormLabel,
4
- Input
5
- } from "./chunk-5THS4K5D.js";
2
+ Checkbox
3
+ } from "./chunk-F2LYQPXV.js";
6
4
  import {
7
5
  Button,
8
- usePages
9
- } from "./chunk-ZSPCE6MZ.js";
6
+ LinkField,
7
+ Select
8
+ } from "./chunk-OUYB2GCW.js";
10
9
  import {
11
10
  DeleteIcon,
12
11
  DragHandle,
12
+ FormLabel,
13
13
  IconButton,
14
+ Input,
14
15
  SettingsIcon,
15
16
  useMediaLibrary,
16
17
  useResolvedMedia
17
- } from "./chunk-D6TLUVOP.js";
18
+ } from "./chunk-ELQ4C677.js";
18
19
  import {
19
20
  formatFileSize
20
- } from "./chunk-XBYJQ5RS.js";
21
+ } from "./chunk-XQMDWXD6.js";
21
22
  import {
22
23
  cn
23
24
  } from "./chunk-7EOSDFS3.js";
@@ -100,128 +101,11 @@ function SettingsButton({ onClick }) {
100
101
  }
101
102
 
102
103
  // src/components/editor/SettingsForm.tsx
103
- import { useId as useId2, useState as useState3 } from "react";
104
-
105
- // src/components/shared/Select.tsx
106
- import { useId } from "react";
107
- import { ChevronDown } from "lucide-react";
108
- import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
109
- function Select({
110
- label,
111
- value,
112
- onChange,
113
- options,
114
- disabled,
115
- className,
116
- selectClassName
117
- }) {
118
- const id = useId();
119
- return /* @__PURE__ */ jsxs3("div", { className, children: [
120
- label && /* @__PURE__ */ jsx5(FormLabel, { htmlFor: id, children: label }),
121
- /* @__PURE__ */ jsxs3("div", { className: "relative", children: [
122
- /* @__PURE__ */ jsx5(
123
- "select",
124
- {
125
- id,
126
- value,
127
- onChange: (e) => onChange(e.target.value),
128
- disabled,
129
- className: cn(
130
- "w-full appearance-none rounded border border-base-200 bg-base py-2 pr-8 pl-3 text-sm text-base-contrast",
131
- "focus:border-base-contrast focus:outline-none focus:ring-1 focus:ring-base-contrast",
132
- disabled && "cursor-not-allowed opacity-50",
133
- selectClassName
134
- ),
135
- children: options.map((opt) => /* @__PURE__ */ jsx5("option", { value: opt.value, children: opt.label }, opt.value))
136
- }
137
- ),
138
- /* @__PURE__ */ jsx5(
139
- ChevronDown,
140
- {
141
- size: 14,
142
- className: "pointer-events-none absolute right-2.5 top-1/2 -translate-y-1/2 text-base-contrast-light"
143
- }
144
- )
145
- ] })
146
- ] });
147
- }
148
-
149
- // src/components/shared/LinkField.tsx
150
- import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
151
- var TARGET_OPTIONS = [
152
- { label: "Same tab (_self)", value: "_self" },
153
- { label: "New tab (_blank)", value: "_blank" }
154
- ];
155
- function LinkField({ label, value, onChange }) {
156
- const { pages, getPageHeadings } = usePages();
157
- const isInternal = value.kind === "internal";
158
- function setMode(kind) {
159
- if (kind === value.kind) return;
160
- onChange(kind === "external" ? { kind: "external", href: "", target: value.target } : { kind: "internal", pageId: "", anchorSectionId: null, target: "_self" });
161
- }
162
- const pageId = isInternal ? value.pageId : "";
163
- const headings = pageId ? getPageHeadings(pageId) : [];
164
- return /* @__PURE__ */ jsxs4("div", { className: "flex flex-col gap-3", children: [
165
- /* @__PURE__ */ jsx6(FormLabel, { children: label }),
166
- /* @__PURE__ */ jsx6("div", { className: "flex gap-2", role: "tablist", children: ["external", "internal"].map((kind) => /* @__PURE__ */ jsx6(
167
- "button",
168
- {
169
- type: "button",
170
- role: "tab",
171
- "aria-selected": value.kind === kind,
172
- onClick: () => setMode(kind),
173
- className: cn(
174
- "cursor-pointer rounded border px-3 py-1 text-sm capitalize",
175
- value.kind === kind ? "border-primary bg-primary text-primary-contrast" : "border-base-200 text-base-contrast"
176
- ),
177
- children: kind === "external" ? "External URL" : "Internal page"
178
- },
179
- kind
180
- )) }),
181
- value.kind === "external" ? /* @__PURE__ */ jsx6(
182
- Input,
183
- {
184
- label: "URL",
185
- value: value.href,
186
- placeholder: "https://...",
187
- onChange: (href) => onChange({ kind: "external", href, target: value.target })
188
- }
189
- ) : /* @__PURE__ */ jsxs4(Fragment2, { children: [
190
- /* @__PURE__ */ jsx6(
191
- Select,
192
- {
193
- label: "Page",
194
- value: value.pageId,
195
- options: [{ label: "Select a page\u2026", value: "" }, ...pages.map((p) => ({ label: p.title, value: p.id }))],
196
- onChange: (pid) => onChange({ kind: "internal", pageId: pid, anchorSectionId: null, target: value.target })
197
- }
198
- ),
199
- /* @__PURE__ */ jsx6(
200
- Select,
201
- {
202
- label: "Section",
203
- value: value.anchorSectionId ?? "",
204
- disabled: !pageId,
205
- options: [{ label: "None (top of page)", value: "" }, ...headings.map((h) => ({ label: h.label, value: h.id }))],
206
- onChange: (anchor) => onChange({ kind: "internal", pageId, anchorSectionId: anchor || null, target: value.target })
207
- }
208
- )
209
- ] }),
210
- value.kind === "external" && /* @__PURE__ */ jsx6(
211
- Select,
212
- {
213
- label: "Opens in",
214
- value: value.target,
215
- options: TARGET_OPTIONS,
216
- onChange: (t) => onChange({ ...value, target: t })
217
- }
218
- )
219
- ] });
220
- }
104
+ import { useId, useState as useState3 } from "react";
221
105
 
222
106
  // src/components/shared/VideoSourceField.tsx
223
107
  import { useState } from "react";
224
- import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
108
+ import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
225
109
  var ASPECTS = [
226
110
  { label: "9:16", width: 9, height: 16 },
227
111
  { label: "4:5", width: 4, height: 5 },
@@ -270,9 +154,9 @@ function VideoSourceField({ value, onChange }) {
270
154
  setLoading(false);
271
155
  }
272
156
  }
273
- return /* @__PURE__ */ jsxs5("div", { className: "flex flex-col gap-3", children: [
274
- /* @__PURE__ */ jsx7(FormLabel, { children: "Source" }),
275
- /* @__PURE__ */ jsx7("div", { className: "flex gap-2", role: "tablist", children: ["library", "embed"].map((m) => /* @__PURE__ */ jsx7(
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(
276
160
  "button",
277
161
  {
278
162
  type: "button",
@@ -287,9 +171,9 @@ function VideoSourceField({ value, onChange }) {
287
171
  },
288
172
  m
289
173
  )) }),
290
- mode === "library" ? /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-3", children: [
291
- libraryImageId ? resolved.poster ? /* @__PURE__ */ jsx7("img", { src: resolved.poster, alt: "", className: "h-12 w-20 rounded object-cover" }) : /* @__PURE__ */ jsx7("span", { className: "text-sm text-base-contrast-light", children: "Video selected" }) : /* @__PURE__ */ jsx7("span", { className: "text-sm text-base-contrast-light", children: "No video selected" }),
292
- /* @__PURE__ */ jsx7(
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(
293
177
  Button,
294
178
  {
295
179
  type: "button",
@@ -299,9 +183,9 @@ function VideoSourceField({ value, onChange }) {
299
183
  children: "Choose video"
300
184
  }
301
185
  )
302
- ] }) : /* @__PURE__ */ jsxs5("div", { className: "flex flex-col gap-2", children: [
303
- /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2", children: [
304
- /* @__PURE__ */ jsx7(
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(
305
189
  "input",
306
190
  {
307
191
  type: "text",
@@ -321,7 +205,7 @@ function VideoSourceField({ value, onChange }) {
321
205
  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"
322
206
  }
323
207
  ),
324
- /* @__PURE__ */ jsx7(
208
+ /* @__PURE__ */ jsx5(
325
209
  Button,
326
210
  {
327
211
  type: "button",
@@ -333,13 +217,13 @@ function VideoSourceField({ value, onChange }) {
333
217
  }
334
218
  )
335
219
  ] }),
336
- error ? /* @__PURE__ */ jsx7("p", { className: "text-xs text-red-600", children: error }) : null,
337
- !error && fallback ? /* @__PURE__ */ jsx7("p", { className: "text-xs text-base-contrast-light/70", children: "Added \u2014 couldn't fetch exact dimensions, using 16:9." }) : null,
338
- value?.type === "external" && value.provider === "instagram" ? /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2", children: [
339
- /* @__PURE__ */ jsx7("span", { className: "text-xs text-base-contrast-light", children: "Aspect" }),
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" }),
340
224
  ASPECTS.map(({ label, width, height }) => {
341
225
  const active = value.width === width && value.height === height;
342
- return /* @__PURE__ */ jsx7(
226
+ return /* @__PURE__ */ jsx5(
343
227
  "button",
344
228
  {
345
229
  type: "button",
@@ -373,22 +257,22 @@ function useResolvedDocument(documentId) {
373
257
  }
374
258
 
375
259
  // src/components/shared/DocumentSourceField.tsx
376
- import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
260
+ import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
377
261
  function DocumentSourceField({ value, onChange }) {
378
262
  const mediaLibrary = useMediaLibrary();
379
263
  const documentId = value?.documentId || void 0;
380
264
  const { entry, missing } = useResolvedDocument(documentId);
381
- return /* @__PURE__ */ jsxs6("div", { className: "flex flex-col gap-3", children: [
382
- /* @__PURE__ */ jsx8(FormLabel, { children: "Document" }),
383
- /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-3", children: [
384
- entry ? /* @__PURE__ */ jsxs6("span", { className: "min-w-0 flex-1 truncate text-sm text-base-contrast", children: [
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: [
385
269
  entry.filename,
386
- /* @__PURE__ */ jsxs6("span", { className: "text-base-contrast-light", children: [
270
+ /* @__PURE__ */ jsxs4("span", { className: "text-base-contrast-light", children: [
387
271
  " \xB7 ",
388
272
  formatFileSize(entry.size)
389
273
  ] })
390
- ] }) : /* @__PURE__ */ jsx8("span", { className: "flex-1 text-sm text-base-contrast-light", children: missing ? "File missing" : "No document selected" }),
391
- /* @__PURE__ */ jsx8(
274
+ ] }) : /* @__PURE__ */ jsx6("span", { className: "flex-1 text-sm text-base-contrast-light", children: missing ? "File missing" : "No document selected" }),
275
+ /* @__PURE__ */ jsx6(
392
276
  Button,
393
277
  {
394
278
  type: "button",
@@ -404,7 +288,7 @@ function DocumentSourceField({ value, onChange }) {
404
288
 
405
289
  // src/components/shared/Tabs.tsx
406
290
  import { useState as useState2 } from "react";
407
- import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
291
+ import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
408
292
  function Tabs({ tabs, defaultTabId, activeTabId, onTabChange, fullBleedTabBar }) {
409
293
  const [uncontrolledId, setUncontrolledId] = useState2(defaultTabId ?? tabs[0]?.id);
410
294
  const isControlled = activeTabId !== void 0;
@@ -414,8 +298,8 @@ function Tabs({ tabs, defaultTabId, activeTabId, onTabChange, fullBleedTabBar })
414
298
  if (!isControlled) setUncontrolledId(id);
415
299
  onTabChange?.(id);
416
300
  }
417
- return /* @__PURE__ */ jsxs7("div", { className: "flex flex-1 flex-col overflow-hidden", children: [
418
- /* @__PURE__ */ jsx9("div", { className: cn("border-b border-base-200", fullBleedTabBar && "-mx-6 px-6"), children: /* @__PURE__ */ jsx9("div", { className: "flex", role: "tablist", children: tabs.map((tab) => /* @__PURE__ */ jsx9(
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(
419
303
  "button",
420
304
  {
421
305
  type: "button",
@@ -430,12 +314,12 @@ function Tabs({ tabs, defaultTabId, activeTabId, onTabChange, fullBleedTabBar })
430
314
  },
431
315
  tab.id
432
316
  )) }) }),
433
- /* @__PURE__ */ jsx9("div", { role: "tabpanel", className: cn("flex min-h-0 flex-1 flex-col px-px", fullBleedTabBar && "pt-4"), children: activeTab?.content })
317
+ /* @__PURE__ */ jsx7("div", { role: "tabpanel", className: cn("flex min-h-0 flex-1 flex-col px-px", fullBleedTabBar && "pt-4"), children: activeTab?.content })
434
318
  ] });
435
319
  }
436
320
 
437
321
  // src/components/editor/SettingsForm.tsx
438
- import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
322
+ import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
439
323
  function resolveValues(schema, values) {
440
324
  const resolved = {};
441
325
  for (const [key, field] of Object.entries(schema)) {
@@ -474,10 +358,10 @@ function RangeField({
474
358
  value,
475
359
  onChange
476
360
  }) {
477
- const id = useId2();
478
- return /* @__PURE__ */ jsxs8("div", { children: [
479
- /* @__PURE__ */ jsx10(FormLabel, { htmlFor: id, children: field.label }),
480
- /* @__PURE__ */ jsx10(
361
+ const id = useId();
362
+ return /* @__PURE__ */ jsxs6("div", { children: [
363
+ /* @__PURE__ */ jsx8(FormLabel, { htmlFor: id, children: field.label }),
364
+ /* @__PURE__ */ jsx8(
481
365
  "input",
482
366
  {
483
367
  id,
@@ -497,7 +381,7 @@ function RangeField({
497
381
  function renderField(key, field, value, handleFieldChange) {
498
382
  switch (field.type) {
499
383
  case "text":
500
- return /* @__PURE__ */ jsx10(
384
+ return /* @__PURE__ */ jsx8(
501
385
  Input,
502
386
  {
503
387
  label: field.label,
@@ -508,7 +392,7 @@ function renderField(key, field, value, handleFieldChange) {
508
392
  key
509
393
  );
510
394
  case "number":
511
- return /* @__PURE__ */ jsx10(
395
+ return /* @__PURE__ */ jsx8(
512
396
  Input,
513
397
  {
514
398
  label: field.label,
@@ -519,7 +403,7 @@ function renderField(key, field, value, handleFieldChange) {
519
403
  key
520
404
  );
521
405
  case "checkbox":
522
- return /* @__PURE__ */ jsx10(
406
+ return /* @__PURE__ */ jsx8(
523
407
  Checkbox,
524
408
  {
525
409
  label: field.label,
@@ -529,7 +413,7 @@ function renderField(key, field, value, handleFieldChange) {
529
413
  key
530
414
  );
531
415
  case "select":
532
- return /* @__PURE__ */ jsx10(
416
+ return /* @__PURE__ */ jsx8(
533
417
  Select,
534
418
  {
535
419
  label: field.label,
@@ -540,7 +424,7 @@ function renderField(key, field, value, handleFieldChange) {
540
424
  key
541
425
  );
542
426
  case "range":
543
- return /* @__PURE__ */ jsx10(
427
+ return /* @__PURE__ */ jsx8(
544
428
  RangeField,
545
429
  {
546
430
  field,
@@ -550,7 +434,7 @@ function renderField(key, field, value, handleFieldChange) {
550
434
  key
551
435
  );
552
436
  case "link":
553
- return /* @__PURE__ */ jsx10(
437
+ return /* @__PURE__ */ jsx8(
554
438
  LinkField,
555
439
  {
556
440
  label: field.label,
@@ -560,7 +444,7 @@ function renderField(key, field, value, handleFieldChange) {
560
444
  key
561
445
  );
562
446
  case "video-source":
563
- return /* @__PURE__ */ jsx10(
447
+ return /* @__PURE__ */ jsx8(
564
448
  VideoSourceField,
565
449
  {
566
450
  value,
@@ -569,7 +453,7 @@ function renderField(key, field, value, handleFieldChange) {
569
453
  key
570
454
  );
571
455
  case "document-source":
572
- return /* @__PURE__ */ jsx10(
456
+ return /* @__PURE__ */ jsx8(
573
457
  DocumentSourceField,
574
458
  {
575
459
  value,
@@ -594,12 +478,12 @@ function SettingsForm({ schema, values, onChange, tabs }) {
594
478
  const otherKeys = Object.keys(schema).filter((key) => !listed.has(key));
595
479
  const panel = "flex min-h-0 flex-1 flex-col gap-4 overflow-y-auto px-px";
596
480
  const tabItems = [
597
- ...tabs.map((t) => ({ id: t.label, label: t.label, content: /* @__PURE__ */ jsx10("div", { className: panel, children: fields(t.fields) }) })),
598
- ...otherKeys.length > 0 ? [{ id: "__other__", label: "Other", content: /* @__PURE__ */ jsx10("div", { className: panel, children: fields(otherKeys) }) }] : []
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) }) }] : []
599
483
  ];
600
- return /* @__PURE__ */ jsx10(Tabs, { tabs: tabItems, fullBleedTabBar: true });
484
+ return /* @__PURE__ */ jsx8(Tabs, { tabs: tabItems, fullBleedTabBar: true });
601
485
  }
602
- return /* @__PURE__ */ jsx10("div", { className: "flex flex-col gap-4", children: Object.entries(schema).map(([key, field]) => renderField(key, field, local[key], handleFieldChange)) });
486
+ return /* @__PURE__ */ jsx8("div", { className: "flex flex-col gap-4", children: Object.entries(schema).map(([key, field]) => renderField(key, field, local[key], handleFieldChange)) });
603
487
  }
604
488
 
605
489
  // src/components/shared/Popover.tsx
@@ -616,37 +500,12 @@ var FOCUSABLE_SELECTOR = [
616
500
  "textarea:not([disabled])",
617
501
  '[tabindex]:not([tabindex="-1"])'
618
502
  ].join(", ");
619
- function useFocusTrap(ref, active) {
503
+ function useInitialFocus(ref, active) {
620
504
  useEffect(() => {
621
505
  if (!active || !ref.current) return;
622
- const container = ref.current;
623
506
  const previouslyFocused = document.activeElement;
624
- const getFocusable = () => Array.from(container.querySelectorAll(FOCUSABLE_SELECTOR));
625
- const focusable = getFocusable();
626
- if (focusable.length > 0) {
627
- focusable[0].focus();
628
- }
629
- const handleKeyDown = (e) => {
630
- if (e.key !== "Tab") return;
631
- const elements = getFocusable();
632
- if (elements.length === 0) return;
633
- const first = elements[0];
634
- const last = elements[elements.length - 1];
635
- if (e.shiftKey) {
636
- if (document.activeElement === first) {
637
- e.preventDefault();
638
- last.focus();
639
- }
640
- } else {
641
- if (document.activeElement === last) {
642
- e.preventDefault();
643
- first.focus();
644
- }
645
- }
646
- };
647
- container.addEventListener("keydown", handleKeyDown);
507
+ ref.current.querySelector(FOCUSABLE_SELECTOR)?.focus();
648
508
  return () => {
649
- container.removeEventListener("keydown", handleKeyDown);
650
509
  if (previouslyFocused && document.body.contains(previouslyFocused)) {
651
510
  previouslyFocused.focus();
652
511
  }
@@ -655,7 +514,7 @@ function useFocusTrap(ref, active) {
655
514
  }
656
515
 
657
516
  // src/components/shared/Popover.tsx
658
- import { jsx as jsx11 } from "react/jsx-runtime";
517
+ import { jsx as jsx9 } from "react/jsx-runtime";
659
518
  function Popover({
660
519
  isOpen,
661
520
  onClose,
@@ -669,7 +528,7 @@ function Popover({
669
528
  const panelRef = useRef(null);
670
529
  const [resolvedAlign, setResolvedAlign] = useState4("start");
671
530
  const [fixedPos, setFixedPos] = useState4(null);
672
- useFocusTrap(panelRef, isOpen && (!portal || fixedPos !== null));
531
+ useInitialFocus(panelRef, isOpen && (!portal || fixedPos !== null));
673
532
  useLayoutEffect(() => {
674
533
  if (!portal) return;
675
534
  if (!isOpen) {
@@ -738,7 +597,7 @@ function Popover({
738
597
  if (portal) {
739
598
  if (!fixedPos) return null;
740
599
  return createPortal(
741
- /* @__PURE__ */ jsx11(
600
+ /* @__PURE__ */ jsx9(
742
601
  "div",
743
602
  {
744
603
  ref: panelRef,
@@ -757,7 +616,7 @@ function Popover({
757
616
  document.body
758
617
  );
759
618
  }
760
- return /* @__PURE__ */ jsx11(
619
+ return /* @__PURE__ */ jsx9(
761
620
  "div",
762
621
  {
763
622
  ref: panelRef,
@@ -775,10 +634,10 @@ function Popover({
775
634
 
776
635
  // src/components/shared/PopoverItem.tsx
777
636
  import { forwardRef as forwardRef2 } from "react";
778
- import { jsx as jsx12 } from "react/jsx-runtime";
637
+ import { jsx as jsx10 } from "react/jsx-runtime";
779
638
  var PopoverItem = forwardRef2(
780
639
  function PopoverItem2({ className, children, ...rest }, ref) {
781
- return /* @__PURE__ */ jsx12(
640
+ return /* @__PURE__ */ jsx10(
782
641
  "button",
783
642
  {
784
643
  ref,
@@ -9,7 +9,7 @@ import {
9
9
  stripHtmlToPlainText,
10
10
  trimTrailingSpacers,
11
11
  truncate
12
- } from "./chunk-IPKZ5FU6.js";
12
+ } from "./chunk-NXGIHSL5.js";
13
13
  import {
14
14
  DeleteButton,
15
15
  DragHandle,
@@ -23,11 +23,12 @@ import {
23
23
  buildBlockDropData,
24
24
  canDropBlock,
25
25
  isBlockDragData
26
- } from "./chunk-ZHHJVKU7.js";
26
+ } from "./chunk-7WQJ57XG.js";
27
27
  import {
28
28
  EditableRichText,
29
- defineHeadingSection
30
- } from "./chunk-LUAI5DWR.js";
29
+ defineHeadingSection,
30
+ useSanitizedHtml
31
+ } from "./chunk-7MI3HCOF.js";
31
32
  import {
32
33
  EditablePlainText,
33
34
  ImageDropZone,
@@ -37,31 +38,28 @@ import {
37
38
  containerGridClass,
38
39
  masonryColumnsClass,
39
40
  spacerHiddenClass
40
- } from "./chunk-5IZ2KTMU.js";
41
+ } from "./chunk-3GAG6ZXB.js";
41
42
  import {
42
43
  useMediaLibrary,
43
44
  useResolvedMedia
44
- } from "./chunk-D6TLUVOP.js";
45
+ } from "./chunk-ELQ4C677.js";
45
46
  import {
46
47
  embedUrl
47
48
  } from "./chunk-Y4JQGO6G.js";
48
49
  import {
49
50
  DEFAULT_LINK,
50
51
  LinkValueSchema
51
- } from "./chunk-PZJL2S3Z.js";
52
- import {
53
- sanitizeHtml
54
- } from "./chunk-72CG6AA2.js";
52
+ } from "./chunk-3ZRQ4G5F.js";
55
53
  import {
56
54
  cn
57
55
  } from "./chunk-7EOSDFS3.js";
58
56
  import {
59
57
  getSectionSchema
60
- } from "./chunk-TZQPOR5A.js";
58
+ } from "./chunk-DMCGN5AS.js";
61
59
  import {
62
60
  defineSection,
63
61
  getSection
64
- } from "./chunk-VKAGMEKE.js";
62
+ } from "./chunk-FTPETWXE.js";
65
63
  import {
66
64
  SingleMediaReferenceSchema
67
65
  } from "./chunk-GGXZZ77Z.js";
@@ -117,6 +115,7 @@ import { AlignLeft } from "lucide-react";
117
115
  // src/components/sections/Prose/Prose.tsx
118
116
  import { jsx as jsx4 } from "react/jsx-runtime";
119
117
  function Prose({ body, onChange }) {
118
+ const safeHtml = useSanitizedHtml(body);
120
119
  if (onChange) {
121
120
  return /* @__PURE__ */ jsx4("div", { className: "prose-content", children: /* @__PURE__ */ jsx4(
122
121
  EditableRichText,
@@ -133,7 +132,7 @@ function Prose({ body, onChange }) {
133
132
  "div",
134
133
  {
135
134
  className: "prose-content",
136
- dangerouslySetInnerHTML: { __html: sanitizeHtml(body) }
135
+ dangerouslySetInnerHTML: { __html: safeHtml }
137
136
  }
138
137
  );
139
138
  }
@@ -1,6 +1,7 @@
1
1
  import {
2
- getAllSchemas
3
- } from "./chunk-VKAGMEKE.js";
2
+ getAllSchemas,
3
+ getSchema
4
+ } from "./chunk-FTPETWXE.js";
4
5
  import {
5
6
  LayoutEnvelopeSchema
6
7
  } from "./chunk-NSCT3AMV.js";
@@ -17,8 +18,14 @@ function getSectionContentSchema() {
17
18
  function getSectionSchema() {
18
19
  return z.object({ id: z.string(), layout: LayoutEnvelopeSchema.optional() }).and(getSectionContentSchema());
19
20
  }
21
+ function getSectionSchemaForType(type) {
22
+ const schema = getSchema(type);
23
+ if (!schema) return null;
24
+ return z.object({ id: z.string(), layout: LayoutEnvelopeSchema.optional() }).and(schema);
25
+ }
20
26
 
21
27
  export {
22
28
  getSectionContentSchema,
23
- getSectionSchema
29
+ getSectionSchema,
30
+ getSectionSchemaForType
24
31
  };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getMediaProvider
3
- } from "./chunk-XBYJQ5RS.js";
3
+ } from "./chunk-XQMDWXD6.js";
4
4
  import {
5
5
  cn
6
6
  } from "./chunk-7EOSDFS3.js";
@@ -106,6 +106,50 @@ var IconButton = forwardRef(
106
106
  }
107
107
  );
108
108
 
109
+ // src/components/shared/FormLabel.tsx
110
+ import { jsx as jsx3 } from "react/jsx-runtime";
111
+ function FormLabel({ htmlFor, children, className }) {
112
+ return /* @__PURE__ */ jsx3(
113
+ "label",
114
+ {
115
+ htmlFor,
116
+ className: cn("mb-1.5 block text-sm font-medium text-base-contrast", className),
117
+ children
118
+ }
119
+ );
120
+ }
121
+
122
+ // src/components/shared/Input.tsx
123
+ import { forwardRef as forwardRef2, useId } from "react";
124
+ import { jsx as jsx4, jsxs } from "react/jsx-runtime";
125
+ var Input = forwardRef2(function Input2({ label, value, onChange, type = "text", className, disabled, error, ...rest }, ref) {
126
+ const id = useId();
127
+ const errorId = `${id}-error`;
128
+ return /* @__PURE__ */ jsxs("div", { className, children: [
129
+ /* @__PURE__ */ jsx4(FormLabel, { htmlFor: id, children: label }),
130
+ /* @__PURE__ */ jsx4(
131
+ "input",
132
+ {
133
+ ref,
134
+ id,
135
+ type,
136
+ value,
137
+ onChange: (e) => onChange(e.target.value),
138
+ disabled,
139
+ "aria-invalid": error ? true : void 0,
140
+ "aria-describedby": error ? errorId : void 0,
141
+ className: cn(
142
+ "w-full rounded border bg-base px-3 py-2 text-sm text-base-contrast focus:outline-none focus:ring-1",
143
+ error ? "border-red-600 focus:border-red-600 focus:ring-red-600" : "border-base-200 focus:border-base-contrast focus:ring-base-contrast",
144
+ disabled && "cursor-not-allowed opacity-50"
145
+ ),
146
+ ...rest
147
+ }
148
+ ),
149
+ error && /* @__PURE__ */ jsx4("p", { id: errorId, className: "mt-1 text-xs text-red-600", children: error })
150
+ ] });
151
+ });
152
+
109
153
  export {
110
154
  useMediaLibrary,
111
155
  useResolvedMedia,
@@ -113,5 +157,7 @@ export {
113
157
  AddIcon,
114
158
  DeleteIcon,
115
159
  SettingsIcon,
116
- IconButton
160
+ IconButton,
161
+ FormLabel,
162
+ Input
117
163
  };