@drawnagency/primitives 0.1.118 → 0.1.120

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (279) hide show
  1. package/dist/{chunk-O37AV27P.js → chunk-5JYHTHVR.js} +28 -0
  2. package/dist/{chunk-W72BPGR3.js → chunk-BZKHHUIN.js} +44 -8
  3. package/dist/{chunk-4NSOKEA7.js → chunk-HFHM4MNK.js} +12 -7
  4. package/dist/{chunk-CEFFP3CH.js → chunk-HZTPF6OK.js} +304 -83
  5. package/dist/{chunk-RIITGTV3.js → chunk-LQHBC7C6.js} +37 -2
  6. package/dist/{chunk-VY3IFGE3.js → chunk-QAMAIDXZ.js} +1 -1
  7. package/dist/{chunk-HRX3XJBU.js → chunk-RIN2QCYJ.js} +9 -11
  8. package/dist/{chunk-ZOTRHHUB.js → chunk-UNFPATDE.js} +8 -10
  9. package/dist/{chunk-ERLIL4RU.js → chunk-UZBFVVTC.js} +35 -37
  10. package/dist/{chunk-67P34WNW.js → chunk-ZKVQMIMJ.js} +3 -20
  11. package/dist/collab/rebase.js +4 -5
  12. package/dist/components/chat/ChatComposer.d.ts +0 -4
  13. package/dist/components/chat/ChatComposer.d.ts.map +1 -1
  14. package/dist/components/chat/ChatPanel.d.ts +2 -3
  15. package/dist/components/chat/ChatPanel.d.ts.map +1 -1
  16. package/dist/components/chat/markdown.d.ts +2 -3
  17. package/dist/components/chat/markdown.d.ts.map +1 -1
  18. package/dist/components/editor/AudienceIndicator.d.ts +3 -1
  19. package/dist/components/editor/AudienceIndicator.d.ts.map +1 -1
  20. package/dist/components/editor/IndicatorPill.d.ts +3 -1
  21. package/dist/components/editor/IndicatorPill.d.ts.map +1 -1
  22. package/dist/components/editor/PagesModal.d.ts +0 -2
  23. package/dist/components/editor/PagesModal.d.ts.map +1 -1
  24. package/dist/components/editor/SectionBulkEditModal.d.ts +25 -0
  25. package/dist/components/editor/SectionBulkEditModal.d.ts.map +1 -0
  26. package/dist/components/editor/StatusIndicator.d.ts +3 -1
  27. package/dist/components/editor/StatusIndicator.d.ts.map +1 -1
  28. package/dist/components/editor/index.js +28 -26
  29. package/dist/components/primitives/index.js +11 -15
  30. package/dist/components/sections/brand-guide.js +10 -13
  31. package/dist/components/sections/register-schemas.js +16 -21
  32. package/dist/components/sections/register.js +16 -21
  33. package/dist/components/shared/Popover.d.ts +1 -1
  34. package/dist/components/shared/Popover.d.ts.map +1 -1
  35. package/dist/components/shared/SectionSummaryRow.d.ts +1 -1
  36. package/dist/components/shell/AudienceChips.d.ts +1 -3
  37. package/dist/components/shell/AudienceChips.d.ts.map +1 -1
  38. package/dist/components/shell/EditorModal.d.ts.map +1 -1
  39. package/dist/components/shell/EditorShell.d.ts +0 -34
  40. package/dist/components/shell/EditorShell.d.ts.map +1 -1
  41. package/dist/components/shell/SiteSettingsModal.d.ts.map +1 -1
  42. package/dist/hooks/useSortableNavRow.d.ts +1 -1
  43. package/dist/hooks/useSortableRow.d.ts +1 -1
  44. package/dist/index.js +83 -90
  45. package/dist/lib/index-ops.js +5 -6
  46. package/dist/lib/index.js +27 -32
  47. package/dist/lib/pages.d.ts +0 -2
  48. package/dist/lib/pages.d.ts.map +1 -1
  49. package/dist/lib/sidecars.js +2 -2
  50. package/dist/lib/site-validation.js +13 -14
  51. package/dist/lib/storage-tier.js +4 -4
  52. package/dist/schemas/index.js +42 -45
  53. package/dist/schemas/site-config.d.ts +1 -277
  54. package/dist/schemas/site-config.d.ts.map +1 -1
  55. package/package.json +2 -42
  56. package/src/components/chat/ChatComposer.tsx +0 -4
  57. package/src/components/chat/ChatPanel.tsx +2 -3
  58. package/src/components/chat/markdown.ts +2 -3
  59. package/src/components/editor/AudienceIndicator.tsx +8 -4
  60. package/src/components/editor/IndicatorPill.tsx +4 -0
  61. package/src/components/editor/PagesModal.tsx +1 -15
  62. package/src/components/editor/SectionBulkEditModal.tsx +328 -0
  63. package/src/components/editor/StatusIndicator.tsx +7 -6
  64. package/src/components/shared/Popover.tsx +17 -4
  65. package/src/components/shared/SectionSummaryRow.tsx +1 -1
  66. package/src/components/shell/AudienceChips.tsx +1 -3
  67. package/src/components/shell/EditorModal.tsx +5 -2
  68. package/src/components/shell/EditorShell.tsx +15 -119
  69. package/src/components/shell/SiteSettingsModal.tsx +0 -11
  70. package/src/lib/pages.ts +0 -22
  71. package/src/schemas/index.ts +0 -4
  72. package/src/schemas/site-config.ts +4 -32
  73. package/dist/chunk-4TZJZU2T.js +0 -92
  74. package/dist/chunk-DIMDRBFK.js +0 -11
  75. package/dist/chunk-FV7JQRCN.js +0 -94
  76. package/dist/chunk-IIDKW7AV.js +0 -41
  77. package/dist/chunk-JCDZAFX2.js +0 -224
  78. package/dist/chunk-MM7KZS5C.js +0 -30
  79. package/dist/chunk-QQ3S3P5P.js +0 -38
  80. package/dist/chunk-TEOAKGZA.js +0 -784
  81. package/dist/chunk-VAYZJKVR.js +0 -209
  82. package/dist/components/editor/SectionOrderingModal.d.ts +0 -10
  83. package/dist/components/editor/SectionOrderingModal.d.ts.map +0 -1
  84. package/dist/components/shell/DocInspector.d.ts +0 -18
  85. package/dist/components/shell/DocInspector.d.ts.map +0 -1
  86. package/dist/components/shell/DocumentEditorOverlay.d.ts +0 -29
  87. package/dist/components/shell/DocumentEditorOverlay.d.ts.map +0 -1
  88. package/dist/components/shell/DocumentPresentOverlay.d.ts +0 -30
  89. package/dist/components/shell/DocumentPresentOverlay.d.ts.map +0 -1
  90. package/dist/components/shell/SiteSettingsDecks.d.ts +0 -13
  91. package/dist/components/shell/SiteSettingsDecks.d.ts.map +0 -1
  92. package/dist/deck/DeckComponentView.d.ts +0 -13
  93. package/dist/deck/DeckComponentView.d.ts.map +0 -1
  94. package/dist/deck/DeckPlayer.d.ts +0 -26
  95. package/dist/deck/DeckPlayer.d.ts.map +0 -1
  96. package/dist/deck/DeckSlideView.d.ts +0 -17
  97. package/dist/deck/DeckSlideView.d.ts.map +0 -1
  98. package/dist/deck/DeckStage.d.ts +0 -16
  99. package/dist/deck/DeckStage.d.ts.map +0 -1
  100. package/dist/deck/components/DeckImage.d.ts +0 -14
  101. package/dist/deck/components/DeckImage.d.ts.map +0 -1
  102. package/dist/deck/components/DeckImageGrid.d.ts +0 -27
  103. package/dist/deck/components/DeckImageGrid.d.ts.map +0 -1
  104. package/dist/deck/components/DeckRichText.d.ts +0 -22
  105. package/dist/deck/components/DeckRichText.d.ts.map +0 -1
  106. package/dist/deck/components/DeckVideo.d.ts +0 -15
  107. package/dist/deck/components/DeckVideo.d.ts.map +0 -1
  108. package/dist/deck/editing.d.ts +0 -50
  109. package/dist/deck/editing.d.ts.map +0 -1
  110. package/dist/deck/flip.d.ts +0 -11
  111. package/dist/deck/flip.d.ts.map +0 -1
  112. package/dist/deck/index.d.ts +0 -24
  113. package/dist/deck/index.d.ts.map +0 -1
  114. package/dist/deck/index.js +0 -51
  115. package/dist/deck/layouts/CenteredTextLayout.d.ts +0 -12
  116. package/dist/deck/layouts/CenteredTextLayout.d.ts.map +0 -1
  117. package/dist/deck/layouts/ColumnSplitLayout.d.ts +0 -14
  118. package/dist/deck/layouts/ColumnSplitLayout.d.ts.map +0 -1
  119. package/dist/deck/layouts/FullBleedImageLayout.d.ts +0 -14
  120. package/dist/deck/layouts/FullBleedImageLayout.d.ts.map +0 -1
  121. package/dist/deck/media.d.ts +0 -33
  122. package/dist/deck/media.d.ts.map +0 -1
  123. package/dist/deck/tokens.d.ts +0 -22
  124. package/dist/deck/tokens.d.ts.map +0 -1
  125. package/dist/deck/useStageScale.d.ts +0 -10
  126. package/dist/deck/useStageScale.d.ts.map +0 -1
  127. package/dist/deck-builder/DeckBuilderApp.d.ts +0 -30
  128. package/dist/deck-builder/DeckBuilderApp.d.ts.map +0 -1
  129. package/dist/deck-builder/DeckBuilderTopBar.d.ts +0 -24
  130. package/dist/deck-builder/DeckBuilderTopBar.d.ts.map +0 -1
  131. package/dist/deck-builder/DeckChatPanel.d.ts +0 -45
  132. package/dist/deck-builder/DeckChatPanel.d.ts.map +0 -1
  133. package/dist/deck-builder/DeckEditor.d.ts +0 -37
  134. package/dist/deck-builder/DeckEditor.d.ts.map +0 -1
  135. package/dist/deck-builder/DeckLibrary.d.ts +0 -22
  136. package/dist/deck-builder/DeckLibrary.d.ts.map +0 -1
  137. package/dist/deck-builder/DeckSlideSurface.d.ts +0 -31
  138. package/dist/deck-builder/DeckSlideSurface.d.ts.map +0 -1
  139. package/dist/deck-builder/deck-api.d.ts +0 -76
  140. package/dist/deck-builder/deck-api.d.ts.map +0 -1
  141. package/dist/deck-builder/deck-chat-client.d.ts +0 -44
  142. package/dist/deck-builder/deck-chat-client.d.ts.map +0 -1
  143. package/dist/deck-builder/deck-chat-history.d.ts +0 -10
  144. package/dist/deck-builder/deck-chat-history.d.ts.map +0 -1
  145. package/dist/deck-builder/index.d.ts +0 -13
  146. package/dist/deck-builder/index.d.ts.map +0 -1
  147. package/dist/deck-builder/index.js +0 -1498
  148. package/dist/deck-builder/starter-deck.d.ts +0 -23
  149. package/dist/deck-builder/starter-deck.d.ts.map +0 -1
  150. package/dist/deck-builder/types.d.ts +0 -29
  151. package/dist/deck-builder/types.d.ts.map +0 -1
  152. package/dist/deck-builder/useSortableSlide.d.ts +0 -29
  153. package/dist/deck-builder/useSortableSlide.d.ts.map +0 -1
  154. package/dist/document/assets/fonts/albra-grotesk-bold.woff +0 -0
  155. package/dist/document/assets/fonts/albra-grotesk-regular.woff +0 -0
  156. package/dist/document/assets/fonts/kapra-neue-expanded-medium.woff +0 -0
  157. package/dist/document/assets/fonts/kapra-neue-expanded-regular.woff +0 -0
  158. package/dist/document/components/DocCoverPage.d.ts +0 -11
  159. package/dist/document/components/DocCoverPage.d.ts.map +0 -1
  160. package/dist/document/components/DocPage.d.ts +0 -10
  161. package/dist/document/components/DocPage.d.ts.map +0 -1
  162. package/dist/document/components/DocRail.d.ts +0 -28
  163. package/dist/document/components/DocRail.d.ts.map +0 -1
  164. package/dist/document/components/DocSectionPage.d.ts +0 -12
  165. package/dist/document/components/DocSectionPage.d.ts.map +0 -1
  166. package/dist/document/components/DocViewer.d.ts +0 -21
  167. package/dist/document/components/DocViewer.d.ts.map +0 -1
  168. package/dist/document/components/Wordmark.d.ts +0 -4
  169. package/dist/document/components/Wordmark.d.ts.map +0 -1
  170. package/dist/document/components/measure.d.ts +0 -7
  171. package/dist/document/components/measure.d.ts.map +0 -1
  172. package/dist/document/components/useDocPages.d.ts +0 -12
  173. package/dist/document/components/useDocPages.d.ts.map +0 -1
  174. package/dist/document/engine/blocks.d.ts +0 -2
  175. package/dist/document/engine/blocks.d.ts.map +0 -1
  176. package/dist/document/engine/harvest.d.ts +0 -3
  177. package/dist/document/engine/harvest.d.ts.map +0 -1
  178. package/dist/document/engine/masonry.d.ts +0 -26
  179. package/dist/document/engine/masonry.d.ts.map +0 -1
  180. package/dist/document/engine/paginate.d.ts +0 -43
  181. package/dist/document/engine/paginate.d.ts.map +0 -1
  182. package/dist/document/engine/settings.d.ts +0 -91
  183. package/dist/document/engine/settings.d.ts.map +0 -1
  184. package/dist/document/engine/types.d.ts +0 -44
  185. package/dist/document/engine/types.d.ts.map +0 -1
  186. package/dist/document/index.d.ts +0 -13
  187. package/dist/document/index.d.ts.map +0 -1
  188. package/dist/document/index.js +0 -1030
  189. package/dist/document/styles/document.css +0 -217
  190. package/dist/lib/deck-access.d.ts +0 -86
  191. package/dist/lib/deck-access.d.ts.map +0 -1
  192. package/dist/lib/deck-access.js +0 -58
  193. package/dist/lib/deck-dexie.d.ts +0 -88
  194. package/dist/lib/deck-dexie.d.ts.map +0 -1
  195. package/dist/lib/deck-dexie.js +0 -22
  196. package/dist/lib/deck-edit.d.ts +0 -67
  197. package/dist/lib/deck-edit.d.ts.map +0 -1
  198. package/dist/lib/deck-media-assets.d.ts +0 -27
  199. package/dist/lib/deck-media-assets.d.ts.map +0 -1
  200. package/dist/lib/deck-media-assets.js +0 -25
  201. package/dist/lib/deck-media-refs.d.ts +0 -35
  202. package/dist/lib/deck-media-refs.d.ts.map +0 -1
  203. package/dist/lib/deck-media-refs.js +0 -36
  204. package/dist/lib/deck-tool.d.ts +0 -25
  205. package/dist/lib/deck-tool.d.ts.map +0 -1
  206. package/dist/lib/deck-tool.js +0 -58
  207. package/dist/lib/document-input.d.ts +0 -25
  208. package/dist/lib/document-input.d.ts.map +0 -1
  209. package/dist/schemas/deck-meta.d.ts +0 -85
  210. package/dist/schemas/deck-meta.d.ts.map +0 -1
  211. package/dist/schemas/deck-meta.js +0 -64
  212. package/dist/schemas/deck.d.ts +0 -954
  213. package/dist/schemas/deck.d.ts.map +0 -1
  214. package/dist/schemas/deck.js +0 -65
  215. package/src/components/editor/SectionOrderingModal.tsx +0 -80
  216. package/src/components/shell/DocInspector.tsx +0 -314
  217. package/src/components/shell/DocumentEditorOverlay.tsx +0 -179
  218. package/src/components/shell/DocumentPresentOverlay.tsx +0 -87
  219. package/src/components/shell/SiteSettingsDecks.tsx +0 -41
  220. package/src/deck/DeckComponentView.tsx +0 -28
  221. package/src/deck/DeckPlayer.tsx +0 -166
  222. package/src/deck/DeckSlideView.tsx +0 -38
  223. package/src/deck/DeckStage.tsx +0 -39
  224. package/src/deck/components/DeckImage.tsx +0 -38
  225. package/src/deck/components/DeckImageGrid.tsx +0 -254
  226. package/src/deck/components/DeckRichText.tsx +0 -111
  227. package/src/deck/components/DeckVideo.tsx +0 -81
  228. package/src/deck/editing.tsx +0 -201
  229. package/src/deck/flip.ts +0 -70
  230. package/src/deck/index.ts +0 -30
  231. package/src/deck/layouts/CenteredTextLayout.tsx +0 -29
  232. package/src/deck/layouts/ColumnSplitLayout.tsx +0 -69
  233. package/src/deck/layouts/FullBleedImageLayout.tsx +0 -58
  234. package/src/deck/media.tsx +0 -46
  235. package/src/deck/tokens.ts +0 -57
  236. package/src/deck/useStageScale.ts +0 -44
  237. package/src/deck-builder/DeckBuilderApp.tsx +0 -572
  238. package/src/deck-builder/DeckBuilderTopBar.tsx +0 -62
  239. package/src/deck-builder/DeckChatPanel.tsx +0 -334
  240. package/src/deck-builder/DeckEditor.tsx +0 -258
  241. package/src/deck-builder/DeckLibrary.tsx +0 -195
  242. package/src/deck-builder/DeckSlideSurface.tsx +0 -55
  243. package/src/deck-builder/deck-api.ts +0 -177
  244. package/src/deck-builder/deck-chat-client.ts +0 -129
  245. package/src/deck-builder/deck-chat-history.ts +0 -62
  246. package/src/deck-builder/index.ts +0 -12
  247. package/src/deck-builder/starter-deck.ts +0 -86
  248. package/src/deck-builder/types.ts +0 -24
  249. package/src/deck-builder/useSortableSlide.ts +0 -102
  250. package/src/document/assets/fonts/albra-grotesk-bold.woff +0 -0
  251. package/src/document/assets/fonts/albra-grotesk-regular.woff +0 -0
  252. package/src/document/assets/fonts/kapra-neue-expanded-medium.woff +0 -0
  253. package/src/document/assets/fonts/kapra-neue-expanded-regular.woff +0 -0
  254. package/src/document/components/DocCoverPage.tsx +0 -45
  255. package/src/document/components/DocPage.tsx +0 -40
  256. package/src/document/components/DocRail.tsx +0 -189
  257. package/src/document/components/DocSectionPage.tsx +0 -48
  258. package/src/document/components/DocViewer.tsx +0 -313
  259. package/src/document/components/Wordmark.tsx +0 -18
  260. package/src/document/components/measure.tsx +0 -133
  261. package/src/document/components/useDocPages.ts +0 -95
  262. package/src/document/engine/blocks.ts +0 -116
  263. package/src/document/engine/harvest.ts +0 -95
  264. package/src/document/engine/masonry.ts +0 -158
  265. package/src/document/engine/paginate.ts +0 -232
  266. package/src/document/engine/settings.ts +0 -125
  267. package/src/document/engine/types.ts +0 -64
  268. package/src/document/index.ts +0 -18
  269. package/src/document/styles/document.css +0 -217
  270. package/src/lib/deck-access.ts +0 -132
  271. package/src/lib/deck-dexie.ts +0 -190
  272. package/src/lib/deck-edit.ts +0 -196
  273. package/src/lib/deck-media-assets.ts +0 -57
  274. package/src/lib/deck-media-refs.ts +0 -67
  275. package/src/lib/deck-tool.ts +0 -95
  276. package/src/lib/document-input.ts +0 -57
  277. package/src/schemas/deck-meta.ts +0 -88
  278. package/src/schemas/deck.ts +0 -478
  279. package/dist/{chunk-DJABADOO.js → chunk-AJ2QOAZI.js} +3 -3
