@toriistudio/v0-playground 0.6.0 → 0.7.1
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/index.d.mts +22 -1
- package/dist/index.d.ts +22 -1
- package/dist/index.js +794 -127
- package/dist/index.mjs +800 -120
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
// src/components/Playground
|
|
2
|
-
import { useEffect as
|
|
1
|
+
// src/components/Playground.tsx
|
|
2
|
+
import { useEffect as useEffect7, useMemo as useMemo5, useState as useState5 } from "react";
|
|
3
3
|
import { Check as Check3, Copy as Copy2 } from "lucide-react";
|
|
4
4
|
|
|
5
5
|
// src/context/ResizableLayout.tsx
|
|
@@ -411,7 +411,8 @@ var ControlsProvider = ({ children }) => {
|
|
|
411
411
|
const [schema, setSchema] = useState2({});
|
|
412
412
|
const [values, setValues] = useState2({});
|
|
413
413
|
const [config, setConfig] = useState2({
|
|
414
|
-
showCopyButton: true
|
|
414
|
+
showCopyButton: true,
|
|
415
|
+
showCodeSnippet: false
|
|
415
416
|
});
|
|
416
417
|
const [componentName, setComponentName] = useState2();
|
|
417
418
|
const [channelName, setChannelName] = useState2(null);
|
|
@@ -434,17 +435,30 @@ var ControlsProvider = ({ children }) => {
|
|
|
434
435
|
setComponentName(opts.componentName);
|
|
435
436
|
}
|
|
436
437
|
if (opts?.config) {
|
|
437
|
-
const {
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
...otherConfig
|
|
441
|
-
|
|
438
|
+
const {
|
|
439
|
+
addAdvancedPaletteControl,
|
|
440
|
+
addMediaUploadControl,
|
|
441
|
+
...otherConfig
|
|
442
|
+
} = opts.config;
|
|
443
|
+
setConfig((prev) => {
|
|
444
|
+
const nextConfig = {
|
|
445
|
+
...prev,
|
|
446
|
+
...otherConfig
|
|
447
|
+
};
|
|
448
|
+
if (Object.prototype.hasOwnProperty.call(
|
|
442
449
|
opts.config,
|
|
443
450
|
"addAdvancedPaletteControl"
|
|
444
|
-
)
|
|
445
|
-
addAdvancedPaletteControl
|
|
446
|
-
}
|
|
447
|
-
|
|
451
|
+
)) {
|
|
452
|
+
nextConfig.addAdvancedPaletteControl = addAdvancedPaletteControl ? resolveAdvancedPaletteConfig(addAdvancedPaletteControl) : void 0;
|
|
453
|
+
}
|
|
454
|
+
if (Object.prototype.hasOwnProperty.call(
|
|
455
|
+
opts.config,
|
|
456
|
+
"addMediaUploadControl"
|
|
457
|
+
)) {
|
|
458
|
+
nextConfig.addMediaUploadControl = addMediaUploadControl ? { ...addMediaUploadControl } : void 0;
|
|
459
|
+
}
|
|
460
|
+
return nextConfig;
|
|
461
|
+
});
|
|
448
462
|
}
|
|
449
463
|
setSchema((prevSchema) => ({ ...prevSchema, ...newSchema }));
|
|
450
464
|
setValues((prevValues) => {
|
|
@@ -609,7 +623,7 @@ var useControls = (schema, options) => {
|
|
|
609
623
|
resolvedAdvancedConfig.onPaletteChange(clonePalette(palette));
|
|
610
624
|
}, [ctx.values, resolvedAdvancedConfig]);
|
|
611
625
|
const typedValues = ctx.values;
|
|
612
|
-
const
|
|
626
|
+
const jsx15 = useCallback(() => {
|
|
613
627
|
if (!options?.componentName) return "";
|
|
614
628
|
const props = Object.entries(typedValues).map(([key, val]) => {
|
|
615
629
|
if (typeof val === "string") return `${key}="${val}"`;
|
|
@@ -623,13 +637,19 @@ var useControls = (schema, options) => {
|
|
|
623
637
|
controls: ctx.values,
|
|
624
638
|
schema: ctx.schema,
|
|
625
639
|
setValue: ctx.setValue,
|
|
626
|
-
jsx:
|
|
640
|
+
jsx: jsx15
|
|
627
641
|
};
|
|
628
642
|
};
|
|
629
643
|
var useUrlSyncedControls = useControls;
|
|
630
644
|
|
|
631
|
-
// src/components/ControlPanel
|
|
632
|
-
import {
|
|
645
|
+
// src/components/ControlPanel.tsx
|
|
646
|
+
import {
|
|
647
|
+
useState as useState4,
|
|
648
|
+
useMemo as useMemo4,
|
|
649
|
+
useCallback as useCallback4,
|
|
650
|
+
useEffect as useEffect6,
|
|
651
|
+
useRef as useRef5
|
|
652
|
+
} from "react";
|
|
633
653
|
import {
|
|
634
654
|
Check as Check2,
|
|
635
655
|
Copy,
|
|
@@ -911,7 +931,7 @@ Button.displayName = "Button";
|
|
|
911
931
|
// src/constants/layout.ts
|
|
912
932
|
var MOBILE_CONTROL_PANEL_PEEK = 112;
|
|
913
933
|
|
|
914
|
-
// src/components/AdvancedPaletteControl
|
|
934
|
+
// src/components/AdvancedPaletteControl.tsx
|
|
915
935
|
import {
|
|
916
936
|
useCallback as useCallback2,
|
|
917
937
|
useEffect as useEffect4,
|
|
@@ -1064,15 +1084,539 @@ var AdvancedPaletteControl = ({
|
|
|
1064
1084
|
};
|
|
1065
1085
|
var AdvancedPaletteControl_default = AdvancedPaletteControl;
|
|
1066
1086
|
|
|
1067
|
-
// src/components/
|
|
1068
|
-
import {
|
|
1087
|
+
// src/components/MediaUploadControl.tsx
|
|
1088
|
+
import {
|
|
1089
|
+
useCallback as useCallback3,
|
|
1090
|
+
useEffect as useEffect5,
|
|
1091
|
+
useId,
|
|
1092
|
+
useMemo as useMemo3,
|
|
1093
|
+
useRef as useRef4,
|
|
1094
|
+
useSyncExternalStore
|
|
1095
|
+
} from "react";
|
|
1096
|
+
import { X } from "lucide-react";
|
|
1097
|
+
|
|
1098
|
+
// src/state/mediaSelectionStore.ts
|
|
1099
|
+
var snapshot = {
|
|
1100
|
+
media: null,
|
|
1101
|
+
error: null
|
|
1102
|
+
};
|
|
1103
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
1104
|
+
var emitChange = () => {
|
|
1105
|
+
for (const listener of listeners) {
|
|
1106
|
+
listener();
|
|
1107
|
+
}
|
|
1108
|
+
};
|
|
1109
|
+
var mediaSelectionStore = {
|
|
1110
|
+
subscribe: (listener) => {
|
|
1111
|
+
listeners.add(listener);
|
|
1112
|
+
return () => {
|
|
1113
|
+
listeners.delete(listener);
|
|
1114
|
+
};
|
|
1115
|
+
},
|
|
1116
|
+
getSnapshot: () => snapshot,
|
|
1117
|
+
setSnapshot: (next) => {
|
|
1118
|
+
snapshot = next;
|
|
1119
|
+
emitChange();
|
|
1120
|
+
}
|
|
1121
|
+
};
|
|
1122
|
+
|
|
1123
|
+
// src/components/MediaUploadControl.tsx
|
|
1124
|
+
import { jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1125
|
+
var DEFAULT_PRESET_MEDIA = [
|
|
1126
|
+
{
|
|
1127
|
+
src: "https://res.cloudinary.com/dz8kk1l4r/image/upload/v1763233793/astronaut_q84mbj.png",
|
|
1128
|
+
label: "Astronaut",
|
|
1129
|
+
type: "image"
|
|
1130
|
+
},
|
|
1131
|
+
{
|
|
1132
|
+
src: "https://res.cloudinary.com/dz8kk1l4r/image/upload/v1763233793/surreal-head_r0ozcd.png",
|
|
1133
|
+
label: "Futuristic",
|
|
1134
|
+
type: "image"
|
|
1135
|
+
},
|
|
1136
|
+
{
|
|
1137
|
+
src: "https://res.cloudinary.com/dz8kk1l4r/image/upload/v1763233797/futuristic_bpwdzt.png",
|
|
1138
|
+
label: "Surreal",
|
|
1139
|
+
type: "image"
|
|
1140
|
+
},
|
|
1141
|
+
{
|
|
1142
|
+
src: "https://res.cloudinary.com/dz8kk1l4r/image/upload/v1763233793/portrait_hd7dyc.png",
|
|
1143
|
+
label: "Portrait",
|
|
1144
|
+
type: "image"
|
|
1145
|
+
}
|
|
1146
|
+
];
|
|
1147
|
+
function MediaUploadControl({
|
|
1148
|
+
onSelectMedia,
|
|
1149
|
+
onClear,
|
|
1150
|
+
presetMedia,
|
|
1151
|
+
maxPresetCount
|
|
1152
|
+
}) {
|
|
1153
|
+
const inputId = useId();
|
|
1154
|
+
const inputRef = useRef4(null);
|
|
1155
|
+
const uploadedUrlRef = useRef4(null);
|
|
1156
|
+
const { media, error } = useSyncExternalStore(
|
|
1157
|
+
mediaSelectionStore.subscribe,
|
|
1158
|
+
mediaSelectionStore.getSnapshot,
|
|
1159
|
+
mediaSelectionStore.getSnapshot
|
|
1160
|
+
);
|
|
1161
|
+
const VIDEO_EXTENSIONS = useMemo3(
|
|
1162
|
+
() => [".mp4", ".webm", ".ogg", ".ogv", ".mov", ".m4v"],
|
|
1163
|
+
[]
|
|
1164
|
+
);
|
|
1165
|
+
const setSelection = useCallback3(
|
|
1166
|
+
(next) => {
|
|
1167
|
+
mediaSelectionStore.setSnapshot(next);
|
|
1168
|
+
},
|
|
1169
|
+
[]
|
|
1170
|
+
);
|
|
1171
|
+
const handleFileChange = (event) => {
|
|
1172
|
+
const file = event.target.files?.[0];
|
|
1173
|
+
if (!file) {
|
|
1174
|
+
return;
|
|
1175
|
+
}
|
|
1176
|
+
if (uploadedUrlRef.current) {
|
|
1177
|
+
URL.revokeObjectURL(uploadedUrlRef.current);
|
|
1178
|
+
uploadedUrlRef.current = null;
|
|
1179
|
+
}
|
|
1180
|
+
const objectUrl = URL.createObjectURL(file);
|
|
1181
|
+
uploadedUrlRef.current = objectUrl;
|
|
1182
|
+
const lowerName = file.name?.toLowerCase() ?? "";
|
|
1183
|
+
const hasVideoExtension = VIDEO_EXTENSIONS.some(
|
|
1184
|
+
(ext) => lowerName.endsWith(ext)
|
|
1185
|
+
);
|
|
1186
|
+
const isVideo = file.type.startsWith("video/") || hasVideoExtension;
|
|
1187
|
+
if (isVideo) {
|
|
1188
|
+
setSelection({
|
|
1189
|
+
media: null,
|
|
1190
|
+
error: "Videos are not supported in this effect yet."
|
|
1191
|
+
});
|
|
1192
|
+
return;
|
|
1193
|
+
}
|
|
1194
|
+
const nextMedia = { src: objectUrl, type: "image" };
|
|
1195
|
+
setSelection({ media: nextMedia, error: null });
|
|
1196
|
+
onSelectMedia(nextMedia);
|
|
1197
|
+
};
|
|
1198
|
+
const handleClearSelection = () => {
|
|
1199
|
+
if (uploadedUrlRef.current) {
|
|
1200
|
+
URL.revokeObjectURL(uploadedUrlRef.current);
|
|
1201
|
+
uploadedUrlRef.current = null;
|
|
1202
|
+
}
|
|
1203
|
+
setSelection({ media: null, error: null });
|
|
1204
|
+
onClear();
|
|
1205
|
+
};
|
|
1206
|
+
const handlePresetSelect = (entry) => {
|
|
1207
|
+
if (entry.type === "video") {
|
|
1208
|
+
setSelection({
|
|
1209
|
+
media: null,
|
|
1210
|
+
error: "Videos are not supported in this effect yet."
|
|
1211
|
+
});
|
|
1212
|
+
return;
|
|
1213
|
+
}
|
|
1214
|
+
const nextMedia = { src: entry.src, type: entry.type };
|
|
1215
|
+
setSelection({ media: nextMedia, error: null });
|
|
1216
|
+
onSelectMedia(nextMedia);
|
|
1217
|
+
};
|
|
1218
|
+
useEffect5(() => {
|
|
1219
|
+
return () => {
|
|
1220
|
+
if (uploadedUrlRef.current) {
|
|
1221
|
+
URL.revokeObjectURL(uploadedUrlRef.current);
|
|
1222
|
+
uploadedUrlRef.current = null;
|
|
1223
|
+
}
|
|
1224
|
+
};
|
|
1225
|
+
}, []);
|
|
1226
|
+
const presets = useMemo3(() => {
|
|
1227
|
+
const source = presetMedia ?? DEFAULT_PRESET_MEDIA;
|
|
1228
|
+
if (typeof maxPresetCount === "number" && Number.isFinite(maxPresetCount)) {
|
|
1229
|
+
const safeCount = Math.max(0, Math.floor(maxPresetCount));
|
|
1230
|
+
return source.slice(0, safeCount);
|
|
1231
|
+
}
|
|
1232
|
+
return source;
|
|
1233
|
+
}, [presetMedia, maxPresetCount]);
|
|
1234
|
+
return /* @__PURE__ */ jsxs5(
|
|
1235
|
+
"div",
|
|
1236
|
+
{
|
|
1237
|
+
style: {
|
|
1238
|
+
display: "flex",
|
|
1239
|
+
flexDirection: "column",
|
|
1240
|
+
gap: "0.5rem"
|
|
1241
|
+
},
|
|
1242
|
+
children: [
|
|
1243
|
+
/* @__PURE__ */ jsx10("label", { htmlFor: inputId, style: { fontSize: "0.85rem", fontWeight: 500 }, children: "Upload media" }),
|
|
1244
|
+
/* @__PURE__ */ jsx10(
|
|
1245
|
+
"input",
|
|
1246
|
+
{
|
|
1247
|
+
id: inputId,
|
|
1248
|
+
type: "file",
|
|
1249
|
+
accept: "image/*",
|
|
1250
|
+
ref: inputRef,
|
|
1251
|
+
style: { display: "none" },
|
|
1252
|
+
onChange: handleFileChange
|
|
1253
|
+
}
|
|
1254
|
+
),
|
|
1255
|
+
/* @__PURE__ */ jsxs5(
|
|
1256
|
+
"div",
|
|
1257
|
+
{
|
|
1258
|
+
style: {
|
|
1259
|
+
display: "flex",
|
|
1260
|
+
alignItems: "center",
|
|
1261
|
+
gap: "0.75rem"
|
|
1262
|
+
},
|
|
1263
|
+
children: [
|
|
1264
|
+
/* @__PURE__ */ jsx10(
|
|
1265
|
+
"button",
|
|
1266
|
+
{
|
|
1267
|
+
type: "button",
|
|
1268
|
+
onClick: () => inputRef.current?.click(),
|
|
1269
|
+
style: {
|
|
1270
|
+
padding: "0.35rem 0.75rem",
|
|
1271
|
+
borderRadius: "0.4rem",
|
|
1272
|
+
border: "1px solid rgba(255, 255, 255, 0.25)",
|
|
1273
|
+
background: "rgba(255, 255, 255, 0.08)",
|
|
1274
|
+
color: "inherit",
|
|
1275
|
+
cursor: "pointer"
|
|
1276
|
+
},
|
|
1277
|
+
children: "Choose file"
|
|
1278
|
+
}
|
|
1279
|
+
),
|
|
1280
|
+
media ? /* @__PURE__ */ jsx10(
|
|
1281
|
+
"div",
|
|
1282
|
+
{
|
|
1283
|
+
style: {
|
|
1284
|
+
width: 36,
|
|
1285
|
+
height: 36,
|
|
1286
|
+
borderRadius: "0.35rem",
|
|
1287
|
+
overflow: "hidden",
|
|
1288
|
+
border: "1px solid rgba(255, 255, 255, 0.15)"
|
|
1289
|
+
},
|
|
1290
|
+
children: /* @__PURE__ */ jsx10(
|
|
1291
|
+
"img",
|
|
1292
|
+
{
|
|
1293
|
+
src: media.src,
|
|
1294
|
+
alt: "Thumbnail",
|
|
1295
|
+
style: {
|
|
1296
|
+
width: "100%",
|
|
1297
|
+
height: "100%",
|
|
1298
|
+
objectFit: "cover",
|
|
1299
|
+
display: "block"
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1302
|
+
)
|
|
1303
|
+
}
|
|
1304
|
+
) : null,
|
|
1305
|
+
media ? /* @__PURE__ */ jsx10(
|
|
1306
|
+
"button",
|
|
1307
|
+
{
|
|
1308
|
+
type: "button",
|
|
1309
|
+
onClick: handleClearSelection,
|
|
1310
|
+
style: {
|
|
1311
|
+
display: "flex",
|
|
1312
|
+
alignItems: "center",
|
|
1313
|
+
justifyContent: "center",
|
|
1314
|
+
padding: "0.3rem",
|
|
1315
|
+
borderRadius: "0.4rem",
|
|
1316
|
+
border: "1px solid rgba(255,255,255,0.2)",
|
|
1317
|
+
background: "transparent",
|
|
1318
|
+
color: "inherit",
|
|
1319
|
+
cursor: "pointer"
|
|
1320
|
+
},
|
|
1321
|
+
"aria-label": "Clear selection",
|
|
1322
|
+
title: "Clear selection",
|
|
1323
|
+
children: /* @__PURE__ */ jsx10(X, { size: 16, strokeWidth: 2 })
|
|
1324
|
+
}
|
|
1325
|
+
) : null
|
|
1326
|
+
]
|
|
1327
|
+
}
|
|
1328
|
+
),
|
|
1329
|
+
presets.length > 0 ? /* @__PURE__ */ jsx10(
|
|
1330
|
+
"div",
|
|
1331
|
+
{
|
|
1332
|
+
style: {
|
|
1333
|
+
display: "grid",
|
|
1334
|
+
gridTemplateColumns: "repeat(2, minmax(0, 1fr))",
|
|
1335
|
+
gap: "0.5rem"
|
|
1336
|
+
},
|
|
1337
|
+
children: presets.map((entry) => {
|
|
1338
|
+
const isSelected = media?.src === entry.src && media?.type === entry.type;
|
|
1339
|
+
return /* @__PURE__ */ jsxs5(
|
|
1340
|
+
"button",
|
|
1341
|
+
{
|
|
1342
|
+
type: "button",
|
|
1343
|
+
onClick: () => handlePresetSelect(entry),
|
|
1344
|
+
style: {
|
|
1345
|
+
width: "100%",
|
|
1346
|
+
borderRadius: "0.4rem",
|
|
1347
|
+
border: "1px solid rgba(255,255,255,0.25)",
|
|
1348
|
+
outline: isSelected ? "2px solid #fff" : "none",
|
|
1349
|
+
outlineOffset: 2,
|
|
1350
|
+
padding: 0,
|
|
1351
|
+
overflow: "hidden",
|
|
1352
|
+
background: "transparent",
|
|
1353
|
+
cursor: "pointer"
|
|
1354
|
+
},
|
|
1355
|
+
children: [
|
|
1356
|
+
/* @__PURE__ */ jsx10(
|
|
1357
|
+
"img",
|
|
1358
|
+
{
|
|
1359
|
+
src: entry.src,
|
|
1360
|
+
alt: entry.label,
|
|
1361
|
+
style: {
|
|
1362
|
+
width: "100%",
|
|
1363
|
+
height: 100,
|
|
1364
|
+
objectFit: "cover",
|
|
1365
|
+
display: "block"
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
),
|
|
1369
|
+
/* @__PURE__ */ jsx10(
|
|
1370
|
+
"span",
|
|
1371
|
+
{
|
|
1372
|
+
style: {
|
|
1373
|
+
display: "block",
|
|
1374
|
+
padding: "0.35rem",
|
|
1375
|
+
fontSize: "0.75rem",
|
|
1376
|
+
textAlign: "left",
|
|
1377
|
+
background: "rgba(0,0,0,0.45)"
|
|
1378
|
+
},
|
|
1379
|
+
children: entry.label
|
|
1380
|
+
}
|
|
1381
|
+
)
|
|
1382
|
+
]
|
|
1383
|
+
},
|
|
1384
|
+
`${entry.src}-${entry.type}`
|
|
1385
|
+
);
|
|
1386
|
+
})
|
|
1387
|
+
}
|
|
1388
|
+
) : null,
|
|
1389
|
+
error ? /* @__PURE__ */ jsx10("p", { style: { color: "#ff9da4", fontSize: "0.8rem" }, children: error }) : null
|
|
1390
|
+
]
|
|
1391
|
+
}
|
|
1392
|
+
);
|
|
1393
|
+
}
|
|
1394
|
+
|
|
1395
|
+
// src/components/ControlPanel.tsx
|
|
1396
|
+
import { Fragment, jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1397
|
+
var splitPropsString = (input) => {
|
|
1398
|
+
const props = [];
|
|
1399
|
+
let current = "";
|
|
1400
|
+
let curlyDepth = 0;
|
|
1401
|
+
let squareDepth = 0;
|
|
1402
|
+
let parenDepth = 0;
|
|
1403
|
+
let inSingleQuote = false;
|
|
1404
|
+
let inDoubleQuote = false;
|
|
1405
|
+
let inBacktick = false;
|
|
1406
|
+
let escapeNext = false;
|
|
1407
|
+
for (const char of input) {
|
|
1408
|
+
if (escapeNext) {
|
|
1409
|
+
current += char;
|
|
1410
|
+
escapeNext = false;
|
|
1411
|
+
continue;
|
|
1412
|
+
}
|
|
1413
|
+
if (char === "\\") {
|
|
1414
|
+
current += char;
|
|
1415
|
+
escapeNext = true;
|
|
1416
|
+
continue;
|
|
1417
|
+
}
|
|
1418
|
+
if (char === "'" && !inDoubleQuote && !inBacktick) {
|
|
1419
|
+
inSingleQuote = !inSingleQuote;
|
|
1420
|
+
current += char;
|
|
1421
|
+
continue;
|
|
1422
|
+
}
|
|
1423
|
+
if (char === '"' && !inSingleQuote && !inBacktick) {
|
|
1424
|
+
inDoubleQuote = !inDoubleQuote;
|
|
1425
|
+
current += char;
|
|
1426
|
+
continue;
|
|
1427
|
+
}
|
|
1428
|
+
if (char === "`" && !inSingleQuote && !inDoubleQuote) {
|
|
1429
|
+
inBacktick = !inBacktick;
|
|
1430
|
+
current += char;
|
|
1431
|
+
continue;
|
|
1432
|
+
}
|
|
1433
|
+
if (!inSingleQuote && !inDoubleQuote && !inBacktick) {
|
|
1434
|
+
if (char === "{") {
|
|
1435
|
+
curlyDepth += 1;
|
|
1436
|
+
} else if (char === "}") {
|
|
1437
|
+
curlyDepth = Math.max(0, curlyDepth - 1);
|
|
1438
|
+
} else if (char === "[") {
|
|
1439
|
+
squareDepth += 1;
|
|
1440
|
+
} else if (char === "]") {
|
|
1441
|
+
squareDepth = Math.max(0, squareDepth - 1);
|
|
1442
|
+
} else if (char === "(") {
|
|
1443
|
+
parenDepth += 1;
|
|
1444
|
+
} else if (char === ")") {
|
|
1445
|
+
parenDepth = Math.max(0, parenDepth - 1);
|
|
1446
|
+
}
|
|
1447
|
+
}
|
|
1448
|
+
const atTopLevel = !inSingleQuote && !inDoubleQuote && !inBacktick && curlyDepth === 0 && squareDepth === 0 && parenDepth === 0;
|
|
1449
|
+
if (atTopLevel && /\s/.test(char)) {
|
|
1450
|
+
if (current.trim()) {
|
|
1451
|
+
props.push(current.trim());
|
|
1452
|
+
}
|
|
1453
|
+
current = "";
|
|
1454
|
+
continue;
|
|
1455
|
+
}
|
|
1456
|
+
current += char;
|
|
1457
|
+
}
|
|
1458
|
+
if (current.trim()) {
|
|
1459
|
+
props.push(current.trim());
|
|
1460
|
+
}
|
|
1461
|
+
return props;
|
|
1462
|
+
};
|
|
1463
|
+
var formatJsxCodeSnippet = (input) => {
|
|
1464
|
+
const trimmed = input.trim();
|
|
1465
|
+
if (!trimmed) return "";
|
|
1466
|
+
if (trimmed.includes("\n")) {
|
|
1467
|
+
return trimmed;
|
|
1468
|
+
}
|
|
1469
|
+
if (!trimmed.startsWith("<") || !trimmed.endsWith(">")) {
|
|
1470
|
+
return trimmed;
|
|
1471
|
+
}
|
|
1472
|
+
if (!trimmed.endsWith("/>")) {
|
|
1473
|
+
return trimmed;
|
|
1474
|
+
}
|
|
1475
|
+
const inner = trimmed.slice(1, -2).trim();
|
|
1476
|
+
const firstSpaceIndex = inner.indexOf(" ");
|
|
1477
|
+
if (firstSpaceIndex === -1) {
|
|
1478
|
+
return `<${inner} />`;
|
|
1479
|
+
}
|
|
1480
|
+
const componentName = inner.slice(0, firstSpaceIndex);
|
|
1481
|
+
const propsString = inner.slice(firstSpaceIndex + 1).trim();
|
|
1482
|
+
if (!propsString) {
|
|
1483
|
+
return `<${componentName} />`;
|
|
1484
|
+
}
|
|
1485
|
+
const propsList = splitPropsString(propsString);
|
|
1486
|
+
if (propsList.length === 0) {
|
|
1487
|
+
return `<${componentName} ${propsString} />`;
|
|
1488
|
+
}
|
|
1489
|
+
const formattedProps = propsList.map((prop) => ` ${prop}`).join("\n");
|
|
1490
|
+
return `<${componentName}
|
|
1491
|
+
${formattedProps}
|
|
1492
|
+
/>`;
|
|
1493
|
+
};
|
|
1494
|
+
var isWhitespace = (char) => /\s/.test(char);
|
|
1495
|
+
var isAttrNameChar = (char) => /[A-Za-z0-9_$\-.:]/.test(char);
|
|
1496
|
+
var isAlphaStart = (char) => /[A-Za-z_$]/.test(char);
|
|
1497
|
+
var tokenizeJsx = (input) => {
|
|
1498
|
+
const tokens = [];
|
|
1499
|
+
let i = 0;
|
|
1500
|
+
while (i < input.length) {
|
|
1501
|
+
const char = input[i];
|
|
1502
|
+
if (char === "<") {
|
|
1503
|
+
tokens.push({ type: "punctuation", value: "<" });
|
|
1504
|
+
i += 1;
|
|
1505
|
+
if (input[i] === "/") {
|
|
1506
|
+
tokens.push({ type: "punctuation", value: "/" });
|
|
1507
|
+
i += 1;
|
|
1508
|
+
}
|
|
1509
|
+
const start = i;
|
|
1510
|
+
while (i < input.length && isAttrNameChar(input[i])) {
|
|
1511
|
+
i += 1;
|
|
1512
|
+
}
|
|
1513
|
+
if (i > start) {
|
|
1514
|
+
tokens.push({ type: "tag", value: input.slice(start, i) });
|
|
1515
|
+
}
|
|
1516
|
+
continue;
|
|
1517
|
+
}
|
|
1518
|
+
if (char === "/" && input[i + 1] === ">") {
|
|
1519
|
+
tokens.push({ type: "punctuation", value: "/>" });
|
|
1520
|
+
i += 2;
|
|
1521
|
+
continue;
|
|
1522
|
+
}
|
|
1523
|
+
if (char === ">") {
|
|
1524
|
+
tokens.push({ type: "punctuation", value: ">" });
|
|
1525
|
+
i += 1;
|
|
1526
|
+
continue;
|
|
1527
|
+
}
|
|
1528
|
+
if (char === "=") {
|
|
1529
|
+
tokens.push({ type: "punctuation", value: "=" });
|
|
1530
|
+
i += 1;
|
|
1531
|
+
continue;
|
|
1532
|
+
}
|
|
1533
|
+
if (char === '"' || char === "'" || char === "`") {
|
|
1534
|
+
const quote = char;
|
|
1535
|
+
let j = i + 1;
|
|
1536
|
+
let value = quote;
|
|
1537
|
+
while (j < input.length) {
|
|
1538
|
+
const current = input[j];
|
|
1539
|
+
value += current;
|
|
1540
|
+
if (current === quote && input[j - 1] !== "\\") {
|
|
1541
|
+
break;
|
|
1542
|
+
}
|
|
1543
|
+
j += 1;
|
|
1544
|
+
}
|
|
1545
|
+
tokens.push({ type: "string", value });
|
|
1546
|
+
i = j + 1;
|
|
1547
|
+
continue;
|
|
1548
|
+
}
|
|
1549
|
+
if (char === "{") {
|
|
1550
|
+
let depth = 1;
|
|
1551
|
+
let j = i + 1;
|
|
1552
|
+
while (j < input.length && depth > 0) {
|
|
1553
|
+
if (input[j] === "{") {
|
|
1554
|
+
depth += 1;
|
|
1555
|
+
} else if (input[j] === "}") {
|
|
1556
|
+
depth -= 1;
|
|
1557
|
+
}
|
|
1558
|
+
j += 1;
|
|
1559
|
+
}
|
|
1560
|
+
const expression = input.slice(i, j);
|
|
1561
|
+
tokens.push({ type: "expression", value: expression });
|
|
1562
|
+
i = j;
|
|
1563
|
+
continue;
|
|
1564
|
+
}
|
|
1565
|
+
if (isAlphaStart(char)) {
|
|
1566
|
+
const start = i;
|
|
1567
|
+
i += 1;
|
|
1568
|
+
while (i < input.length && isAttrNameChar(input[i])) {
|
|
1569
|
+
i += 1;
|
|
1570
|
+
}
|
|
1571
|
+
const word = input.slice(start, i);
|
|
1572
|
+
let k = i;
|
|
1573
|
+
while (k < input.length && isWhitespace(input[k])) {
|
|
1574
|
+
k += 1;
|
|
1575
|
+
}
|
|
1576
|
+
if (input[k] === "=") {
|
|
1577
|
+
tokens.push({ type: "attrName", value: word });
|
|
1578
|
+
} else {
|
|
1579
|
+
tokens.push({ type: "plain", value: word });
|
|
1580
|
+
}
|
|
1581
|
+
continue;
|
|
1582
|
+
}
|
|
1583
|
+
tokens.push({ type: "plain", value: char });
|
|
1584
|
+
i += 1;
|
|
1585
|
+
}
|
|
1586
|
+
return tokens;
|
|
1587
|
+
};
|
|
1588
|
+
var TOKEN_CLASS_MAP = {
|
|
1589
|
+
tag: "text-sky-300",
|
|
1590
|
+
attrName: "text-amber-200",
|
|
1591
|
+
string: "text-emerald-300",
|
|
1592
|
+
expression: "text-purple-300",
|
|
1593
|
+
punctuation: "text-stone-400"
|
|
1594
|
+
};
|
|
1595
|
+
var highlightJsx = (input) => {
|
|
1596
|
+
const tokens = tokenizeJsx(input);
|
|
1597
|
+
const nodes = [];
|
|
1598
|
+
tokens.forEach((token, index) => {
|
|
1599
|
+
if (token.type === "plain") {
|
|
1600
|
+
nodes.push(token.value);
|
|
1601
|
+
} else {
|
|
1602
|
+
nodes.push(
|
|
1603
|
+
/* @__PURE__ */ jsx11("span", { className: TOKEN_CLASS_MAP[token.type], children: token.value }, `token-${index}`)
|
|
1604
|
+
);
|
|
1605
|
+
}
|
|
1606
|
+
});
|
|
1607
|
+
return nodes;
|
|
1608
|
+
};
|
|
1069
1609
|
var ControlPanel = () => {
|
|
1070
1610
|
const [copied, setCopied] = useState4(false);
|
|
1611
|
+
const [codeCopied, setCodeCopied] = useState4(false);
|
|
1612
|
+
const [isCodeVisible, setIsCodeVisible] = useState4(false);
|
|
1071
1613
|
const [folderStates, setFolderStates] = useState4({});
|
|
1614
|
+
const codeCopyTimeoutRef = useRef5(null);
|
|
1072
1615
|
const { leftPanelWidth, isDesktop, isHydrated } = useResizableLayout();
|
|
1073
1616
|
const { schema, setValue, values, componentName, config } = useControlsContext();
|
|
1617
|
+
const isControlsOnlyView = typeof window !== "undefined" && new URLSearchParams(window.location.search).get(CONTROLS_ONLY_PARAM) === "true";
|
|
1074
1618
|
const previewUrl = usePreviewUrl(values);
|
|
1075
|
-
const buildUrl =
|
|
1619
|
+
const buildUrl = useCallback4(
|
|
1076
1620
|
(modifier) => {
|
|
1077
1621
|
if (!previewUrl) return "";
|
|
1078
1622
|
const [path, search = ""] = previewUrl.split("?");
|
|
@@ -1083,13 +1627,13 @@ var ControlPanel = () => {
|
|
|
1083
1627
|
},
|
|
1084
1628
|
[previewUrl]
|
|
1085
1629
|
);
|
|
1086
|
-
const presentationUrl =
|
|
1630
|
+
const presentationUrl = useMemo4(() => {
|
|
1087
1631
|
if (!previewUrl) return "";
|
|
1088
1632
|
return buildUrl((params) => {
|
|
1089
1633
|
params.set(PRESENTATION_PARAM, "true");
|
|
1090
1634
|
});
|
|
1091
1635
|
}, [buildUrl, previewUrl]);
|
|
1092
|
-
const controlsOnlyUrl =
|
|
1636
|
+
const controlsOnlyUrl = useMemo4(() => {
|
|
1093
1637
|
if (!previewUrl) return "";
|
|
1094
1638
|
return buildUrl((params) => {
|
|
1095
1639
|
params.delete(NO_CONTROLS_PARAM);
|
|
@@ -1097,7 +1641,7 @@ var ControlPanel = () => {
|
|
|
1097
1641
|
params.set(CONTROLS_ONLY_PARAM, "true");
|
|
1098
1642
|
});
|
|
1099
1643
|
}, [buildUrl, previewUrl]);
|
|
1100
|
-
const handlePresentationClick =
|
|
1644
|
+
const handlePresentationClick = useCallback4(() => {
|
|
1101
1645
|
if (typeof window === "undefined" || !presentationUrl) return;
|
|
1102
1646
|
window.open(presentationUrl, "_blank", "noopener,noreferrer");
|
|
1103
1647
|
if (controlsOnlyUrl) {
|
|
@@ -1105,10 +1649,7 @@ var ControlPanel = () => {
|
|
|
1105
1649
|
const viewportHeight = window.innerHeight || 900;
|
|
1106
1650
|
const controlsWidth = Math.max(
|
|
1107
1651
|
320,
|
|
1108
|
-
Math.min(
|
|
1109
|
-
600,
|
|
1110
|
-
Math.round(viewportWidth * leftPanelWidth / 100)
|
|
1111
|
-
)
|
|
1652
|
+
Math.min(600, Math.round(viewportWidth * leftPanelWidth / 100))
|
|
1112
1653
|
);
|
|
1113
1654
|
const controlsHeight = Math.max(600, viewportHeight);
|
|
1114
1655
|
const controlsFeatures = [
|
|
@@ -1124,7 +1665,7 @@ var ControlPanel = () => {
|
|
|
1124
1665
|
window.open(controlsOnlyUrl, "v0-controls", controlsFeatures);
|
|
1125
1666
|
}
|
|
1126
1667
|
}, [controlsOnlyUrl, leftPanelWidth, presentationUrl]);
|
|
1127
|
-
const
|
|
1668
|
+
const jsx15 = useMemo4(() => {
|
|
1128
1669
|
if (!componentName) return "";
|
|
1129
1670
|
const props = Object.entries(values).map(([key, val]) => {
|
|
1130
1671
|
if (typeof val === "string") return `${key}="${val}"`;
|
|
@@ -1169,7 +1710,7 @@ var ControlPanel = () => {
|
|
|
1169
1710
|
const advancedConfig = config?.addAdvancedPaletteControl;
|
|
1170
1711
|
let advancedPaletteControlNode = null;
|
|
1171
1712
|
if (advancedConfig) {
|
|
1172
|
-
const advancedNode = /* @__PURE__ */
|
|
1713
|
+
const advancedNode = /* @__PURE__ */ jsx11(
|
|
1173
1714
|
AdvancedPaletteControl_default,
|
|
1174
1715
|
{
|
|
1175
1716
|
config: advancedConfig
|
|
@@ -1195,12 +1736,52 @@ var ControlPanel = () => {
|
|
|
1195
1736
|
advancedPaletteControlNode = advancedNode;
|
|
1196
1737
|
}
|
|
1197
1738
|
}
|
|
1198
|
-
const
|
|
1199
|
-
|
|
1200
|
-
)
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1739
|
+
const mediaUploadConfig = config?.addMediaUploadControl;
|
|
1740
|
+
let mediaUploadControlNode = null;
|
|
1741
|
+
if (mediaUploadConfig) {
|
|
1742
|
+
const mediaUploadNode = /* @__PURE__ */ jsx11(
|
|
1743
|
+
MediaUploadControl,
|
|
1744
|
+
{
|
|
1745
|
+
onSelectMedia: (media) => {
|
|
1746
|
+
mediaUploadConfig.onSelectMedia?.(media);
|
|
1747
|
+
},
|
|
1748
|
+
onClear: () => {
|
|
1749
|
+
mediaUploadConfig.onClear?.();
|
|
1750
|
+
},
|
|
1751
|
+
presetMedia: mediaUploadConfig.presetMedia,
|
|
1752
|
+
maxPresetCount: mediaUploadConfig.maxPresetCount
|
|
1753
|
+
},
|
|
1754
|
+
"mediaUploadControl"
|
|
1755
|
+
);
|
|
1756
|
+
const mediaFolder = mediaUploadConfig.folder?.trim();
|
|
1757
|
+
if (mediaFolder) {
|
|
1758
|
+
const placement = mediaUploadConfig.folderPlacement ?? "bottom";
|
|
1759
|
+
ensureFolder(mediaFolder);
|
|
1760
|
+
if (!folderControls.has(mediaFolder)) {
|
|
1761
|
+
folderControls.set(mediaFolder, []);
|
|
1762
|
+
}
|
|
1763
|
+
const existingPlacement = folderPlacement.get(mediaFolder);
|
|
1764
|
+
if (!existingPlacement || placement === "top") {
|
|
1765
|
+
folderPlacement.set(mediaFolder, placement);
|
|
1766
|
+
}
|
|
1767
|
+
if (!folderExtras.has(mediaFolder)) {
|
|
1768
|
+
folderExtras.set(mediaFolder, []);
|
|
1769
|
+
}
|
|
1770
|
+
folderExtras.get(mediaFolder).push(mediaUploadNode);
|
|
1771
|
+
} else {
|
|
1772
|
+
mediaUploadControlNode = mediaUploadNode;
|
|
1773
|
+
}
|
|
1774
|
+
}
|
|
1775
|
+
const rootButtonControls = [];
|
|
1776
|
+
const rootNormalControls = [];
|
|
1777
|
+
rootControls.forEach((entry) => {
|
|
1778
|
+
const [key, control] = entry;
|
|
1779
|
+
if (control.type === "button") {
|
|
1780
|
+
rootButtonControls.push([key, control]);
|
|
1781
|
+
} else {
|
|
1782
|
+
rootNormalControls.push(entry);
|
|
1783
|
+
}
|
|
1784
|
+
});
|
|
1204
1785
|
const folderGroups = folderOrder.map((folder) => ({
|
|
1205
1786
|
folder,
|
|
1206
1787
|
entries: folderControls.get(folder) ?? [],
|
|
@@ -1209,7 +1790,7 @@ var ControlPanel = () => {
|
|
|
1209
1790
|
})).filter((group) => group.entries.length > 0 || group.extras.length > 0);
|
|
1210
1791
|
const hasRootButtonControls = rootButtonControls.length > 0;
|
|
1211
1792
|
const hasAnyFolders = folderGroups.length > 0;
|
|
1212
|
-
const jsonToComponentString =
|
|
1793
|
+
const jsonToComponentString = useCallback4(
|
|
1213
1794
|
({
|
|
1214
1795
|
componentName: componentNameOverride,
|
|
1215
1796
|
props
|
|
@@ -1240,16 +1821,75 @@ var ControlPanel = () => {
|
|
|
1240
1821
|
componentName,
|
|
1241
1822
|
values,
|
|
1242
1823
|
schema,
|
|
1243
|
-
jsx:
|
|
1824
|
+
jsx: jsx15,
|
|
1244
1825
|
jsonToComponentString
|
|
1245
|
-
}) ??
|
|
1826
|
+
}) ?? jsx15;
|
|
1246
1827
|
const shouldShowCopyButton = config?.showCopyButton !== false && Boolean(copyText);
|
|
1828
|
+
const baseSnippet = copyText || jsx15;
|
|
1829
|
+
const formattedCode = useMemo4(
|
|
1830
|
+
() => formatJsxCodeSnippet(baseSnippet),
|
|
1831
|
+
[baseSnippet]
|
|
1832
|
+
);
|
|
1833
|
+
const hasCodeSnippet = Boolean(config?.showCodeSnippet && formattedCode);
|
|
1834
|
+
const highlightedCode = useMemo4(
|
|
1835
|
+
() => formattedCode ? highlightJsx(formattedCode) : null,
|
|
1836
|
+
[formattedCode]
|
|
1837
|
+
);
|
|
1838
|
+
useEffect6(() => {
|
|
1839
|
+
if (!hasCodeSnippet) {
|
|
1840
|
+
setIsCodeVisible(false);
|
|
1841
|
+
}
|
|
1842
|
+
}, [hasCodeSnippet]);
|
|
1843
|
+
useEffect6(() => {
|
|
1844
|
+
setCodeCopied(false);
|
|
1845
|
+
if (codeCopyTimeoutRef.current) {
|
|
1846
|
+
clearTimeout(codeCopyTimeoutRef.current);
|
|
1847
|
+
codeCopyTimeoutRef.current = null;
|
|
1848
|
+
}
|
|
1849
|
+
}, [formattedCode]);
|
|
1850
|
+
useEffect6(() => {
|
|
1851
|
+
return () => {
|
|
1852
|
+
if (codeCopyTimeoutRef.current) {
|
|
1853
|
+
clearTimeout(codeCopyTimeoutRef.current);
|
|
1854
|
+
}
|
|
1855
|
+
};
|
|
1856
|
+
}, []);
|
|
1857
|
+
const handleToggleCodeVisibility = useCallback4(() => {
|
|
1858
|
+
setIsCodeVisible((prev) => {
|
|
1859
|
+
const next = !prev;
|
|
1860
|
+
if (!next) {
|
|
1861
|
+
setCodeCopied(false);
|
|
1862
|
+
if (codeCopyTimeoutRef.current) {
|
|
1863
|
+
clearTimeout(codeCopyTimeoutRef.current);
|
|
1864
|
+
codeCopyTimeoutRef.current = null;
|
|
1865
|
+
}
|
|
1866
|
+
}
|
|
1867
|
+
return next;
|
|
1868
|
+
});
|
|
1869
|
+
}, []);
|
|
1870
|
+
const handleCodeCopy = useCallback4(() => {
|
|
1871
|
+
if (!formattedCode) return;
|
|
1872
|
+
if (typeof navigator === "undefined" || !navigator.clipboard || typeof navigator.clipboard.writeText !== "function") {
|
|
1873
|
+
return;
|
|
1874
|
+
}
|
|
1875
|
+
navigator.clipboard.writeText(formattedCode).then(() => {
|
|
1876
|
+
setCodeCopied(true);
|
|
1877
|
+
if (codeCopyTimeoutRef.current) {
|
|
1878
|
+
clearTimeout(codeCopyTimeoutRef.current);
|
|
1879
|
+
}
|
|
1880
|
+
codeCopyTimeoutRef.current = setTimeout(() => {
|
|
1881
|
+
setCodeCopied(false);
|
|
1882
|
+
codeCopyTimeoutRef.current = null;
|
|
1883
|
+
}, 3e3);
|
|
1884
|
+
}).catch(() => {
|
|
1885
|
+
});
|
|
1886
|
+
}, [formattedCode]);
|
|
1247
1887
|
const labelize = (key) => key.replace(/([A-Z])/g, " $1").replace(/[\-_]/g, " ").replace(/\s+/g, " ").trim().replace(/(^|\s)\S/g, (s) => s.toUpperCase());
|
|
1248
|
-
const renderButtonControl = (key, control, variant) => /* @__PURE__ */
|
|
1888
|
+
const renderButtonControl = (key, control, variant) => /* @__PURE__ */ jsx11(
|
|
1249
1889
|
"div",
|
|
1250
1890
|
{
|
|
1251
1891
|
className: variant === "root" ? "flex-1 [&_[data-slot=button]]:w-full" : "[&_[data-slot=button]]:w-full",
|
|
1252
|
-
children: control.render ? control.render() : /* @__PURE__ */
|
|
1892
|
+
children: control.render ? control.render() : /* @__PURE__ */ jsx11(
|
|
1253
1893
|
"button",
|
|
1254
1894
|
{
|
|
1255
1895
|
onClick: control.onClick,
|
|
@@ -1267,9 +1907,9 @@ var ControlPanel = () => {
|
|
|
1267
1907
|
const value = values[key];
|
|
1268
1908
|
switch (control.type) {
|
|
1269
1909
|
case "boolean":
|
|
1270
|
-
return /* @__PURE__ */
|
|
1271
|
-
/* @__PURE__ */
|
|
1272
|
-
/* @__PURE__ */
|
|
1910
|
+
return /* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-between", children: [
|
|
1911
|
+
/* @__PURE__ */ jsx11(Label, { htmlFor: key, className: "cursor-pointer", children: labelize(key) }),
|
|
1912
|
+
/* @__PURE__ */ jsx11(
|
|
1273
1913
|
Switch,
|
|
1274
1914
|
{
|
|
1275
1915
|
id: key,
|
|
@@ -1280,10 +1920,10 @@ var ControlPanel = () => {
|
|
|
1280
1920
|
)
|
|
1281
1921
|
] }, key);
|
|
1282
1922
|
case "number":
|
|
1283
|
-
return /* @__PURE__ */
|
|
1284
|
-
/* @__PURE__ */
|
|
1285
|
-
/* @__PURE__ */
|
|
1286
|
-
/* @__PURE__ */
|
|
1923
|
+
return /* @__PURE__ */ jsxs6("div", { className: "space-y-3 w-full", children: [
|
|
1924
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-between", children: [
|
|
1925
|
+
/* @__PURE__ */ jsx11(Label, { className: "text-stone-300", htmlFor: key, children: labelize(key) }),
|
|
1926
|
+
/* @__PURE__ */ jsx11(
|
|
1287
1927
|
Input,
|
|
1288
1928
|
{
|
|
1289
1929
|
type: "number",
|
|
@@ -1300,7 +1940,7 @@ var ControlPanel = () => {
|
|
|
1300
1940
|
}
|
|
1301
1941
|
)
|
|
1302
1942
|
] }),
|
|
1303
|
-
/* @__PURE__ */
|
|
1943
|
+
/* @__PURE__ */ jsx11(
|
|
1304
1944
|
Slider,
|
|
1305
1945
|
{
|
|
1306
1946
|
id: key,
|
|
@@ -1314,9 +1954,9 @@ var ControlPanel = () => {
|
|
|
1314
1954
|
)
|
|
1315
1955
|
] }, key);
|
|
1316
1956
|
case "string":
|
|
1317
|
-
return /* @__PURE__ */
|
|
1318
|
-
/* @__PURE__ */
|
|
1319
|
-
/* @__PURE__ */
|
|
1957
|
+
return /* @__PURE__ */ jsxs6("div", { className: "space-y-2 w-full", children: [
|
|
1958
|
+
/* @__PURE__ */ jsx11(Label, { className: "text-stone-300", htmlFor: key, children: labelize(key) }),
|
|
1959
|
+
/* @__PURE__ */ jsx11(
|
|
1320
1960
|
Input,
|
|
1321
1961
|
{
|
|
1322
1962
|
id: key,
|
|
@@ -1328,9 +1968,9 @@ var ControlPanel = () => {
|
|
|
1328
1968
|
)
|
|
1329
1969
|
] }, key);
|
|
1330
1970
|
case "color":
|
|
1331
|
-
return /* @__PURE__ */
|
|
1332
|
-
/* @__PURE__ */
|
|
1333
|
-
/* @__PURE__ */
|
|
1971
|
+
return /* @__PURE__ */ jsxs6("div", { className: "space-y-2 w-full", children: [
|
|
1972
|
+
/* @__PURE__ */ jsx11(Label, { className: "text-stone-300", htmlFor: key, children: labelize(key) }),
|
|
1973
|
+
/* @__PURE__ */ jsx11(
|
|
1334
1974
|
"input",
|
|
1335
1975
|
{
|
|
1336
1976
|
type: "color",
|
|
@@ -1342,11 +1982,11 @@ var ControlPanel = () => {
|
|
|
1342
1982
|
)
|
|
1343
1983
|
] }, key);
|
|
1344
1984
|
case "select":
|
|
1345
|
-
return /* @__PURE__ */
|
|
1346
|
-
/* @__PURE__ */
|
|
1347
|
-
/* @__PURE__ */
|
|
1348
|
-
/* @__PURE__ */
|
|
1349
|
-
/* @__PURE__ */
|
|
1985
|
+
return /* @__PURE__ */ jsx11("div", { className: "space-y-2", children: /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-3", children: [
|
|
1986
|
+
/* @__PURE__ */ jsx11(Label, { className: "min-w-fit", htmlFor: key, children: labelize(key) }),
|
|
1987
|
+
/* @__PURE__ */ jsxs6(Select, { value, onValueChange: (val) => setValue(key, val), children: [
|
|
1988
|
+
/* @__PURE__ */ jsx11(SelectTrigger, { className: "flex-1 cursor-pointer", children: /* @__PURE__ */ jsx11(SelectValue, { placeholder: "Select option" }) }),
|
|
1989
|
+
/* @__PURE__ */ jsx11(SelectContent, { className: "cursor-pointer z-[9999]", children: Object.entries(control.options).map(([label]) => /* @__PURE__ */ jsx11(
|
|
1350
1990
|
SelectItem,
|
|
1351
1991
|
{
|
|
1352
1992
|
value: label,
|
|
@@ -1363,12 +2003,12 @@ var ControlPanel = () => {
|
|
|
1363
2003
|
};
|
|
1364
2004
|
const renderFolder = (folder, entries, extras = []) => {
|
|
1365
2005
|
const isOpen = folderStates[folder] ?? true;
|
|
1366
|
-
return /* @__PURE__ */
|
|
2006
|
+
return /* @__PURE__ */ jsxs6(
|
|
1367
2007
|
"div",
|
|
1368
2008
|
{
|
|
1369
2009
|
className: "border border-stone-700/60 rounded-lg bg-stone-900/70",
|
|
1370
2010
|
children: [
|
|
1371
|
-
/* @__PURE__ */
|
|
2011
|
+
/* @__PURE__ */ jsxs6(
|
|
1372
2012
|
"button",
|
|
1373
2013
|
{
|
|
1374
2014
|
type: "button",
|
|
@@ -1378,8 +2018,8 @@ var ControlPanel = () => {
|
|
|
1378
2018
|
})),
|
|
1379
2019
|
className: "w-full flex items-center justify-between px-4 py-3 text-left font-semibold text-stone-200 tracking-wide",
|
|
1380
2020
|
children: [
|
|
1381
|
-
/* @__PURE__ */
|
|
1382
|
-
/* @__PURE__ */
|
|
2021
|
+
/* @__PURE__ */ jsx11("span", { children: folder }),
|
|
2022
|
+
/* @__PURE__ */ jsx11(
|
|
1383
2023
|
ChevronDown2,
|
|
1384
2024
|
{
|
|
1385
2025
|
className: `w-4 h-4 transition-transform duration-200 ${isOpen ? "rotate-180" : ""}`
|
|
@@ -1388,7 +2028,7 @@ var ControlPanel = () => {
|
|
|
1388
2028
|
]
|
|
1389
2029
|
}
|
|
1390
2030
|
),
|
|
1391
|
-
isOpen && /* @__PURE__ */
|
|
2031
|
+
isOpen && /* @__PURE__ */ jsxs6("div", { className: "px-4 pb-4 pt-0 space-y-5", children: [
|
|
1392
2032
|
entries.map(
|
|
1393
2033
|
([key, control]) => renderControl(key, control, "folder")
|
|
1394
2034
|
),
|
|
@@ -1410,7 +2050,7 @@ var ControlPanel = () => {
|
|
|
1410
2050
|
height: "auto",
|
|
1411
2051
|
flex: "0 0 auto"
|
|
1412
2052
|
};
|
|
1413
|
-
if (isHydrated) {
|
|
2053
|
+
if (isHydrated && !isControlsOnlyView) {
|
|
1414
2054
|
if (isDesktop) {
|
|
1415
2055
|
Object.assign(panelStyle, {
|
|
1416
2056
|
position: "absolute",
|
|
@@ -1427,47 +2067,87 @@ var ControlPanel = () => {
|
|
|
1427
2067
|
});
|
|
1428
2068
|
}
|
|
1429
2069
|
}
|
|
1430
|
-
return /* @__PURE__ */
|
|
2070
|
+
return /* @__PURE__ */ jsx11(
|
|
1431
2071
|
"div",
|
|
1432
2072
|
{
|
|
1433
2073
|
className: `order-2 md:order-1 w-full md:h-auto p-2 md:p-4 bg-stone-900 font-mono text-stone-300 transition-opacity duration-300 z-max ${!isHydrated ? "opacity-0" : "opacity-100"}`,
|
|
1434
2074
|
onPointerDown: (e) => e.stopPropagation(),
|
|
1435
2075
|
onTouchStart: (e) => e.stopPropagation(),
|
|
1436
2076
|
style: panelStyle,
|
|
1437
|
-
children: /* @__PURE__ */
|
|
1438
|
-
/* @__PURE__ */
|
|
1439
|
-
/* @__PURE__ */
|
|
2077
|
+
children: /* @__PURE__ */ jsxs6("div", { className: "dark mb-10 space-y-6 p-4 md:p-6 bg-stone-900/95 backdrop-blur-md border-2 border-stone-700 rounded-xl shadow-lg", children: [
|
|
2078
|
+
/* @__PURE__ */ jsx11("div", { className: "space-y-1", children: /* @__PURE__ */ jsx11("h1", { className: "text-lg text-stone-100 font-semibold", children: config?.mainLabel ?? "Controls" }) }),
|
|
2079
|
+
/* @__PURE__ */ jsxs6("div", { className: "space-y-6", children: [
|
|
1440
2080
|
topFolderSections,
|
|
1441
|
-
hasRootButtonControls && /* @__PURE__ */
|
|
2081
|
+
hasRootButtonControls && /* @__PURE__ */ jsx11("div", { className: "flex flex-wrap gap-2", children: rootButtonControls.map(
|
|
1442
2082
|
([key, control]) => renderButtonControl(key, control, "root")
|
|
1443
2083
|
) }),
|
|
1444
2084
|
advancedPaletteControlNode,
|
|
2085
|
+
mediaUploadControlNode,
|
|
1445
2086
|
rootNormalControls.map(
|
|
1446
2087
|
([key, control]) => renderControl(key, control, "root")
|
|
1447
2088
|
),
|
|
1448
2089
|
bottomFolderSections,
|
|
1449
|
-
|
|
2090
|
+
hasCodeSnippet && /* @__PURE__ */ jsxs6("div", { className: "border border-stone-700/60 rounded-lg bg-stone-900/70", children: [
|
|
2091
|
+
/* @__PURE__ */ jsxs6(
|
|
2092
|
+
"button",
|
|
2093
|
+
{
|
|
2094
|
+
type: "button",
|
|
2095
|
+
onClick: handleToggleCodeVisibility,
|
|
2096
|
+
className: "w-full flex items-center justify-between px-4 py-3 text-left font-semibold text-stone-200 tracking-wide",
|
|
2097
|
+
"aria-expanded": isCodeVisible,
|
|
2098
|
+
children: [
|
|
2099
|
+
/* @__PURE__ */ jsx11("span", { children: isCodeVisible ? "Hide Code" : "Show Code" }),
|
|
2100
|
+
/* @__PURE__ */ jsx11(
|
|
2101
|
+
ChevronDown2,
|
|
2102
|
+
{
|
|
2103
|
+
className: `w-4 h-4 transition-transform duration-200 ${isCodeVisible ? "rotate-180" : ""}`
|
|
2104
|
+
}
|
|
2105
|
+
)
|
|
2106
|
+
]
|
|
2107
|
+
}
|
|
2108
|
+
),
|
|
2109
|
+
isCodeVisible && /* @__PURE__ */ jsxs6("div", { className: "relative border-t border-stone-700/60 bg-stone-950/60 px-4 py-4 rounded-b-lg", children: [
|
|
2110
|
+
/* @__PURE__ */ jsx11(
|
|
2111
|
+
"button",
|
|
2112
|
+
{
|
|
2113
|
+
type: "button",
|
|
2114
|
+
onClick: handleCodeCopy,
|
|
2115
|
+
className: "absolute top-3 right-3 flex items-center gap-1 rounded-md border border-stone-700 bg-stone-800 px-2 py-1 text-xs font-medium text-white shadow hover:bg-stone-700",
|
|
2116
|
+
children: codeCopied ? /* @__PURE__ */ jsxs6(Fragment, { children: [
|
|
2117
|
+
/* @__PURE__ */ jsx11(Check2, { className: "h-3.5 w-3.5" }),
|
|
2118
|
+
"Copied"
|
|
2119
|
+
] }) : /* @__PURE__ */ jsxs6(Fragment, { children: [
|
|
2120
|
+
/* @__PURE__ */ jsx11(Copy, { className: "h-3.5 w-3.5" }),
|
|
2121
|
+
"Copy"
|
|
2122
|
+
] })
|
|
2123
|
+
}
|
|
2124
|
+
),
|
|
2125
|
+
/* @__PURE__ */ jsx11("pre", { className: "whitespace-pre overflow-x-auto text-xs md:text-sm text-stone-200 pr-14", children: /* @__PURE__ */ jsx11("code", { className: "block text-stone-200", children: highlightedCode ?? formattedCode }) })
|
|
2126
|
+
] })
|
|
2127
|
+
] }),
|
|
2128
|
+
shouldShowCopyButton && /* @__PURE__ */ jsx11("div", { className: "flex-1 pt-4", children: /* @__PURE__ */ jsx11(
|
|
1450
2129
|
"button",
|
|
1451
2130
|
{
|
|
1452
2131
|
onClick: () => {
|
|
1453
|
-
|
|
1454
|
-
|
|
2132
|
+
const copyPayload = formattedCode || baseSnippet;
|
|
2133
|
+
if (!copyPayload) return;
|
|
2134
|
+
navigator.clipboard.writeText(copyPayload);
|
|
1455
2135
|
setCopied(true);
|
|
1456
2136
|
setTimeout(() => setCopied(false), 5e3);
|
|
1457
2137
|
},
|
|
1458
2138
|
className: "w-full px-4 py-2 text-sm bg-stone-800 hover:bg-stone-700 text-white rounded-md flex items-center justify-center gap-2 shadow",
|
|
1459
|
-
children: copied ? /* @__PURE__ */
|
|
1460
|
-
/* @__PURE__ */
|
|
2139
|
+
children: copied ? /* @__PURE__ */ jsxs6(Fragment, { children: [
|
|
2140
|
+
/* @__PURE__ */ jsx11(Check2, { className: "w-4 h-4" }),
|
|
1461
2141
|
"Copied"
|
|
1462
|
-
] }) : /* @__PURE__ */
|
|
1463
|
-
/* @__PURE__ */
|
|
2142
|
+
] }) : /* @__PURE__ */ jsxs6(Fragment, { children: [
|
|
2143
|
+
/* @__PURE__ */ jsx11(Copy, { className: "w-4 h-4" }),
|
|
1464
2144
|
"Copy to Clipboard"
|
|
1465
2145
|
] })
|
|
1466
2146
|
}
|
|
1467
2147
|
) }, "control-panel-jsx")
|
|
1468
2148
|
] }),
|
|
1469
|
-
previewUrl && /* @__PURE__ */
|
|
1470
|
-
/* @__PURE__ */
|
|
2149
|
+
previewUrl && /* @__PURE__ */ jsxs6("div", { className: "flex flex-col gap-2", children: [
|
|
2150
|
+
/* @__PURE__ */ jsx11(Button, { asChild: true, className: "w-full", children: /* @__PURE__ */ jsxs6(
|
|
1471
2151
|
"a",
|
|
1472
2152
|
{
|
|
1473
2153
|
href: previewUrl,
|
|
@@ -1475,12 +2155,12 @@ var ControlPanel = () => {
|
|
|
1475
2155
|
rel: "noopener noreferrer",
|
|
1476
2156
|
className: "w-full px-4 py-2 text-sm text-center bg-stone-900 hover:bg-stone-800 text-white rounded-md border border-stone-700",
|
|
1477
2157
|
children: [
|
|
1478
|
-
/* @__PURE__ */
|
|
2158
|
+
/* @__PURE__ */ jsx11(SquareArrowOutUpRight, {}),
|
|
1479
2159
|
" Open in a New Tab"
|
|
1480
2160
|
]
|
|
1481
2161
|
}
|
|
1482
2162
|
) }),
|
|
1483
|
-
config?.showPresentationButton && presentationUrl && /* @__PURE__ */
|
|
2163
|
+
config?.showPresentationButton && presentationUrl && /* @__PURE__ */ jsxs6(
|
|
1484
2164
|
Button,
|
|
1485
2165
|
{
|
|
1486
2166
|
type: "button",
|
|
@@ -1488,7 +2168,7 @@ var ControlPanel = () => {
|
|
|
1488
2168
|
variant: "secondary",
|
|
1489
2169
|
className: "w-full bg-stone-800 text-white hover:bg-stone-700 border border-stone-700",
|
|
1490
2170
|
children: [
|
|
1491
|
-
/* @__PURE__ */
|
|
2171
|
+
/* @__PURE__ */ jsx11(Presentation, {}),
|
|
1492
2172
|
" Presentation Mode"
|
|
1493
2173
|
]
|
|
1494
2174
|
}
|
|
@@ -1500,16 +2180,16 @@ var ControlPanel = () => {
|
|
|
1500
2180
|
};
|
|
1501
2181
|
var ControlPanel_default = ControlPanel;
|
|
1502
2182
|
|
|
1503
|
-
// src/components/PreviewContainer
|
|
1504
|
-
import { useRef as
|
|
2183
|
+
// src/components/PreviewContainer.tsx
|
|
2184
|
+
import { useRef as useRef6 } from "react";
|
|
1505
2185
|
|
|
1506
|
-
// src/components/Grid
|
|
1507
|
-
import { jsx as
|
|
2186
|
+
// src/components/Grid.tsx
|
|
2187
|
+
import { jsx as jsx12 } from "react/jsx-runtime";
|
|
1508
2188
|
function Grid() {
|
|
1509
|
-
return /* @__PURE__ */
|
|
2189
|
+
return /* @__PURE__ */ jsx12(
|
|
1510
2190
|
"div",
|
|
1511
2191
|
{
|
|
1512
|
-
className: "absolute inset-0 w-
|
|
2192
|
+
className: "absolute inset-0 w-full h-full z-[0] blur-[1px]",
|
|
1513
2193
|
style: {
|
|
1514
2194
|
backgroundImage: `
|
|
1515
2195
|
linear-gradient(to right,rgb(13, 13, 13) 1px, transparent 1px),
|
|
@@ -1523,40 +2203,40 @@ function Grid() {
|
|
|
1523
2203
|
}
|
|
1524
2204
|
var Grid_default = Grid;
|
|
1525
2205
|
|
|
1526
|
-
// src/components/PreviewContainer
|
|
1527
|
-
import { jsx as
|
|
2206
|
+
// src/components/PreviewContainer.tsx
|
|
2207
|
+
import { jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1528
2208
|
var PreviewContainer = ({ children, hideControls }) => {
|
|
1529
2209
|
const { config } = useControlsContext();
|
|
1530
2210
|
const { leftPanelWidth, isDesktop, isHydrated, containerRef } = useResizableLayout();
|
|
1531
|
-
const previewRef =
|
|
1532
|
-
return /* @__PURE__ */
|
|
2211
|
+
const previewRef = useRef6(null);
|
|
2212
|
+
return /* @__PURE__ */ jsx13(
|
|
1533
2213
|
"div",
|
|
1534
2214
|
{
|
|
1535
2215
|
ref: previewRef,
|
|
1536
|
-
className: "order-1 md:order-2 flex-1 bg-black overflow-auto flex items-center justify-center relative",
|
|
2216
|
+
className: "order-1 md:order-2 flex-1 md:flex-none bg-black overflow-auto flex items-center justify-center relative",
|
|
1537
2217
|
style: isHydrated && isDesktop && !hideControls ? {
|
|
1538
2218
|
width: `${100 - leftPanelWidth}%`,
|
|
1539
2219
|
marginLeft: `${leftPanelWidth}%`
|
|
1540
2220
|
} : {},
|
|
1541
|
-
children: /* @__PURE__ */
|
|
1542
|
-
config?.showGrid && /* @__PURE__ */
|
|
1543
|
-
/* @__PURE__ */
|
|
2221
|
+
children: /* @__PURE__ */ jsxs7("div", { className: "w-full h-screen", children: [
|
|
2222
|
+
config?.showGrid && /* @__PURE__ */ jsx13(Grid_default, {}),
|
|
2223
|
+
/* @__PURE__ */ jsx13("div", { className: "w-full h-full flex items-center justify-center relative", children })
|
|
1544
2224
|
] })
|
|
1545
2225
|
}
|
|
1546
2226
|
);
|
|
1547
2227
|
};
|
|
1548
2228
|
var PreviewContainer_default = PreviewContainer;
|
|
1549
2229
|
|
|
1550
|
-
// src/components/Playground
|
|
1551
|
-
import { jsx as
|
|
1552
|
-
var HiddenPreview = ({ children }) => /* @__PURE__ */
|
|
2230
|
+
// src/components/Playground.tsx
|
|
2231
|
+
import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
2232
|
+
var HiddenPreview = ({ children }) => /* @__PURE__ */ jsx14("div", { "aria-hidden": "true", className: "hidden", children });
|
|
1553
2233
|
function Playground({ children }) {
|
|
1554
2234
|
const [isHydrated, setIsHydrated] = useState5(false);
|
|
1555
2235
|
const [copied, setCopied] = useState5(false);
|
|
1556
|
-
|
|
2236
|
+
useEffect7(() => {
|
|
1557
2237
|
setIsHydrated(true);
|
|
1558
2238
|
}, []);
|
|
1559
|
-
const { showControls, isPresentationMode, isControlsOnly } =
|
|
2239
|
+
const { showControls, isPresentationMode, isControlsOnly } = useMemo5(() => {
|
|
1560
2240
|
if (typeof window === "undefined") {
|
|
1561
2241
|
return {
|
|
1562
2242
|
showControls: true,
|
|
@@ -1583,54 +2263,54 @@ function Playground({ children }) {
|
|
|
1583
2263
|
setTimeout(() => setCopied(false), 2e3);
|
|
1584
2264
|
};
|
|
1585
2265
|
if (!isHydrated) return null;
|
|
1586
|
-
return /* @__PURE__ */
|
|
1587
|
-
shouldShowShareButton && /* @__PURE__ */
|
|
2266
|
+
return /* @__PURE__ */ jsx14(ResizableLayout, { hideControls: layoutHideControls, children: /* @__PURE__ */ jsxs8(ControlsProvider, { children: [
|
|
2267
|
+
shouldShowShareButton && /* @__PURE__ */ jsxs8(
|
|
1588
2268
|
"button",
|
|
1589
2269
|
{
|
|
1590
2270
|
onClick: handleCopy,
|
|
1591
2271
|
className: "absolute top-4 right-4 z-50 flex items-center gap-1 rounded bg-black/70 px-3 py-1 text-white hover:bg-black",
|
|
1592
2272
|
children: [
|
|
1593
|
-
copied ? /* @__PURE__ */
|
|
2273
|
+
copied ? /* @__PURE__ */ jsx14(Check3, { size: 16 }) : /* @__PURE__ */ jsx14(Copy2, { size: 16 }),
|
|
1594
2274
|
copied ? "Copied!" : "Share"
|
|
1595
2275
|
]
|
|
1596
2276
|
}
|
|
1597
2277
|
),
|
|
1598
|
-
isControlsOnly ? /* @__PURE__ */
|
|
1599
|
-
showControls && /* @__PURE__ */
|
|
2278
|
+
isControlsOnly ? /* @__PURE__ */ jsx14(HiddenPreview, { children }) : /* @__PURE__ */ jsx14(PreviewContainer_default, { hideControls: layoutHideControls, children }),
|
|
2279
|
+
showControls && /* @__PURE__ */ jsx14(ControlPanel_default, {})
|
|
1600
2280
|
] }) });
|
|
1601
2281
|
}
|
|
1602
2282
|
|
|
1603
2283
|
// src/hooks/useAdvancedPaletteControls.ts
|
|
1604
|
-
import { useCallback as
|
|
2284
|
+
import { useCallback as useCallback5, useEffect as useEffect8, useMemo as useMemo6, useRef as useRef7, useState as useState6 } from "react";
|
|
1605
2285
|
var cloneForCallbacks = (palette) => clonePalette(palette);
|
|
1606
2286
|
var useAdvancedPaletteControls = (options = {}) => {
|
|
1607
|
-
const resolvedDefaultPalette =
|
|
2287
|
+
const resolvedDefaultPalette = useMemo6(
|
|
1608
2288
|
() => createAdvancedPalette(options.defaultPalette),
|
|
1609
2289
|
[options.defaultPalette]
|
|
1610
2290
|
);
|
|
1611
|
-
const resolvedFallbackPalette =
|
|
2291
|
+
const resolvedFallbackPalette = useMemo6(
|
|
1612
2292
|
() => options.fallbackPalette ? createAdvancedPalette(options.fallbackPalette) : resolvedDefaultPalette,
|
|
1613
2293
|
[options.fallbackPalette, resolvedDefaultPalette]
|
|
1614
2294
|
);
|
|
1615
2295
|
const [palette, setPaletteState] = useState6(
|
|
1616
2296
|
() => clonePalette(resolvedDefaultPalette)
|
|
1617
2297
|
);
|
|
1618
|
-
const defaultSignatureRef =
|
|
2298
|
+
const defaultSignatureRef = useRef7(
|
|
1619
2299
|
createPaletteSignature(resolvedDefaultPalette)
|
|
1620
2300
|
);
|
|
1621
|
-
|
|
2301
|
+
useEffect8(() => {
|
|
1622
2302
|
const nextSignature = createPaletteSignature(resolvedDefaultPalette);
|
|
1623
2303
|
if (defaultSignatureRef.current === nextSignature) return;
|
|
1624
2304
|
defaultSignatureRef.current = nextSignature;
|
|
1625
2305
|
setPaletteState(clonePalette(resolvedDefaultPalette));
|
|
1626
2306
|
}, [resolvedDefaultPalette]);
|
|
1627
|
-
const notifyChange =
|
|
2307
|
+
const notifyChange = useCallback5(
|
|
1628
2308
|
(nextPalette) => {
|
|
1629
2309
|
options.onChange?.(cloneForCallbacks(nextPalette));
|
|
1630
2310
|
},
|
|
1631
2311
|
[options.onChange]
|
|
1632
2312
|
);
|
|
1633
|
-
const setPalette =
|
|
2313
|
+
const setPalette = useCallback5(
|
|
1634
2314
|
(source) => {
|
|
1635
2315
|
const nextPalette = createAdvancedPalette(
|
|
1636
2316
|
source ?? resolvedDefaultPalette
|
|
@@ -1640,7 +2320,7 @@ var useAdvancedPaletteControls = (options = {}) => {
|
|
|
1640
2320
|
},
|
|
1641
2321
|
[notifyChange, resolvedDefaultPalette]
|
|
1642
2322
|
);
|
|
1643
|
-
const updatePalette =
|
|
2323
|
+
const updatePalette = useCallback5(
|
|
1644
2324
|
(updater) => {
|
|
1645
2325
|
setPaletteState((current) => {
|
|
1646
2326
|
const nextSource = updater(clonePalette(current));
|
|
@@ -1653,18 +2333,18 @@ var useAdvancedPaletteControls = (options = {}) => {
|
|
|
1653
2333
|
},
|
|
1654
2334
|
[notifyChange, resolvedDefaultPalette]
|
|
1655
2335
|
);
|
|
1656
|
-
const resetPalette =
|
|
2336
|
+
const resetPalette = useCallback5(() => {
|
|
1657
2337
|
setPaletteState(clonePalette(resolvedDefaultPalette));
|
|
1658
2338
|
notifyChange(resolvedDefaultPalette);
|
|
1659
2339
|
}, [notifyChange, resolvedDefaultPalette]);
|
|
1660
|
-
const handleControlPaletteChange =
|
|
2340
|
+
const handleControlPaletteChange = useCallback5(
|
|
1661
2341
|
(nextPalette) => {
|
|
1662
2342
|
setPaletteState(clonePalette(nextPalette));
|
|
1663
2343
|
notifyChange(nextPalette);
|
|
1664
2344
|
},
|
|
1665
2345
|
[notifyChange]
|
|
1666
2346
|
);
|
|
1667
|
-
const controlConfig =
|
|
2347
|
+
const controlConfig = useMemo6(
|
|
1668
2348
|
() => ({
|
|
1669
2349
|
...options.control ?? {},
|
|
1670
2350
|
defaultPalette: resolvedDefaultPalette,
|
|
@@ -1672,7 +2352,7 @@ var useAdvancedPaletteControls = (options = {}) => {
|
|
|
1672
2352
|
}),
|
|
1673
2353
|
[handleControlPaletteChange, options.control, resolvedDefaultPalette]
|
|
1674
2354
|
);
|
|
1675
|
-
const hexColors =
|
|
2355
|
+
const hexColors = useMemo6(
|
|
1676
2356
|
() => advancedPaletteToHexColors(palette, {
|
|
1677
2357
|
sectionOrder: options.sectionOrder,
|
|
1678
2358
|
fallbackPalette: resolvedFallbackPalette,
|
|
@@ -1685,11 +2365,11 @@ var useAdvancedPaletteControls = (options = {}) => {
|
|
|
1685
2365
|
resolvedFallbackPalette
|
|
1686
2366
|
]
|
|
1687
2367
|
);
|
|
1688
|
-
const paletteSignature =
|
|
2368
|
+
const paletteSignature = useMemo6(
|
|
1689
2369
|
() => createPaletteSignature(palette),
|
|
1690
2370
|
[palette]
|
|
1691
2371
|
);
|
|
1692
|
-
const paletteGradient =
|
|
2372
|
+
const paletteGradient = useMemo6(
|
|
1693
2373
|
() => computePaletteGradient(palette, options.gradientSteps),
|
|
1694
2374
|
[options.gradientSteps, palette]
|
|
1695
2375
|
);
|