@drawnagency/primitives 0.1.71 → 0.1.73
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-RTYJZAKR.js → chunk-7T2WQSWF.js} +12 -12
- package/dist/chunk-IFHRHV7S.js +117 -0
- package/dist/{chunk-2BHPWO7M.js → chunk-N6AE6NBB.js} +158 -32
- package/dist/{chunk-WXVKX6PY.js → chunk-NKVZGPR6.js} +41 -95
- package/dist/{chunk-3DCG4DNU.js → chunk-PZJL2S3Z.js} +8 -4
- package/dist/chunk-RBTSUR5V.js +37 -0
- package/dist/{chunk-6UDYJQL6.js → chunk-S55OZ7F2.js} +9 -1
- package/dist/{chunk-NR7UB6DZ.js → chunk-SFKYUKVN.js} +1 -1
- package/dist/{chunk-YMVYTYGQ.js → chunk-SWIHUIFT.js} +28 -16
- package/dist/{chunk-KWBM27UR.js → chunk-T7MP7ANP.js} +13 -64
- package/dist/{chunk-MU3CDERQ.js → chunk-XTRTK26E.js} +276 -96
- package/dist/{chunk-GKV77AA6.js → chunk-ZRWGV5O6.js} +3 -3
- package/dist/chunk-ZSPCE6MZ.js +70 -0
- package/dist/components/editor/SettingsForm.d.ts.map +1 -1
- package/dist/components/editor/index.js +6 -3
- package/dist/components/primitives/ResolvedMedia.d.ts.map +1 -1
- package/dist/components/primitives/index.js +7 -7
- package/dist/components/sections/Media/MediaBlock.d.ts.map +1 -1
- 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/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 +4 -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 +28 -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/save-chunks.d.ts +28 -0
- package/dist/lib/save-chunks.d.ts.map +1 -0
- 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 +6 -2
- package/dist/media/resolve.d.ts +14 -0
- package/dist/media/resolve.d.ts.map +1 -1
- 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 +1 -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/editor/SettingsForm.tsx +11 -0
- package/src/components/primitives/ResolvedMedia.tsx +10 -5
- package/src/components/sections/Media/MediaBlock.tsx +2 -1
- 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/EditorShell.tsx +16 -2
- package/src/components/shell/MediaLibraryModal.tsx +47 -1
- package/src/hooks/useEditorPublish.ts +137 -50
- package/src/hooks/useMediaPipeline.ts +188 -25
- package/src/lib/registry.ts +7 -0
- package/src/lib/save-chunks.ts +53 -0
- package/src/lib/video-url.ts +39 -0
- package/src/media/resolve.ts +18 -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/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,25 +1,25 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Checkbox,
|
|
3
|
-
FormLabel,
|
|
4
|
-
Input
|
|
5
|
-
} from "./chunk-5THS4K5D.js";
|
|
6
1
|
import {
|
|
7
2
|
EditableGrid,
|
|
8
3
|
EditablePlainText,
|
|
9
4
|
MediaBlock,
|
|
10
5
|
containerGridClass,
|
|
11
6
|
useEditableCollection
|
|
12
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-T7MP7ANP.js";
|
|
8
|
+
import {
|
|
9
|
+
Checkbox,
|
|
10
|
+
FormLabel,
|
|
11
|
+
Input
|
|
12
|
+
} from "./chunk-5THS4K5D.js";
|
|
13
13
|
import {
|
|
14
14
|
AddIcon,
|
|
15
15
|
DeleteIcon,
|
|
16
16
|
DragHandle,
|
|
17
17
|
IconButton
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-IFHRHV7S.js";
|
|
19
19
|
import {
|
|
20
20
|
DEFAULT_LINK,
|
|
21
21
|
LinkValueSchema
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-PZJL2S3Z.js";
|
|
23
23
|
import {
|
|
24
24
|
curatedIcons,
|
|
25
25
|
getIcon
|
|
@@ -27,13 +27,13 @@ import {
|
|
|
27
27
|
import {
|
|
28
28
|
cn
|
|
29
29
|
} from "./chunk-7EOSDFS3.js";
|
|
30
|
-
import {
|
|
31
|
-
HexColorSchema,
|
|
32
|
-
SingleMediaReferenceSchema
|
|
33
|
-
} from "./chunk-YMVYTYGQ.js";
|
|
34
30
|
import {
|
|
35
31
|
defineSection
|
|
36
32
|
} from "./chunk-VKAGMEKE.js";
|
|
33
|
+
import {
|
|
34
|
+
HexColorSchema,
|
|
35
|
+
SingleMediaReferenceSchema
|
|
36
|
+
} from "./chunk-SWIHUIFT.js";
|
|
37
37
|
|
|
38
38
|
// src/components/sections/Colors/index.tsx
|
|
39
39
|
import { z as z2 } from "zod";
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getMediaProvider
|
|
3
|
+
} from "./chunk-S55OZ7F2.js";
|
|
4
|
+
import {
|
|
5
|
+
cn
|
|
6
|
+
} from "./chunk-7EOSDFS3.js";
|
|
7
|
+
|
|
8
|
+
// src/components/shell/MediaLibraryContext.tsx
|
|
9
|
+
import { createContext, useContext } from "react";
|
|
10
|
+
var MediaLibraryContext = createContext(null);
|
|
11
|
+
function useMediaLibrary() {
|
|
12
|
+
return useContext(MediaLibraryContext);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// src/hooks/useResolvedMedia.ts
|
|
16
|
+
import { useMemo } from "react";
|
|
17
|
+
function useResolvedMedia(imageId) {
|
|
18
|
+
const ctx = useMediaLibrary();
|
|
19
|
+
return useMemo(() => {
|
|
20
|
+
if (!imageId || !ctx) {
|
|
21
|
+
return { src: void 0, srcset: void 0, poster: void 0, alt: "", kind: "image" };
|
|
22
|
+
}
|
|
23
|
+
const { manifest, pendingItems, pendingLocalUrls, siteConfig } = ctx;
|
|
24
|
+
const sizes = siteConfig?.media?.sizes ?? [640, 1080, 1920];
|
|
25
|
+
const manifestItem = manifest.images[imageId];
|
|
26
|
+
const pendingItem = pendingItems.find((i) => i.id === imageId);
|
|
27
|
+
const item = manifestItem ?? pendingItem;
|
|
28
|
+
const alt = item?.alt ?? "";
|
|
29
|
+
const kind = item?.kind ?? "image";
|
|
30
|
+
const width = item?.width;
|
|
31
|
+
const height = item?.height;
|
|
32
|
+
const localUrl = pendingLocalUrls[imageId];
|
|
33
|
+
if (localUrl) {
|
|
34
|
+
return { src: localUrl, srcset: void 0, poster: void 0, alt, kind, width, height };
|
|
35
|
+
}
|
|
36
|
+
if (manifestItem) {
|
|
37
|
+
const provider = getMediaProvider();
|
|
38
|
+
const resolved = provider.resolve(manifestItem, sizes);
|
|
39
|
+
if (resolved && resolved.tag === "img") {
|
|
40
|
+
return {
|
|
41
|
+
src: resolved.src,
|
|
42
|
+
srcset: "srcSet" in resolved ? resolved.srcSet : void 0,
|
|
43
|
+
poster: void 0,
|
|
44
|
+
alt,
|
|
45
|
+
kind,
|
|
46
|
+
width: resolved.width,
|
|
47
|
+
height: resolved.height
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
if (resolved && resolved.tag === "video") {
|
|
51
|
+
return { src: resolved.src, srcset: void 0, poster: resolved.poster, alt, kind, width: resolved.width, height: resolved.height };
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return { src: void 0, srcset: void 0, poster: void 0, alt, kind, width, height };
|
|
55
|
+
}, [imageId, ctx]);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// src/components/shared/icons.tsx
|
|
59
|
+
import { GripVertical, Plus, Trash2, X, Settings } from "lucide-react";
|
|
60
|
+
import { GripVertical as GripVertical2, Plus as Plus2, Trash2 as Trash22, X as X2, Settings as Settings2 } from "lucide-react";
|
|
61
|
+
import { jsx } from "react/jsx-runtime";
|
|
62
|
+
function DragHandle({ size = 16 }) {
|
|
63
|
+
return /* @__PURE__ */ jsx(GripVertical, { size });
|
|
64
|
+
}
|
|
65
|
+
function AddIcon({ size = 14 }) {
|
|
66
|
+
return /* @__PURE__ */ jsx(Plus, { size });
|
|
67
|
+
}
|
|
68
|
+
function DeleteIcon({ size = 14 }) {
|
|
69
|
+
return /* @__PURE__ */ jsx(Trash2, { size });
|
|
70
|
+
}
|
|
71
|
+
function SettingsIcon({ size = 14 }) {
|
|
72
|
+
return /* @__PURE__ */ jsx(Settings, { size });
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// src/components/shared/IconButton.tsx
|
|
76
|
+
import { forwardRef } from "react";
|
|
77
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
78
|
+
var sizeClasses = {
|
|
79
|
+
sm: "h-chrome-sm w-chrome-sm",
|
|
80
|
+
md: "h-chrome-md w-chrome-md",
|
|
81
|
+
lg: "h-chrome-lg w-chrome-lg"
|
|
82
|
+
};
|
|
83
|
+
var intentClasses = {
|
|
84
|
+
default: "text-base-contrast-light hover:text-base-contrast",
|
|
85
|
+
destructive: "text-destructive hover:text-destructive-hover",
|
|
86
|
+
primary: "text-primary/60 hover:text-primary"
|
|
87
|
+
};
|
|
88
|
+
var IconButton = forwardRef(
|
|
89
|
+
function IconButton2({ icon, label, size = "md", intent = "default", className, ...rest }, ref) {
|
|
90
|
+
return /* @__PURE__ */ jsx2(
|
|
91
|
+
"button",
|
|
92
|
+
{
|
|
93
|
+
ref,
|
|
94
|
+
type: "button",
|
|
95
|
+
className: cn(
|
|
96
|
+
"cursor-pointer flex items-center justify-center rounded transition-colors",
|
|
97
|
+
sizeClasses[size],
|
|
98
|
+
intentClasses[intent],
|
|
99
|
+
className
|
|
100
|
+
),
|
|
101
|
+
"aria-label": label,
|
|
102
|
+
...rest,
|
|
103
|
+
children: icon
|
|
104
|
+
}
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
export {
|
|
110
|
+
useMediaLibrary,
|
|
111
|
+
useResolvedMedia,
|
|
112
|
+
DragHandle,
|
|
113
|
+
AddIcon,
|
|
114
|
+
DeleteIcon,
|
|
115
|
+
SettingsIcon,
|
|
116
|
+
IconButton
|
|
117
|
+
};
|
|
@@ -1,17 +1,20 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Button,
|
|
3
|
+
usePages
|
|
4
|
+
} from "./chunk-ZSPCE6MZ.js";
|
|
1
5
|
import {
|
|
2
6
|
Checkbox,
|
|
3
7
|
FormLabel,
|
|
4
8
|
Input
|
|
5
9
|
} from "./chunk-5THS4K5D.js";
|
|
6
|
-
import {
|
|
7
|
-
usePages
|
|
8
|
-
} from "./chunk-4E66N6UV.js";
|
|
9
10
|
import {
|
|
10
11
|
DeleteIcon,
|
|
11
12
|
DragHandle,
|
|
12
13
|
IconButton,
|
|
13
|
-
SettingsIcon
|
|
14
|
-
|
|
14
|
+
SettingsIcon,
|
|
15
|
+
useMediaLibrary,
|
|
16
|
+
useResolvedMedia
|
|
17
|
+
} from "./chunk-IFHRHV7S.js";
|
|
15
18
|
import {
|
|
16
19
|
cn
|
|
17
20
|
} from "./chunk-7EOSDFS3.js";
|
|
@@ -86,7 +89,7 @@ function SettingsButton({ onClick }) {
|
|
|
86
89
|
}
|
|
87
90
|
|
|
88
91
|
// src/components/editor/SettingsForm.tsx
|
|
89
|
-
import { useId as useId2, useState as
|
|
92
|
+
import { useId as useId2, useState as useState3 } from "react";
|
|
90
93
|
|
|
91
94
|
// src/components/shared/Select.tsx
|
|
92
95
|
import { useId } from "react";
|
|
@@ -205,11 +208,125 @@ function LinkField({ label, value, onChange }) {
|
|
|
205
208
|
] });
|
|
206
209
|
}
|
|
207
210
|
|
|
208
|
-
// src/components/shared/
|
|
211
|
+
// src/components/shared/VideoSourceField.tsx
|
|
209
212
|
import { useState } from "react";
|
|
210
213
|
import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
214
|
+
function VideoSourceField({ value, onChange }) {
|
|
215
|
+
const mediaLibrary = useMediaLibrary();
|
|
216
|
+
const [mode, setMode] = useState(value?.type === "external" ? "embed" : "library");
|
|
217
|
+
const [url, setUrl] = useState(value?.type === "external" ? value.url : "");
|
|
218
|
+
const [loading, setLoading] = useState(false);
|
|
219
|
+
const [error, setError] = useState(null);
|
|
220
|
+
const [fallback, setFallback] = useState(false);
|
|
221
|
+
const libraryImageId = value?.type === "library" ? value.ref.imageId : void 0;
|
|
222
|
+
const resolved = useResolvedMedia(libraryImageId);
|
|
223
|
+
async function submitEmbed() {
|
|
224
|
+
if (loading) return;
|
|
225
|
+
const trimmed = url.trim();
|
|
226
|
+
if (!trimmed) return;
|
|
227
|
+
setLoading(true);
|
|
228
|
+
setError(null);
|
|
229
|
+
setFallback(false);
|
|
230
|
+
try {
|
|
231
|
+
const res = await fetch(`/api/media/oembed?url=${encodeURIComponent(trimmed)}`);
|
|
232
|
+
const body = await res.json();
|
|
233
|
+
if (!res.ok) {
|
|
234
|
+
setError(body?.message ?? "Couldn't load that video.");
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
onChange({
|
|
238
|
+
type: "external",
|
|
239
|
+
provider: body.provider,
|
|
240
|
+
id: body.id,
|
|
241
|
+
url: body.url,
|
|
242
|
+
width: body.width,
|
|
243
|
+
height: body.height
|
|
244
|
+
});
|
|
245
|
+
if (body.fallback) {
|
|
246
|
+
setFallback(true);
|
|
247
|
+
} else {
|
|
248
|
+
setUrl("");
|
|
249
|
+
}
|
|
250
|
+
} catch {
|
|
251
|
+
setError("Couldn't reach the video service.");
|
|
252
|
+
} finally {
|
|
253
|
+
setLoading(false);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
return /* @__PURE__ */ jsxs5("div", { className: "flex flex-col gap-3", children: [
|
|
257
|
+
/* @__PURE__ */ jsx7(FormLabel, { children: "Source" }),
|
|
258
|
+
/* @__PURE__ */ jsx7("div", { className: "flex gap-2", role: "tablist", children: ["library", "embed"].map((m) => /* @__PURE__ */ jsx7(
|
|
259
|
+
"button",
|
|
260
|
+
{
|
|
261
|
+
type: "button",
|
|
262
|
+
role: "tab",
|
|
263
|
+
"aria-selected": mode === m,
|
|
264
|
+
onClick: () => setMode(m),
|
|
265
|
+
className: cn(
|
|
266
|
+
"cursor-pointer rounded border px-3 py-1 text-sm",
|
|
267
|
+
mode === m ? "border-primary bg-primary text-primary-contrast" : "border-base-200 text-base-contrast"
|
|
268
|
+
),
|
|
269
|
+
children: m === "library" ? "Choose from library" : "Paste embed URL"
|
|
270
|
+
},
|
|
271
|
+
m
|
|
272
|
+
)) }),
|
|
273
|
+
mode === "library" ? /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-3", children: [
|
|
274
|
+
libraryImageId ? resolved.poster ? /* @__PURE__ */ jsx7("img", { src: resolved.poster, alt: "", className: "h-12 w-20 rounded object-cover" }) : /* @__PURE__ */ jsx7("span", { className: "text-sm text-base-contrast-light", children: "Video selected" }) : /* @__PURE__ */ jsx7("span", { className: "text-sm text-base-contrast-light", children: "No video selected" }),
|
|
275
|
+
/* @__PURE__ */ jsx7(
|
|
276
|
+
Button,
|
|
277
|
+
{
|
|
278
|
+
type: "button",
|
|
279
|
+
variant: "secondary",
|
|
280
|
+
size: "sm",
|
|
281
|
+
onClick: () => mediaLibrary?.openSelectModal((id) => onChange({ type: "library", ref: { imageId: id } })),
|
|
282
|
+
children: "Choose video"
|
|
283
|
+
}
|
|
284
|
+
)
|
|
285
|
+
] }) : /* @__PURE__ */ jsxs5("div", { className: "flex flex-col gap-2", children: [
|
|
286
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2", children: [
|
|
287
|
+
/* @__PURE__ */ jsx7(
|
|
288
|
+
"input",
|
|
289
|
+
{
|
|
290
|
+
type: "text",
|
|
291
|
+
value: url,
|
|
292
|
+
onChange: (e) => {
|
|
293
|
+
setUrl(e.target.value);
|
|
294
|
+
setError(null);
|
|
295
|
+
setFallback(false);
|
|
296
|
+
},
|
|
297
|
+
onKeyDown: (e) => {
|
|
298
|
+
if (e.key === "Enter") {
|
|
299
|
+
e.preventDefault();
|
|
300
|
+
void submitEmbed();
|
|
301
|
+
}
|
|
302
|
+
},
|
|
303
|
+
placeholder: "Paste a YouTube or Vimeo URL\u2026",
|
|
304
|
+
className: "flex-1 rounded border border-base-200 bg-base px-2 py-1 text-sm text-base-contrast placeholder:text-base-contrast-light focus:outline-none focus:ring-1 focus:ring-primary"
|
|
305
|
+
}
|
|
306
|
+
),
|
|
307
|
+
/* @__PURE__ */ jsx7(
|
|
308
|
+
Button,
|
|
309
|
+
{
|
|
310
|
+
type: "button",
|
|
311
|
+
variant: "primary",
|
|
312
|
+
size: "sm",
|
|
313
|
+
onClick: () => void submitEmbed(),
|
|
314
|
+
disabled: loading || !url.trim(),
|
|
315
|
+
children: loading ? "Loading\u2026" : "Use link"
|
|
316
|
+
}
|
|
317
|
+
)
|
|
318
|
+
] }),
|
|
319
|
+
error ? /* @__PURE__ */ jsx7("p", { className: "text-xs text-red-600", children: error }) : null,
|
|
320
|
+
!error && fallback ? /* @__PURE__ */ jsx7("p", { className: "text-xs text-base-contrast-light/70", children: "Added \u2014 couldn't fetch exact dimensions, using 16:9." }) : null
|
|
321
|
+
] })
|
|
322
|
+
] });
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// src/components/shared/Tabs.tsx
|
|
326
|
+
import { useState as useState2 } from "react";
|
|
327
|
+
import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
211
328
|
function Tabs({ tabs, defaultTabId, activeTabId, onTabChange, fullBleedTabBar }) {
|
|
212
|
-
const [uncontrolledId, setUncontrolledId] =
|
|
329
|
+
const [uncontrolledId, setUncontrolledId] = useState2(defaultTabId ?? tabs[0]?.id);
|
|
213
330
|
const isControlled = activeTabId !== void 0;
|
|
214
331
|
const activeId = isControlled ? activeTabId : uncontrolledId;
|
|
215
332
|
const activeTab = tabs.find((t) => t.id === activeId) ?? tabs[0];
|
|
@@ -217,8 +334,8 @@ function Tabs({ tabs, defaultTabId, activeTabId, onTabChange, fullBleedTabBar })
|
|
|
217
334
|
if (!isControlled) setUncontrolledId(id);
|
|
218
335
|
onTabChange?.(id);
|
|
219
336
|
}
|
|
220
|
-
return /* @__PURE__ */
|
|
221
|
-
/* @__PURE__ */
|
|
337
|
+
return /* @__PURE__ */ jsxs6("div", { className: "flex flex-1 flex-col overflow-hidden", children: [
|
|
338
|
+
/* @__PURE__ */ jsx8("div", { className: cn("border-b border-base-200", fullBleedTabBar && "-mx-6 px-6"), children: /* @__PURE__ */ jsx8("div", { className: "flex", role: "tablist", children: tabs.map((tab) => /* @__PURE__ */ jsx8(
|
|
222
339
|
"button",
|
|
223
340
|
{
|
|
224
341
|
type: "button",
|
|
@@ -233,12 +350,12 @@ function Tabs({ tabs, defaultTabId, activeTabId, onTabChange, fullBleedTabBar })
|
|
|
233
350
|
},
|
|
234
351
|
tab.id
|
|
235
352
|
)) }) }),
|
|
236
|
-
/* @__PURE__ */
|
|
353
|
+
/* @__PURE__ */ jsx8("div", { role: "tabpanel", className: cn(fullBleedTabBar && "pt-4"), children: activeTab?.content })
|
|
237
354
|
] });
|
|
238
355
|
}
|
|
239
356
|
|
|
240
357
|
// src/components/editor/SettingsForm.tsx
|
|
241
|
-
import { jsx as
|
|
358
|
+
import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
242
359
|
function resolveValues(schema, values) {
|
|
243
360
|
const resolved = {};
|
|
244
361
|
for (const [key, field] of Object.entries(schema)) {
|
|
@@ -278,9 +395,9 @@ function RangeField({
|
|
|
278
395
|
onChange
|
|
279
396
|
}) {
|
|
280
397
|
const id = useId2();
|
|
281
|
-
return /* @__PURE__ */
|
|
282
|
-
/* @__PURE__ */
|
|
283
|
-
/* @__PURE__ */
|
|
398
|
+
return /* @__PURE__ */ jsxs7("div", { children: [
|
|
399
|
+
/* @__PURE__ */ jsx9(FormLabel, { htmlFor: id, children: field.label }),
|
|
400
|
+
/* @__PURE__ */ jsx9(
|
|
284
401
|
"input",
|
|
285
402
|
{
|
|
286
403
|
id,
|
|
@@ -300,7 +417,7 @@ function RangeField({
|
|
|
300
417
|
function renderField(key, field, value, handleFieldChange) {
|
|
301
418
|
switch (field.type) {
|
|
302
419
|
case "text":
|
|
303
|
-
return /* @__PURE__ */
|
|
420
|
+
return /* @__PURE__ */ jsx9(
|
|
304
421
|
Input,
|
|
305
422
|
{
|
|
306
423
|
label: field.label,
|
|
@@ -311,7 +428,7 @@ function renderField(key, field, value, handleFieldChange) {
|
|
|
311
428
|
key
|
|
312
429
|
);
|
|
313
430
|
case "number":
|
|
314
|
-
return /* @__PURE__ */
|
|
431
|
+
return /* @__PURE__ */ jsx9(
|
|
315
432
|
Input,
|
|
316
433
|
{
|
|
317
434
|
label: field.label,
|
|
@@ -322,7 +439,7 @@ function renderField(key, field, value, handleFieldChange) {
|
|
|
322
439
|
key
|
|
323
440
|
);
|
|
324
441
|
case "checkbox":
|
|
325
|
-
return /* @__PURE__ */
|
|
442
|
+
return /* @__PURE__ */ jsx9(
|
|
326
443
|
Checkbox,
|
|
327
444
|
{
|
|
328
445
|
label: field.label,
|
|
@@ -332,7 +449,7 @@ function renderField(key, field, value, handleFieldChange) {
|
|
|
332
449
|
key
|
|
333
450
|
);
|
|
334
451
|
case "select":
|
|
335
|
-
return /* @__PURE__ */
|
|
452
|
+
return /* @__PURE__ */ jsx9(
|
|
336
453
|
Select,
|
|
337
454
|
{
|
|
338
455
|
label: field.label,
|
|
@@ -343,7 +460,7 @@ function renderField(key, field, value, handleFieldChange) {
|
|
|
343
460
|
key
|
|
344
461
|
);
|
|
345
462
|
case "range":
|
|
346
|
-
return /* @__PURE__ */
|
|
463
|
+
return /* @__PURE__ */ jsx9(
|
|
347
464
|
RangeField,
|
|
348
465
|
{
|
|
349
466
|
field,
|
|
@@ -353,7 +470,7 @@ function renderField(key, field, value, handleFieldChange) {
|
|
|
353
470
|
key
|
|
354
471
|
);
|
|
355
472
|
case "link":
|
|
356
|
-
return /* @__PURE__ */
|
|
473
|
+
return /* @__PURE__ */ jsx9(
|
|
357
474
|
LinkField,
|
|
358
475
|
{
|
|
359
476
|
label: field.label,
|
|
@@ -362,12 +479,21 @@ function renderField(key, field, value, handleFieldChange) {
|
|
|
362
479
|
},
|
|
363
480
|
key
|
|
364
481
|
);
|
|
482
|
+
case "video-source":
|
|
483
|
+
return /* @__PURE__ */ jsx9(
|
|
484
|
+
VideoSourceField,
|
|
485
|
+
{
|
|
486
|
+
value,
|
|
487
|
+
onChange: (v) => handleFieldChange(key, v)
|
|
488
|
+
},
|
|
489
|
+
key
|
|
490
|
+
);
|
|
365
491
|
default:
|
|
366
492
|
return null;
|
|
367
493
|
}
|
|
368
494
|
}
|
|
369
495
|
function SettingsForm({ schema, values, onChange, tabs }) {
|
|
370
|
-
const [local, setLocal] =
|
|
496
|
+
const [local, setLocal] = useState3(() => resolveValues(schema, values));
|
|
371
497
|
function handleFieldChange(key, newValue) {
|
|
372
498
|
const next = { ...local, [key]: newValue };
|
|
373
499
|
setLocal(next);
|
|
@@ -378,16 +504,16 @@ function SettingsForm({ schema, values, onChange, tabs }) {
|
|
|
378
504
|
const listed = new Set(tabs.flatMap((t) => t.fields));
|
|
379
505
|
const otherKeys = Object.keys(schema).filter((key) => !listed.has(key));
|
|
380
506
|
const tabItems = [
|
|
381
|
-
...tabs.map((t) => ({ id: t.label, label: t.label, content: /* @__PURE__ */
|
|
382
|
-
...otherKeys.length > 0 ? [{ id: "__other__", label: "Other", content: /* @__PURE__ */
|
|
507
|
+
...tabs.map((t) => ({ id: t.label, label: t.label, content: /* @__PURE__ */ jsx9("div", { className: "flex flex-col gap-4", children: fields(t.fields) }) })),
|
|
508
|
+
...otherKeys.length > 0 ? [{ id: "__other__", label: "Other", content: /* @__PURE__ */ jsx9("div", { className: "flex flex-col gap-4", children: fields(otherKeys) }) }] : []
|
|
383
509
|
];
|
|
384
|
-
return /* @__PURE__ */
|
|
510
|
+
return /* @__PURE__ */ jsx9(Tabs, { tabs: tabItems, fullBleedTabBar: true });
|
|
385
511
|
}
|
|
386
|
-
return /* @__PURE__ */
|
|
512
|
+
return /* @__PURE__ */ jsx9("div", { className: "flex flex-col gap-4", children: Object.entries(schema).map(([key, field]) => renderField(key, field, local[key], handleFieldChange)) });
|
|
387
513
|
}
|
|
388
514
|
|
|
389
515
|
// src/components/shared/Popover.tsx
|
|
390
|
-
import { useEffect as useEffect2, useLayoutEffect, useRef, useState as
|
|
516
|
+
import { useEffect as useEffect2, useLayoutEffect, useRef, useState as useState4 } from "react";
|
|
391
517
|
|
|
392
518
|
// src/hooks/useFocusTrap.ts
|
|
393
519
|
import { useEffect } from "react";
|
|
@@ -438,7 +564,7 @@ function useFocusTrap(ref, active) {
|
|
|
438
564
|
}
|
|
439
565
|
|
|
440
566
|
// src/components/shared/Popover.tsx
|
|
441
|
-
import { jsx as
|
|
567
|
+
import { jsx as jsx10 } from "react/jsx-runtime";
|
|
442
568
|
function Popover({
|
|
443
569
|
isOpen,
|
|
444
570
|
onClose,
|
|
@@ -448,7 +574,7 @@ function Popover({
|
|
|
448
574
|
className
|
|
449
575
|
}) {
|
|
450
576
|
const panelRef = useRef(null);
|
|
451
|
-
const [resolvedAlign, setResolvedAlign] =
|
|
577
|
+
const [resolvedAlign, setResolvedAlign] = useState4("start");
|
|
452
578
|
useFocusTrap(panelRef, isOpen);
|
|
453
579
|
useLayoutEffect(() => {
|
|
454
580
|
if (!isOpen || align !== "auto") {
|
|
@@ -488,7 +614,7 @@ function Popover({
|
|
|
488
614
|
}, [isOpen, onClose, anchorRef]);
|
|
489
615
|
if (!isOpen) return null;
|
|
490
616
|
const effectiveAlign = align === "auto" ? resolvedAlign : align;
|
|
491
|
-
return /* @__PURE__ */
|
|
617
|
+
return /* @__PURE__ */ jsx10(
|
|
492
618
|
"div",
|
|
493
619
|
{
|
|
494
620
|
ref: panelRef,
|
|
@@ -506,10 +632,10 @@ function Popover({
|
|
|
506
632
|
|
|
507
633
|
// src/components/shared/PopoverItem.tsx
|
|
508
634
|
import { forwardRef as forwardRef2 } from "react";
|
|
509
|
-
import { jsx as
|
|
635
|
+
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
510
636
|
var PopoverItem = forwardRef2(
|
|
511
637
|
function PopoverItem2({ className, children, ...rest }, ref) {
|
|
512
|
-
return /* @__PURE__ */
|
|
638
|
+
return /* @__PURE__ */ jsx11(
|
|
513
639
|
"button",
|
|
514
640
|
{
|
|
515
641
|
ref,
|