@@ -1,3 +1,6 @@
1
+ import {
2
+ Button
3
+ } from "./chunk-GGYY3JQJ.js";
1
4
  import {
2
5
  Checkbox,
3
6
  Tabs
@@ -5,22 +8,13 @@ import {
5
8
  import {
6
9
  DragHandle,
7
10
  FormLabel,
11
+ IconButton,
8
12
  Input,
9
13
  LinkField,
10
14
  Select,
11
15
  useMediaLibrary,
12
16
  useResolvedMedia
13
- } from "./chunk-RIITGTV3.js";
14
- import {
15
- Kbd,
16
- Tooltip
17
- } from "./chunk-JCDZAFX2.js";
18
- import {
19
- Button
20
- } from "./chunk-GGYY3JQJ.js";
21
- import {
22
- IconButton
23
- } from "./chunk-IIDKW7AV.js";
17
+ } from "./chunk-LQHBC7C6.js";
24
18
  import {
25
19
  formatFileSize
26
20
  } from "./chunk-CDBURDPX.js";
@@ -30,16 +24,45 @@ import {
30
24
 
31
25
  // src/components/editor/DragHandle.tsx
32
26
  import { forwardRef } from "react";
33
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
27
+
28
+ // src/components/shared/Tooltip.tsx
29
+ import { jsx, jsxs } from "react/jsx-runtime";
30
+ var sideClasses = {
31
+ bottom: "left-1/2 top-full mt-1.5 -translate-x-1/2",
32
+ right: "left-full top-1/2 ml-1.5 -translate-y-1/2",
33
+ "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"
34
+ };
35
+ function Tooltip({ content, children, className, side = "bottom" }) {
36
+ return /* @__PURE__ */ jsxs("div", { className: cn("group/tooltip relative inline-flex", className), children: [
37
+ children,
38
+ /* @__PURE__ */ jsx(
39
+ "span",
40
+ {
41
+ className: cn(
42
+ "pointer-events-none absolute z-50 opacity-0 transition-opacity delay-300 group-hover/tooltip:opacity-100",
43
+ sideClasses[side]
44
+ ),
45
+ role: "tooltip",
46
+ 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 })
47
+ }
48
+ )
49
+ ] });
50
+ }
51
+ function Kbd({ children }) {
52
+ return /* @__PURE__ */ jsx("strong", { className: "text-tooltip-contrast", children });
53
+ }
54
+
55
+ // src/components/editor/DragHandle.tsx
56
+ import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
34
57
  var DragHandle2 = forwardRef(function DragHandle3({ tooltipSide, tabIndex = -1, "aria-describedby": ariaDescribedBy }, ref) {
35
- return /* @__PURE__ */ jsx(Tooltip, { side: tooltipSide, content: /* @__PURE__ */ jsxs(Fragment, { children: [
36
- /* @__PURE__ */ jsx(Kbd, { children: "Drag" }),
58
+ return /* @__PURE__ */ jsx2(Tooltip, { side: tooltipSide, content: /* @__PURE__ */ jsxs2(Fragment, { children: [
59
+ /* @__PURE__ */ jsx2(Kbd, { children: "Drag" }),
37
60
  " to move"
38
- ] }), children: /* @__PURE__ */ jsx(
61
+ ] }), children: /* @__PURE__ */ jsx2(
39
62
  IconButton,
40
63
  {
41
64
  ref,
42
- icon: /* @__PURE__ */ jsx(DragHandle, { size: 18 }),
65
+ icon: /* @__PURE__ */ jsx2(DragHandle, { size: 18 }),
43
66
  label: "Drag to reorder section",
44
67
  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",
45
68
  tabIndex,
@@ -50,12 +73,12 @@ var DragHandle2 = forwardRef(function DragHandle3({ tooltipSide, tabIndex = -1,
50
73
 
51
74
  // src/components/editor/DeleteButton.tsx
52
75
  import { Trash2 } from "lucide-react";
53
- import { jsx as jsx2 } from "react/jsx-runtime";
76
+ import { jsx as jsx3 } from "react/jsx-runtime";
54
77
  function DeleteButton({ onDelete }) {
55
- return /* @__PURE__ */ jsx2(
78
+ return /* @__PURE__ */ jsx3(
56
79
  IconButton,
57
80
  {
58
- icon: /* @__PURE__ */ jsx2(Trash2, { size: 16 }),
81
+ icon: /* @__PURE__ */ jsx3(Trash2, { size: 16 }),
59
82
  label: "Delete section",
60
83
  intent: "destructive",
61
84
  onClick: onDelete,
@@ -66,12 +89,12 @@ function DeleteButton({ onDelete }) {
66
89
 
67
90
  // src/components/editor/SettingsButton.tsx
68
91
  import { Settings } from "lucide-react";
69
- import { jsx as jsx3 } from "react/jsx-runtime";
92
+ import { jsx as jsx4 } from "react/jsx-runtime";
70
93
  function SettingsButton({ onClick }) {
71
- return /* @__PURE__ */ jsx3(
94
+ return /* @__PURE__ */ jsx4(
72
95
  IconButton,
73
96
  {
74
- icon: /* @__PURE__ */ jsx3(Settings, { size: 16 }),
97
+ icon: /* @__PURE__ */ jsx4(Settings, { size: 16 }),
75
98
  label: "Section settings",
76
99
  onClick,
77
100
  className: "pointer-events-auto"
@@ -84,7 +107,7 @@ import { useId, useState as useState2 } from "react";
84
107
 
85
108
  // src/components/shared/VideoSourceField.tsx
86
109
  import { useState } from "react";
87
- import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
110
+ import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
88
111
  var ASPECTS = [
89
112
  { label: "9:16", width: 9, height: 16 },
90
113
  { label: "4:5", width: 4, height: 5 },
@@ -133,9 +156,9 @@ function VideoSourceField({ value, onChange }) {
133
156
  setLoading(false);
134
157
  }
135
158
  }
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(
159
+ return /* @__PURE__ */ jsxs3("div", { className: "flex flex-col gap-3", children: [
160
+ /* @__PURE__ */ jsx5(FormLabel, { children: "Source" }),
161
+ /* @__PURE__ */ jsx5("div", { className: "flex gap-2", role: "tablist", children: ["library", "embed"].map((m) => /* @__PURE__ */ jsx5(
139
162
  "button",
140
163
  {
141
164
  type: "button",
@@ -150,9 +173,9 @@ function VideoSourceField({ value, onChange }) {
150
173
  },
151
174
  m
152
175
  )) }),
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(
176
+ mode === "library" ? /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-3", children: [
177
+ 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" }),
178
+ /* @__PURE__ */ jsx5(
156
179
  Button,
157
180
  {
158
181
  type: "button",
@@ -162,9 +185,9 @@ function VideoSourceField({ value, onChange }) {
162
185
  children: "Choose video"
163
186
  }
164
187
  )
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(
188
+ ] }) : /* @__PURE__ */ jsxs3("div", { className: "flex flex-col gap-2", children: [
189
+ /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-2", children: [
190
+ /* @__PURE__ */ jsx5(
168
191
  "input",
169
192
  {
170
193
  type: "text",
@@ -184,7 +207,7 @@ function VideoSourceField({ value, onChange }) {
184
207
  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"
185
208
  }
186
209
  ),
187
- /* @__PURE__ */ jsx4(
210
+ /* @__PURE__ */ jsx5(
188
211
  Button,
189
212
  {
190
213
  type: "button",
@@ -196,13 +219,13 @@ function VideoSourceField({ value, onChange }) {
196
219
  }
197
220
  )
198
221
  ] }),
199
- error ? /* @__PURE__ */ jsx4("p", { className: "text-xs text-danger", 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" }),
222
+ error ? /* @__PURE__ */ jsx5("p", { className: "text-xs text-danger", children: error }) : null,
223
+ !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,
224
+ value?.type === "external" && value.provider === "instagram" ? /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-2", children: [
225
+ /* @__PURE__ */ jsx5("span", { className: "text-xs text-base-contrast-light", children: "Aspect" }),
203
226
  ASPECTS.map(({ label, width, height }) => {
204
227
  const active = value.width === width && value.height === height;
205
- return /* @__PURE__ */ jsx4(
228
+ return /* @__PURE__ */ jsx5(
206
229
  "button",
207
230
  {
208
231
  type: "button",
@@ -236,22 +259,22 @@ function useResolvedDocument(documentId) {
236
259
  }
237
260
 
238
261
  // src/components/shared/DocumentSourceField.tsx
239
- import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
262
+ import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
240
263
  function DocumentSourceField({ value, onChange }) {
241
264
  const mediaLibrary = useMediaLibrary();
242
265
  const documentId = value?.documentId || void 0;
243
266
  const { entry, missing } = useResolvedDocument(documentId);
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: [
267
+ return /* @__PURE__ */ jsxs4("div", { className: "flex flex-col gap-3", children: [
268
+ /* @__PURE__ */ jsx6(FormLabel, { children: "Document" }),
269
+ /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-3", children: [
270
+ entry ? /* @__PURE__ */ jsxs4("span", { className: "min-w-0 flex-1 truncate text-sm text-base-contrast", children: [
248
271
  entry.filename,
249
- /* @__PURE__ */ jsxs3("span", { className: "text-base-contrast-light", children: [
272
+ /* @__PURE__ */ jsxs4("span", { className: "text-base-contrast-light", children: [
250
273
  " \xB7 ",
251
274
  formatFileSize(entry.size)
252
275
  ] })
253
- ] }) : /* @__PURE__ */ jsx5("span", { className: "flex-1 text-sm text-base-contrast-light", children: missing ? "File missing" : "No document selected" }),
254
- /* @__PURE__ */ jsx5(
276
+ ] }) : /* @__PURE__ */ jsx6("span", { className: "flex-1 text-sm text-base-contrast-light", children: missing ? "File missing" : "No document selected" }),
277
+ /* @__PURE__ */ jsx6(
255
278
  Button,
256
279
  {
257
280
  type: "button",
@@ -266,11 +289,11 @@ function DocumentSourceField({ value, onChange }) {
266
289
  }
267
290
 
268
291
  // src/components/shared/SegmentedControl.tsx
269
- import { jsx as jsx6 } from "react/jsx-runtime";
292
+ import { jsx as jsx7 } from "react/jsx-runtime";
270
293
  function SegmentedControl({ options, value, onChange, className }) {
271
- return /* @__PURE__ */ jsx6("div", { role: "radiogroup", className: cn("inline-flex rounded border border-base-200 bg-base-accent", className), children: options.map((option) => {
294
+ return /* @__PURE__ */ jsx7("div", { role: "radiogroup", className: cn("inline-flex rounded border border-base-200 bg-base-accent", className), children: options.map((option) => {
272
295
  const selected = option.value === value;
273
- return /* @__PURE__ */ jsx6(
296
+ return /* @__PURE__ */ jsx7(
274
297
  "button",
275
298
  {
276
299
  type: "button",
@@ -292,9 +315,9 @@ function SegmentedControl({ options, value, onChange, className }) {
292
315
  }
293
316
 
294
317
  // src/components/shared/ColorPicker.tsx
295
- import { jsx as jsx7 } from "react/jsx-runtime";
318
+ import { jsx as jsx8 } from "react/jsx-runtime";
296
319
  function ColorPicker({ value, onChange, label = "Color", className }) {
297
- return /* @__PURE__ */ jsx7(
320
+ return /* @__PURE__ */ jsx8(
298
321
  "label",
299
322
  {
300
323
  className: cn(
@@ -302,7 +325,7 @@ function ColorPicker({ value, onChange, label = "Color", className }) {
302
325
  className
303
326
  ),
304
327
  style: { backgroundColor: value },
305
- children: /* @__PURE__ */ jsx7(
328
+ children: /* @__PURE__ */ jsx8(
306
329
  "input",
307
330
  {
308
331
  type: "color",
@@ -324,7 +347,7 @@ function useBrandSwatches() {
324
347
  }
325
348
 
326
349
  // src/components/shared/ImageBackgroundField.tsx
327
- import { jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
350
+ import { jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
328
351
  var MODES = [
329
352
  { value: "none", label: "None" },
330
353
  { value: "theme", label: "Light / Dark" },
@@ -343,11 +366,11 @@ function ImageBackgroundField({ label, value, onChange }) {
343
366
  else if (next === "custom") onChange({ mode: "custom", color: "#ffffff" });
344
367
  else onChange(void 0);
345
368
  }
346
- return /* @__PURE__ */ jsxs4("div", { className: "flex flex-col gap-3", children: [
347
- /* @__PURE__ */ jsx8(FormLabel, { children: label }),
348
- /* @__PURE__ */ jsx8(SegmentedControl, { options: MODES, value: mode, onChange: setMode, className: "self-start" }),
349
- value?.mode === "theme" && /* @__PURE__ */ jsxs4("div", { className: "grid grid-cols-2 gap-3", children: [
350
- /* @__PURE__ */ jsx8(
369
+ return /* @__PURE__ */ jsxs5("div", { className: "flex flex-col gap-3", children: [
370
+ /* @__PURE__ */ jsx9(FormLabel, { children: label }),
371
+ /* @__PURE__ */ jsx9(SegmentedControl, { options: MODES, value: mode, onChange: setMode, className: "self-start" }),
372
+ value?.mode === "theme" && /* @__PURE__ */ jsxs5("div", { className: "grid grid-cols-2 gap-3", children: [
373
+ /* @__PURE__ */ jsx9(
351
374
  Select,
352
375
  {
353
376
  label: "Light mode",
@@ -356,7 +379,7 @@ function ImageBackgroundField({ label, value, onChange }) {
356
379
  onChange: (light) => onChange({ ...value, light })
357
380
  }
358
381
  ),
359
- /* @__PURE__ */ jsx8(
382
+ /* @__PURE__ */ jsx9(
360
383
  Select,
361
384
  {
362
385
  label: "Dark mode",
@@ -366,9 +389,9 @@ function ImageBackgroundField({ label, value, onChange }) {
366
389
  }
367
390
  )
368
391
  ] }),
369
- value?.mode === "custom" && /* @__PURE__ */ jsxs4("div", { className: "flex flex-col gap-2", children: [
370
- /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2", children: [
371
- /* @__PURE__ */ jsx8(
392
+ value?.mode === "custom" && /* @__PURE__ */ jsxs5("div", { className: "flex flex-col gap-2", children: [
393
+ /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2", children: [
394
+ /* @__PURE__ */ jsx9(
372
395
  ColorPicker,
373
396
  {
374
397
  label: "Background color",
@@ -376,9 +399,9 @@ function ImageBackgroundField({ label, value, onChange }) {
376
399
  onChange: (color) => onChange({ mode: "custom", color })
377
400
  }
378
401
  ),
379
- /* @__PURE__ */ jsx8("span", { className: "font-mono text-xs text-base-contrast-light", children: value.color })
402
+ /* @__PURE__ */ jsx9("span", { className: "font-mono text-xs text-base-contrast-light", children: value.color })
380
403
  ] }),
381
- swatches.length > 0 && /* @__PURE__ */ jsx8("div", { role: "group", "aria-label": "Brand colors", className: "flex flex-wrap gap-2", children: swatches.map((s) => /* @__PURE__ */ jsx8(
404
+ swatches.length > 0 && /* @__PURE__ */ jsx9("div", { role: "group", "aria-label": "Brand colors", className: "flex flex-wrap gap-2", children: swatches.map((s) => /* @__PURE__ */ jsx9(
382
405
  "button",
383
406
  {
384
407
  type: "button",
@@ -399,7 +422,7 @@ function ImageBackgroundField({ label, value, onChange }) {
399
422
  }
400
423
 
401
424
  // src/components/editor/SettingsForm.tsx
402
- import { jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
425
+ import { jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
403
426
  function resolveValues(schema, values) {
404
427
  const resolved = {};
405
428
  for (const [key, field] of Object.entries(schema)) {
@@ -439,9 +462,9 @@ function RangeField({
439
462
  onChange
440
463
  }) {
441
464
  const id = useId();
442
- return /* @__PURE__ */ jsxs5("div", { children: [
443
- /* @__PURE__ */ jsx9(FormLabel, { htmlFor: id, children: field.label }),
444
- /* @__PURE__ */ jsx9(
465
+ return /* @__PURE__ */ jsxs6("div", { children: [
466
+ /* @__PURE__ */ jsx10(FormLabel, { htmlFor: id, children: field.label }),
467
+ /* @__PURE__ */ jsx10(
445
468
  "input",
446
469
  {
447
470
  id,
@@ -461,7 +484,7 @@ function RangeField({
461
484
  function renderField(key, field, value, handleFieldChange, values) {
462
485
  switch (field.type) {
463
486
  case "text":
464
- return /* @__PURE__ */ jsx9(
487
+ return /* @__PURE__ */ jsx10(
465
488
  Input,
466
489
  {
467
490
  label: field.label,
@@ -472,7 +495,7 @@ function renderField(key, field, value, handleFieldChange, values) {
472
495
  key
473
496
  );
474
497
  case "number":
475
- return /* @__PURE__ */ jsx9(
498
+ return /* @__PURE__ */ jsx10(
476
499
  Input,
477
500
  {
478
501
  label: field.label,
@@ -483,7 +506,7 @@ function renderField(key, field, value, handleFieldChange, values) {
483
506
  key
484
507
  );
485
508
  case "checkbox":
486
- return /* @__PURE__ */ jsx9(
509
+ return /* @__PURE__ */ jsx10(
487
510
  Checkbox,
488
511
  {
489
512
  label: field.label,
@@ -493,7 +516,7 @@ function renderField(key, field, value, handleFieldChange, values) {
493
516
  key
494
517
  );
495
518
  case "select":
496
- return /* @__PURE__ */ jsx9(
519
+ return /* @__PURE__ */ jsx10(
497
520
  Select,
498
521
  {
499
522
  label: field.label,
@@ -504,7 +527,7 @@ function renderField(key, field, value, handleFieldChange, values) {
504
527
  key
505
528
  );
506
529
  case "range":
507
- return /* @__PURE__ */ jsx9(
530
+ return /* @__PURE__ */ jsx10(
508
531
  RangeField,
509
532
  {
510
533
  field,
@@ -514,7 +537,7 @@ function renderField(key, field, value, handleFieldChange, values) {
514
537
  key
515
538
  );
516
539
  case "link":
517
- return /* @__PURE__ */ jsx9(
540
+ return /* @__PURE__ */ jsx10(
518
541
  LinkField,
519
542
  {
520
543
  label: field.label,
@@ -524,7 +547,7 @@ function renderField(key, field, value, handleFieldChange, values) {
524
547
  key
525
548
  );
526
549
  case "video-source":
527
- return /* @__PURE__ */ jsx9(
550
+ return /* @__PURE__ */ jsx10(
528
551
  VideoSourceField,
529
552
  {
530
553
  value,
@@ -533,7 +556,7 @@ function renderField(key, field, value, handleFieldChange, values) {
533
556
  key
534
557
  );
535
558
  case "document-source":
536
- return /* @__PURE__ */ jsx9(
559
+ return /* @__PURE__ */ jsx10(
537
560
  DocumentSourceField,
538
561
  {
539
562
  value,
@@ -543,7 +566,7 @@ function renderField(key, field, value, handleFieldChange, values) {
543
566
  );
544
567
  case "image-background":
545
568
  if (field.hidden?.(values)) return null;
546
- return /* @__PURE__ */ jsx9(
569
+ return /* @__PURE__ */ jsx10(
547
570
  ImageBackgroundField,
548
571
  {
549
572
  label: field.label,
@@ -570,14 +593,208 @@ function SettingsForm({ schema, values, onChange, tabs }) {
570
593
  const otherKeys = Object.keys(schema).filter((key) => !listed.has(key));
571
594
  const panel = "flex min-h-0 flex-1 flex-col gap-4 overflow-y-auto px-px";
572
595
  const tabItems = [
573
- ...tabs.map((t) => ({ id: t.label, label: t.label, content: /* @__PURE__ */ jsx9("div", { className: panel, children: fields(t.fields) }) })),
574
- ...otherKeys.length > 0 ? [{ id: "__other__", label: "Other", content: /* @__PURE__ */ jsx9("div", { className: panel, children: fields(otherKeys) }) }] : []
596
+ ...tabs.map((t) => ({ id: t.label, label: t.label, content: /* @__PURE__ */ jsx10("div", { className: panel, children: fields(t.fields) }) })),
597
+ ...otherKeys.length > 0 ? [{ id: "__other__", label: "Other", content: /* @__PURE__ */ jsx10("div", { className: panel, children: fields(otherKeys) }) }] : []
575
598
  ];
576
- return /* @__PURE__ */ jsx9(Tabs, { tabs: tabItems, fullBleedTabBar: true });
599
+ return /* @__PURE__ */ jsx10(Tabs, { tabs: tabItems, fullBleedTabBar: true });
577
600
  }
578
- return /* @__PURE__ */ jsx9("div", { className: "flex flex-col gap-4", children: Object.entries(schema).map(([key, field]) => renderField(key, field, local[key], handleFieldChange, allValues)) });
601
+ return /* @__PURE__ */ jsx10("div", { className: "flex flex-col gap-4", children: Object.entries(schema).map(([key, field]) => renderField(key, field, local[key], handleFieldChange, allValues)) });
579
602
  }
580
603
 
604
+ // src/components/shared/Popover.tsx
605
+ import { useEffect as useEffect3, useLayoutEffect, useRef as useRef2, useState as useState3 } from "react";
606
+ import { createPortal } from "react-dom";
607
+
608
+ // src/hooks/useFocusTrap.ts
609
+ import { useEffect } from "react";
610
+ var FOCUSABLE_SELECTOR = [
611
+ "a[href]",
612
+ "button:not([disabled])",
613
+ "input:not([disabled])",
614
+ "select:not([disabled])",
615
+ "textarea:not([disabled])",
616
+ '[tabindex]:not([tabindex="-1"])'
617
+ ].join(", ");
618
+ function useInitialFocus(ref, active) {
619
+ useEffect(() => {
620
+ if (!active || !ref.current) return;
621
+ const previouslyFocused = document.activeElement;
622
+ ref.current.querySelector(FOCUSABLE_SELECTOR)?.focus();
623
+ return () => {
624
+ if (previouslyFocused && document.body.contains(previouslyFocused)) {
625
+ previouslyFocused.focus();
626
+ }
627
+ };
628
+ }, [active, ref]);
629
+ }
630
+
631
+ // src/hooks/useStackedEscape.ts
632
+ import { useEffect as useEffect2, useRef } from "react";
633
+ function useStackedEscape(onEscape, { enabled, before }) {
634
+ const layerRef = useRef(null);
635
+ useEffect2(() => {
636
+ if (!enabled) return;
637
+ const onKeyDown = (e) => {
638
+ if (e.key !== "Escape") return;
639
+ const own = layerRef.current;
640
+ const layers = document.querySelectorAll("[data-modal-layer]");
641
+ const above = Array.from(layers).some((el) => {
642
+ if (el === own) return false;
643
+ if (!own) return true;
644
+ return Boolean(own.compareDocumentPosition(el) & Node.DOCUMENT_POSITION_FOLLOWING);
645
+ });
646
+ if (above) return;
647
+ if (before?.(e)) return;
648
+ e.preventDefault();
649
+ onEscape();
650
+ };
651
+ document.addEventListener("keydown", onKeyDown);
652
+ return () => document.removeEventListener("keydown", onKeyDown);
653
+ }, [enabled, onEscape, before]);
654
+ return layerRef;
655
+ }
656
+
657
+ // src/components/shared/Popover.tsx
658
+ import { jsx as jsx11 } from "react/jsx-runtime";
659
+ function Popover({
660
+ isOpen,
661
+ onClose,
662
+ anchorRef,
663
+ children,
664
+ align = "auto",
665
+ className,
666
+ portal = false,
667
+ placement = "bottom"
668
+ }) {
669
+ const panelRef = useRef2(null);
670
+ const [resolvedAlign, setResolvedAlign] = useState3("start");
671
+ const [fixedPos, setFixedPos] = useState3(null);
672
+ useInitialFocus(panelRef, isOpen && (!portal || fixedPos !== null));
673
+ useLayoutEffect(() => {
674
+ if (!portal) return;
675
+ if (!isOpen) {
676
+ setFixedPos(null);
677
+ return;
678
+ }
679
+ const anchor = anchorRef.current;
680
+ if (!anchor) return;
681
+ const update = () => {
682
+ const r = anchor.getBoundingClientRect();
683
+ const next = placement === "top" ? { left: r.left, bottom: window.innerHeight - r.top + 4 } : { left: r.left, top: r.bottom + 4 };
684
+ setFixedPos(
685
+ (prev) => prev && prev.left === next.left && prev.top === next.top && prev.bottom === next.bottom ? prev : next
686
+ );
687
+ };
688
+ update();
689
+ window.addEventListener("resize", update);
690
+ window.addEventListener("scroll", update, true);
691
+ return () => {
692
+ window.removeEventListener("resize", update);
693
+ window.removeEventListener("scroll", update, true);
694
+ };
695
+ }, [isOpen, portal, placement, anchorRef]);
696
+ useLayoutEffect(() => {
697
+ if (portal) return;
698
+ if (!isOpen || align !== "auto") {
699
+ if (!isOpen) setResolvedAlign("start");
700
+ return;
701
+ }
702
+ const panel = panelRef.current;
703
+ if (!panel) return;
704
+ panel.style.left = "0";
705
+ panel.style.right = "auto";
706
+ const rect = panel.getBoundingClientRect();
707
+ if (rect.right > window.innerWidth) {
708
+ setResolvedAlign("end");
709
+ } else {
710
+ setResolvedAlign("start");
711
+ }
712
+ panel.style.left = "";
713
+ panel.style.right = "";
714
+ }, [isOpen, align]);
715
+ const escapeLayerRef = useStackedEscape(onClose, { enabled: isOpen });
716
+ useLayoutEffect(() => {
717
+ escapeLayerRef.current = isOpen ? anchorRef.current?.closest("[data-modal-layer]") ?? null : null;
718
+ }, [isOpen, anchorRef, escapeLayerRef]);
719
+ useEffect3(() => {
720
+ if (!isOpen) return;
721
+ function onMouseDown(e) {
722
+ const target = e.target;
723
+ if (panelRef.current?.contains(target)) return;
724
+ if (anchorRef.current?.contains(target)) return;
725
+ const layer = target instanceof Element ? target.closest("[data-modal-layer]") : null;
726
+ if (layer && !layer.contains(anchorRef.current)) return;
727
+ onClose();
728
+ }
729
+ document.addEventListener("mousedown", onMouseDown);
730
+ return () => {
731
+ document.removeEventListener("mousedown", onMouseDown);
732
+ };
733
+ }, [isOpen, onClose, anchorRef]);
734
+ if (!isOpen) return null;
735
+ const effectiveAlign = align === "auto" ? resolvedAlign : align;
736
+ if (portal) {
737
+ if (!fixedPos) return null;
738
+ return createPortal(
739
+ /* @__PURE__ */ jsx11(
740
+ "div",
741
+ {
742
+ ref: panelRef,
743
+ role: "dialog",
744
+ "aria-modal": "false",
745
+ "data-popover": "",
746
+ style: {
747
+ position: "fixed",
748
+ left: `${fixedPos.left}px`,
749
+ ...fixedPos.top !== void 0 ? { top: `${fixedPos.top}px` } : {},
750
+ ...fixedPos.bottom !== void 0 ? { bottom: `${fixedPos.bottom}px` } : {}
751
+ },
752
+ className: cn("z-50 rounded-md border border-base-200 bg-base shadow-lg", className),
753
+ children
754
+ }
755
+ ),
756
+ document.body
757
+ );
758
+ }
759
+ return /* @__PURE__ */ jsx11(
760
+ "div",
761
+ {
762
+ ref: panelRef,
763
+ role: "dialog",
764
+ "aria-modal": "false",
765
+ "data-popover": "",
766
+ className: cn(
767
+ "absolute z-50 rounded-md border border-base-200 bg-base shadow-lg",
768
+ placement === "top" ? "bottom-full mb-1" : "top-full mt-1",
769
+ effectiveAlign === "end" ? "right-0" : "left-0",
770
+ className
771
+ ),
772
+ children
773
+ }
774
+ );
775
+ }
776
+
777
+ // src/components/shared/PopoverItem.tsx
778
+ import { forwardRef as forwardRef2 } from "react";
779
+ import { jsx as jsx12 } from "react/jsx-runtime";
780
+ var PopoverItem = forwardRef2(
781
+ function PopoverItem2({ className, children, ...rest }, ref) {
782
+ return /* @__PURE__ */ jsx12(
783
+ "button",
784
+ {
785
+ ref,
786
+ type: "button",
787
+ className: cn(
788
+ "flex w-full cursor-pointer items-center gap-3 px-3 py-1.5 text-left text-xs hover:bg-base-accent",
789
+ className
790
+ ),
791
+ ...rest,
792
+ children
793
+ }
794
+ );
795
+ }
796
+ );
797
+
581
798
  // src/lib/block-dnd.ts
582
799
  var ROOT_CONTAINER_ID = "__root__";
583
800
  function buildBlockDragData(args) {
@@ -596,8 +813,8 @@ function canDropBlock(source, dropContainerId) {
596
813
  }
597
814
 
598
815
  // src/components/shell/EditorContext.tsx
599
- import { createContext as createContext2, useContext as useContext2, useState as useState3, useCallback } from "react";
600
- import { jsx as jsx10 } from "react/jsx-runtime";
816
+ import { createContext as createContext2, useContext as useContext2, useState as useState4, useCallback } from "react";
817
+ import { jsx as jsx13 } from "react/jsx-runtime";
601
818
  var EditorContext = createContext2(null);
602
819
  function useEditorContext() {
603
820
  const context = useContext2(EditorContext);
@@ -611,9 +828,13 @@ function useOptionalEditorContext() {
611
828
  }
612
829
 
613
830
  export {
831
+ Tooltip,
832
+ Kbd,
614
833
  DragHandle2 as DragHandle,
615
834
  DeleteButton,
616
835
  SettingsButton,
836
+ Popover,
837
+ PopoverItem,
617
838
  SettingsForm,
618
839
  buildBlockDragData,
619
840
  buildBlockDropData,