camox 0.34.0 → 0.36.0

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 (80) hide show
  1. package/dist/core/components/lexical/InlineLexicalEditor.js +1 -1
  2. package/dist/core/components/lexical/SidebarLexicalEditor.js +7 -7
  3. package/dist/core/components/lexical/TextLinkPopover.js +4 -4
  4. package/dist/core/createApp.d.ts +2 -1
  5. package/dist/core/createBlock.d.ts +5 -1451
  6. package/dist/core/createBlock.js +449 -1602
  7. package/dist/core/editing/BlockEditingRuntime.js +36 -0
  8. package/dist/core/editing/CompleteBlockEditingRuntime.js +76 -0
  9. package/dist/core/editing/createEditableBlock.d.ts +1455 -0
  10. package/dist/core/editing/createEditableBlock.js +1751 -0
  11. package/dist/core/lib/lexicalState.js +1 -1
  12. package/dist/features/agent-chat/components/AgentChatSidebar.js +1 -1
  13. package/dist/features/content/components/AssetCard.js +1 -1
  14. package/dist/features/page/PublishedPageContent.js +236 -0
  15. package/dist/features/page/PublishedPageExperience.js +23 -0
  16. package/dist/features/preview/CamoxPreview.d.ts +1 -0
  17. package/dist/features/preview/CamoxPreview.js +110 -93
  18. package/dist/features/preview/EditablePageContent.js +3 -0
  19. package/dist/features/preview/EditablePageExperience.js +24 -0
  20. package/dist/features/preview/components/AddBlockSidebar.js +3 -3
  21. package/dist/features/preview/components/AssetFieldEditor.js +1 -1
  22. package/dist/features/preview/components/AssetLightbox.js +47 -111
  23. package/dist/features/preview/components/BlockActionsPopover.js +6 -6
  24. package/dist/features/preview/components/CreatePageModal.js +4 -4
  25. package/dist/features/preview/components/DebouncedFieldEditor.js +2 -2
  26. package/dist/features/preview/components/DraftSwitchDialog.js +1 -1
  27. package/dist/features/preview/components/FieldToolbar.js +3 -3
  28. package/dist/features/preview/components/Frame.js +1 -1
  29. package/dist/features/preview/components/ItemFieldsEditor.js +3 -3
  30. package/dist/features/preview/components/LeftSidebar.js +1 -1
  31. package/dist/features/preview/components/LinkFieldEditor.js +3 -3
  32. package/dist/features/preview/components/Metadata.js +87 -0
  33. package/dist/features/preview/components/MultipleAssetFieldEditor.js +1 -1
  34. package/dist/features/preview/components/OverlayTracker.js +3 -3
  35. package/dist/features/preview/components/Overlays.js +3 -3
  36. package/dist/features/preview/components/PageEditorSidebar.js +40 -30
  37. package/dist/features/preview/components/PageInfoSidebar.js +158 -74
  38. package/dist/features/preview/components/PageLocationFieldset.js +1 -1
  39. package/dist/features/preview/components/PageNavigatorSidebar.js +244 -316
  40. package/dist/features/preview/components/PageNicknameField.js +2 -2
  41. package/dist/features/preview/components/PagePicker.js +3 -3
  42. package/dist/features/preview/components/PageTree.js +3 -3
  43. package/dist/features/preview/components/PeekedBlock.js +2 -2
  44. package/dist/features/preview/components/PreviewPanel.js +2 -2
  45. package/dist/features/preview/components/PreviewToolbar.js +77 -51
  46. package/dist/features/preview/components/PublishDialog.js +2 -2
  47. package/dist/features/preview/components/RepeatableItemsList.js +1 -1
  48. package/dist/features/preview/components/RightSidebar.js +1 -1
  49. package/dist/features/preview/components/useRepeatableItemActions.js +1 -1
  50. package/dist/features/preview/components/useUpdateBlockPosition.js +1 -1
  51. package/dist/features/preview/previewStore.js +13 -6
  52. package/dist/features/provider/AuthenticatedCamoxProvider.js +63 -0
  53. package/dist/features/provider/CamoxProvider.d.ts +5 -12
  54. package/dist/features/provider/CamoxProvider.js +80 -338
  55. package/dist/features/provider/CoreCamoxProvider.js +37 -0
  56. package/dist/features/provider/LocalhostPreviewProvider.js +159 -0
  57. package/dist/features/provider/components/CommandPalette.js +1 -1
  58. package/dist/features/provider/useAdminShortcuts.js +1 -1
  59. package/dist/features/runtime/hydrationData.js +9 -0
  60. package/dist/features/runtime/pageApp.js +148 -35
  61. package/dist/features/runtime/pageClient.d.ts +1 -2
  62. package/dist/features/runtime/pageClient.js +3 -20
  63. package/dist/features/runtime/runtime.d.ts +1 -0
  64. package/dist/features/runtime/studioApp.js +76 -8
  65. package/dist/features/runtime/studioClient.d.ts +6 -0
  66. package/dist/features/runtime/studioClient.js +20 -0
  67. package/dist/features/runtime/studioNavigation.js +7 -2
  68. package/dist/features/studio/CamoxStudio.js +1 -1
  69. package/dist/features/studio/components/EnvironmentMenu.js +2 -2
  70. package/dist/features/studio/components/Navbar.js +5 -5
  71. package/dist/features/studio/components/ProjectMenu.js +5 -5
  72. package/dist/features/studio/useTheme.js +1 -22
  73. package/dist/features/vite/runtimeDev.js +24 -3
  74. package/dist/features/vite/vite.d.ts +1 -1
  75. package/dist/features/vite/vite.js +9 -3
  76. package/dist/lib/normalized-data.js +6 -6
  77. package/dist/lib/telemetry-client.js +2 -2
  78. package/dist/lib/view-queries.js +28 -0
  79. package/dist/studio.css +1 -1
  80. package/package.json +9 -4
