@drawnagency/primitives 0.1.70 → 0.1.72
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.
- package/dist/{chunk-VVK6ZRCN.js → chunk-2HZB675H.js} +12 -12
- package/dist/chunk-7SIZ2LV5.js +117 -0
- package/dist/{chunk-2BHPWO7M.js → chunk-BTGHF3SW.js} +158 -32
- package/dist/{chunk-3DCG4DNU.js → chunk-PZJL2S3Z.js} +8 -4
- package/dist/chunk-RBTSUR5V.js +37 -0
- package/dist/{chunk-EWKCEPMW.js → chunk-SFKYUKVN.js} +1 -1
- package/dist/{chunk-QKOIEWZ4.js → chunk-SWIHUIFT.js} +38 -18
- package/dist/{chunk-6UDYJQL6.js → chunk-TOBPMMRM.js} +1 -1
- package/dist/{chunk-TYYCKVAW.js → chunk-UBK2IZ6G.js} +276 -96
- package/dist/{chunk-WXVKX6PY.js → chunk-VHINNGIF.js} +41 -95
- package/dist/{chunk-KWBM27UR.js → chunk-WCALKWPO.js} +4 -59
- package/dist/{chunk-WNPMBFD6.js → chunk-ZRWGV5O6.js} +3 -3
- package/dist/chunk-ZSPCE6MZ.js +70 -0
- package/dist/components/chat/ChatPanel.d.ts +4 -1
- package/dist/components/chat/ChatPanel.d.ts.map +1 -1
- package/dist/components/editor/SettingsForm.d.ts.map +1 -1
- package/dist/components/editor/index.js +6 -3
- package/dist/components/primitives/index.js +7 -7
- package/dist/components/sections/Video/VideoBlock.d.ts +31 -0
- package/dist/components/sections/Video/VideoBlock.d.ts.map +1 -0
- package/dist/components/sections/Video/index.d.ts +28 -0
- package/dist/components/sections/Video/index.d.ts.map +1 -0
- package/dist/components/sections/all-sections.d.ts +25 -0
- package/dist/components/sections/all-sections.d.ts.map +1 -1
- package/dist/components/sections/brand-guide.js +7 -7
- package/dist/components/sections/core-sections.d.ts +25 -0
- package/dist/components/sections/core-sections.d.ts.map +1 -1
- package/dist/components/sections/register-schemas.js +13 -12
- package/dist/components/sections/register.js +13 -12
- package/dist/components/shared/Tabs.d.ts +1 -1
- package/dist/components/shared/VideoSourceField.d.ts +8 -0
- package/dist/components/shared/VideoSourceField.d.ts.map +1 -0
- package/dist/components/shell/ChatbotConfigModal.d.ts.map +1 -1
- package/dist/components/shell/EditorShell.d.ts.map +1 -1
- package/dist/components/shell/MediaLibraryModal.d.ts +4 -1
- package/dist/components/shell/MediaLibraryModal.d.ts.map +1 -1
- package/dist/hooks/useEditorPublish.d.ts.map +1 -1
- package/dist/hooks/useMediaPipeline.d.ts +9 -1
- package/dist/hooks/useMediaPipeline.d.ts.map +1 -1
- package/dist/index.js +24 -24
- package/dist/lib/index.js +10 -10
- package/dist/lib/registry.d.ts +6 -0
- package/dist/lib/registry.d.ts.map +1 -1
- package/dist/lib/video-url.d.ts +7 -0
- package/dist/lib/video-url.d.ts.map +1 -0
- package/dist/lib/video-url.js +9 -0
- package/dist/media/index.js +2 -2
- package/dist/media/videoPoster.d.ts +1 -0
- package/dist/media/videoPoster.d.ts.map +1 -1
- package/dist/schemas/index.js +4 -4
- package/dist/schemas/link.d.ts.map +1 -1
- package/dist/schemas/link.js +1 -1
- package/dist/schemas/media.d.ts +13 -0
- package/dist/schemas/media.d.ts.map +1 -1
- package/dist/schemas/shared.d.ts.map +1 -1
- package/dist/schemas/site-config.d.ts +3 -0
- package/dist/schemas/site-config.d.ts.map +1 -1
- package/dist/storage/index.d.ts +1 -1
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/storage/types.d.ts +26 -0
- package/dist/storage/types.d.ts.map +1 -1
- package/package.json +5 -1
- package/src/components/chat/ChatPanel.tsx +78 -49
- package/src/components/editor/SettingsForm.tsx +11 -0
- package/src/components/sections/Video/VideoBlock.tsx +149 -0
- package/src/components/sections/Video/index.tsx +111 -0
- package/src/components/sections/core-sections.ts +2 -0
- package/src/components/shared/Tabs.tsx +2 -2
- package/src/components/shared/VideoSourceField.tsx +144 -0
- package/src/components/shell/ChatbotConfigModal.tsx +44 -3
- package/src/components/shell/EditorShell.tsx +8 -0
- package/src/components/shell/MediaLibraryModal.tsx +47 -1
- package/src/hooks/useEditorPublish.ts +3 -0
- package/src/hooks/useMediaPipeline.ts +188 -25
- package/src/lib/registry.ts +7 -0
- package/src/lib/video-url.ts +39 -0
- package/src/media/videoPoster.ts +2 -2
- package/src/schemas/link.ts +15 -4
- package/src/schemas/media.ts +12 -0
- package/src/schemas/shared.ts +23 -14
- package/src/schemas/site-config.ts +10 -2
- package/src/storage/index.ts +1 -1
- package/src/storage/types.ts +23 -0
- package/dist/chunk-4E66N6UV.js +0 -10
- package/dist/chunk-I5737FJY.js +0 -62
|
@@ -1,9 +1,25 @@
|
|
|
1
|
+
import {
|
|
2
|
+
EditableRichText,
|
|
3
|
+
defineHeadingSection
|
|
4
|
+
} from "./chunk-VHINNGIF.js";
|
|
5
|
+
import {
|
|
6
|
+
embedUrl
|
|
7
|
+
} from "./chunk-RBTSUR5V.js";
|
|
1
8
|
import {
|
|
2
9
|
brandGuideSectionDefs,
|
|
3
10
|
pluralize,
|
|
4
11
|
stripHtmlToPlainText,
|
|
5
12
|
truncate
|
|
6
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-2HZB675H.js";
|
|
14
|
+
import {
|
|
15
|
+
EditablePlainText,
|
|
16
|
+
ImageDropZone,
|
|
17
|
+
MAX_CONTAINER_COLUMNS,
|
|
18
|
+
MediaBlock,
|
|
19
|
+
colSpanClass,
|
|
20
|
+
containerGridClass,
|
|
21
|
+
spacerHiddenClass
|
|
22
|
+
} from "./chunk-WCALKWPO.js";
|
|
7
23
|
import {
|
|
8
24
|
DeleteButton,
|
|
9
25
|
DragHandle,
|
|
@@ -15,23 +31,15 @@ import {
|
|
|
15
31
|
buildBlockDropData,
|
|
16
32
|
canDropBlock,
|
|
17
33
|
isBlockDragData
|
|
18
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-BTGHF3SW.js";
|
|
19
35
|
import {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
} from "./chunk-
|
|
23
|
-
import {
|
|
24
|
-
EditablePlainText,
|
|
25
|
-
MAX_CONTAINER_COLUMNS,
|
|
26
|
-
MediaBlock,
|
|
27
|
-
colSpanClass,
|
|
28
|
-
containerGridClass,
|
|
29
|
-
spacerHiddenClass
|
|
30
|
-
} from "./chunk-KWBM27UR.js";
|
|
36
|
+
useMediaLibrary,
|
|
37
|
+
useResolvedMedia
|
|
38
|
+
} from "./chunk-7SIZ2LV5.js";
|
|
31
39
|
import {
|
|
32
40
|
DEFAULT_LINK,
|
|
33
41
|
LinkValueSchema
|
|
34
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-PZJL2S3Z.js";
|
|
35
43
|
import {
|
|
36
44
|
sanitizeHtml
|
|
37
45
|
} from "./chunk-53DKVAB6.js";
|
|
@@ -41,13 +49,13 @@ import {
|
|
|
41
49
|
import {
|
|
42
50
|
getSectionSchema
|
|
43
51
|
} from "./chunk-TZQPOR5A.js";
|
|
44
|
-
import {
|
|
45
|
-
SingleMediaReferenceSchema
|
|
46
|
-
} from "./chunk-QKOIEWZ4.js";
|
|
47
52
|
import {
|
|
48
53
|
defineSection,
|
|
49
54
|
getSection
|
|
50
55
|
} from "./chunk-VKAGMEKE.js";
|
|
56
|
+
import {
|
|
57
|
+
SingleMediaReferenceSchema
|
|
58
|
+
} from "./chunk-SWIHUIFT.js";
|
|
51
59
|
|
|
52
60
|
// src/components/sections/LinkHeading/index.tsx
|
|
53
61
|
import { Heading1 } from "lucide-react";
|
|
@@ -209,20 +217,191 @@ var Media_default = defineSection({
|
|
|
209
217
|
]
|
|
210
218
|
});
|
|
211
219
|
|
|
212
|
-
// src/components/sections/
|
|
220
|
+
// src/components/sections/Video/index.tsx
|
|
213
221
|
import { z as z3 } from "zod";
|
|
222
|
+
import { Clapperboard } from "lucide-react";
|
|
223
|
+
|
|
224
|
+
// src/components/sections/Video/VideoBlock.tsx
|
|
225
|
+
import { jsx as jsx7, jsxs } from "react/jsx-runtime";
|
|
226
|
+
function VideoBlock({ source, caption, options, isEditMode, onSourceChange, onCaptionChange }) {
|
|
227
|
+
const mediaLibrary = useMediaLibrary();
|
|
228
|
+
const imageId = source.type === "library" ? source.ref.imageId : void 0;
|
|
229
|
+
const posterId = source.type === "library" ? source.poster?.imageId : void 0;
|
|
230
|
+
const resolved = useResolvedMedia(imageId);
|
|
231
|
+
const posterOverride = useResolvedMedia(posterId);
|
|
232
|
+
const playback = options.playback ?? "click";
|
|
233
|
+
const editable = Boolean(isEditMode && onSourceChange);
|
|
234
|
+
const captionEditable = Boolean(isEditMode && onCaptionChange);
|
|
235
|
+
const showCaptionBlock = Boolean(options.showCaption && (captionEditable || caption));
|
|
236
|
+
const replaceWithLibraryVideo = editable ? (newImageId) => onSourceChange({ type: "library", ref: { imageId: newImageId } }) : void 0;
|
|
237
|
+
let media;
|
|
238
|
+
let aspect;
|
|
239
|
+
if (source.type === "external") {
|
|
240
|
+
aspect = `${source.width} / ${source.height}`;
|
|
241
|
+
media = /* @__PURE__ */ jsx7(
|
|
242
|
+
"iframe",
|
|
243
|
+
{
|
|
244
|
+
src: embedUrl(source),
|
|
245
|
+
title: caption || "Embedded video",
|
|
246
|
+
loading: "lazy",
|
|
247
|
+
allow: "autoplay; fullscreen; picture-in-picture; encrypted-media",
|
|
248
|
+
allowFullScreen: true,
|
|
249
|
+
className: "absolute inset-0 h-full w-full border-0"
|
|
250
|
+
}
|
|
251
|
+
);
|
|
252
|
+
} else {
|
|
253
|
+
const baked = source.ref;
|
|
254
|
+
const bakedSrc = typeof baked.src === "string" ? baked.src : void 0;
|
|
255
|
+
const bakedPoster = typeof baked.poster === "string" ? baked.poster : void 0;
|
|
256
|
+
const bakedWidth = typeof baked.width === "number" ? baked.width : void 0;
|
|
257
|
+
const bakedHeight = typeof baked.height === "number" ? baked.height : void 0;
|
|
258
|
+
const bakedPosterOverride = source.poster;
|
|
259
|
+
const bakedPosterOverrideSrc = typeof bakedPosterOverride?.src === "string" ? bakedPosterOverride.src : void 0;
|
|
260
|
+
const src = bakedSrc ?? resolved.src;
|
|
261
|
+
const poster = bakedPosterOverrideSrc ?? posterOverride.src ?? bakedPoster ?? resolved.poster;
|
|
262
|
+
const width = bakedWidth ?? resolved.width;
|
|
263
|
+
const height = bakedHeight ?? resolved.height;
|
|
264
|
+
aspect = width && height ? `${width} / ${height}` : void 0;
|
|
265
|
+
const playbackProps = playback === "ambient" ? { autoPlay: true, muted: true, loop: true, playsInline: true } : { controls: true, preload: "metadata" };
|
|
266
|
+
const videoEl = imageId ? /* @__PURE__ */ jsx7(
|
|
267
|
+
"video",
|
|
268
|
+
{
|
|
269
|
+
src,
|
|
270
|
+
poster,
|
|
271
|
+
width,
|
|
272
|
+
height,
|
|
273
|
+
className: "absolute inset-0 h-full w-full object-contain",
|
|
274
|
+
...playbackProps
|
|
275
|
+
}
|
|
276
|
+
) : /* @__PURE__ */ jsx7("div", { className: "absolute inset-0 flex items-center justify-center bg-base-accent text-base-contrast-light/50", children: /* @__PURE__ */ jsx7("span", { className: "text-sm", children: "No video selected" }) });
|
|
277
|
+
media = replaceWithLibraryVideo ? /* @__PURE__ */ jsx7(ImageDropZone, { onImageSelected: replaceWithLibraryVideo, className: "absolute inset-0 h-full w-full", children: videoEl }) : videoEl;
|
|
278
|
+
}
|
|
279
|
+
const onSurfaceClick = replaceWithLibraryVideo && mediaLibrary ? () => mediaLibrary.openSelectModal((id) => replaceWithLibraryVideo(id)) : void 0;
|
|
280
|
+
return /* @__PURE__ */ jsxs("figure", { className: "w-full", children: [
|
|
281
|
+
/* @__PURE__ */ jsx7(
|
|
282
|
+
"div",
|
|
283
|
+
{
|
|
284
|
+
"data-testid": "video-open-surface",
|
|
285
|
+
className: cn("relative w-full overflow-hidden", onSurfaceClick && "cursor-pointer"),
|
|
286
|
+
style: { aspectRatio: aspect ?? "16 / 9" },
|
|
287
|
+
onClick: onSurfaceClick,
|
|
288
|
+
onPointerDown: onSurfaceClick ? (e) => e.stopPropagation() : void 0,
|
|
289
|
+
children: media
|
|
290
|
+
}
|
|
291
|
+
),
|
|
292
|
+
showCaptionBlock && /* @__PURE__ */ jsx7("figcaption", { className: "mt-2 min-h-[1em] text-sm text-base-contrast-light/70", children: captionEditable ? /* @__PURE__ */ jsx7(
|
|
293
|
+
EditablePlainText,
|
|
294
|
+
{
|
|
295
|
+
tag: "span",
|
|
296
|
+
value: caption ?? "",
|
|
297
|
+
onChange: onCaptionChange,
|
|
298
|
+
isEditMode: true,
|
|
299
|
+
placeholder: "Caption",
|
|
300
|
+
className: "block min-h-[1em]"
|
|
301
|
+
}
|
|
302
|
+
) : caption })
|
|
303
|
+
] });
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// src/components/sections/Video/index.tsx
|
|
307
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
308
|
+
var LibrarySource = z3.object({
|
|
309
|
+
type: z3.literal("library"),
|
|
310
|
+
ref: z3.object({
|
|
311
|
+
imageId: z3.string().default("").describe("Media-library id of the video asset. Required for library videos.")
|
|
312
|
+
}),
|
|
313
|
+
// Kept as a SIBLING of `ref` (not nested inside it): the SSR ref-baker
|
|
314
|
+
// (resolveManifestReferences) matches objects structurally by a top-level
|
|
315
|
+
// `imageId` key and merges the resolved video's own poster onto that same
|
|
316
|
+
// object. Nesting the override inside `ref` would collide with that bake
|
|
317
|
+
// and get silently overwritten on the published viewer. As a sibling with
|
|
318
|
+
// its own `imageId`, it gets baked independently.
|
|
319
|
+
poster: z3.object({
|
|
320
|
+
imageId: z3.string().describe("Media-library image id used as the poster frame instead of the auto-generated one.")
|
|
321
|
+
}).optional().describe("Optional poster-image override for a library video.")
|
|
322
|
+
});
|
|
323
|
+
var ExternalSource = z3.object({
|
|
324
|
+
type: z3.literal("external"),
|
|
325
|
+
provider: z3.enum(["youtube", "vimeo"]).describe("Hosting provider, derived from the pasted URL."),
|
|
326
|
+
id: z3.string().describe("Provider video id parsed from the pasted URL."),
|
|
327
|
+
url: z3.string().describe("The original video page URL as pasted."),
|
|
328
|
+
width: z3.number().positive().describe("Native width used for the aspect-ratio box (from oEmbed; 16 when unknown)."),
|
|
329
|
+
height: z3.number().positive().describe("Native height used for the aspect-ratio box (from oEmbed; 9 when unknown).")
|
|
330
|
+
});
|
|
331
|
+
var schema3 = z3.object({
|
|
332
|
+
type: z3.literal("video"),
|
|
333
|
+
content: z3.object({
|
|
334
|
+
source: z3.discriminatedUnion("type", [LibrarySource, ExternalSource]).describe("Where the video comes from: a media-library upload or an external YouTube/Vimeo URL."),
|
|
335
|
+
caption: z3.string().optional().describe("Optional caption rendered beneath the player when Show caption is on.")
|
|
336
|
+
}),
|
|
337
|
+
options: z3.object({
|
|
338
|
+
playback: z3.enum(["ambient", "click"]).describe("'click' (default): poster + native controls with audio. 'ambient': autoplays muted in a loop with no controls.").optional(),
|
|
339
|
+
showCaption: z3.boolean().describe("When true, render the caption beneath the player.").optional()
|
|
340
|
+
}).default({})
|
|
341
|
+
});
|
|
342
|
+
var Video_default = defineSection({
|
|
343
|
+
type: "video",
|
|
344
|
+
label: "Video",
|
|
345
|
+
icon: /* @__PURE__ */ jsx8(Clapperboard, { size: 18 }),
|
|
346
|
+
schema: schema3,
|
|
347
|
+
authoringNote: "A watchable video player \u2014 self-hosted from the media library or embedded from YouTube/Vimeo. Use playback 'click' for content viewers press play on (controls + audio) and 'ambient' for silent looping footage. For decorative loops inside grids prefer the Media block; large self-hosted files require the site's asset storage.",
|
|
348
|
+
component: ({ content, options, onChange }) => /* @__PURE__ */ jsx8(
|
|
349
|
+
VideoBlock,
|
|
350
|
+
{
|
|
351
|
+
source: content.content.source,
|
|
352
|
+
caption: content.content.caption,
|
|
353
|
+
options: options ?? {},
|
|
354
|
+
isEditMode: !!onChange,
|
|
355
|
+
onSourceChange: onChange ? (source) => onChange({ ...content, content: { ...content.content, source } }) : void 0,
|
|
356
|
+
onCaptionChange: onChange ? (caption) => onChange({ ...content, content: { ...content.content, caption: caption || void 0 } }) : void 0
|
|
357
|
+
}
|
|
358
|
+
),
|
|
359
|
+
defaults: () => ({
|
|
360
|
+
type: "video",
|
|
361
|
+
content: { source: { type: "library", ref: { imageId: "" } } },
|
|
362
|
+
options: {}
|
|
363
|
+
}),
|
|
364
|
+
getLabel: () => "Video",
|
|
365
|
+
getThumbnails: (content) => content.content.source.type === "library" && content.content.source.ref.imageId ? [{ type: "image", src: content.content.source.ref.imageId }] : [],
|
|
366
|
+
settings: {
|
|
367
|
+
source: {
|
|
368
|
+
type: "video-source",
|
|
369
|
+
label: "Source",
|
|
370
|
+
target: "content",
|
|
371
|
+
default: { type: "library", ref: { imageId: "" } }
|
|
372
|
+
},
|
|
373
|
+
playback: {
|
|
374
|
+
type: "select",
|
|
375
|
+
label: "Playback",
|
|
376
|
+
default: "click",
|
|
377
|
+
options: [
|
|
378
|
+
{ label: "Click to play (controls + audio)", value: "click" },
|
|
379
|
+
{ label: "Ambient loop (muted, no controls)", value: "ambient" }
|
|
380
|
+
]
|
|
381
|
+
},
|
|
382
|
+
showCaption: { type: "checkbox", label: "Show caption", default: false }
|
|
383
|
+
},
|
|
384
|
+
inheritableSettings: ["playback", "showCaption"],
|
|
385
|
+
settingsTabs: [
|
|
386
|
+
{ label: "Source", fields: ["source"] },
|
|
387
|
+
{ label: "Display", fields: ["playback", "showCaption"] }
|
|
388
|
+
]
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
// src/components/sections/Button/index.tsx
|
|
392
|
+
import { z as z4 } from "zod";
|
|
214
393
|
import { RectangleHorizontal } from "lucide-react";
|
|
215
394
|
|
|
216
395
|
// src/components/sections/Button/CTAButton.tsx
|
|
217
396
|
import { Download } from "lucide-react";
|
|
218
|
-
import { jsx as
|
|
397
|
+
import { jsx as jsx9, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
219
398
|
function Button({ text, link, download, onChange }) {
|
|
220
399
|
const base = "inline-block rounded-md px-6 py-3 font-bold transition-colors";
|
|
221
400
|
const variant = "border-2 border-primary text-primary hover:bg-primary hover:text-primary-contrast";
|
|
222
401
|
if (onChange) {
|
|
223
|
-
return /* @__PURE__ */
|
|
224
|
-
download && /* @__PURE__ */
|
|
225
|
-
/* @__PURE__ */
|
|
402
|
+
return /* @__PURE__ */ jsxs2("span", { className: cn(base, variant, "inline-flex items-center gap-2"), children: [
|
|
403
|
+
download && /* @__PURE__ */ jsx9(Download, { size: 16, className: "shrink-0" }),
|
|
404
|
+
/* @__PURE__ */ jsx9(
|
|
226
405
|
EditablePlainText,
|
|
227
406
|
{
|
|
228
407
|
tag: "span",
|
|
@@ -237,7 +416,7 @@ function Button({ text, link, download, onChange }) {
|
|
|
237
416
|
const href = link && link.kind === "external" ? link.href : "";
|
|
238
417
|
const target = link?.target;
|
|
239
418
|
if (href) {
|
|
240
|
-
return /* @__PURE__ */
|
|
419
|
+
return /* @__PURE__ */ jsxs2(
|
|
241
420
|
"a",
|
|
242
421
|
{
|
|
243
422
|
href,
|
|
@@ -245,34 +424,34 @@ function Button({ text, link, download, onChange }) {
|
|
|
245
424
|
download: download ? "" : void 0,
|
|
246
425
|
className: cn(base, variant, download && "inline-flex items-center gap-2"),
|
|
247
426
|
children: [
|
|
248
|
-
download && /* @__PURE__ */
|
|
427
|
+
download && /* @__PURE__ */ jsx9(Download, { size: 16, className: "shrink-0" }),
|
|
249
428
|
text
|
|
250
429
|
]
|
|
251
430
|
}
|
|
252
431
|
);
|
|
253
432
|
}
|
|
254
|
-
return /* @__PURE__ */
|
|
433
|
+
return /* @__PURE__ */ jsx9("button", { className: cn("cursor-pointer", base, variant), children: text });
|
|
255
434
|
}
|
|
256
435
|
|
|
257
436
|
// src/components/sections/Button/index.tsx
|
|
258
|
-
import { jsx as
|
|
259
|
-
var
|
|
260
|
-
type:
|
|
261
|
-
content:
|
|
262
|
-
text:
|
|
437
|
+
import { jsx as jsx10 } from "react/jsx-runtime";
|
|
438
|
+
var schema4 = z4.object({
|
|
439
|
+
type: z4.literal("button"),
|
|
440
|
+
content: z4.object({
|
|
441
|
+
text: z4.string().describe("The button label. Plain text, short (a few words)."),
|
|
263
442
|
link: LinkValueSchema.describe(
|
|
264
443
|
"Where the button points \u2014 an internal page or a safe external URL."
|
|
265
444
|
).optional(),
|
|
266
|
-
download:
|
|
445
|
+
download: z4.boolean().describe("When true, the link is treated as a file download rather than navigation.").optional()
|
|
267
446
|
})
|
|
268
447
|
});
|
|
269
448
|
var Button_default = defineSection({
|
|
270
449
|
type: "button",
|
|
271
450
|
label: "Button",
|
|
272
|
-
icon: /* @__PURE__ */
|
|
273
|
-
schema:
|
|
451
|
+
icon: /* @__PURE__ */ jsx10(RectangleHorizontal, { size: 18 }),
|
|
452
|
+
schema: schema4,
|
|
274
453
|
authoringNote: "A call-to-action button linking to an internal page or external URL, optionally as a file download. Use for a single prominent action.",
|
|
275
|
-
component: ({ content, onChange }) => /* @__PURE__ */
|
|
454
|
+
component: ({ content, onChange }) => /* @__PURE__ */ jsx10(
|
|
276
455
|
Button,
|
|
277
456
|
{
|
|
278
457
|
text: content.content.text,
|
|
@@ -290,7 +469,7 @@ var Button_default = defineSection({
|
|
|
290
469
|
});
|
|
291
470
|
|
|
292
471
|
// src/components/sections/Container/index.tsx
|
|
293
|
-
import { z as
|
|
472
|
+
import { z as z5 } from "zod";
|
|
294
473
|
import { LayoutTemplate } from "lucide-react";
|
|
295
474
|
|
|
296
475
|
// src/components/sections/Container/Container.tsx
|
|
@@ -303,14 +482,14 @@ import { CopyPlus } from "lucide-react";
|
|
|
303
482
|
// src/components/editor/ColSpanControl.tsx
|
|
304
483
|
import { useRef, useState } from "react";
|
|
305
484
|
import { Columns3 } from "lucide-react";
|
|
306
|
-
import { jsx as
|
|
485
|
+
import { jsx as jsx11, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
307
486
|
function ColSpanControl({ colSpan, columns, onChange }) {
|
|
308
487
|
const buttonRef = useRef(null);
|
|
309
488
|
const [open, setOpen] = useState(false);
|
|
310
489
|
if (columns <= 1) return null;
|
|
311
490
|
const current = Math.min(Math.max(colSpan, 1), columns);
|
|
312
|
-
return /* @__PURE__ */
|
|
313
|
-
/* @__PURE__ */
|
|
491
|
+
return /* @__PURE__ */ jsxs3("div", { className: "relative", children: [
|
|
492
|
+
/* @__PURE__ */ jsx11(
|
|
314
493
|
"button",
|
|
315
494
|
{
|
|
316
495
|
ref: buttonRef,
|
|
@@ -320,10 +499,10 @@ function ColSpanControl({ colSpan, columns, onChange }) {
|
|
|
320
499
|
"aria-expanded": open,
|
|
321
500
|
onClick: () => setOpen((v) => !v),
|
|
322
501
|
className: "pointer-events-auto inline-flex cursor-pointer items-center gap-1 rounded p-1 text-xs text-base-contrast-light hover:text-primary",
|
|
323
|
-
children: /* @__PURE__ */
|
|
502
|
+
children: /* @__PURE__ */ jsx11(Columns3, { size: 14 })
|
|
324
503
|
}
|
|
325
504
|
),
|
|
326
|
-
/* @__PURE__ */
|
|
505
|
+
/* @__PURE__ */ jsx11(Popover, { isOpen: open, onClose: () => setOpen(false), anchorRef: buttonRef, className: "min-w-28", children: /* @__PURE__ */ jsx11("ul", { role: "list", className: "py-1", children: Array.from({ length: columns }, (_, i) => i + 1).map((span) => /* @__PURE__ */ jsx11("li", { children: /* @__PURE__ */ jsxs3(
|
|
327
506
|
PopoverItem,
|
|
328
507
|
{
|
|
329
508
|
"aria-current": span === current,
|
|
@@ -342,7 +521,7 @@ function ColSpanControl({ colSpan, columns, onChange }) {
|
|
|
342
521
|
}
|
|
343
522
|
|
|
344
523
|
// src/components/editor/ChildBlockWrapper.tsx
|
|
345
|
-
import { jsx as
|
|
524
|
+
import { jsx as jsx12, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
346
525
|
var ChildBlockWrapper = forwardRef(
|
|
347
526
|
function ChildBlockWrapper2({
|
|
348
527
|
label,
|
|
@@ -358,7 +537,7 @@ var ChildBlockWrapper = forwardRef(
|
|
|
358
537
|
onOpenSettings,
|
|
359
538
|
children
|
|
360
539
|
}, ref) {
|
|
361
|
-
return /* @__PURE__ */
|
|
540
|
+
return /* @__PURE__ */ jsxs4(
|
|
362
541
|
"div",
|
|
363
542
|
{
|
|
364
543
|
ref,
|
|
@@ -368,39 +547,39 @@ var ChildBlockWrapper = forwardRef(
|
|
|
368
547
|
"hover:outline hover:outline-2 hover:outline-primary/30"
|
|
369
548
|
),
|
|
370
549
|
children: [
|
|
371
|
-
/* @__PURE__ */
|
|
372
|
-
/* @__PURE__ */
|
|
373
|
-
/* @__PURE__ */
|
|
374
|
-
/* @__PURE__ */
|
|
375
|
-
hasSettings && onOpenSettings && /* @__PURE__ */
|
|
376
|
-
/* @__PURE__ */
|
|
550
|
+
/* @__PURE__ */ jsxs4("div", { className: "absolute top-0 left-0 -translate-x-full z-20 flex flex-col items-center gap-1 opacity-0 transition-opacity group-hover/childblock:opacity-100 group-focus-within/childblock:opacity-100 pointer-events-none", children: [
|
|
551
|
+
/* @__PURE__ */ jsx12("span", { className: "sr-only", children: label }),
|
|
552
|
+
/* @__PURE__ */ jsx12("div", { className: "pointer-events-auto", children: /* @__PURE__ */ jsx12(DragHandle, { ref: dragHandleRef }) }),
|
|
553
|
+
/* @__PURE__ */ jsx12("div", { className: "pointer-events-auto", children: /* @__PURE__ */ jsx12(ColSpanControl, { colSpan, columns, onChange: onColSpanChange }) }),
|
|
554
|
+
hasSettings && onOpenSettings && /* @__PURE__ */ jsx12("div", { className: "pointer-events-auto", children: /* @__PURE__ */ jsx12(SettingsButton, { onClick: onOpenSettings }) }),
|
|
555
|
+
/* @__PURE__ */ jsx12("div", { className: "pointer-events-auto", children: /* @__PURE__ */ jsx12(
|
|
377
556
|
"button",
|
|
378
557
|
{
|
|
379
558
|
type: "button",
|
|
380
559
|
"aria-label": "Duplicate block",
|
|
381
560
|
onClick: onDuplicate,
|
|
382
561
|
className: "cursor-pointer rounded p-1 text-base-contrast-light hover:text-primary",
|
|
383
|
-
children: /* @__PURE__ */
|
|
562
|
+
children: /* @__PURE__ */ jsx12(CopyPlus, { size: 16 })
|
|
384
563
|
}
|
|
385
564
|
) }),
|
|
386
|
-
/* @__PURE__ */
|
|
565
|
+
/* @__PURE__ */ jsx12("div", { className: "pointer-events-auto", children: /* @__PURE__ */ jsx12(DeleteButton, { onDelete }) })
|
|
387
566
|
] }),
|
|
388
|
-
closestEdge === "left" && /* @__PURE__ */
|
|
567
|
+
closestEdge === "left" && /* @__PURE__ */ jsx12(
|
|
389
568
|
"div",
|
|
390
569
|
{
|
|
391
570
|
"data-drop-edge": "left",
|
|
392
571
|
className: "absolute bottom-0 left-0 top-0 z-10 w-0.5 -translate-x-1 bg-primary"
|
|
393
572
|
}
|
|
394
573
|
),
|
|
395
|
-
closestEdge === "right" && /* @__PURE__ */
|
|
574
|
+
closestEdge === "right" && /* @__PURE__ */ jsx12(
|
|
396
575
|
"div",
|
|
397
576
|
{
|
|
398
577
|
"data-drop-edge": "right",
|
|
399
578
|
className: "absolute bottom-0 right-0 top-0 z-10 w-0.5 translate-x-1 bg-primary"
|
|
400
579
|
}
|
|
401
580
|
),
|
|
402
|
-
closestEdge === "top" && /* @__PURE__ */
|
|
403
|
-
closestEdge === "bottom" && /* @__PURE__ */
|
|
581
|
+
closestEdge === "top" && /* @__PURE__ */ jsx12("div", { "data-drop-edge": "top", className: "absolute left-0 right-0 top-0 z-10 h-0.5 -translate-y-1 bg-primary" }),
|
|
582
|
+
closestEdge === "bottom" && /* @__PURE__ */ jsx12("div", { "data-drop-edge": "bottom", className: "absolute left-0 right-0 bottom-0 z-10 h-0.5 translate-y-1 bg-primary" }),
|
|
404
583
|
children
|
|
405
584
|
]
|
|
406
585
|
}
|
|
@@ -570,7 +749,7 @@ function trimTrailingSpacers(container) {
|
|
|
570
749
|
}
|
|
571
750
|
|
|
572
751
|
// src/components/sections/Container/Container.tsx
|
|
573
|
-
import { jsx as
|
|
752
|
+
import { jsx as jsx13, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
574
753
|
var ROW_EDGES = ["left", "right"];
|
|
575
754
|
var COL_EDGES = ["top", "bottom"];
|
|
576
755
|
function ContainerChild({
|
|
@@ -601,14 +780,14 @@ function ContainerChild({
|
|
|
601
780
|
allowedEdges: flow === "column" ? COL_EDGES : ROW_EDGES,
|
|
602
781
|
enabled: true
|
|
603
782
|
});
|
|
604
|
-
return /* @__PURE__ */
|
|
783
|
+
return /* @__PURE__ */ jsx13(
|
|
605
784
|
"div",
|
|
606
785
|
{
|
|
607
786
|
ref: dragRef,
|
|
608
787
|
className: cellClass,
|
|
609
788
|
"data-child-index": index,
|
|
610
789
|
"data-child-id": child.id,
|
|
611
|
-
children: /* @__PURE__ */
|
|
790
|
+
children: /* @__PURE__ */ jsx13(
|
|
612
791
|
ChildBlockWrapper,
|
|
613
792
|
{
|
|
614
793
|
label,
|
|
@@ -622,7 +801,7 @@ function ContainerChild({
|
|
|
622
801
|
onDuplicate,
|
|
623
802
|
onColSpanChange,
|
|
624
803
|
onOpenSettings,
|
|
625
|
-
children: /* @__PURE__ */
|
|
804
|
+
children: /* @__PURE__ */ jsx13(
|
|
626
805
|
ChildComp,
|
|
627
806
|
{
|
|
628
807
|
content: child,
|
|
@@ -650,7 +829,7 @@ function EmptyColumnCell({
|
|
|
650
829
|
enabled: true
|
|
651
830
|
});
|
|
652
831
|
const active = closestEdge !== null;
|
|
653
|
-
return /* @__PURE__ */
|
|
832
|
+
return /* @__PURE__ */ jsx13(
|
|
654
833
|
"div",
|
|
655
834
|
{
|
|
656
835
|
ref: dropRef,
|
|
@@ -688,7 +867,7 @@ function Container({ content, isEditMode, onChange, openModal }) {
|
|
|
688
867
|
flow === "column" && "grid-flow-col"
|
|
689
868
|
);
|
|
690
869
|
if (!editable) {
|
|
691
|
-
return /* @__PURE__ */
|
|
870
|
+
return /* @__PURE__ */ jsx13("div", { className: "@container", children: /* @__PURE__ */ jsx13("div", { className: gridClass, children: children.map((child, index) => {
|
|
692
871
|
const def = getSection(child.type);
|
|
693
872
|
if (!def) return null;
|
|
694
873
|
const Child = def.component;
|
|
@@ -699,7 +878,7 @@ function Container({ content, isEditMode, onChange, openModal }) {
|
|
|
699
878
|
colSpanClass[columns]?.[Math.min(span, columns)] || void 0,
|
|
700
879
|
child.type === "spacer" && spacerHiddenClass[columns]
|
|
701
880
|
);
|
|
702
|
-
return /* @__PURE__ */
|
|
881
|
+
return /* @__PURE__ */ jsx13("div", { className: cellClass, children: /* @__PURE__ */ jsx13(Child, { content: child, options: mergedOptions, isEditMode }) }, child.id ?? index);
|
|
703
882
|
}) }) });
|
|
704
883
|
}
|
|
705
884
|
function columnStartOf(index) {
|
|
@@ -713,7 +892,7 @@ function Container({ content, isEditMode, onChange, openModal }) {
|
|
|
713
892
|
const def = getSection(child.type);
|
|
714
893
|
if (!def) return null;
|
|
715
894
|
if (isSpacer(child)) {
|
|
716
|
-
return /* @__PURE__ */
|
|
895
|
+
return /* @__PURE__ */ jsx13(
|
|
717
896
|
EmptyColumnCell,
|
|
718
897
|
{
|
|
719
898
|
containerId: container.id,
|
|
@@ -741,12 +920,12 @@ function Container({ content, isEditMode, onChange, openModal }) {
|
|
|
741
920
|
const CustomForm = def.settingsForm;
|
|
742
921
|
openModal(
|
|
743
922
|
`${def.label} Settings`,
|
|
744
|
-
/* @__PURE__ */
|
|
923
|
+
/* @__PURE__ */ jsx13(CustomForm, { ...seed, onChange: applyResult })
|
|
745
924
|
);
|
|
746
925
|
} else if (def.settings) {
|
|
747
926
|
openModal(
|
|
748
927
|
`${def.label} Settings`,
|
|
749
|
-
/* @__PURE__ */
|
|
928
|
+
/* @__PURE__ */ jsx13(
|
|
750
929
|
SettingsForm,
|
|
751
930
|
{
|
|
752
931
|
schema: def.settings,
|
|
@@ -758,7 +937,7 @@ function Container({ content, isEditMode, onChange, openModal }) {
|
|
|
758
937
|
);
|
|
759
938
|
}
|
|
760
939
|
} : void 0;
|
|
761
|
-
return /* @__PURE__ */
|
|
940
|
+
return /* @__PURE__ */ jsx13(
|
|
762
941
|
ContainerChild,
|
|
763
942
|
{
|
|
764
943
|
containerId: container.id,
|
|
@@ -784,9 +963,9 @@ function Container({ content, isEditMode, onChange, openModal }) {
|
|
|
784
963
|
}
|
|
785
964
|
const occupied = occupiedColumns(children, columns);
|
|
786
965
|
const emptyCols = occupied < columns ? columns - occupied : 0;
|
|
787
|
-
return /* @__PURE__ */
|
|
966
|
+
return /* @__PURE__ */ jsx13("div", { className: "@container", children: /* @__PURE__ */ jsxs5("div", { className: gridClass, children: [
|
|
788
967
|
children.map(renderEditChild),
|
|
789
|
-
Array.from({ length: emptyCols }, (_, i) => /* @__PURE__ */
|
|
968
|
+
Array.from({ length: emptyCols }, (_, i) => /* @__PURE__ */ jsx13(
|
|
790
969
|
EmptyColumnCell,
|
|
791
970
|
{
|
|
792
971
|
containerId: container.id,
|
|
@@ -800,7 +979,7 @@ function Container({ content, isEditMode, onChange, openModal }) {
|
|
|
800
979
|
|
|
801
980
|
// src/components/sections/Container/ContainerSettingsForm.tsx
|
|
802
981
|
import { useState as useState3 } from "react";
|
|
803
|
-
import { jsx as
|
|
982
|
+
import { jsx as jsx14, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
804
983
|
function inheritableSchema(children) {
|
|
805
984
|
const out = {};
|
|
806
985
|
for (const child of children) {
|
|
@@ -850,10 +1029,10 @@ function ContainerSettingsForm({
|
|
|
850
1029
|
]
|
|
851
1030
|
}
|
|
852
1031
|
};
|
|
853
|
-
return /* @__PURE__ */
|
|
854
|
-
/* @__PURE__ */
|
|
855
|
-
/* @__PURE__ */
|
|
856
|
-
/* @__PURE__ */
|
|
1032
|
+
return /* @__PURE__ */ jsxs6("div", { className: "flex flex-col gap-6", children: [
|
|
1033
|
+
/* @__PURE__ */ jsxs6("fieldset", { className: "flex flex-col gap-4", children: [
|
|
1034
|
+
/* @__PURE__ */ jsx14("legend", { className: "mb-2 text-sm font-semibold text-base-contrast", children: "Layout" }),
|
|
1035
|
+
/* @__PURE__ */ jsx14(
|
|
857
1036
|
SettingsForm,
|
|
858
1037
|
{
|
|
859
1038
|
schema: layoutSchema,
|
|
@@ -869,9 +1048,9 @@ function ContainerSettingsForm({
|
|
|
869
1048
|
}
|
|
870
1049
|
)
|
|
871
1050
|
] }),
|
|
872
|
-
hasChildDefaults && /* @__PURE__ */
|
|
873
|
-
/* @__PURE__ */
|
|
874
|
-
/* @__PURE__ */
|
|
1051
|
+
hasChildDefaults && /* @__PURE__ */ jsxs6("fieldset", { className: "flex flex-col gap-4 border-t border-base-200 pt-4", children: [
|
|
1052
|
+
/* @__PURE__ */ jsx14("legend", { className: "mb-2 text-sm font-semibold text-base-contrast", children: "Apply to all items" }),
|
|
1053
|
+
/* @__PURE__ */ jsx14(
|
|
875
1054
|
SettingsForm,
|
|
876
1055
|
{
|
|
877
1056
|
schema: childSchema,
|
|
@@ -888,18 +1067,18 @@ function ContainerSettingsForm({
|
|
|
888
1067
|
}
|
|
889
1068
|
|
|
890
1069
|
// src/components/sections/Container/index.tsx
|
|
891
|
-
import { jsx as
|
|
892
|
-
var
|
|
893
|
-
type:
|
|
894
|
-
content:
|
|
895
|
-
columns:
|
|
896
|
-
flow:
|
|
1070
|
+
import { jsx as jsx15 } from "react/jsx-runtime";
|
|
1071
|
+
var schema5 = z5.object({
|
|
1072
|
+
type: z5.literal("container"),
|
|
1073
|
+
content: z5.object({
|
|
1074
|
+
columns: z5.number().int().min(1).max(MAX_CONTAINER_COLUMNS).describe("Number of columns in the grid. Children flow across this many columns.").default(1),
|
|
1075
|
+
flow: z5.enum(["row", "column"]).describe(
|
|
897
1076
|
"Layout direction: 'row' (children flow left-to-right across columns) or 'column' (stacked)."
|
|
898
1077
|
).default("row"),
|
|
899
|
-
childDefaults:
|
|
1078
|
+
childDefaults: z5.record(z5.string(), z5.unknown()).describe("Optional default option values applied to child sections (inheritable settings only).").optional(),
|
|
900
1079
|
// Recursive: children are full blocks. z.lazy defers evaluation to parse
|
|
901
1080
|
// time, by which point every section schema (incl. container) is registered.
|
|
902
|
-
children:
|
|
1081
|
+
children: z5.array(z5.lazy(() => getSectionSchema())).default([])
|
|
903
1082
|
}).transform((c) => ({
|
|
904
1083
|
...c,
|
|
905
1084
|
children: c.children.map(
|
|
@@ -910,10 +1089,10 @@ var schema4 = z4.object({
|
|
|
910
1089
|
var Container_default = defineSection({
|
|
911
1090
|
type: "container",
|
|
912
1091
|
label: "Container",
|
|
913
|
-
icon: /* @__PURE__ */
|
|
914
|
-
schema:
|
|
1092
|
+
icon: /* @__PURE__ */ jsx15(LayoutTemplate, { size: 18 }),
|
|
1093
|
+
schema: schema5,
|
|
915
1094
|
authoringNote: "A layout wrapper that arranges child sections into columns/rows. Use to place blocks side by side or build multi-column layouts; set columns and add children.",
|
|
916
|
-
component: ({ content, onChange, isEditMode, openModal }) => /* @__PURE__ */
|
|
1095
|
+
component: ({ content, onChange, isEditMode, openModal }) => /* @__PURE__ */ jsx15(Container, { content, isEditMode: !!isEditMode, onChange, openModal }),
|
|
917
1096
|
defaults: () => ({
|
|
918
1097
|
type: "container",
|
|
919
1098
|
content: { columns: 1, flow: "row", children: [] }
|
|
@@ -923,28 +1102,28 @@ var Container_default = defineSection({
|
|
|
923
1102
|
});
|
|
924
1103
|
|
|
925
1104
|
// src/components/sections/Spacer/index.tsx
|
|
926
|
-
import { z as
|
|
1105
|
+
import { z as z6 } from "zod";
|
|
927
1106
|
import { SquareDashed } from "lucide-react";
|
|
928
1107
|
|
|
929
1108
|
// src/components/sections/Spacer/Spacer.tsx
|
|
930
|
-
import { jsx as
|
|
1109
|
+
import { jsx as jsx16 } from "react/jsx-runtime";
|
|
931
1110
|
function Spacer() {
|
|
932
|
-
return /* @__PURE__ */
|
|
1111
|
+
return /* @__PURE__ */ jsx16("div", { "data-spacer": true, "aria-hidden": "true", className: "h-full" });
|
|
933
1112
|
}
|
|
934
1113
|
|
|
935
1114
|
// src/components/sections/Spacer/index.tsx
|
|
936
|
-
import { jsx as
|
|
937
|
-
var
|
|
938
|
-
type:
|
|
939
|
-
content:
|
|
1115
|
+
import { jsx as jsx17 } from "react/jsx-runtime";
|
|
1116
|
+
var schema6 = z6.object({
|
|
1117
|
+
type: z6.literal("spacer"),
|
|
1118
|
+
content: z6.object({}).default({})
|
|
940
1119
|
});
|
|
941
1120
|
var Spacer_default = defineSection({
|
|
942
1121
|
type: "spacer",
|
|
943
1122
|
label: "Spacer",
|
|
944
|
-
icon: /* @__PURE__ */
|
|
945
|
-
schema:
|
|
1123
|
+
icon: /* @__PURE__ */ jsx17(SquareDashed, { size: 18 }),
|
|
1124
|
+
schema: schema6,
|
|
946
1125
|
authoringNote: "Vertical whitespace between sections. Use sparingly to add breathing room where default section spacing is insufficient.",
|
|
947
|
-
component: () => /* @__PURE__ */
|
|
1126
|
+
component: () => /* @__PURE__ */ jsx17(Spacer, {}),
|
|
948
1127
|
defaults: () => ({ type: "spacer", content: {} })
|
|
949
1128
|
});
|
|
950
1129
|
|
|
@@ -955,6 +1134,7 @@ var coreSectionDefs = [
|
|
|
955
1134
|
SubSubHeading_default,
|
|
956
1135
|
Prose_default,
|
|
957
1136
|
Media_default,
|
|
1137
|
+
Video_default,
|
|
958
1138
|
Button_default,
|
|
959
1139
|
Container_default,
|
|
960
1140
|
Spacer_default
|