@@ -0,0 +1,1751 @@
1
+ import { useLocation } from "../../features/navigation/navigation.js";
2
+ import { useProjectSlug } from "../../lib/auth.js";
3
+ import { isFileMarker, isItemMarker, resolveFileMarker, useNormalizedData } from "../../lib/normalized-data.js";
4
+ import { Type as Type$1, resolveToMarkdown } from "../lib/contentType.js";
5
+ import { buildImageSrcSet, getDefaultImageSizes, getDefaultImageWidth, transformImageUrl } from "../lib/imageTransform.js";
6
+ import { markdownToReactNodes } from "../lib/lexicalReact.js";
7
+ import { blockMutations, pageQueries, projectQueries, repeatableItemMutations } from "../../lib/queries.js";
8
+ import { trackClientEvent } from "../../lib/telemetry-client.js";
9
+ import { previewStore } from "../../features/preview/previewStore.js";
10
+ import { postOverlayMessage } from "../../features/preview/overlayMessages.js";
11
+ import { useFrame } from "../../features/preview/components/Frame.js";
12
+ import { AddBlockControlBar } from "../components/AddBlockControlBar.js";
13
+ import { InlineLexicalEditor } from "../components/lexical/InlineLexicalEditor.js";
14
+ import { useFieldSelection } from "../hooks/useFieldSelection.js";
15
+ import { useIsEditable } from "../hooks/useIsEditable.js";
16
+ import { useOverlayMessage } from "../hooks/useOverlayMessage.js";
17
+ import { c } from "react/compiler-runtime";
18
+ import { Type } from "@sinclair/typebox";
19
+ import { useMutation, useQuery } from "@tanstack/react-query";
20
+ import { generateKeyBetween } from "fractional-indexing";
21
+ import * as React from "react";
22
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
23
+ import { useSelector } from "@xstate/store-react";
24
+ import { Popover, PopoverContent, PopoverTrigger } from "@camox/ui/popover";
25
+ import { Label } from "@camox/ui/label";
26
+ import { Input } from "@camox/ui/input";
27
+ import { createPortal } from "react-dom";
28
+
29
+ //#region src/core/editing/createEditableBlock.tsx
30
+ /** Normalize legacy links (no `type` field) to the new union shape */
31
+ const normalizeLinkValue = (value) => {
32
+ if (!value.type) return {
33
+ type: "external",
34
+ ...value
35
+ };
36
+ return value;
37
+ };
38
+ /**
39
+ * Resolve a LinkValue to an href string.
40
+ *
41
+ * Hash-only and empty hrefs are anchored to `currentPathname` so TanStack Router's
42
+ * `<Link to>` builds the same `href` on SSR and client — bare `"#"` otherwise
43
+ * resolves inconsistently across environments, causing hydration mismatches.
44
+ */
45
+ const resolveLinkHref = (link, pages, currentPathname) => {
46
+ if (link.type === "page") return (pages?.find((p) => String(p.id) === link.pageId))?.fullPath ?? currentPathname;
47
+ if (!link.href || link.href.startsWith("#")) return `${currentPathname}${link.href ?? ""}`;
48
+ return link.href;
49
+ };
50
+ /**
51
+ * Recursively walks schema properties to generate RepeatableItemSeed objects.
52
+ * Sets `_itemId` placeholder markers on `content` for each repeatable field,
53
+ * and pushes seed objects into `allSeeds`.
54
+ */
55
+ function buildInitialSeeds(properties, parentTempId, content, allSeeds, counter) {
56
+ for (const [fieldName, fieldSchema] of Object.entries(properties)) {
57
+ if (fieldSchema.type !== "array" || !fieldSchema.items?.properties) continue;
58
+ const ft = fieldSchema.fieldType;
59
+ if (ft === "ImageList" || ft === "FileList") continue;
60
+ const defaultCount = fieldSchema.defaultItems ?? fieldSchema.minItems ?? 0;
61
+ if (defaultCount <= 0) continue;
62
+ const itemProperties = fieldSchema.items.properties;
63
+ const itemContent = {};
64
+ for (const [propName, propSchema] of Object.entries(itemProperties)) {
65
+ if (propSchema.type === "array" && propSchema.items?.properties) continue;
66
+ if ("default" in propSchema) itemContent[propName] = propSchema.default;
67
+ }
68
+ const itemSettingsDefaults = fieldSchema.defaultItemSettings;
69
+ const markers = [];
70
+ let prevPosition = null;
71
+ for (let i = 0; i < defaultCount; i++) {
72
+ const tempId = `seed_${++counter.value}`;
73
+ const position = generateKeyBetween(prevPosition, null);
74
+ prevPosition = position;
75
+ allSeeds.push({
76
+ tempId,
77
+ parentTempId,
78
+ fieldName,
79
+ content: { ...itemContent },
80
+ settings: itemSettingsDefaults ? { ...itemSettingsDefaults } : void 0,
81
+ position
82
+ });
83
+ markers.push({ _itemId: tempId });
84
+ buildInitialSeeds(itemProperties, tempId, {}, allSeeds, counter);
85
+ }
86
+ content[fieldName] = markers;
87
+ }
88
+ }
89
+ /**
90
+ * Recursively walks schema properties to generate fake repeatable items for peek mode.
91
+ * Sets `_itemId` markers on `content` for each repeatable field,
92
+ * and pushes the corresponding fake items into `allItems`.
93
+ */
94
+ function buildPeekItems(properties, blockId, parentItemId, content, allItems, counter) {
95
+ for (const [fieldName, fieldSchema] of Object.entries(properties)) {
96
+ if (fieldSchema.type !== "array" || !fieldSchema.items?.properties) continue;
97
+ if (fieldSchema.fieldType === "ImageList" || fieldSchema.fieldType === "FileList") continue;
98
+ const defaultCount = fieldSchema.defaultItems ?? fieldSchema.minItems ?? 0;
99
+ if (defaultCount <= 0) continue;
100
+ const itemProperties = fieldSchema.items.properties;
101
+ const itemContent = {};
102
+ for (const [propName, propSchema] of Object.entries(itemProperties)) {
103
+ if (propSchema.type === "array" && propSchema.items?.properties) continue;
104
+ if ("default" in propSchema) itemContent[propName] = propSchema.default;
105
+ }
106
+ const itemSettingsDefaults = fieldSchema.defaultItemSettings;
107
+ const markers = [];
108
+ let prevPosition = null;
109
+ for (let i = 0; i < defaultCount; i++) {
110
+ const itemId = --counter.value;
111
+ const position = generateKeyBetween(prevPosition, null);
112
+ prevPosition = position;
113
+ allItems.push({
114
+ id: itemId,
115
+ blockId,
116
+ parentItemId,
117
+ fieldName,
118
+ content: { ...itemContent },
119
+ settings: itemSettingsDefaults ? { ...itemSettingsDefaults } : null,
120
+ summary: "",
121
+ position,
122
+ createdAt: 0,
123
+ updatedAt: 0
124
+ });
125
+ markers.push({ _itemId: itemId });
126
+ const nestedContent = {};
127
+ buildPeekItems(itemProperties, blockId, itemId, nestedContent, allItems, counter);
128
+ const item = allItems.find((it) => it.id === itemId);
129
+ item.content = {
130
+ ...item.content,
131
+ ...nestedContent
132
+ };
133
+ }
134
+ content[fieldName] = markers;
135
+ }
136
+ }
137
+ function createEditableBlock(options) {
138
+ const typeboxSchema = Type.Object(options.content);
139
+ const contentSchema = {
140
+ type: "object",
141
+ title: options.title,
142
+ description: options.description,
143
+ properties: typeboxSchema.properties,
144
+ required: Object.keys(options.content),
145
+ toMarkdown: resolveToMarkdown(options.toMarkdown, options.settings, "block")
146
+ };
147
+ const settingsTypeboxSchema = options.settings ? Type.Object(options.settings) : null;
148
+ const settingsSchema = settingsTypeboxSchema ? {
149
+ type: "object",
150
+ properties: settingsTypeboxSchema.properties,
151
+ required: Object.keys(options.settings)
152
+ } : void 0;
153
+ const contentDefaults = {};
154
+ const contentDefaultsForStorage = {};
155
+ for (const [key, prop] of Object.entries(typeboxSchema.properties)) if ("default" in prop) {
156
+ contentDefaults[key] = prop.default;
157
+ const ft = prop.fieldType;
158
+ if (ft === "Image" || ft === "File" || ft === "ImageList" || ft === "FileList" || ft === "Repeater") continue;
159
+ contentDefaultsForStorage[key] = prop.default;
160
+ }
161
+ const repeatableItemDefaults = {};
162
+ const repeatableItemSettingsDefaults = {};
163
+ for (const [key, prop] of Object.entries(typeboxSchema.properties)) {
164
+ const p = prop;
165
+ if (p.type === "array" && p.items?.properties) {
166
+ const itemDefaults = {};
167
+ for (const [itemKey, itemProp] of Object.entries(p.items.properties)) if (itemProp && typeof itemProp === "object" && "default" in itemProp) itemDefaults[itemKey] = itemProp.default;
168
+ if (Object.keys(itemDefaults).length > 0) repeatableItemDefaults[key] = itemDefaults;
169
+ if (p.defaultItemSettings && typeof p.defaultItemSettings === "object") repeatableItemSettingsDefaults[key] = p.defaultItemSettings;
170
+ }
171
+ }
172
+ const settingsDefaults = {};
173
+ if (settingsTypeboxSchema) {
174
+ for (const [key, prop] of Object.entries(settingsTypeboxSchema.properties)) if ("default" in prop) settingsDefaults[key] = prop.default;
175
+ }
176
+ const Context = React.createContext(null);
177
+ const RepeaterItemContext = React.createContext(null);
178
+ const RepeaterHoverContext = React.createContext(false);
179
+ /**
180
+ * Build a field ID that matches the sidebar's `getFieldId` format.
181
+ * Root fields: blockId__fieldName
182
+ * Repeater item fields: blockId__itemId__fieldName
183
+ */
184
+ const getOverlayFieldId = (blockId, repeaterContext, fieldName) => {
185
+ if (repeaterContext?.itemId != null) return `${blockId}__${repeaterContext.itemId}__${fieldName}`;
186
+ return `${blockId}__${fieldName}`;
187
+ };
188
+ const Field = ({ name, components, children }) => {
189
+ const blockContext = React.use(Context);
190
+ if (!blockContext) throw new Error("Field must be used within a Block Component");
191
+ const { blockId, content, mode } = blockContext;
192
+ const isContentEditable = useIsEditable(mode);
193
+ const elementRef = React.useRef(null);
194
+ const { window: iframeWindow } = useFrame();
195
+ const projectSlug = useProjectSlug();
196
+ const { data: project } = useQuery(projectQueries.getBySlug(projectSlug));
197
+ const { data: pages } = useQuery({
198
+ ...pageQueries.list(project?.id ?? 0),
199
+ enabled: !!project
200
+ });
201
+ const currentPathname = useLocation({ select: (l) => l.pathname });
202
+ const repeaterContext = React.use(RepeaterItemContext);
203
+ const fieldId = getOverlayFieldId(blockId, repeaterContext, String(name));
204
+ const fieldValue = repeaterContext ? repeaterContext.itemContent[name] : content[name];
205
+ const [isHovered, setIsHovered] = React.useState(false);
206
+ const [isEditorFocused, setIsEditorFocused] = React.useState(false);
207
+ const isSelectedFromSelection = useFieldSelection(blockId, String(name), "String", repeaterContext?.itemId);
208
+ const isFocused = isEditorFocused || isSelectedFromSelection;
209
+ const isHoveredFromSidebar = useOverlayMessage(iframeWindow, isContentEditable, "CAMOX_HOVER_FIELD", "CAMOX_HOVER_FIELD_END", { fieldId });
210
+ React.useEffect(() => {
211
+ setIsHovered(isHoveredFromSidebar);
212
+ }, [isHoveredFromSidebar]);
213
+ const updateBlockContent = useMutation(blockMutations.updateContent());
214
+ const updateRepeatableContent = useMutation(repeatableItemMutations.updateContent());
215
+ const handleChange = React.useCallback((newValue) => {
216
+ if (repeaterContext) {
217
+ const { itemId } = repeaterContext;
218
+ if (itemId != null) updateRepeatableContent.mutate({
219
+ id: itemId,
220
+ content: { [name]: newValue }
221
+ });
222
+ } else updateBlockContent.mutate({
223
+ id: blockId,
224
+ content: { [name]: newValue }
225
+ });
226
+ }, [
227
+ blockId,
228
+ name,
229
+ repeaterContext,
230
+ updateBlockContent,
231
+ updateRepeatableContent
232
+ ]);
233
+ const handleFocus = React.useCallback(() => {
234
+ setIsEditorFocused(true);
235
+ if (repeaterContext?.itemId != null) previewStore.send({
236
+ type: "selectItemField",
237
+ blockId,
238
+ itemId: repeaterContext.itemId,
239
+ fieldName: name.toString(),
240
+ fieldType: "String"
241
+ });
242
+ else previewStore.send({
243
+ type: "selectBlockField",
244
+ blockId,
245
+ fieldName: name.toString(),
246
+ fieldType: "String"
247
+ });
248
+ }, [
249
+ blockId,
250
+ name,
251
+ repeaterContext?.itemId
252
+ ]);
253
+ const handleBlur = React.useCallback((wasEdited) => {
254
+ setIsEditorFocused(false);
255
+ if (wasEdited) trackClientEvent("block_edited", {
256
+ via: "inline-lexical",
257
+ blockType: options.id,
258
+ field: String(name)
259
+ });
260
+ }, [name]);
261
+ const handleMouseEnter = () => {
262
+ if (isContentEditable) setIsHovered(true);
263
+ };
264
+ const handleMouseLeave = () => {
265
+ if (isContentEditable) setIsHovered(false);
266
+ };
267
+ const fieldData = { text: fieldValue };
268
+ if (!isContentEditable) return /* @__PURE__ */ jsx(Fragment, { children: children({ children: markdownToReactNodes(fieldValue, {
269
+ pages,
270
+ fallbackHref: currentPathname,
271
+ components
272
+ }) }, fieldData) });
273
+ return /* @__PURE__ */ jsx(Fragment, { children: children({
274
+ ref: elementRef,
275
+ "data-camox-field-id": fieldId,
276
+ "data-camox-hovered": isHovered || void 0,
277
+ "data-camox-focused": isFocused || void 0,
278
+ "data-camox-overlay-mode": mode === "layout" ? "layout" : void 0,
279
+ onMouseEnter: handleMouseEnter,
280
+ onMouseLeave: handleMouseLeave,
281
+ children: /* @__PURE__ */ jsx(InlineLexicalEditor, {
282
+ initialState: fieldValue,
283
+ externalState: fieldValue,
284
+ onChange: handleChange,
285
+ onFocus: handleFocus,
286
+ onBlur: handleBlur
287
+ })
288
+ }, fieldData) });
289
+ };
290
+ const Embed = (t0) => {
291
+ const $ = c(59);
292
+ if ($[0] !== "e263b48438d7cbcbf7882d7283db437d4762f01fd895729e78d2eda64650183d") {
293
+ for (let $i = 0; $i < 59; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
294
+ $[0] = "e263b48438d7cbcbf7882d7283db437d4762f01fd895729e78d2eda64650183d";
295
+ }
296
+ const { name, children } = t0;
297
+ const blockContext = React.use(Context);
298
+ if (!blockContext) throw new Error("Embed must be used within a Block Component");
299
+ const { blockId, content, mode } = blockContext;
300
+ const isContentEditable = useIsEditable(mode);
301
+ const { window: iframeWindow } = useFrame();
302
+ const repeaterContext = React.use(RepeaterItemContext);
303
+ const fieldValue = repeaterContext ? repeaterContext.itemContent[name] : content[name];
304
+ const t1 = String(name);
305
+ let t2;
306
+ if ($[1] !== blockId || $[2] !== repeaterContext || $[3] !== t1) {
307
+ t2 = getOverlayFieldId(blockId, repeaterContext, t1);
308
+ $[1] = blockId;
309
+ $[2] = repeaterContext;
310
+ $[3] = t1;
311
+ $[4] = t2;
312
+ } else t2 = $[4];
313
+ const fieldId = t2;
314
+ const [isOpen, setIsOpen] = React.useState(false);
315
+ const [urlValue, setUrlValue] = React.useState(fieldValue);
316
+ const [isHovered, setIsHovered] = React.useState(false);
317
+ const timerRef = React.useRef(null);
318
+ let t3;
319
+ if ($[5] !== fieldId) {
320
+ t3 = { fieldId };
321
+ $[5] = fieldId;
322
+ $[6] = t3;
323
+ } else t3 = $[6];
324
+ const isHoveredFromSidebar = useOverlayMessage(iframeWindow, isContentEditable, "CAMOX_HOVER_FIELD", "CAMOX_HOVER_FIELD_END", t3);
325
+ let t4;
326
+ let t5;
327
+ if ($[7] !== isHoveredFromSidebar) {
328
+ t4 = () => {
329
+ setIsHovered(isHoveredFromSidebar);
330
+ };
331
+ t5 = [isHoveredFromSidebar];
332
+ $[7] = isHoveredFromSidebar;
333
+ $[8] = t4;
334
+ $[9] = t5;
335
+ } else {
336
+ t4 = $[8];
337
+ t5 = $[9];
338
+ }
339
+ React.useEffect(t4, t5);
340
+ let t6;
341
+ if ($[10] === Symbol.for("react.memo_cache_sentinel")) {
342
+ t6 = blockMutations.updateContent();
343
+ $[10] = t6;
344
+ } else t6 = $[10];
345
+ const updateBlockContent = useMutation(t6);
346
+ let t7;
347
+ if ($[11] === Symbol.for("react.memo_cache_sentinel")) {
348
+ t7 = repeatableItemMutations.updateContent();
349
+ $[11] = t7;
350
+ } else t7 = $[11];
351
+ const updateRepeatableContent = useMutation(t7);
352
+ let t8;
353
+ let t9;
354
+ if ($[12] !== fieldValue || $[13] !== isOpen) {
355
+ t8 = () => {
356
+ if (!isOpen) setUrlValue(fieldValue);
357
+ };
358
+ t9 = [fieldValue, isOpen];
359
+ $[12] = fieldValue;
360
+ $[13] = isOpen;
361
+ $[14] = t8;
362
+ $[15] = t9;
363
+ } else {
364
+ t8 = $[14];
365
+ t9 = $[15];
366
+ }
367
+ React.useEffect(t8, t9);
368
+ let t10;
369
+ let t11;
370
+ if ($[16] === Symbol.for("react.memo_cache_sentinel")) {
371
+ t10 = () => () => {
372
+ if (timerRef.current) clearTimeout(timerRef.current);
373
+ };
374
+ t11 = [];
375
+ $[16] = t10;
376
+ $[17] = t11;
377
+ } else {
378
+ t10 = $[16];
379
+ t11 = $[17];
380
+ }
381
+ React.useEffect(t10, t11);
382
+ let t12;
383
+ if ($[18] !== blockId || $[19] !== name || $[20] !== repeaterContext || $[21] !== updateBlockContent || $[22] !== updateRepeatableContent) {
384
+ t12 = (e) => {
385
+ const newValue = e.target.value;
386
+ setUrlValue(newValue);
387
+ if (timerRef.current) clearTimeout(timerRef.current);
388
+ timerRef.current = window.setTimeout(() => {
389
+ if (repeaterContext?.itemId != null) updateRepeatableContent.mutate({
390
+ id: repeaterContext.itemId,
391
+ content: { [name]: newValue }
392
+ });
393
+ else updateBlockContent.mutate({
394
+ id: blockId,
395
+ content: { [name]: newValue }
396
+ });
397
+ }, 500);
398
+ };
399
+ $[18] = blockId;
400
+ $[19] = name;
401
+ $[20] = repeaterContext;
402
+ $[21] = updateBlockContent;
403
+ $[22] = updateRepeatableContent;
404
+ $[23] = t12;
405
+ } else t12 = $[23];
406
+ const handleUrlChange = t12;
407
+ let t13;
408
+ if ($[24] !== blockId || $[25] !== name || $[26] !== repeaterContext) {
409
+ t13 = (open, _eventDetails) => {
410
+ setIsOpen(open);
411
+ if (open) if (repeaterContext?.itemId != null) previewStore.send({
412
+ type: "selectItemField",
413
+ blockId,
414
+ itemId: repeaterContext.itemId,
415
+ fieldName: name.toString(),
416
+ fieldType: "Embed"
417
+ });
418
+ else previewStore.send({
419
+ type: "selectBlockField",
420
+ blockId,
421
+ fieldName: name.toString(),
422
+ fieldType: "Embed"
423
+ });
424
+ };
425
+ $[24] = blockId;
426
+ $[25] = name;
427
+ $[26] = repeaterContext;
428
+ $[27] = t13;
429
+ } else t13 = $[27];
430
+ const handleOpenChange = t13;
431
+ const t14 = isContentEditable ? isOpen : false;
432
+ const t15 = isContentEditable ? handleOpenChange : void 0;
433
+ const t16 = isContentEditable ? fieldId : void 0;
434
+ const t17 = isContentEditable ? "embed" : void 0;
435
+ const t18 = isContentEditable && isHovered || void 0;
436
+ const t19 = isContentEditable && isOpen || void 0;
437
+ const t20 = mode === "layout" ? "layout" : void 0;
438
+ let t21;
439
+ if ($[28] !== isContentEditable) {
440
+ t21 = isContentEditable ? () => setIsHovered(true) : void 0;
441
+ $[28] = isContentEditable;
442
+ $[29] = t21;
443
+ } else t21 = $[29];
444
+ let t22;
445
+ if ($[30] !== isContentEditable) {
446
+ t22 = isContentEditable ? () => setIsHovered(false) : void 0;
447
+ $[30] = isContentEditable;
448
+ $[31] = t22;
449
+ } else t22 = $[31];
450
+ let t23;
451
+ if ($[32] !== t16 || $[33] !== t17 || $[34] !== t18 || $[35] !== t19 || $[36] !== t20 || $[37] !== t21 || $[38] !== t22) {
452
+ t23 = /* @__PURE__ */ jsx("div", {
453
+ "data-camox-field-id": t16,
454
+ "data-camox-field-type": t17,
455
+ "data-camox-hovered": t18,
456
+ "data-camox-focused": t19,
457
+ "data-camox-overlay-mode": t20,
458
+ onMouseEnter: t21,
459
+ onMouseLeave: t22
460
+ });
461
+ $[32] = t16;
462
+ $[33] = t17;
463
+ $[34] = t18;
464
+ $[35] = t19;
465
+ $[36] = t20;
466
+ $[37] = t21;
467
+ $[38] = t22;
468
+ $[39] = t23;
469
+ } else t23 = $[39];
470
+ let t24;
471
+ if ($[40] !== children || $[41] !== fieldValue) {
472
+ t24 = children({ src: fieldValue }, { url: fieldValue });
473
+ $[40] = children;
474
+ $[41] = fieldValue;
475
+ $[42] = t24;
476
+ } else t24 = $[42];
477
+ let t25;
478
+ if ($[43] !== isContentEditable) {
479
+ t25 = isContentEditable && /* @__PURE__ */ jsx("div", { style: {
480
+ position: "absolute",
481
+ inset: 0,
482
+ zIndex: 10
483
+ } });
484
+ $[43] = isContentEditable;
485
+ $[44] = t25;
486
+ } else t25 = $[44];
487
+ let t26;
488
+ if ($[45] !== t23 || $[46] !== t24 || $[47] !== t25) {
489
+ t26 = /* @__PURE__ */ jsxs(PopoverTrigger, {
490
+ render: t23,
491
+ nativeButton: false,
492
+ children: [t24, t25]
493
+ });
494
+ $[45] = t23;
495
+ $[46] = t24;
496
+ $[47] = t25;
497
+ $[48] = t26;
498
+ } else t26 = $[48];
499
+ let t27;
500
+ if ($[49] !== handleUrlChange || $[50] !== isContentEditable || $[51] !== name || $[52] !== urlValue) {
501
+ t27 = isContentEditable && /* @__PURE__ */ jsx(PopoverContent, {
502
+ className: "w-96 gap-2",
503
+ children: /* @__PURE__ */ jsxs("form", {
504
+ className: "grid gap-2",
505
+ children: [/* @__PURE__ */ jsx(Label, {
506
+ htmlFor: "url",
507
+ children: options.content[name]?.title ?? String(name)
508
+ }), /* @__PURE__ */ jsx(Input, {
509
+ type: "url",
510
+ id: "url",
511
+ value: urlValue,
512
+ onChange: handleUrlChange
513
+ })]
514
+ })
515
+ });
516
+ $[49] = handleUrlChange;
517
+ $[50] = isContentEditable;
518
+ $[51] = name;
519
+ $[52] = urlValue;
520
+ $[53] = t27;
521
+ } else t27 = $[53];
522
+ let t28;
523
+ if ($[54] !== t14 || $[55] !== t15 || $[56] !== t26 || $[57] !== t27) {
524
+ t28 = /* @__PURE__ */ jsxs(Popover, {
525
+ open: t14,
526
+ onOpenChange: t15,
527
+ children: [t26, t27]
528
+ });
529
+ $[54] = t14;
530
+ $[55] = t15;
531
+ $[56] = t26;
532
+ $[57] = t27;
533
+ $[58] = t28;
534
+ } else t28 = $[58];
535
+ return t28;
536
+ };
537
+ const Link = (t0) => {
538
+ const $ = c(38);
539
+ if ($[0] !== "e263b48438d7cbcbf7882d7283db437d4762f01fd895729e78d2eda64650183d") {
540
+ for (let $i = 0; $i < 38; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
541
+ $[0] = "e263b48438d7cbcbf7882d7283db437d4762f01fd895729e78d2eda64650183d";
542
+ }
543
+ const { name, children } = t0;
544
+ const blockContext = React.use(Context);
545
+ if (!blockContext) throw new Error("Link must be used within a Block Component");
546
+ const { blockId, content, mode } = blockContext;
547
+ const isContentEditable = useIsEditable(mode);
548
+ const elementRef = React.useRef(null);
549
+ const { window: iframeWindow } = useFrame();
550
+ const repeaterContext = React.use(RepeaterItemContext);
551
+ const fieldValue = normalizeLinkValue(repeaterContext ? repeaterContext.itemContent[name] : content[name]);
552
+ let t1;
553
+ if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
554
+ t1 = blockMutations.updateContent();
555
+ $[1] = t1;
556
+ } else t1 = $[1];
557
+ const updateBlockContent = useMutation(t1);
558
+ let t2;
559
+ if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
560
+ t2 = repeatableItemMutations.updateContent();
561
+ $[2] = t2;
562
+ } else t2 = $[2];
563
+ const updateRepeatableContent = useMutation(t2);
564
+ const projectSlug = useProjectSlug();
565
+ let t3;
566
+ if ($[3] !== projectSlug) {
567
+ t3 = projectQueries.getBySlug(projectSlug);
568
+ $[3] = projectSlug;
569
+ $[4] = t3;
570
+ } else t3 = $[4];
571
+ const { data: project } = useQuery(t3);
572
+ let t4;
573
+ if ($[5] !== project?.id) {
574
+ t4 = pageQueries.list(project?.id ?? 0);
575
+ $[5] = project?.id;
576
+ $[6] = t4;
577
+ } else t4 = $[6];
578
+ const t5 = !!project;
579
+ let t6;
580
+ if ($[7] !== t4 || $[8] !== t5) {
581
+ t6 = {
582
+ ...t4,
583
+ enabled: t5
584
+ };
585
+ $[7] = t4;
586
+ $[8] = t5;
587
+ $[9] = t6;
588
+ } else t6 = $[9];
589
+ const { data: pages } = useQuery(t6);
590
+ let t7;
591
+ if ($[10] === Symbol.for("react.memo_cache_sentinel")) {
592
+ t7 = { select: _temp };
593
+ $[10] = t7;
594
+ } else t7 = $[10];
595
+ const resolvedHref = resolveLinkHref(fieldValue, pages, useLocation(t7));
596
+ const fieldId = getOverlayFieldId(blockId, repeaterContext, String(name));
597
+ const [isEditing, setIsEditing] = React.useState(false);
598
+ const [displayText, setDisplayText] = React.useState(fieldValue.text);
599
+ const [isHovered, setIsHovered] = React.useState(false);
600
+ const [isEditorFocused, setIsEditorFocused] = React.useState(false);
601
+ const isSelectedFromSelection = useFieldSelection(blockId, String(name), "Link", repeaterContext?.itemId);
602
+ const isFocused = isEditorFocused || isSelectedFromSelection;
603
+ React.useEffect(() => {
604
+ if (!isEditing) setDisplayText(fieldValue.text);
605
+ }, [fieldValue.text, isEditing]);
606
+ const isHoveredFromSidebar = useOverlayMessage(iframeWindow, isContentEditable, "CAMOX_HOVER_FIELD", "CAMOX_HOVER_FIELD_END", { fieldId });
607
+ let t8;
608
+ let t9;
609
+ if ($[11] !== isHoveredFromSidebar) {
610
+ t8 = () => {
611
+ setIsHovered(isHoveredFromSidebar);
612
+ };
613
+ t9 = [isHoveredFromSidebar];
614
+ $[11] = isHoveredFromSidebar;
615
+ $[12] = t8;
616
+ $[13] = t9;
617
+ } else {
618
+ t8 = $[12];
619
+ t9 = $[13];
620
+ }
621
+ React.useEffect(t8, t9);
622
+ let t10;
623
+ if ($[14] !== blockId || $[15] !== name || $[16] !== repeaterContext || $[17] !== updateBlockContent || $[18] !== updateRepeatableContent) {
624
+ t10 = (newLinkValue) => {
625
+ if (repeaterContext?.itemId != null) updateRepeatableContent.mutate({
626
+ id: repeaterContext.itemId,
627
+ content: { [name]: newLinkValue }
628
+ });
629
+ else updateBlockContent.mutate({
630
+ id: blockId,
631
+ content: { [name]: newLinkValue }
632
+ });
633
+ };
634
+ $[14] = blockId;
635
+ $[15] = name;
636
+ $[16] = repeaterContext;
637
+ $[17] = updateBlockContent;
638
+ $[18] = updateRepeatableContent;
639
+ $[19] = t10;
640
+ } else t10 = $[19];
641
+ const saveLinkValue = t10;
642
+ const handleInput = (e) => {
643
+ const newText = e.target.textContent || "";
644
+ saveLinkValue({
645
+ ...fieldValue,
646
+ text: newText
647
+ });
648
+ };
649
+ let t11;
650
+ if ($[20] !== blockId || $[21] !== name || $[22] !== repeaterContext) {
651
+ t11 = () => {
652
+ setIsEditing(true);
653
+ setIsEditorFocused(true);
654
+ if (repeaterContext?.itemId != null) previewStore.send({
655
+ type: "selectItemField",
656
+ blockId,
657
+ itemId: repeaterContext.itemId,
658
+ fieldName: String(name),
659
+ fieldType: "Link"
660
+ });
661
+ else previewStore.send({
662
+ type: "selectBlockField",
663
+ blockId,
664
+ fieldName: String(name),
665
+ fieldType: "Link"
666
+ });
667
+ };
668
+ $[20] = blockId;
669
+ $[21] = name;
670
+ $[22] = repeaterContext;
671
+ $[23] = t11;
672
+ } else t11 = $[23];
673
+ const handleFocus = t11;
674
+ let t12;
675
+ if ($[24] === Symbol.for("react.memo_cache_sentinel")) {
676
+ t12 = () => {
677
+ setIsEditing(false);
678
+ setIsEditorFocused(false);
679
+ };
680
+ $[24] = t12;
681
+ } else t12 = $[24];
682
+ const handleBlur = t12;
683
+ let t13;
684
+ if ($[25] === Symbol.for("react.memo_cache_sentinel")) {
685
+ t13 = (e_0) => {
686
+ e_0.stopPropagation();
687
+ previewStore.send({ type: "toggleContentSheet" });
688
+ setIsEditorFocused(false);
689
+ setIsEditing(false);
690
+ };
691
+ $[25] = t13;
692
+ } else t13 = $[25];
693
+ const handleEditLink = t13;
694
+ const linkData = {
695
+ text: displayText,
696
+ href: resolvedHref,
697
+ newTab: fieldValue.newTab
698
+ };
699
+ if (!isContentEditable) return /* @__PURE__ */ jsx(Fragment, { children: children({
700
+ to: resolvedHref,
701
+ target: fieldValue.newTab ? "_blank" : void 0,
702
+ rel: fieldValue.newTab ? "noreferrer" : void 0,
703
+ children: fieldValue.text
704
+ }, linkData) });
705
+ let t14;
706
+ let t15;
707
+ if ($[26] === Symbol.for("react.memo_cache_sentinel")) {
708
+ t14 = () => setIsHovered(true);
709
+ t15 = () => setIsHovered(false);
710
+ $[26] = t14;
711
+ $[27] = t15;
712
+ } else {
713
+ t14 = $[26];
714
+ t15 = $[27];
715
+ }
716
+ const linkProps = {
717
+ ref: elementRef,
718
+ to: resolvedHref,
719
+ target: fieldValue.newTab ? "_blank" : void 0,
720
+ rel: fieldValue.newTab ? "noreferrer" : void 0,
721
+ children: displayText,
722
+ "data-camox-field-id": fieldId,
723
+ "data-camox-hovered": isHovered || void 0,
724
+ "data-camox-focused": isFocused || void 0,
725
+ "data-camox-overlay-mode": mode === "layout" ? "layout" : void 0,
726
+ contentEditable: true,
727
+ onClick: _temp2,
728
+ onInput: handleInput,
729
+ onFocus: handleFocus,
730
+ onBlur: handleBlur,
731
+ onMouseEnter: t14,
732
+ onMouseLeave: t15,
733
+ onKeyDown: _temp3,
734
+ spellCheck: false,
735
+ suppressContentEditableWarning: true
736
+ };
737
+ const T0 = Popover;
738
+ const t16 = children(linkProps, linkData);
739
+ let t17;
740
+ if ($[28] !== handleEditLink) {
741
+ t17 = /* @__PURE__ */ jsx("button", {
742
+ type: "button",
743
+ className: "hover:bg-accent flex items-center gap-1.5 rounded-md px-2 py-1 text-sm transition-colors",
744
+ onMouseDown: _temp4,
745
+ onClick: handleEditLink,
746
+ children: "Edit link"
747
+ });
748
+ $[28] = handleEditLink;
749
+ $[29] = t17;
750
+ } else t17 = $[29];
751
+ let t18;
752
+ if ($[30] !== elementRef || $[31] !== t17) {
753
+ t18 = /* @__PURE__ */ jsx(PopoverContent, {
754
+ className: "w-auto p-2",
755
+ initialFocus: false,
756
+ anchor: elementRef,
757
+ align: "end",
758
+ children: t17
759
+ });
760
+ $[30] = elementRef;
761
+ $[31] = t17;
762
+ $[32] = t18;
763
+ } else t18 = $[32];
764
+ let t19;
765
+ if ($[33] !== T0 || $[34] !== isEditorFocused || $[35] !== t16 || $[36] !== t18) {
766
+ t19 = /* @__PURE__ */ jsxs(T0, {
767
+ open: isEditorFocused,
768
+ children: [t16, t18]
769
+ });
770
+ $[33] = T0;
771
+ $[34] = isEditorFocused;
772
+ $[35] = t16;
773
+ $[36] = t18;
774
+ $[37] = t19;
775
+ } else t19 = $[37];
776
+ return t19;
777
+ };
778
+ const Image = (t0) => {
779
+ const $ = c(22);
780
+ if ($[0] !== "e263b48438d7cbcbf7882d7283db437d4762f01fd895729e78d2eda64650183d") {
781
+ for (let $i = 0; $i < 22; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
782
+ $[0] = "e263b48438d7cbcbf7882d7283db437d4762f01fd895729e78d2eda64650183d";
783
+ }
784
+ const { name, children } = t0;
785
+ const blockContext = React.use(Context);
786
+ if (!blockContext) throw new Error("Image must be used within a Block Component");
787
+ const { blockId, content, mode } = blockContext;
788
+ const isContentEditable = useIsEditable(mode);
789
+ const { window: iframeWindow } = useFrame();
790
+ const repeaterContext = React.use(RepeaterItemContext);
791
+ const { filesMap } = useNormalizedData();
792
+ const rawSource = repeaterContext ? repeaterContext.itemContent[name] : content[name];
793
+ const rawValue = isFileMarker(rawSource) ? resolveFileMarker(rawSource, filesMap) : rawSource;
794
+ const defaultValue = repeaterContext ? repeatableItemDefaults[repeaterContext.arrayFieldName]?.[String(name)] : contentDefaults[String(name)];
795
+ const fieldValue = rawValue ?? defaultValue;
796
+ const isInlineArrayItem = repeaterContext != null && repeaterContext.itemId == null;
797
+ const overlayFieldName = isInlineArrayItem ? repeaterContext.arrayFieldName : String(name);
798
+ const overlayItemId = isInlineArrayItem ? repeaterContext.containerItemId : repeaterContext?.itemId;
799
+ const fieldId = overlayItemId != null ? `${blockId}__${overlayItemId}__${overlayFieldName}` : `${blockId}__${overlayFieldName}`;
800
+ const [isHovered, setIsHovered] = React.useState(false);
801
+ const isFocused = useFieldSelection(blockId, overlayFieldName, "Image", overlayItemId);
802
+ let t1;
803
+ if ($[1] !== fieldId) {
804
+ t1 = { fieldId };
805
+ $[1] = fieldId;
806
+ $[2] = t1;
807
+ } else t1 = $[2];
808
+ const isHoveredFromSidebar = useOverlayMessage(iframeWindow, isContentEditable, "CAMOX_HOVER_FIELD", "CAMOX_HOVER_FIELD_END", t1);
809
+ let t2;
810
+ let t3;
811
+ if ($[3] !== isHoveredFromSidebar) {
812
+ t2 = () => {
813
+ setIsHovered(isHoveredFromSidebar);
814
+ };
815
+ t3 = [isHoveredFromSidebar];
816
+ $[3] = isHoveredFromSidebar;
817
+ $[4] = t2;
818
+ $[5] = t3;
819
+ } else {
820
+ t2 = $[4];
821
+ t3 = $[5];
822
+ }
823
+ React.useEffect(t2, t3);
824
+ let t4;
825
+ if ($[6] !== blockId || $[7] !== isContentEditable || $[8] !== overlayFieldName || $[9] !== overlayItemId) {
826
+ t4 = () => {
827
+ if (!isContentEditable) return;
828
+ if (overlayItemId != null) previewStore.send({
829
+ type: "selectItemField",
830
+ blockId,
831
+ itemId: overlayItemId,
832
+ fieldName: overlayFieldName,
833
+ fieldType: "Image"
834
+ });
835
+ else previewStore.send({
836
+ type: "selectBlockField",
837
+ blockId,
838
+ fieldName: overlayFieldName,
839
+ fieldType: "Image"
840
+ });
841
+ previewStore.send({ type: "toggleContentSheet" });
842
+ };
843
+ $[6] = blockId;
844
+ $[7] = isContentEditable;
845
+ $[8] = overlayFieldName;
846
+ $[9] = overlayItemId;
847
+ $[10] = t4;
848
+ } else t4 = $[10];
849
+ const handleClick = t4;
850
+ const imageProps = {
851
+ src: transformImageUrl(fieldValue.url, {
852
+ width: getDefaultImageWidth(),
853
+ mimeType: fieldValue.mimeType,
854
+ size: fieldValue.size
855
+ }),
856
+ srcSet: buildImageSrcSet(fieldValue.url, fieldValue.mimeType, fieldValue.size),
857
+ sizes: getDefaultImageSizes(),
858
+ alt: fieldValue.alt
859
+ };
860
+ if (!isContentEditable) return /* @__PURE__ */ jsx(Fragment, { children: children(imageProps, fieldValue) });
861
+ const t5 = "image";
862
+ const t6 = isHovered || void 0;
863
+ const t7 = isFocused || void 0;
864
+ const t8 = mode === "layout" ? "layout" : void 0;
865
+ let t10;
866
+ let t9;
867
+ if ($[11] === Symbol.for("react.memo_cache_sentinel")) {
868
+ t9 = () => setIsHovered(true);
869
+ t10 = () => setIsHovered(false);
870
+ $[11] = t10;
871
+ $[12] = t9;
872
+ } else {
873
+ t10 = $[11];
874
+ t9 = $[12];
875
+ }
876
+ const t11 = children(imageProps, fieldValue);
877
+ let t12;
878
+ if ($[13] !== fieldId || $[14] !== handleClick || $[15] !== t10 || $[16] !== t11 || $[17] !== t6 || $[18] !== t7 || $[19] !== t8 || $[20] !== t9) {
879
+ t12 = /* @__PURE__ */ jsx("div", {
880
+ "data-camox-field-id": fieldId,
881
+ "data-camox-field-type": t5,
882
+ "data-camox-hovered": t6,
883
+ "data-camox-focused": t7,
884
+ "data-camox-overlay-mode": t8,
885
+ onMouseEnter: t9,
886
+ onMouseLeave: t10,
887
+ onClick: handleClick,
888
+ children: t11
889
+ });
890
+ $[13] = fieldId;
891
+ $[14] = handleClick;
892
+ $[15] = t10;
893
+ $[16] = t11;
894
+ $[17] = t6;
895
+ $[18] = t7;
896
+ $[19] = t8;
897
+ $[20] = t9;
898
+ $[21] = t12;
899
+ } else t12 = $[21];
900
+ return t12;
901
+ };
902
+ const File = (t0) => {
903
+ const $ = c(9);
904
+ if ($[0] !== "e263b48438d7cbcbf7882d7283db437d4762f01fd895729e78d2eda64650183d") {
905
+ for (let $i = 0; $i < 9; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
906
+ $[0] = "e263b48438d7cbcbf7882d7283db437d4762f01fd895729e78d2eda64650183d";
907
+ }
908
+ const { name, children } = t0;
909
+ const blockContext = React.use(Context);
910
+ if (!blockContext) throw new Error("File must be used within a Block Component");
911
+ const { content } = blockContext;
912
+ const repeaterContext = React.use(RepeaterItemContext);
913
+ const { filesMap } = useNormalizedData();
914
+ const rawSource = repeaterContext ? repeaterContext.itemContent[name] : content[name];
915
+ let t1;
916
+ if ($[1] !== children || $[2] !== filesMap || $[3] !== name || $[4] !== rawSource || $[5] !== repeaterContext) {
917
+ const rawValue = isFileMarker(rawSource) ? resolveFileMarker(rawSource, filesMap) : rawSource;
918
+ const defaultValue = repeaterContext ? repeatableItemDefaults[repeaterContext.arrayFieldName]?.[String(name)] : contentDefaults[String(name)];
919
+ const fieldValue = rawValue ?? defaultValue;
920
+ t1 = children({
921
+ href: fieldValue.url,
922
+ download: fieldValue.filename
923
+ }, fieldValue);
924
+ $[1] = children;
925
+ $[2] = filesMap;
926
+ $[3] = name;
927
+ $[4] = rawSource;
928
+ $[5] = repeaterContext;
929
+ $[6] = t1;
930
+ } else t1 = $[6];
931
+ let t2;
932
+ if ($[7] !== t1) {
933
+ t2 = /* @__PURE__ */ jsx(Fragment, { children: t1 });
934
+ $[7] = t1;
935
+ $[8] = t2;
936
+ } else t2 = $[8];
937
+ return t2;
938
+ };
939
+ const ASSET_LIST_SELF_KEY = "__camox_asset_self__";
940
+ const _AssetList = ({ name, children }) => {
941
+ const blockContext = React.use(Context);
942
+ if (!blockContext) throw new Error("ImageList/FileList must be used within a Block Component");
943
+ const parentRepeaterContext = React.use(RepeaterItemContext);
944
+ const { filesMap } = useNormalizedData();
945
+ const fieldName = String(name);
946
+ const fieldSchema = parentRepeaterContext ? typeboxSchema.properties[parentRepeaterContext.arrayFieldName]?.items?.properties?.[fieldName] : typeboxSchema.properties[fieldName];
947
+ const ft = fieldSchema?.fieldType;
948
+ if (ft !== "ImageList" && ft !== "FileList") throw new Error(`"${fieldName}" is not a Type.ImageList or Type.FileList field`);
949
+ const source = parentRepeaterContext ? parentRepeaterContext.itemContent[fieldName] : blockContext.content[fieldName];
950
+ let arr = Array.isArray(source) ? source : [];
951
+ if (arr.length === 0) {
952
+ const defaultCount = fieldSchema.defaultItems ?? 0;
953
+ const itemDefault = fieldSchema.items?.default;
954
+ if (defaultCount > 0 && itemDefault) arr = Array.from({ length: defaultCount }, () => itemDefault);
955
+ }
956
+ const resolved = arr.map((v) => isFileMarker(v) ? resolveFileMarker(v, filesMap) : v).filter((v) => v != null && typeof v === "object" && "url" in v);
957
+ const Single = ft === "ImageList" ? Image : File;
958
+ return /* @__PURE__ */ jsx(RepeaterHoverProvider, {
959
+ blockId: blockContext.blockId,
960
+ fieldName,
961
+ children: resolved.map((value, index) => /* @__PURE__ */ jsx(RepeaterItemContext.Provider, {
962
+ value: {
963
+ arrayFieldName: fieldName,
964
+ itemIndex: index,
965
+ itemContent: { [ASSET_LIST_SELF_KEY]: value },
966
+ itemSettings: {},
967
+ itemId: void 0,
968
+ containerItemId: parentRepeaterContext?.itemId ?? parentRepeaterContext?.containerItemId
969
+ },
970
+ children: /* @__PURE__ */ jsx(Single, {
971
+ name: ASSET_LIST_SELF_KEY,
972
+ children
973
+ })
974
+ }, index))
975
+ });
976
+ };
977
+ const ImageList = _AssetList;
978
+ const FileList = _AssetList;
979
+ const RepeaterItemWrapper = (t0) => {
980
+ const $ = c(9);
981
+ if ($[0] !== "e263b48438d7cbcbf7882d7283db437d4762f01fd895729e78d2eda64650183d") {
982
+ for (let $i = 0; $i < 9; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
983
+ $[0] = "e263b48438d7cbcbf7882d7283db437d4762f01fd895729e78d2eda64650183d";
984
+ }
985
+ const { itemId, blockId, mode, children } = t0;
986
+ const isContentEditable = useIsEditable(mode);
987
+ const { window: iframeWindow } = useFrame();
988
+ const isRepeaterHovered = React.useContext(RepeaterHoverContext);
989
+ const t1 = String(blockId);
990
+ const t2 = String(itemId);
991
+ let t3;
992
+ if ($[1] !== t1 || $[2] !== t2) {
993
+ t3 = {
994
+ blockId: t1,
995
+ itemId: t2
996
+ };
997
+ $[1] = t1;
998
+ $[2] = t2;
999
+ $[3] = t3;
1000
+ } else t3 = $[3];
1001
+ const isHovered = useOverlayMessage(iframeWindow, isContentEditable, "CAMOX_HOVER_REPEATER_ITEM", "CAMOX_HOVER_REPEATER_ITEM_END", t3);
1002
+ const showOverlay = isContentEditable && (isHovered || isRepeaterHovered);
1003
+ const t4 = isContentEditable ? itemId : void 0;
1004
+ const t5 = showOverlay || void 0;
1005
+ const t6 = mode === "layout" ? "layout" : void 0;
1006
+ let t7;
1007
+ if ($[4] !== children || $[5] !== t4 || $[6] !== t5 || $[7] !== t6) {
1008
+ t7 = /* @__PURE__ */ jsx("div", {
1009
+ "data-camox-repeater-item-id": t4,
1010
+ "data-camox-hovered": t5,
1011
+ "data-camox-overlay-mode": t6,
1012
+ children
1013
+ });
1014
+ $[4] = children;
1015
+ $[5] = t4;
1016
+ $[6] = t5;
1017
+ $[7] = t6;
1018
+ $[8] = t7;
1019
+ } else t7 = $[8];
1020
+ return t7;
1021
+ };
1022
+ const RepeaterHoverProvider = (t0) => {
1023
+ const $ = c(7);
1024
+ if ($[0] !== "e263b48438d7cbcbf7882d7283db437d4762f01fd895729e78d2eda64650183d") {
1025
+ for (let $i = 0; $i < 7; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
1026
+ $[0] = "e263b48438d7cbcbf7882d7283db437d4762f01fd895729e78d2eda64650183d";
1027
+ }
1028
+ const { blockId, fieldName, children } = t0;
1029
+ const isContentEditable = useIsEditable("site");
1030
+ const { window: iframeWindow } = useFrame();
1031
+ const t1 = String(blockId);
1032
+ let t2;
1033
+ if ($[1] !== fieldName || $[2] !== t1) {
1034
+ t2 = {
1035
+ blockId: t1,
1036
+ fieldName
1037
+ };
1038
+ $[1] = fieldName;
1039
+ $[2] = t1;
1040
+ $[3] = t2;
1041
+ } else t2 = $[3];
1042
+ const isHovered = useOverlayMessage(iframeWindow, isContentEditable, "CAMOX_HOVER_REPEATER", "CAMOX_HOVER_REPEATER_END", t2);
1043
+ let t3;
1044
+ if ($[4] !== children || $[5] !== isHovered) {
1045
+ t3 = /* @__PURE__ */ jsx(RepeaterHoverContext.Provider, {
1046
+ value: isHovered,
1047
+ children
1048
+ });
1049
+ $[4] = children;
1050
+ $[5] = isHovered;
1051
+ $[6] = t3;
1052
+ } else t3 = $[6];
1053
+ return t3;
1054
+ };
1055
+ const Repeater = (t0) => {
1056
+ const $ = c(27);
1057
+ if ($[0] !== "e263b48438d7cbcbf7882d7283db437d4762f01fd895729e78d2eda64650183d") {
1058
+ for (let $i = 0; $i < 27; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
1059
+ $[0] = "e263b48438d7cbcbf7882d7283db437d4762f01fd895729e78d2eda64650183d";
1060
+ }
1061
+ const { name, children } = t0;
1062
+ const blockContext = React.use(Context);
1063
+ if (!blockContext) throw new Error("Repeater must be used within a Block Component");
1064
+ const { blockId, content, mode } = blockContext;
1065
+ const parentRepeaterContext = React.use(RepeaterItemContext);
1066
+ const fieldName = String(name);
1067
+ const ItemField = Field;
1068
+ const ItemLink = Link;
1069
+ const ItemEmbed = Embed;
1070
+ const ItemImage = Image;
1071
+ const ItemImageList = _AssetList;
1072
+ const ItemFileList = _AssetList;
1073
+ const ItemFile = File;
1074
+ const ItemRepeater = Repeater;
1075
+ const source = parentRepeaterContext ? parentRepeaterContext.itemContent[name] : content[name];
1076
+ const { itemsMap } = useNormalizedData();
1077
+ let T0;
1078
+ let t1;
1079
+ let t2;
1080
+ let t3;
1081
+ if ($[1] !== blockId || $[2] !== children || $[3] !== fieldName || $[4] !== itemsMap || $[5] !== mode || $[6] !== name || $[7] !== parentRepeaterContext?.containerItemId || $[8] !== source) {
1082
+ let arrayValue = source ?? [];
1083
+ if (!Array.isArray(arrayValue)) throw new Error(`Field "${String(name)}" is not an array`);
1084
+ let t4;
1085
+ if ($[13] !== itemsMap) {
1086
+ t4 = (item) => {
1087
+ if (isItemMarker(item)) return itemsMap.get(item._itemId) ?? null;
1088
+ return item;
1089
+ };
1090
+ $[13] = itemsMap;
1091
+ $[14] = t4;
1092
+ } else t4 = $[14];
1093
+ arrayValue = arrayValue.map(t4).filter(Boolean);
1094
+ const settingsDefaultsForField = repeatableItemSettingsDefaults[fieldName];
1095
+ T0 = RepeaterHoverProvider;
1096
+ t1 = blockId;
1097
+ t2 = fieldName;
1098
+ let t5;
1099
+ if ($[15] !== blockId || $[16] !== children || $[17] !== fieldName || $[18] !== mode || $[19] !== parentRepeaterContext?.containerItemId || $[20] !== settingsDefaultsForField) {
1100
+ t5 = (item_0, index) => {
1101
+ const isDbItem = item_0.content !== void 0 && item_0.id != null;
1102
+ const itemContent = {
1103
+ ...repeatableItemDefaults[fieldName],
1104
+ ...isDbItem ? item_0.content : item_0
1105
+ };
1106
+ const itemSettings = {
1107
+ ...settingsDefaultsForField,
1108
+ ...isDbItem ? item_0.settings : null
1109
+ };
1110
+ const itemId = isDbItem ? item_0.id : void 0;
1111
+ const useItemSetting = (settingName) => itemSettings[settingName];
1112
+ const itemApi = {
1113
+ Field: ItemField,
1114
+ Link: ItemLink,
1115
+ Embed: ItemEmbed,
1116
+ Image: ItemImage,
1117
+ File: ItemFile,
1118
+ ImageList: ItemImageList,
1119
+ FileList: ItemFileList,
1120
+ Repeater: ItemRepeater,
1121
+ useSetting: useItemSetting
1122
+ };
1123
+ return /* @__PURE__ */ jsx(RepeaterItemContext.Provider, {
1124
+ value: {
1125
+ arrayFieldName: fieldName,
1126
+ itemIndex: index,
1127
+ itemContent,
1128
+ itemSettings,
1129
+ itemId,
1130
+ containerItemId: itemId ?? parentRepeaterContext?.containerItemId
1131
+ },
1132
+ children: /* @__PURE__ */ jsx(RepeaterItemWrapper, {
1133
+ itemId,
1134
+ blockId,
1135
+ mode,
1136
+ children: children(itemApi, index)
1137
+ })
1138
+ }, itemId ?? index);
1139
+ };
1140
+ $[15] = blockId;
1141
+ $[16] = children;
1142
+ $[17] = fieldName;
1143
+ $[18] = mode;
1144
+ $[19] = parentRepeaterContext?.containerItemId;
1145
+ $[20] = settingsDefaultsForField;
1146
+ $[21] = t5;
1147
+ } else t5 = $[21];
1148
+ t3 = arrayValue.map(t5);
1149
+ $[1] = blockId;
1150
+ $[2] = children;
1151
+ $[3] = fieldName;
1152
+ $[4] = itemsMap;
1153
+ $[5] = mode;
1154
+ $[6] = name;
1155
+ $[7] = parentRepeaterContext?.containerItemId;
1156
+ $[8] = source;
1157
+ $[9] = T0;
1158
+ $[10] = t1;
1159
+ $[11] = t2;
1160
+ $[12] = t3;
1161
+ } else {
1162
+ T0 = $[9];
1163
+ t1 = $[10];
1164
+ t2 = $[11];
1165
+ t3 = $[12];
1166
+ }
1167
+ let t4;
1168
+ if ($[22] !== T0 || $[23] !== t1 || $[24] !== t2 || $[25] !== t3) {
1169
+ t4 = /* @__PURE__ */ jsx(T0, {
1170
+ blockId: t1,
1171
+ fieldName: t2,
1172
+ children: t3
1173
+ });
1174
+ $[22] = T0;
1175
+ $[23] = t1;
1176
+ $[24] = t2;
1177
+ $[25] = t3;
1178
+ $[26] = t4;
1179
+ } else t4 = $[26];
1180
+ return t4;
1181
+ };
1182
+ const BlockComponent = (t0) => {
1183
+ const $ = c(78);
1184
+ if ($[0] !== "e263b48438d7cbcbf7882d7283db437d4762f01fd895729e78d2eda64650183d") {
1185
+ for (let $i = 0; $i < 78; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
1186
+ $[0] = "e263b48438d7cbcbf7882d7283db437d4762f01fd895729e78d2eda64650183d";
1187
+ }
1188
+ const { blockData, mode, isFirstBlock, showAddBlockTop, showAddBlockBottom, addBlockAfterPosition } = t0;
1189
+ const isContentEditable = useIsEditable(mode);
1190
+ const { window: iframeWindow } = useFrame();
1191
+ const [isHovered, setIsHovered] = React.useState(false);
1192
+ const selection = useSelector(previewStore, _temp5);
1193
+ const isPageEditorSidebarOpen = useSelector(previewStore, _temp6);
1194
+ const isAddBlockSidebarOpen = useSelector(previewStore, _temp7);
1195
+ const pendingAgentBlockFocus = useSelector(previewStore, _temp8);
1196
+ const isBlockSelected = selection?.blockId === blockData._id;
1197
+ const ref = React.useRef(null);
1198
+ const [isFirstRender, setIsFirstRender] = React.useState(true);
1199
+ let t1;
1200
+ let t2;
1201
+ if ($[1] !== isFirstRender) {
1202
+ t1 = () => {
1203
+ if (isFirstRender) setIsFirstRender(false);
1204
+ };
1205
+ t2 = [isFirstRender];
1206
+ $[1] = isFirstRender;
1207
+ $[2] = t1;
1208
+ $[3] = t2;
1209
+ } else {
1210
+ t1 = $[2];
1211
+ t2 = $[3];
1212
+ }
1213
+ React.useEffect(t1, t2);
1214
+ let t3;
1215
+ if ($[4] !== blockData._id || $[5] !== isBlockSelected || $[6] !== isFirstRender || $[7] !== pendingAgentBlockFocus?.blockId) {
1216
+ t3 = () => {
1217
+ if (!isBlockSelected || !ref.current) return;
1218
+ if (pendingAgentBlockFocus?.blockId === blockData._id) return;
1219
+ ref.current.scrollIntoView({
1220
+ behavior: isFirstRender ? "instant" : "smooth",
1221
+ block: isFirstRender ? "start" : "nearest"
1222
+ });
1223
+ };
1224
+ $[4] = blockData._id;
1225
+ $[5] = isBlockSelected;
1226
+ $[6] = isFirstRender;
1227
+ $[7] = pendingAgentBlockFocus?.blockId;
1228
+ $[8] = t3;
1229
+ } else t3 = $[8];
1230
+ let t4;
1231
+ if ($[9] !== blockData._id || $[10] !== isBlockSelected || $[11] !== isFirstRender || $[12] !== isPageEditorSidebarOpen || $[13] !== pendingAgentBlockFocus) {
1232
+ t4 = [
1233
+ blockData._id,
1234
+ isBlockSelected,
1235
+ isFirstRender,
1236
+ isPageEditorSidebarOpen,
1237
+ pendingAgentBlockFocus
1238
+ ];
1239
+ $[9] = blockData._id;
1240
+ $[10] = isBlockSelected;
1241
+ $[11] = isFirstRender;
1242
+ $[12] = isPageEditorSidebarOpen;
1243
+ $[13] = pendingAgentBlockFocus;
1244
+ $[14] = t4;
1245
+ } else t4 = $[14];
1246
+ React.useEffect(t3, t4);
1247
+ let t5;
1248
+ let t6;
1249
+ if ($[15] !== blockData._id || $[16] !== pendingAgentBlockFocus) {
1250
+ t5 = () => {
1251
+ if (!pendingAgentBlockFocus || pendingAgentBlockFocus.blockId !== blockData._id) return;
1252
+ if (!ref.current) return;
1253
+ ref.current.scrollIntoView({
1254
+ behavior: "smooth",
1255
+ block: "nearest"
1256
+ });
1257
+ previewStore.send({
1258
+ type: "clearPendingAgentBlockFocus",
1259
+ requestId: pendingAgentBlockFocus.requestId
1260
+ });
1261
+ };
1262
+ t6 = [blockData._id, pendingAgentBlockFocus];
1263
+ $[15] = blockData._id;
1264
+ $[16] = pendingAgentBlockFocus;
1265
+ $[17] = t5;
1266
+ $[18] = t6;
1267
+ } else {
1268
+ t5 = $[17];
1269
+ t6 = $[18];
1270
+ }
1271
+ React.useEffect(t5, t6);
1272
+ const t7 = String(blockData._id);
1273
+ let t8;
1274
+ if ($[19] !== t7) {
1275
+ t8 = { blockId: t7 };
1276
+ $[19] = t7;
1277
+ $[20] = t8;
1278
+ } else t8 = $[20];
1279
+ const isHoveredFromSidebar = useOverlayMessage(iframeWindow, isContentEditable, "CAMOX_HOVER_BLOCK", "CAMOX_HOVER_BLOCK_END", t8);
1280
+ let t10;
1281
+ let t9;
1282
+ if ($[21] !== isHoveredFromSidebar) {
1283
+ t9 = () => {
1284
+ setIsHovered(isHoveredFromSidebar);
1285
+ };
1286
+ t10 = [isHoveredFromSidebar];
1287
+ $[21] = isHoveredFromSidebar;
1288
+ $[22] = t10;
1289
+ $[23] = t9;
1290
+ } else {
1291
+ t10 = $[22];
1292
+ t9 = $[23];
1293
+ }
1294
+ React.useEffect(t9, t10);
1295
+ let result;
1296
+ if ($[24] !== blockData.content) {
1297
+ result = { ...blockData.content };
1298
+ for (const key in result) {
1299
+ const value = result[key];
1300
+ if (Array.isArray(value) && value.length > 0 && value[0]?.content !== void 0) result[key] = value.map(_temp9);
1301
+ }
1302
+ $[24] = blockData.content;
1303
+ $[25] = result;
1304
+ } else result = $[25];
1305
+ const normalizedContent = result;
1306
+ let t11;
1307
+ if ($[26] !== blockData._id || $[27] !== isContentEditable) {
1308
+ t11 = (e) => {
1309
+ if (!isContentEditable) return;
1310
+ if (e.target.closest("[data-camox-field-id]")) return;
1311
+ previewStore.send({
1312
+ type: "setFocusedBlock",
1313
+ blockId: blockData._id
1314
+ });
1315
+ };
1316
+ $[26] = blockData._id;
1317
+ $[27] = isContentEditable;
1318
+ $[28] = t11;
1319
+ } else t11 = $[28];
1320
+ const handleClick = t11;
1321
+ let t12;
1322
+ if ($[29] !== isContentEditable) {
1323
+ t12 = () => {
1324
+ if (isContentEditable) setIsHovered(true);
1325
+ };
1326
+ $[29] = isContentEditable;
1327
+ $[30] = t12;
1328
+ } else t12 = $[30];
1329
+ const handleMouseEnter = t12;
1330
+ let t13;
1331
+ if ($[31] !== isContentEditable) {
1332
+ t13 = () => {
1333
+ if (isContentEditable) setIsHovered(false);
1334
+ };
1335
+ $[31] = isContentEditable;
1336
+ $[32] = t13;
1337
+ } else t13 = $[32];
1338
+ const handleMouseLeave = t13;
1339
+ let t14;
1340
+ if ($[33] !== addBlockAfterPosition || $[34] !== blockData.position) {
1341
+ t14 = (insertPosition) => {
1342
+ postOverlayMessage({
1343
+ type: "CAMOX_ADD_BLOCK_REQUEST",
1344
+ blockPosition: blockData.position,
1345
+ insertPosition,
1346
+ ...addBlockAfterPosition !== void 0 && { afterPosition: addBlockAfterPosition }
1347
+ });
1348
+ };
1349
+ $[33] = addBlockAfterPosition;
1350
+ $[34] = blockData.position;
1351
+ $[35] = t14;
1352
+ } else t14 = $[35];
1353
+ const handleAddBlockClick = t14;
1354
+ const shouldShowOverlay = isContentEditable && (isHovered || isBlockSelected) && !isAddBlockSidebarOpen;
1355
+ const shouldShowAddBlockOverlay = isAddBlockSidebarOpen && mode !== "peek";
1356
+ let t15;
1357
+ if ($[36] === Symbol.for("react.memo_cache_sentinel")) {
1358
+ t15 = {
1359
+ position: "relative",
1360
+ scrollMargin: "5rem",
1361
+ background: "var(--background)"
1362
+ };
1363
+ $[36] = t15;
1364
+ } else t15 = $[36];
1365
+ const t16 = isContentEditable ? blockData._id : void 0;
1366
+ const t17 = shouldShowOverlay && !isBlockSelected || void 0;
1367
+ const t18 = shouldShowOverlay && isBlockSelected || void 0;
1368
+ const t19 = mode === "layout" ? "layout" : void 0;
1369
+ const t20 = blockData._id;
1370
+ let t21;
1371
+ if ($[37] !== blockData.content) {
1372
+ t21 = {
1373
+ ...contentDefaults,
1374
+ ...blockData.content
1375
+ };
1376
+ $[37] = blockData.content;
1377
+ $[38] = t21;
1378
+ } else t21 = $[38];
1379
+ const merged = t21;
1380
+ let overrides;
1381
+ if ($[39] !== merged) {
1382
+ overrides = {};
1383
+ for (const key_0 in merged) {
1384
+ const val = merged[key_0];
1385
+ if (val && typeof val === "object" && "url" in val && !val.url && contentDefaults[key_0]) overrides[key_0] = contentDefaults[key_0];
1386
+ }
1387
+ $[39] = merged;
1388
+ $[40] = overrides;
1389
+ } else overrides = $[40];
1390
+ let t22;
1391
+ if ($[41] !== merged || $[42] !== overrides) {
1392
+ t22 = {
1393
+ ...merged,
1394
+ ...overrides
1395
+ };
1396
+ $[41] = merged;
1397
+ $[42] = overrides;
1398
+ $[43] = t22;
1399
+ } else t22 = $[43];
1400
+ const t23 = t22;
1401
+ let t24;
1402
+ if ($[44] !== blockData.settings) {
1403
+ t24 = {
1404
+ ...settingsDefaults,
1405
+ ...blockData.settings
1406
+ };
1407
+ $[44] = blockData.settings;
1408
+ $[45] = t24;
1409
+ } else t24 = $[45];
1410
+ const t25 = t24;
1411
+ let t26;
1412
+ if ($[46] !== blockData._id || $[47] !== isHovered || $[48] !== mode || $[49] !== t23 || $[50] !== t25) {
1413
+ t26 = {
1414
+ blockId: t20,
1415
+ content: t23,
1416
+ settings: t25,
1417
+ mode,
1418
+ isHovered,
1419
+ setIsHovered
1420
+ };
1421
+ $[46] = blockData._id;
1422
+ $[47] = isHovered;
1423
+ $[48] = mode;
1424
+ $[49] = t23;
1425
+ $[50] = t25;
1426
+ $[51] = t26;
1427
+ } else t26 = $[51];
1428
+ let t27;
1429
+ if ($[52] !== normalizedContent) {
1430
+ t27 = /* @__PURE__ */ jsx(options.component, { content: normalizedContent });
1431
+ $[52] = normalizedContent;
1432
+ $[53] = t27;
1433
+ } else t27 = $[53];
1434
+ let t28;
1435
+ if ($[54] !== t26 || $[55] !== t27) {
1436
+ t28 = /* @__PURE__ */ jsx(Context.Provider, {
1437
+ value: t26,
1438
+ children: t27
1439
+ });
1440
+ $[54] = t26;
1441
+ $[55] = t27;
1442
+ $[56] = t28;
1443
+ } else t28 = $[56];
1444
+ const t29 = shouldShowAddBlockOverlay || void 0;
1445
+ let t30;
1446
+ if ($[57] !== t29) {
1447
+ t30 = /* @__PURE__ */ jsx("div", {
1448
+ className: "camox-sheet-overlay",
1449
+ "data-camox-visible": t29
1450
+ });
1451
+ $[57] = t29;
1452
+ $[58] = t30;
1453
+ } else t30 = $[58];
1454
+ let t31;
1455
+ if ($[59] !== handleAddBlockClick || $[60] !== isAddBlockSidebarOpen || $[61] !== isFirstBlock || $[62] !== mode || $[63] !== shouldShowOverlay || $[64] !== showAddBlockBottom || $[65] !== showAddBlockTop) {
1456
+ t31 = shouldShowOverlay && /* @__PURE__ */ jsxs(Fragment, { children: [(showAddBlockTop ?? (mode !== "layout" && !isFirstBlock)) && /* @__PURE__ */ jsx(AddBlockControlBar, {
1457
+ position: "top",
1458
+ hidden: isAddBlockSidebarOpen,
1459
+ onMouseLeave: () => setIsHovered(false),
1460
+ onClick: () => handleAddBlockClick("before")
1461
+ }), (showAddBlockBottom ?? mode !== "layout") && /* @__PURE__ */ jsx(AddBlockControlBar, {
1462
+ position: "bottom",
1463
+ hidden: isAddBlockSidebarOpen,
1464
+ onMouseLeave: () => setIsHovered(false),
1465
+ onClick: () => handleAddBlockClick("after")
1466
+ })] });
1467
+ $[59] = handleAddBlockClick;
1468
+ $[60] = isAddBlockSidebarOpen;
1469
+ $[61] = isFirstBlock;
1470
+ $[62] = mode;
1471
+ $[63] = shouldShowOverlay;
1472
+ $[64] = showAddBlockBottom;
1473
+ $[65] = showAddBlockTop;
1474
+ $[66] = t31;
1475
+ } else t31 = $[66];
1476
+ let t32;
1477
+ if ($[67] !== handleClick || $[68] !== handleMouseEnter || $[69] !== handleMouseLeave || $[70] !== t16 || $[71] !== t17 || $[72] !== t18 || $[73] !== t19 || $[74] !== t28 || $[75] !== t30 || $[76] !== t31) {
1478
+ t32 = /* @__PURE__ */ jsxs("div", {
1479
+ className: "group visual-editing-block",
1480
+ ref,
1481
+ style: t15,
1482
+ "data-camox-block-id": t16,
1483
+ "data-camox-hovered": t17,
1484
+ "data-camox-focused": t18,
1485
+ "data-camox-overlay-mode": t19,
1486
+ onClick: handleClick,
1487
+ onMouseEnter: handleMouseEnter,
1488
+ onMouseLeave: handleMouseLeave,
1489
+ children: [
1490
+ t28,
1491
+ t30,
1492
+ t31
1493
+ ]
1494
+ });
1495
+ $[67] = handleClick;
1496
+ $[68] = handleMouseEnter;
1497
+ $[69] = handleMouseLeave;
1498
+ $[70] = t16;
1499
+ $[71] = t17;
1500
+ $[72] = t18;
1501
+ $[73] = t19;
1502
+ $[74] = t28;
1503
+ $[75] = t30;
1504
+ $[76] = t31;
1505
+ $[77] = t32;
1506
+ } else t32 = $[77];
1507
+ return t32;
1508
+ };
1509
+ const useSetting = (name) => {
1510
+ const ctx = React.use(Context);
1511
+ if (!ctx) throw new Error("useSetting must be used within a Block Component");
1512
+ return ctx.settings[name];
1513
+ };
1514
+ /**
1515
+ * Wraps block content that renders outside the block's visual bounds (fixed navbars, modals, portals, etc.).
1516
+ * Provides the same hover, selection, and sheet overlays as the main BlockComponent.
1517
+ */
1518
+ const Detached = (t0) => {
1519
+ const $ = c(31);
1520
+ if ($[0] !== "e263b48438d7cbcbf7882d7283db437d4762f01fd895729e78d2eda64650183d") {
1521
+ for (let $i = 0; $i < 31; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
1522
+ $[0] = "e263b48438d7cbcbf7882d7283db437d4762f01fd895729e78d2eda64650183d";
1523
+ }
1524
+ const { children } = t0;
1525
+ const ctx = React.use(Context);
1526
+ if (!ctx) throw new Error("Detached must be used within a Block Component");
1527
+ const { blockId, mode, isHovered, setIsHovered } = ctx;
1528
+ const isContentEditable = useIsEditable(mode);
1529
+ const { window: iframeWindow } = useFrame();
1530
+ const selection = useSelector(previewStore, _temp0);
1531
+ const isAddBlockSidebarOpen = useSelector(previewStore, _temp1);
1532
+ const isBlockSelected = selection?.blockId === blockId;
1533
+ const t1 = String(blockId);
1534
+ let t2;
1535
+ if ($[1] !== t1) {
1536
+ t2 = { blockId: t1 };
1537
+ $[1] = t1;
1538
+ $[2] = t2;
1539
+ } else t2 = $[2];
1540
+ const isHoveredFromSidebar = useOverlayMessage(iframeWindow, isContentEditable, "CAMOX_HOVER_BLOCK", "CAMOX_HOVER_BLOCK_END", t2);
1541
+ let t3;
1542
+ let t4;
1543
+ if ($[3] !== isHoveredFromSidebar || $[4] !== setIsHovered) {
1544
+ t3 = () => {
1545
+ setIsHovered(isHoveredFromSidebar);
1546
+ };
1547
+ t4 = [isHoveredFromSidebar, setIsHovered];
1548
+ $[3] = isHoveredFromSidebar;
1549
+ $[4] = setIsHovered;
1550
+ $[5] = t3;
1551
+ $[6] = t4;
1552
+ } else {
1553
+ t3 = $[5];
1554
+ t4 = $[6];
1555
+ }
1556
+ React.useEffect(t3, t4);
1557
+ const shouldShowOverlay = isContentEditable && (isHovered || isBlockSelected) && !isAddBlockSidebarOpen;
1558
+ const shouldHideForAddBlockSidebar = isAddBlockSidebarOpen && mode !== "peek";
1559
+ let t5;
1560
+ if ($[7] !== blockId || $[8] !== isContentEditable) {
1561
+ t5 = (e) => {
1562
+ if (!isContentEditable) return;
1563
+ e.stopPropagation();
1564
+ previewStore.send({
1565
+ type: "setFocusedBlock",
1566
+ blockId
1567
+ });
1568
+ };
1569
+ $[7] = blockId;
1570
+ $[8] = isContentEditable;
1571
+ $[9] = t5;
1572
+ } else t5 = $[9];
1573
+ const handleClick = t5;
1574
+ let t6;
1575
+ if ($[10] !== isContentEditable || $[11] !== setIsHovered) {
1576
+ t6 = () => {
1577
+ if (isContentEditable) setIsHovered(true);
1578
+ };
1579
+ $[10] = isContentEditable;
1580
+ $[11] = setIsHovered;
1581
+ $[12] = t6;
1582
+ } else t6 = $[12];
1583
+ const handleMouseEnter = t6;
1584
+ let t7;
1585
+ if ($[13] !== isContentEditable || $[14] !== setIsHovered) {
1586
+ t7 = () => {
1587
+ if (isContentEditable) setIsHovered(false);
1588
+ };
1589
+ $[13] = isContentEditable;
1590
+ $[14] = setIsHovered;
1591
+ $[15] = t7;
1592
+ } else t7 = $[15];
1593
+ const handleMouseLeave = t7;
1594
+ const [container, setContainer] = React.useState(null);
1595
+ const t8 = shouldHideForAddBlockSidebar ? 0 : 1;
1596
+ let t9;
1597
+ if ($[16] !== children || $[17] !== handleClick || $[18] !== handleMouseEnter || $[19] !== handleMouseLeave || $[20] !== t8) {
1598
+ t9 = children({
1599
+ ref: setContainer,
1600
+ style: { opacity: t8 },
1601
+ onClick: handleClick,
1602
+ onMouseEnter: handleMouseEnter,
1603
+ onMouseLeave: handleMouseLeave
1604
+ });
1605
+ $[16] = children;
1606
+ $[17] = handleClick;
1607
+ $[18] = handleMouseEnter;
1608
+ $[19] = handleMouseLeave;
1609
+ $[20] = t8;
1610
+ $[21] = t9;
1611
+ } else t9 = $[21];
1612
+ let t10;
1613
+ if ($[22] !== blockId || $[23] !== container || $[24] !== isBlockSelected || $[25] !== mode || $[26] !== shouldShowOverlay) {
1614
+ t10 = container && createPortal(/* @__PURE__ */ jsx(Fragment, { children: shouldShowOverlay && /* @__PURE__ */ jsx("div", {
1615
+ "data-camox-block-id": blockId,
1616
+ "data-camox-detached": true,
1617
+ "data-camox-hovered": !isBlockSelected || void 0,
1618
+ "data-camox-focused": isBlockSelected || void 0,
1619
+ "data-camox-overlay-mode": mode === "layout" ? "layout" : void 0,
1620
+ style: {
1621
+ position: "absolute",
1622
+ pointerEvents: "none",
1623
+ zIndex: 10
1624
+ }
1625
+ }) }), container);
1626
+ $[22] = blockId;
1627
+ $[23] = container;
1628
+ $[24] = isBlockSelected;
1629
+ $[25] = mode;
1630
+ $[26] = shouldShowOverlay;
1631
+ $[27] = t10;
1632
+ } else t10 = $[27];
1633
+ let t11;
1634
+ if ($[28] !== t10 || $[29] !== t9) {
1635
+ t11 = /* @__PURE__ */ jsxs(Fragment, { children: [t9, t10] });
1636
+ $[28] = t10;
1637
+ $[29] = t9;
1638
+ $[30] = t11;
1639
+ } else t11 = $[30];
1640
+ return t11;
1641
+ };
1642
+ return {
1643
+ Detached,
1644
+ Field,
1645
+ Embed,
1646
+ Link,
1647
+ Image,
1648
+ File,
1649
+ ImageList,
1650
+ FileList,
1651
+ Repeater,
1652
+ useSetting,
1653
+ _internal: {
1654
+ /**
1655
+ * The react component to be used at the page level when mapping on blocks content.
1656
+ * It exposes context that will be consumed by the Field component, and provides visual editing
1657
+ * capabilities (e.g. delete and reorder blocks).
1658
+ */
1659
+ Component: BlockComponent,
1660
+ id: options.id,
1661
+ title: options.title,
1662
+ description: options.description,
1663
+ contentSchema,
1664
+ settingsSchema,
1665
+ layoutOnly: options.layoutOnly ?? false,
1666
+ getInitialBundle: () => {
1667
+ const counter = { value: 0 };
1668
+ const allSeeds = [];
1669
+ const content = { ...contentDefaults };
1670
+ buildInitialSeeds(typeboxSchema.properties, null, content, allSeeds, counter);
1671
+ const storageContent = {};
1672
+ for (const [key, prop] of Object.entries(typeboxSchema.properties)) {
1673
+ const ft = prop.fieldType;
1674
+ if (ft === "Image" || ft === "File" || ft === "ImageList" || ft === "FileList" || ft === "Repeater") continue;
1675
+ if ("default" in prop) storageContent[key] = prop.default;
1676
+ }
1677
+ return {
1678
+ content: storageContent,
1679
+ settings: { ...settingsDefaults },
1680
+ repeatableItems: allSeeds
1681
+ };
1682
+ },
1683
+ getInitialContent: () => {
1684
+ return { ...contentDefaultsForStorage };
1685
+ },
1686
+ getInitialSettings: () => {
1687
+ return { ...settingsDefaults };
1688
+ },
1689
+ getPeekBundle: () => {
1690
+ const PEEK_BLOCK_ID = -1;
1691
+ const counter = { value: 0 };
1692
+ const allItems = [];
1693
+ const content = { ...contentDefaults };
1694
+ buildPeekItems(typeboxSchema.properties, PEEK_BLOCK_ID, null, content, allItems, counter);
1695
+ return {
1696
+ block: {
1697
+ id: PEEK_BLOCK_ID,
1698
+ pageId: null,
1699
+ layoutId: null,
1700
+ type: options.id,
1701
+ content,
1702
+ settings: settingsDefaults,
1703
+ placement: null,
1704
+ summary: "",
1705
+ position: "",
1706
+ createdAt: 0,
1707
+ updatedAt: 0
1708
+ },
1709
+ repeatableItems: allItems,
1710
+ files: []
1711
+ };
1712
+ }
1713
+ }
1714
+ };
1715
+ }
1716
+ function _temp(l) {
1717
+ return l.pathname;
1718
+ }
1719
+ function _temp2(e_1) {
1720
+ return e_1.preventDefault();
1721
+ }
1722
+ function _temp3(e_2) {
1723
+ if (e_2.key === "Escape") e_2.target.blur();
1724
+ }
1725
+ function _temp4(e_3) {
1726
+ return e_3.preventDefault();
1727
+ }
1728
+ function _temp5(state) {
1729
+ return state.context.selection;
1730
+ }
1731
+ function _temp6(state_0) {
1732
+ return state_0.context.isPageEditorSidebarOpen;
1733
+ }
1734
+ function _temp7(state_1) {
1735
+ return state_1.context.isAddBlockSidebarOpen;
1736
+ }
1737
+ function _temp8(state_2) {
1738
+ return state_2.context.pendingAgentBlockFocus;
1739
+ }
1740
+ function _temp9(item) {
1741
+ return item.content;
1742
+ }
1743
+ function _temp0(state) {
1744
+ return state.context.selection;
1745
+ }
1746
+ function _temp1(state_0) {
1747
+ return state_0.context.isAddBlockSidebarOpen;
1748
+ }
1749
+
1750
+ //#endregion
1751
+ export { createEditableBlock };