@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.js
CHANGED
|
@@ -49,9 +49,9 @@ __export(src_exports, {
|
|
|
49
49
|
});
|
|
50
50
|
module.exports = __toCommonJS(src_exports);
|
|
51
51
|
|
|
52
|
-
// src/components/Playground
|
|
53
|
-
var
|
|
54
|
-
var
|
|
52
|
+
// src/components/Playground.tsx
|
|
53
|
+
var import_react8 = require("react");
|
|
54
|
+
var import_lucide_react5 = require("lucide-react");
|
|
55
55
|
|
|
56
56
|
// src/context/ResizableLayout.tsx
|
|
57
57
|
var import_react = require("react");
|
|
@@ -448,7 +448,8 @@ var ControlsProvider = ({ children }) => {
|
|
|
448
448
|
const [schema, setSchema] = (0, import_react2.useState)({});
|
|
449
449
|
const [values, setValues] = (0, import_react2.useState)({});
|
|
450
450
|
const [config, setConfig] = (0, import_react2.useState)({
|
|
451
|
-
showCopyButton: true
|
|
451
|
+
showCopyButton: true,
|
|
452
|
+
showCodeSnippet: false
|
|
452
453
|
});
|
|
453
454
|
const [componentName, setComponentName] = (0, import_react2.useState)();
|
|
454
455
|
const [channelName, setChannelName] = (0, import_react2.useState)(null);
|
|
@@ -471,17 +472,30 @@ var ControlsProvider = ({ children }) => {
|
|
|
471
472
|
setComponentName(opts.componentName);
|
|
472
473
|
}
|
|
473
474
|
if (opts?.config) {
|
|
474
|
-
const {
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
...otherConfig
|
|
478
|
-
|
|
475
|
+
const {
|
|
476
|
+
addAdvancedPaletteControl,
|
|
477
|
+
addMediaUploadControl,
|
|
478
|
+
...otherConfig
|
|
479
|
+
} = opts.config;
|
|
480
|
+
setConfig((prev) => {
|
|
481
|
+
const nextConfig = {
|
|
482
|
+
...prev,
|
|
483
|
+
...otherConfig
|
|
484
|
+
};
|
|
485
|
+
if (Object.prototype.hasOwnProperty.call(
|
|
479
486
|
opts.config,
|
|
480
487
|
"addAdvancedPaletteControl"
|
|
481
|
-
)
|
|
482
|
-
addAdvancedPaletteControl
|
|
483
|
-
}
|
|
484
|
-
|
|
488
|
+
)) {
|
|
489
|
+
nextConfig.addAdvancedPaletteControl = addAdvancedPaletteControl ? resolveAdvancedPaletteConfig(addAdvancedPaletteControl) : void 0;
|
|
490
|
+
}
|
|
491
|
+
if (Object.prototype.hasOwnProperty.call(
|
|
492
|
+
opts.config,
|
|
493
|
+
"addMediaUploadControl"
|
|
494
|
+
)) {
|
|
495
|
+
nextConfig.addMediaUploadControl = addMediaUploadControl ? { ...addMediaUploadControl } : void 0;
|
|
496
|
+
}
|
|
497
|
+
return nextConfig;
|
|
498
|
+
});
|
|
485
499
|
}
|
|
486
500
|
setSchema((prevSchema) => ({ ...prevSchema, ...newSchema }));
|
|
487
501
|
setValues((prevValues) => {
|
|
@@ -646,7 +660,7 @@ var useControls = (schema, options) => {
|
|
|
646
660
|
resolvedAdvancedConfig.onPaletteChange(clonePalette(palette));
|
|
647
661
|
}, [ctx.values, resolvedAdvancedConfig]);
|
|
648
662
|
const typedValues = ctx.values;
|
|
649
|
-
const
|
|
663
|
+
const jsx15 = (0, import_react2.useCallback)(() => {
|
|
650
664
|
if (!options?.componentName) return "";
|
|
651
665
|
const props = Object.entries(typedValues).map(([key, val]) => {
|
|
652
666
|
if (typeof val === "string") return `${key}="${val}"`;
|
|
@@ -660,14 +674,14 @@ var useControls = (schema, options) => {
|
|
|
660
674
|
controls: ctx.values,
|
|
661
675
|
schema: ctx.schema,
|
|
662
676
|
setValue: ctx.setValue,
|
|
663
|
-
jsx:
|
|
677
|
+
jsx: jsx15
|
|
664
678
|
};
|
|
665
679
|
};
|
|
666
680
|
var useUrlSyncedControls = useControls;
|
|
667
681
|
|
|
668
|
-
// src/components/ControlPanel
|
|
669
|
-
var
|
|
670
|
-
var
|
|
682
|
+
// src/components/ControlPanel.tsx
|
|
683
|
+
var import_react6 = require("react");
|
|
684
|
+
var import_lucide_react4 = require("lucide-react");
|
|
671
685
|
|
|
672
686
|
// src/hooks/usePreviewUrl.ts
|
|
673
687
|
var import_react3 = require("react");
|
|
@@ -942,7 +956,7 @@ Button.displayName = "Button";
|
|
|
942
956
|
// src/constants/layout.ts
|
|
943
957
|
var MOBILE_CONTROL_PANEL_PEEK = 112;
|
|
944
958
|
|
|
945
|
-
// src/components/AdvancedPaletteControl
|
|
959
|
+
// src/components/AdvancedPaletteControl.tsx
|
|
946
960
|
var import_react4 = require("react");
|
|
947
961
|
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
948
962
|
var AdvancedPaletteControl = ({
|
|
@@ -1090,15 +1104,532 @@ var AdvancedPaletteControl = ({
|
|
|
1090
1104
|
};
|
|
1091
1105
|
var AdvancedPaletteControl_default = AdvancedPaletteControl;
|
|
1092
1106
|
|
|
1093
|
-
// src/components/
|
|
1107
|
+
// src/components/MediaUploadControl.tsx
|
|
1108
|
+
var import_react5 = require("react");
|
|
1109
|
+
var import_lucide_react3 = require("lucide-react");
|
|
1110
|
+
|
|
1111
|
+
// src/state/mediaSelectionStore.ts
|
|
1112
|
+
var snapshot = {
|
|
1113
|
+
media: null,
|
|
1114
|
+
error: null
|
|
1115
|
+
};
|
|
1116
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
1117
|
+
var emitChange = () => {
|
|
1118
|
+
for (const listener of listeners) {
|
|
1119
|
+
listener();
|
|
1120
|
+
}
|
|
1121
|
+
};
|
|
1122
|
+
var mediaSelectionStore = {
|
|
1123
|
+
subscribe: (listener) => {
|
|
1124
|
+
listeners.add(listener);
|
|
1125
|
+
return () => {
|
|
1126
|
+
listeners.delete(listener);
|
|
1127
|
+
};
|
|
1128
|
+
},
|
|
1129
|
+
getSnapshot: () => snapshot,
|
|
1130
|
+
setSnapshot: (next) => {
|
|
1131
|
+
snapshot = next;
|
|
1132
|
+
emitChange();
|
|
1133
|
+
}
|
|
1134
|
+
};
|
|
1135
|
+
|
|
1136
|
+
// src/components/MediaUploadControl.tsx
|
|
1094
1137
|
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
1138
|
+
var DEFAULT_PRESET_MEDIA = [
|
|
1139
|
+
{
|
|
1140
|
+
src: "https://res.cloudinary.com/dz8kk1l4r/image/upload/v1763233793/astronaut_q84mbj.png",
|
|
1141
|
+
label: "Astronaut",
|
|
1142
|
+
type: "image"
|
|
1143
|
+
},
|
|
1144
|
+
{
|
|
1145
|
+
src: "https://res.cloudinary.com/dz8kk1l4r/image/upload/v1763233793/surreal-head_r0ozcd.png",
|
|
1146
|
+
label: "Futuristic",
|
|
1147
|
+
type: "image"
|
|
1148
|
+
},
|
|
1149
|
+
{
|
|
1150
|
+
src: "https://res.cloudinary.com/dz8kk1l4r/image/upload/v1763233797/futuristic_bpwdzt.png",
|
|
1151
|
+
label: "Surreal",
|
|
1152
|
+
type: "image"
|
|
1153
|
+
},
|
|
1154
|
+
{
|
|
1155
|
+
src: "https://res.cloudinary.com/dz8kk1l4r/image/upload/v1763233793/portrait_hd7dyc.png",
|
|
1156
|
+
label: "Portrait",
|
|
1157
|
+
type: "image"
|
|
1158
|
+
}
|
|
1159
|
+
];
|
|
1160
|
+
function MediaUploadControl({
|
|
1161
|
+
onSelectMedia,
|
|
1162
|
+
onClear,
|
|
1163
|
+
presetMedia,
|
|
1164
|
+
maxPresetCount
|
|
1165
|
+
}) {
|
|
1166
|
+
const inputId = (0, import_react5.useId)();
|
|
1167
|
+
const inputRef = (0, import_react5.useRef)(null);
|
|
1168
|
+
const uploadedUrlRef = (0, import_react5.useRef)(null);
|
|
1169
|
+
const { media, error } = (0, import_react5.useSyncExternalStore)(
|
|
1170
|
+
mediaSelectionStore.subscribe,
|
|
1171
|
+
mediaSelectionStore.getSnapshot,
|
|
1172
|
+
mediaSelectionStore.getSnapshot
|
|
1173
|
+
);
|
|
1174
|
+
const VIDEO_EXTENSIONS = (0, import_react5.useMemo)(
|
|
1175
|
+
() => [".mp4", ".webm", ".ogg", ".ogv", ".mov", ".m4v"],
|
|
1176
|
+
[]
|
|
1177
|
+
);
|
|
1178
|
+
const setSelection = (0, import_react5.useCallback)(
|
|
1179
|
+
(next) => {
|
|
1180
|
+
mediaSelectionStore.setSnapshot(next);
|
|
1181
|
+
},
|
|
1182
|
+
[]
|
|
1183
|
+
);
|
|
1184
|
+
const handleFileChange = (event) => {
|
|
1185
|
+
const file = event.target.files?.[0];
|
|
1186
|
+
if (!file) {
|
|
1187
|
+
return;
|
|
1188
|
+
}
|
|
1189
|
+
if (uploadedUrlRef.current) {
|
|
1190
|
+
URL.revokeObjectURL(uploadedUrlRef.current);
|
|
1191
|
+
uploadedUrlRef.current = null;
|
|
1192
|
+
}
|
|
1193
|
+
const objectUrl = URL.createObjectURL(file);
|
|
1194
|
+
uploadedUrlRef.current = objectUrl;
|
|
1195
|
+
const lowerName = file.name?.toLowerCase() ?? "";
|
|
1196
|
+
const hasVideoExtension = VIDEO_EXTENSIONS.some(
|
|
1197
|
+
(ext) => lowerName.endsWith(ext)
|
|
1198
|
+
);
|
|
1199
|
+
const isVideo = file.type.startsWith("video/") || hasVideoExtension;
|
|
1200
|
+
if (isVideo) {
|
|
1201
|
+
setSelection({
|
|
1202
|
+
media: null,
|
|
1203
|
+
error: "Videos are not supported in this effect yet."
|
|
1204
|
+
});
|
|
1205
|
+
return;
|
|
1206
|
+
}
|
|
1207
|
+
const nextMedia = { src: objectUrl, type: "image" };
|
|
1208
|
+
setSelection({ media: nextMedia, error: null });
|
|
1209
|
+
onSelectMedia(nextMedia);
|
|
1210
|
+
};
|
|
1211
|
+
const handleClearSelection = () => {
|
|
1212
|
+
if (uploadedUrlRef.current) {
|
|
1213
|
+
URL.revokeObjectURL(uploadedUrlRef.current);
|
|
1214
|
+
uploadedUrlRef.current = null;
|
|
1215
|
+
}
|
|
1216
|
+
setSelection({ media: null, error: null });
|
|
1217
|
+
onClear();
|
|
1218
|
+
};
|
|
1219
|
+
const handlePresetSelect = (entry) => {
|
|
1220
|
+
if (entry.type === "video") {
|
|
1221
|
+
setSelection({
|
|
1222
|
+
media: null,
|
|
1223
|
+
error: "Videos are not supported in this effect yet."
|
|
1224
|
+
});
|
|
1225
|
+
return;
|
|
1226
|
+
}
|
|
1227
|
+
const nextMedia = { src: entry.src, type: entry.type };
|
|
1228
|
+
setSelection({ media: nextMedia, error: null });
|
|
1229
|
+
onSelectMedia(nextMedia);
|
|
1230
|
+
};
|
|
1231
|
+
(0, import_react5.useEffect)(() => {
|
|
1232
|
+
return () => {
|
|
1233
|
+
if (uploadedUrlRef.current) {
|
|
1234
|
+
URL.revokeObjectURL(uploadedUrlRef.current);
|
|
1235
|
+
uploadedUrlRef.current = null;
|
|
1236
|
+
}
|
|
1237
|
+
};
|
|
1238
|
+
}, []);
|
|
1239
|
+
const presets = (0, import_react5.useMemo)(() => {
|
|
1240
|
+
const source = presetMedia ?? DEFAULT_PRESET_MEDIA;
|
|
1241
|
+
if (typeof maxPresetCount === "number" && Number.isFinite(maxPresetCount)) {
|
|
1242
|
+
const safeCount = Math.max(0, Math.floor(maxPresetCount));
|
|
1243
|
+
return source.slice(0, safeCount);
|
|
1244
|
+
}
|
|
1245
|
+
return source;
|
|
1246
|
+
}, [presetMedia, maxPresetCount]);
|
|
1247
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
1248
|
+
"div",
|
|
1249
|
+
{
|
|
1250
|
+
style: {
|
|
1251
|
+
display: "flex",
|
|
1252
|
+
flexDirection: "column",
|
|
1253
|
+
gap: "0.5rem"
|
|
1254
|
+
},
|
|
1255
|
+
children: [
|
|
1256
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("label", { htmlFor: inputId, style: { fontSize: "0.85rem", fontWeight: 500 }, children: "Upload media" }),
|
|
1257
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1258
|
+
"input",
|
|
1259
|
+
{
|
|
1260
|
+
id: inputId,
|
|
1261
|
+
type: "file",
|
|
1262
|
+
accept: "image/*",
|
|
1263
|
+
ref: inputRef,
|
|
1264
|
+
style: { display: "none" },
|
|
1265
|
+
onChange: handleFileChange
|
|
1266
|
+
}
|
|
1267
|
+
),
|
|
1268
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
1269
|
+
"div",
|
|
1270
|
+
{
|
|
1271
|
+
style: {
|
|
1272
|
+
display: "flex",
|
|
1273
|
+
alignItems: "center",
|
|
1274
|
+
gap: "0.75rem"
|
|
1275
|
+
},
|
|
1276
|
+
children: [
|
|
1277
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1278
|
+
"button",
|
|
1279
|
+
{
|
|
1280
|
+
type: "button",
|
|
1281
|
+
onClick: () => inputRef.current?.click(),
|
|
1282
|
+
style: {
|
|
1283
|
+
padding: "0.35rem 0.75rem",
|
|
1284
|
+
borderRadius: "0.4rem",
|
|
1285
|
+
border: "1px solid rgba(255, 255, 255, 0.25)",
|
|
1286
|
+
background: "rgba(255, 255, 255, 0.08)",
|
|
1287
|
+
color: "inherit",
|
|
1288
|
+
cursor: "pointer"
|
|
1289
|
+
},
|
|
1290
|
+
children: "Choose file"
|
|
1291
|
+
}
|
|
1292
|
+
),
|
|
1293
|
+
media ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1294
|
+
"div",
|
|
1295
|
+
{
|
|
1296
|
+
style: {
|
|
1297
|
+
width: 36,
|
|
1298
|
+
height: 36,
|
|
1299
|
+
borderRadius: "0.35rem",
|
|
1300
|
+
overflow: "hidden",
|
|
1301
|
+
border: "1px solid rgba(255, 255, 255, 0.15)"
|
|
1302
|
+
},
|
|
1303
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1304
|
+
"img",
|
|
1305
|
+
{
|
|
1306
|
+
src: media.src,
|
|
1307
|
+
alt: "Thumbnail",
|
|
1308
|
+
style: {
|
|
1309
|
+
width: "100%",
|
|
1310
|
+
height: "100%",
|
|
1311
|
+
objectFit: "cover",
|
|
1312
|
+
display: "block"
|
|
1313
|
+
}
|
|
1314
|
+
}
|
|
1315
|
+
)
|
|
1316
|
+
}
|
|
1317
|
+
) : null,
|
|
1318
|
+
media ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1319
|
+
"button",
|
|
1320
|
+
{
|
|
1321
|
+
type: "button",
|
|
1322
|
+
onClick: handleClearSelection,
|
|
1323
|
+
style: {
|
|
1324
|
+
display: "flex",
|
|
1325
|
+
alignItems: "center",
|
|
1326
|
+
justifyContent: "center",
|
|
1327
|
+
padding: "0.3rem",
|
|
1328
|
+
borderRadius: "0.4rem",
|
|
1329
|
+
border: "1px solid rgba(255,255,255,0.2)",
|
|
1330
|
+
background: "transparent",
|
|
1331
|
+
color: "inherit",
|
|
1332
|
+
cursor: "pointer"
|
|
1333
|
+
},
|
|
1334
|
+
"aria-label": "Clear selection",
|
|
1335
|
+
title: "Clear selection",
|
|
1336
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react3.X, { size: 16, strokeWidth: 2 })
|
|
1337
|
+
}
|
|
1338
|
+
) : null
|
|
1339
|
+
]
|
|
1340
|
+
}
|
|
1341
|
+
),
|
|
1342
|
+
presets.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1343
|
+
"div",
|
|
1344
|
+
{
|
|
1345
|
+
style: {
|
|
1346
|
+
display: "grid",
|
|
1347
|
+
gridTemplateColumns: "repeat(2, minmax(0, 1fr))",
|
|
1348
|
+
gap: "0.5rem"
|
|
1349
|
+
},
|
|
1350
|
+
children: presets.map((entry) => {
|
|
1351
|
+
const isSelected = media?.src === entry.src && media?.type === entry.type;
|
|
1352
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
1353
|
+
"button",
|
|
1354
|
+
{
|
|
1355
|
+
type: "button",
|
|
1356
|
+
onClick: () => handlePresetSelect(entry),
|
|
1357
|
+
style: {
|
|
1358
|
+
width: "100%",
|
|
1359
|
+
borderRadius: "0.4rem",
|
|
1360
|
+
border: "1px solid rgba(255,255,255,0.25)",
|
|
1361
|
+
outline: isSelected ? "2px solid #fff" : "none",
|
|
1362
|
+
outlineOffset: 2,
|
|
1363
|
+
padding: 0,
|
|
1364
|
+
overflow: "hidden",
|
|
1365
|
+
background: "transparent",
|
|
1366
|
+
cursor: "pointer"
|
|
1367
|
+
},
|
|
1368
|
+
children: [
|
|
1369
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1370
|
+
"img",
|
|
1371
|
+
{
|
|
1372
|
+
src: entry.src,
|
|
1373
|
+
alt: entry.label,
|
|
1374
|
+
style: {
|
|
1375
|
+
width: "100%",
|
|
1376
|
+
height: 100,
|
|
1377
|
+
objectFit: "cover",
|
|
1378
|
+
display: "block"
|
|
1379
|
+
}
|
|
1380
|
+
}
|
|
1381
|
+
),
|
|
1382
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1383
|
+
"span",
|
|
1384
|
+
{
|
|
1385
|
+
style: {
|
|
1386
|
+
display: "block",
|
|
1387
|
+
padding: "0.35rem",
|
|
1388
|
+
fontSize: "0.75rem",
|
|
1389
|
+
textAlign: "left",
|
|
1390
|
+
background: "rgba(0,0,0,0.45)"
|
|
1391
|
+
},
|
|
1392
|
+
children: entry.label
|
|
1393
|
+
}
|
|
1394
|
+
)
|
|
1395
|
+
]
|
|
1396
|
+
},
|
|
1397
|
+
`${entry.src}-${entry.type}`
|
|
1398
|
+
);
|
|
1399
|
+
})
|
|
1400
|
+
}
|
|
1401
|
+
) : null,
|
|
1402
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { style: { color: "#ff9da4", fontSize: "0.8rem" }, children: error }) : null
|
|
1403
|
+
]
|
|
1404
|
+
}
|
|
1405
|
+
);
|
|
1406
|
+
}
|
|
1407
|
+
|
|
1408
|
+
// src/components/ControlPanel.tsx
|
|
1409
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
1410
|
+
var splitPropsString = (input) => {
|
|
1411
|
+
const props = [];
|
|
1412
|
+
let current = "";
|
|
1413
|
+
let curlyDepth = 0;
|
|
1414
|
+
let squareDepth = 0;
|
|
1415
|
+
let parenDepth = 0;
|
|
1416
|
+
let inSingleQuote = false;
|
|
1417
|
+
let inDoubleQuote = false;
|
|
1418
|
+
let inBacktick = false;
|
|
1419
|
+
let escapeNext = false;
|
|
1420
|
+
for (const char of input) {
|
|
1421
|
+
if (escapeNext) {
|
|
1422
|
+
current += char;
|
|
1423
|
+
escapeNext = false;
|
|
1424
|
+
continue;
|
|
1425
|
+
}
|
|
1426
|
+
if (char === "\\") {
|
|
1427
|
+
current += char;
|
|
1428
|
+
escapeNext = true;
|
|
1429
|
+
continue;
|
|
1430
|
+
}
|
|
1431
|
+
if (char === "'" && !inDoubleQuote && !inBacktick) {
|
|
1432
|
+
inSingleQuote = !inSingleQuote;
|
|
1433
|
+
current += char;
|
|
1434
|
+
continue;
|
|
1435
|
+
}
|
|
1436
|
+
if (char === '"' && !inSingleQuote && !inBacktick) {
|
|
1437
|
+
inDoubleQuote = !inDoubleQuote;
|
|
1438
|
+
current += char;
|
|
1439
|
+
continue;
|
|
1440
|
+
}
|
|
1441
|
+
if (char === "`" && !inSingleQuote && !inDoubleQuote) {
|
|
1442
|
+
inBacktick = !inBacktick;
|
|
1443
|
+
current += char;
|
|
1444
|
+
continue;
|
|
1445
|
+
}
|
|
1446
|
+
if (!inSingleQuote && !inDoubleQuote && !inBacktick) {
|
|
1447
|
+
if (char === "{") {
|
|
1448
|
+
curlyDepth += 1;
|
|
1449
|
+
} else if (char === "}") {
|
|
1450
|
+
curlyDepth = Math.max(0, curlyDepth - 1);
|
|
1451
|
+
} else if (char === "[") {
|
|
1452
|
+
squareDepth += 1;
|
|
1453
|
+
} else if (char === "]") {
|
|
1454
|
+
squareDepth = Math.max(0, squareDepth - 1);
|
|
1455
|
+
} else if (char === "(") {
|
|
1456
|
+
parenDepth += 1;
|
|
1457
|
+
} else if (char === ")") {
|
|
1458
|
+
parenDepth = Math.max(0, parenDepth - 1);
|
|
1459
|
+
}
|
|
1460
|
+
}
|
|
1461
|
+
const atTopLevel = !inSingleQuote && !inDoubleQuote && !inBacktick && curlyDepth === 0 && squareDepth === 0 && parenDepth === 0;
|
|
1462
|
+
if (atTopLevel && /\s/.test(char)) {
|
|
1463
|
+
if (current.trim()) {
|
|
1464
|
+
props.push(current.trim());
|
|
1465
|
+
}
|
|
1466
|
+
current = "";
|
|
1467
|
+
continue;
|
|
1468
|
+
}
|
|
1469
|
+
current += char;
|
|
1470
|
+
}
|
|
1471
|
+
if (current.trim()) {
|
|
1472
|
+
props.push(current.trim());
|
|
1473
|
+
}
|
|
1474
|
+
return props;
|
|
1475
|
+
};
|
|
1476
|
+
var formatJsxCodeSnippet = (input) => {
|
|
1477
|
+
const trimmed = input.trim();
|
|
1478
|
+
if (!trimmed) return "";
|
|
1479
|
+
if (trimmed.includes("\n")) {
|
|
1480
|
+
return trimmed;
|
|
1481
|
+
}
|
|
1482
|
+
if (!trimmed.startsWith("<") || !trimmed.endsWith(">")) {
|
|
1483
|
+
return trimmed;
|
|
1484
|
+
}
|
|
1485
|
+
if (!trimmed.endsWith("/>")) {
|
|
1486
|
+
return trimmed;
|
|
1487
|
+
}
|
|
1488
|
+
const inner = trimmed.slice(1, -2).trim();
|
|
1489
|
+
const firstSpaceIndex = inner.indexOf(" ");
|
|
1490
|
+
if (firstSpaceIndex === -1) {
|
|
1491
|
+
return `<${inner} />`;
|
|
1492
|
+
}
|
|
1493
|
+
const componentName = inner.slice(0, firstSpaceIndex);
|
|
1494
|
+
const propsString = inner.slice(firstSpaceIndex + 1).trim();
|
|
1495
|
+
if (!propsString) {
|
|
1496
|
+
return `<${componentName} />`;
|
|
1497
|
+
}
|
|
1498
|
+
const propsList = splitPropsString(propsString);
|
|
1499
|
+
if (propsList.length === 0) {
|
|
1500
|
+
return `<${componentName} ${propsString} />`;
|
|
1501
|
+
}
|
|
1502
|
+
const formattedProps = propsList.map((prop) => ` ${prop}`).join("\n");
|
|
1503
|
+
return `<${componentName}
|
|
1504
|
+
${formattedProps}
|
|
1505
|
+
/>`;
|
|
1506
|
+
};
|
|
1507
|
+
var isWhitespace = (char) => /\s/.test(char);
|
|
1508
|
+
var isAttrNameChar = (char) => /[A-Za-z0-9_$\-.:]/.test(char);
|
|
1509
|
+
var isAlphaStart = (char) => /[A-Za-z_$]/.test(char);
|
|
1510
|
+
var tokenizeJsx = (input) => {
|
|
1511
|
+
const tokens = [];
|
|
1512
|
+
let i = 0;
|
|
1513
|
+
while (i < input.length) {
|
|
1514
|
+
const char = input[i];
|
|
1515
|
+
if (char === "<") {
|
|
1516
|
+
tokens.push({ type: "punctuation", value: "<" });
|
|
1517
|
+
i += 1;
|
|
1518
|
+
if (input[i] === "/") {
|
|
1519
|
+
tokens.push({ type: "punctuation", value: "/" });
|
|
1520
|
+
i += 1;
|
|
1521
|
+
}
|
|
1522
|
+
const start = i;
|
|
1523
|
+
while (i < input.length && isAttrNameChar(input[i])) {
|
|
1524
|
+
i += 1;
|
|
1525
|
+
}
|
|
1526
|
+
if (i > start) {
|
|
1527
|
+
tokens.push({ type: "tag", value: input.slice(start, i) });
|
|
1528
|
+
}
|
|
1529
|
+
continue;
|
|
1530
|
+
}
|
|
1531
|
+
if (char === "/" && input[i + 1] === ">") {
|
|
1532
|
+
tokens.push({ type: "punctuation", value: "/>" });
|
|
1533
|
+
i += 2;
|
|
1534
|
+
continue;
|
|
1535
|
+
}
|
|
1536
|
+
if (char === ">") {
|
|
1537
|
+
tokens.push({ type: "punctuation", value: ">" });
|
|
1538
|
+
i += 1;
|
|
1539
|
+
continue;
|
|
1540
|
+
}
|
|
1541
|
+
if (char === "=") {
|
|
1542
|
+
tokens.push({ type: "punctuation", value: "=" });
|
|
1543
|
+
i += 1;
|
|
1544
|
+
continue;
|
|
1545
|
+
}
|
|
1546
|
+
if (char === '"' || char === "'" || char === "`") {
|
|
1547
|
+
const quote = char;
|
|
1548
|
+
let j = i + 1;
|
|
1549
|
+
let value = quote;
|
|
1550
|
+
while (j < input.length) {
|
|
1551
|
+
const current = input[j];
|
|
1552
|
+
value += current;
|
|
1553
|
+
if (current === quote && input[j - 1] !== "\\") {
|
|
1554
|
+
break;
|
|
1555
|
+
}
|
|
1556
|
+
j += 1;
|
|
1557
|
+
}
|
|
1558
|
+
tokens.push({ type: "string", value });
|
|
1559
|
+
i = j + 1;
|
|
1560
|
+
continue;
|
|
1561
|
+
}
|
|
1562
|
+
if (char === "{") {
|
|
1563
|
+
let depth = 1;
|
|
1564
|
+
let j = i + 1;
|
|
1565
|
+
while (j < input.length && depth > 0) {
|
|
1566
|
+
if (input[j] === "{") {
|
|
1567
|
+
depth += 1;
|
|
1568
|
+
} else if (input[j] === "}") {
|
|
1569
|
+
depth -= 1;
|
|
1570
|
+
}
|
|
1571
|
+
j += 1;
|
|
1572
|
+
}
|
|
1573
|
+
const expression = input.slice(i, j);
|
|
1574
|
+
tokens.push({ type: "expression", value: expression });
|
|
1575
|
+
i = j;
|
|
1576
|
+
continue;
|
|
1577
|
+
}
|
|
1578
|
+
if (isAlphaStart(char)) {
|
|
1579
|
+
const start = i;
|
|
1580
|
+
i += 1;
|
|
1581
|
+
while (i < input.length && isAttrNameChar(input[i])) {
|
|
1582
|
+
i += 1;
|
|
1583
|
+
}
|
|
1584
|
+
const word = input.slice(start, i);
|
|
1585
|
+
let k = i;
|
|
1586
|
+
while (k < input.length && isWhitespace(input[k])) {
|
|
1587
|
+
k += 1;
|
|
1588
|
+
}
|
|
1589
|
+
if (input[k] === "=") {
|
|
1590
|
+
tokens.push({ type: "attrName", value: word });
|
|
1591
|
+
} else {
|
|
1592
|
+
tokens.push({ type: "plain", value: word });
|
|
1593
|
+
}
|
|
1594
|
+
continue;
|
|
1595
|
+
}
|
|
1596
|
+
tokens.push({ type: "plain", value: char });
|
|
1597
|
+
i += 1;
|
|
1598
|
+
}
|
|
1599
|
+
return tokens;
|
|
1600
|
+
};
|
|
1601
|
+
var TOKEN_CLASS_MAP = {
|
|
1602
|
+
tag: "text-sky-300",
|
|
1603
|
+
attrName: "text-amber-200",
|
|
1604
|
+
string: "text-emerald-300",
|
|
1605
|
+
expression: "text-purple-300",
|
|
1606
|
+
punctuation: "text-stone-400"
|
|
1607
|
+
};
|
|
1608
|
+
var highlightJsx = (input) => {
|
|
1609
|
+
const tokens = tokenizeJsx(input);
|
|
1610
|
+
const nodes = [];
|
|
1611
|
+
tokens.forEach((token, index) => {
|
|
1612
|
+
if (token.type === "plain") {
|
|
1613
|
+
nodes.push(token.value);
|
|
1614
|
+
} else {
|
|
1615
|
+
nodes.push(
|
|
1616
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: TOKEN_CLASS_MAP[token.type], children: token.value }, `token-${index}`)
|
|
1617
|
+
);
|
|
1618
|
+
}
|
|
1619
|
+
});
|
|
1620
|
+
return nodes;
|
|
1621
|
+
};
|
|
1095
1622
|
var ControlPanel = () => {
|
|
1096
|
-
const [copied, setCopied] = (0,
|
|
1097
|
-
const [
|
|
1623
|
+
const [copied, setCopied] = (0, import_react6.useState)(false);
|
|
1624
|
+
const [codeCopied, setCodeCopied] = (0, import_react6.useState)(false);
|
|
1625
|
+
const [isCodeVisible, setIsCodeVisible] = (0, import_react6.useState)(false);
|
|
1626
|
+
const [folderStates, setFolderStates] = (0, import_react6.useState)({});
|
|
1627
|
+
const codeCopyTimeoutRef = (0, import_react6.useRef)(null);
|
|
1098
1628
|
const { leftPanelWidth, isDesktop, isHydrated } = useResizableLayout();
|
|
1099
1629
|
const { schema, setValue, values, componentName, config } = useControlsContext();
|
|
1630
|
+
const isControlsOnlyView = typeof window !== "undefined" && new URLSearchParams(window.location.search).get(CONTROLS_ONLY_PARAM) === "true";
|
|
1100
1631
|
const previewUrl = usePreviewUrl(values);
|
|
1101
|
-
const buildUrl = (0,
|
|
1632
|
+
const buildUrl = (0, import_react6.useCallback)(
|
|
1102
1633
|
(modifier) => {
|
|
1103
1634
|
if (!previewUrl) return "";
|
|
1104
1635
|
const [path, search = ""] = previewUrl.split("?");
|
|
@@ -1109,13 +1640,13 @@ var ControlPanel = () => {
|
|
|
1109
1640
|
},
|
|
1110
1641
|
[previewUrl]
|
|
1111
1642
|
);
|
|
1112
|
-
const presentationUrl = (0,
|
|
1643
|
+
const presentationUrl = (0, import_react6.useMemo)(() => {
|
|
1113
1644
|
if (!previewUrl) return "";
|
|
1114
1645
|
return buildUrl((params) => {
|
|
1115
1646
|
params.set(PRESENTATION_PARAM, "true");
|
|
1116
1647
|
});
|
|
1117
1648
|
}, [buildUrl, previewUrl]);
|
|
1118
|
-
const controlsOnlyUrl = (0,
|
|
1649
|
+
const controlsOnlyUrl = (0, import_react6.useMemo)(() => {
|
|
1119
1650
|
if (!previewUrl) return "";
|
|
1120
1651
|
return buildUrl((params) => {
|
|
1121
1652
|
params.delete(NO_CONTROLS_PARAM);
|
|
@@ -1123,7 +1654,7 @@ var ControlPanel = () => {
|
|
|
1123
1654
|
params.set(CONTROLS_ONLY_PARAM, "true");
|
|
1124
1655
|
});
|
|
1125
1656
|
}, [buildUrl, previewUrl]);
|
|
1126
|
-
const handlePresentationClick = (0,
|
|
1657
|
+
const handlePresentationClick = (0, import_react6.useCallback)(() => {
|
|
1127
1658
|
if (typeof window === "undefined" || !presentationUrl) return;
|
|
1128
1659
|
window.open(presentationUrl, "_blank", "noopener,noreferrer");
|
|
1129
1660
|
if (controlsOnlyUrl) {
|
|
@@ -1131,10 +1662,7 @@ var ControlPanel = () => {
|
|
|
1131
1662
|
const viewportHeight = window.innerHeight || 900;
|
|
1132
1663
|
const controlsWidth = Math.max(
|
|
1133
1664
|
320,
|
|
1134
|
-
Math.min(
|
|
1135
|
-
600,
|
|
1136
|
-
Math.round(viewportWidth * leftPanelWidth / 100)
|
|
1137
|
-
)
|
|
1665
|
+
Math.min(600, Math.round(viewportWidth * leftPanelWidth / 100))
|
|
1138
1666
|
);
|
|
1139
1667
|
const controlsHeight = Math.max(600, viewportHeight);
|
|
1140
1668
|
const controlsFeatures = [
|
|
@@ -1150,7 +1678,7 @@ var ControlPanel = () => {
|
|
|
1150
1678
|
window.open(controlsOnlyUrl, "v0-controls", controlsFeatures);
|
|
1151
1679
|
}
|
|
1152
1680
|
}, [controlsOnlyUrl, leftPanelWidth, presentationUrl]);
|
|
1153
|
-
const
|
|
1681
|
+
const jsx15 = (0, import_react6.useMemo)(() => {
|
|
1154
1682
|
if (!componentName) return "";
|
|
1155
1683
|
const props = Object.entries(values).map(([key, val]) => {
|
|
1156
1684
|
if (typeof val === "string") return `${key}="${val}"`;
|
|
@@ -1195,7 +1723,7 @@ var ControlPanel = () => {
|
|
|
1195
1723
|
const advancedConfig = config?.addAdvancedPaletteControl;
|
|
1196
1724
|
let advancedPaletteControlNode = null;
|
|
1197
1725
|
if (advancedConfig) {
|
|
1198
|
-
const advancedNode = /* @__PURE__ */ (0,
|
|
1726
|
+
const advancedNode = /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1199
1727
|
AdvancedPaletteControl_default,
|
|
1200
1728
|
{
|
|
1201
1729
|
config: advancedConfig
|
|
@@ -1221,12 +1749,52 @@ var ControlPanel = () => {
|
|
|
1221
1749
|
advancedPaletteControlNode = advancedNode;
|
|
1222
1750
|
}
|
|
1223
1751
|
}
|
|
1224
|
-
const
|
|
1225
|
-
|
|
1226
|
-
)
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1752
|
+
const mediaUploadConfig = config?.addMediaUploadControl;
|
|
1753
|
+
let mediaUploadControlNode = null;
|
|
1754
|
+
if (mediaUploadConfig) {
|
|
1755
|
+
const mediaUploadNode = /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1756
|
+
MediaUploadControl,
|
|
1757
|
+
{
|
|
1758
|
+
onSelectMedia: (media) => {
|
|
1759
|
+
mediaUploadConfig.onSelectMedia?.(media);
|
|
1760
|
+
},
|
|
1761
|
+
onClear: () => {
|
|
1762
|
+
mediaUploadConfig.onClear?.();
|
|
1763
|
+
},
|
|
1764
|
+
presetMedia: mediaUploadConfig.presetMedia,
|
|
1765
|
+
maxPresetCount: mediaUploadConfig.maxPresetCount
|
|
1766
|
+
},
|
|
1767
|
+
"mediaUploadControl"
|
|
1768
|
+
);
|
|
1769
|
+
const mediaFolder = mediaUploadConfig.folder?.trim();
|
|
1770
|
+
if (mediaFolder) {
|
|
1771
|
+
const placement = mediaUploadConfig.folderPlacement ?? "bottom";
|
|
1772
|
+
ensureFolder(mediaFolder);
|
|
1773
|
+
if (!folderControls.has(mediaFolder)) {
|
|
1774
|
+
folderControls.set(mediaFolder, []);
|
|
1775
|
+
}
|
|
1776
|
+
const existingPlacement = folderPlacement.get(mediaFolder);
|
|
1777
|
+
if (!existingPlacement || placement === "top") {
|
|
1778
|
+
folderPlacement.set(mediaFolder, placement);
|
|
1779
|
+
}
|
|
1780
|
+
if (!folderExtras.has(mediaFolder)) {
|
|
1781
|
+
folderExtras.set(mediaFolder, []);
|
|
1782
|
+
}
|
|
1783
|
+
folderExtras.get(mediaFolder).push(mediaUploadNode);
|
|
1784
|
+
} else {
|
|
1785
|
+
mediaUploadControlNode = mediaUploadNode;
|
|
1786
|
+
}
|
|
1787
|
+
}
|
|
1788
|
+
const rootButtonControls = [];
|
|
1789
|
+
const rootNormalControls = [];
|
|
1790
|
+
rootControls.forEach((entry) => {
|
|
1791
|
+
const [key, control] = entry;
|
|
1792
|
+
if (control.type === "button") {
|
|
1793
|
+
rootButtonControls.push([key, control]);
|
|
1794
|
+
} else {
|
|
1795
|
+
rootNormalControls.push(entry);
|
|
1796
|
+
}
|
|
1797
|
+
});
|
|
1230
1798
|
const folderGroups = folderOrder.map((folder) => ({
|
|
1231
1799
|
folder,
|
|
1232
1800
|
entries: folderControls.get(folder) ?? [],
|
|
@@ -1235,7 +1803,7 @@ var ControlPanel = () => {
|
|
|
1235
1803
|
})).filter((group) => group.entries.length > 0 || group.extras.length > 0);
|
|
1236
1804
|
const hasRootButtonControls = rootButtonControls.length > 0;
|
|
1237
1805
|
const hasAnyFolders = folderGroups.length > 0;
|
|
1238
|
-
const jsonToComponentString = (0,
|
|
1806
|
+
const jsonToComponentString = (0, import_react6.useCallback)(
|
|
1239
1807
|
({
|
|
1240
1808
|
componentName: componentNameOverride,
|
|
1241
1809
|
props
|
|
@@ -1266,16 +1834,75 @@ var ControlPanel = () => {
|
|
|
1266
1834
|
componentName,
|
|
1267
1835
|
values,
|
|
1268
1836
|
schema,
|
|
1269
|
-
jsx:
|
|
1837
|
+
jsx: jsx15,
|
|
1270
1838
|
jsonToComponentString
|
|
1271
|
-
}) ??
|
|
1839
|
+
}) ?? jsx15;
|
|
1272
1840
|
const shouldShowCopyButton = config?.showCopyButton !== false && Boolean(copyText);
|
|
1841
|
+
const baseSnippet = copyText || jsx15;
|
|
1842
|
+
const formattedCode = (0, import_react6.useMemo)(
|
|
1843
|
+
() => formatJsxCodeSnippet(baseSnippet),
|
|
1844
|
+
[baseSnippet]
|
|
1845
|
+
);
|
|
1846
|
+
const hasCodeSnippet = Boolean(config?.showCodeSnippet && formattedCode);
|
|
1847
|
+
const highlightedCode = (0, import_react6.useMemo)(
|
|
1848
|
+
() => formattedCode ? highlightJsx(formattedCode) : null,
|
|
1849
|
+
[formattedCode]
|
|
1850
|
+
);
|
|
1851
|
+
(0, import_react6.useEffect)(() => {
|
|
1852
|
+
if (!hasCodeSnippet) {
|
|
1853
|
+
setIsCodeVisible(false);
|
|
1854
|
+
}
|
|
1855
|
+
}, [hasCodeSnippet]);
|
|
1856
|
+
(0, import_react6.useEffect)(() => {
|
|
1857
|
+
setCodeCopied(false);
|
|
1858
|
+
if (codeCopyTimeoutRef.current) {
|
|
1859
|
+
clearTimeout(codeCopyTimeoutRef.current);
|
|
1860
|
+
codeCopyTimeoutRef.current = null;
|
|
1861
|
+
}
|
|
1862
|
+
}, [formattedCode]);
|
|
1863
|
+
(0, import_react6.useEffect)(() => {
|
|
1864
|
+
return () => {
|
|
1865
|
+
if (codeCopyTimeoutRef.current) {
|
|
1866
|
+
clearTimeout(codeCopyTimeoutRef.current);
|
|
1867
|
+
}
|
|
1868
|
+
};
|
|
1869
|
+
}, []);
|
|
1870
|
+
const handleToggleCodeVisibility = (0, import_react6.useCallback)(() => {
|
|
1871
|
+
setIsCodeVisible((prev) => {
|
|
1872
|
+
const next = !prev;
|
|
1873
|
+
if (!next) {
|
|
1874
|
+
setCodeCopied(false);
|
|
1875
|
+
if (codeCopyTimeoutRef.current) {
|
|
1876
|
+
clearTimeout(codeCopyTimeoutRef.current);
|
|
1877
|
+
codeCopyTimeoutRef.current = null;
|
|
1878
|
+
}
|
|
1879
|
+
}
|
|
1880
|
+
return next;
|
|
1881
|
+
});
|
|
1882
|
+
}, []);
|
|
1883
|
+
const handleCodeCopy = (0, import_react6.useCallback)(() => {
|
|
1884
|
+
if (!formattedCode) return;
|
|
1885
|
+
if (typeof navigator === "undefined" || !navigator.clipboard || typeof navigator.clipboard.writeText !== "function") {
|
|
1886
|
+
return;
|
|
1887
|
+
}
|
|
1888
|
+
navigator.clipboard.writeText(formattedCode).then(() => {
|
|
1889
|
+
setCodeCopied(true);
|
|
1890
|
+
if (codeCopyTimeoutRef.current) {
|
|
1891
|
+
clearTimeout(codeCopyTimeoutRef.current);
|
|
1892
|
+
}
|
|
1893
|
+
codeCopyTimeoutRef.current = setTimeout(() => {
|
|
1894
|
+
setCodeCopied(false);
|
|
1895
|
+
codeCopyTimeoutRef.current = null;
|
|
1896
|
+
}, 3e3);
|
|
1897
|
+
}).catch(() => {
|
|
1898
|
+
});
|
|
1899
|
+
}, [formattedCode]);
|
|
1273
1900
|
const labelize = (key) => key.replace(/([A-Z])/g, " $1").replace(/[\-_]/g, " ").replace(/\s+/g, " ").trim().replace(/(^|\s)\S/g, (s) => s.toUpperCase());
|
|
1274
|
-
const renderButtonControl = (key, control, variant) => /* @__PURE__ */ (0,
|
|
1901
|
+
const renderButtonControl = (key, control, variant) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1275
1902
|
"div",
|
|
1276
1903
|
{
|
|
1277
1904
|
className: variant === "root" ? "flex-1 [&_[data-slot=button]]:w-full" : "[&_[data-slot=button]]:w-full",
|
|
1278
|
-
children: control.render ? control.render() : /* @__PURE__ */ (0,
|
|
1905
|
+
children: control.render ? control.render() : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1279
1906
|
"button",
|
|
1280
1907
|
{
|
|
1281
1908
|
onClick: control.onClick,
|
|
@@ -1293,9 +1920,9 @@ var ControlPanel = () => {
|
|
|
1293
1920
|
const value = values[key];
|
|
1294
1921
|
switch (control.type) {
|
|
1295
1922
|
case "boolean":
|
|
1296
|
-
return /* @__PURE__ */ (0,
|
|
1297
|
-
/* @__PURE__ */ (0,
|
|
1298
|
-
/* @__PURE__ */ (0,
|
|
1923
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
1924
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Label, { htmlFor: key, className: "cursor-pointer", children: labelize(key) }),
|
|
1925
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1299
1926
|
Switch,
|
|
1300
1927
|
{
|
|
1301
1928
|
id: key,
|
|
@@ -1306,10 +1933,10 @@ var ControlPanel = () => {
|
|
|
1306
1933
|
)
|
|
1307
1934
|
] }, key);
|
|
1308
1935
|
case "number":
|
|
1309
|
-
return /* @__PURE__ */ (0,
|
|
1310
|
-
/* @__PURE__ */ (0,
|
|
1311
|
-
/* @__PURE__ */ (0,
|
|
1312
|
-
/* @__PURE__ */ (0,
|
|
1936
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "space-y-3 w-full", children: [
|
|
1937
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
1938
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Label, { className: "text-stone-300", htmlFor: key, children: labelize(key) }),
|
|
1939
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1313
1940
|
Input,
|
|
1314
1941
|
{
|
|
1315
1942
|
type: "number",
|
|
@@ -1326,7 +1953,7 @@ var ControlPanel = () => {
|
|
|
1326
1953
|
}
|
|
1327
1954
|
)
|
|
1328
1955
|
] }),
|
|
1329
|
-
/* @__PURE__ */ (0,
|
|
1956
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1330
1957
|
Slider,
|
|
1331
1958
|
{
|
|
1332
1959
|
id: key,
|
|
@@ -1340,9 +1967,9 @@ var ControlPanel = () => {
|
|
|
1340
1967
|
)
|
|
1341
1968
|
] }, key);
|
|
1342
1969
|
case "string":
|
|
1343
|
-
return /* @__PURE__ */ (0,
|
|
1344
|
-
/* @__PURE__ */ (0,
|
|
1345
|
-
/* @__PURE__ */ (0,
|
|
1970
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "space-y-2 w-full", children: [
|
|
1971
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Label, { className: "text-stone-300", htmlFor: key, children: labelize(key) }),
|
|
1972
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1346
1973
|
Input,
|
|
1347
1974
|
{
|
|
1348
1975
|
id: key,
|
|
@@ -1354,9 +1981,9 @@ var ControlPanel = () => {
|
|
|
1354
1981
|
)
|
|
1355
1982
|
] }, key);
|
|
1356
1983
|
case "color":
|
|
1357
|
-
return /* @__PURE__ */ (0,
|
|
1358
|
-
/* @__PURE__ */ (0,
|
|
1359
|
-
/* @__PURE__ */ (0,
|
|
1984
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "space-y-2 w-full", children: [
|
|
1985
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Label, { className: "text-stone-300", htmlFor: key, children: labelize(key) }),
|
|
1986
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1360
1987
|
"input",
|
|
1361
1988
|
{
|
|
1362
1989
|
type: "color",
|
|
@@ -1368,11 +1995,11 @@ var ControlPanel = () => {
|
|
|
1368
1995
|
)
|
|
1369
1996
|
] }, key);
|
|
1370
1997
|
case "select":
|
|
1371
|
-
return /* @__PURE__ */ (0,
|
|
1372
|
-
/* @__PURE__ */ (0,
|
|
1373
|
-
/* @__PURE__ */ (0,
|
|
1374
|
-
/* @__PURE__ */ (0,
|
|
1375
|
-
/* @__PURE__ */ (0,
|
|
1998
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "space-y-2", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex items-center gap-3", children: [
|
|
1999
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Label, { className: "min-w-fit", htmlFor: key, children: labelize(key) }),
|
|
2000
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Select, { value, onValueChange: (val) => setValue(key, val), children: [
|
|
2001
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SelectTrigger, { className: "flex-1 cursor-pointer", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SelectValue, { placeholder: "Select option" }) }),
|
|
2002
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SelectContent, { className: "cursor-pointer z-[9999]", children: Object.entries(control.options).map(([label]) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1376
2003
|
SelectItem,
|
|
1377
2004
|
{
|
|
1378
2005
|
value: label,
|
|
@@ -1389,12 +2016,12 @@ var ControlPanel = () => {
|
|
|
1389
2016
|
};
|
|
1390
2017
|
const renderFolder = (folder, entries, extras = []) => {
|
|
1391
2018
|
const isOpen = folderStates[folder] ?? true;
|
|
1392
|
-
return /* @__PURE__ */ (0,
|
|
2019
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
1393
2020
|
"div",
|
|
1394
2021
|
{
|
|
1395
2022
|
className: "border border-stone-700/60 rounded-lg bg-stone-900/70",
|
|
1396
2023
|
children: [
|
|
1397
|
-
/* @__PURE__ */ (0,
|
|
2024
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
1398
2025
|
"button",
|
|
1399
2026
|
{
|
|
1400
2027
|
type: "button",
|
|
@@ -1404,9 +2031,9 @@ var ControlPanel = () => {
|
|
|
1404
2031
|
})),
|
|
1405
2032
|
className: "w-full flex items-center justify-between px-4 py-3 text-left font-semibold text-stone-200 tracking-wide",
|
|
1406
2033
|
children: [
|
|
1407
|
-
/* @__PURE__ */ (0,
|
|
1408
|
-
/* @__PURE__ */ (0,
|
|
1409
|
-
|
|
2034
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { children: folder }),
|
|
2035
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2036
|
+
import_lucide_react4.ChevronDown,
|
|
1410
2037
|
{
|
|
1411
2038
|
className: `w-4 h-4 transition-transform duration-200 ${isOpen ? "rotate-180" : ""}`
|
|
1412
2039
|
}
|
|
@@ -1414,7 +2041,7 @@ var ControlPanel = () => {
|
|
|
1414
2041
|
]
|
|
1415
2042
|
}
|
|
1416
2043
|
),
|
|
1417
|
-
isOpen && /* @__PURE__ */ (0,
|
|
2044
|
+
isOpen && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "px-4 pb-4 pt-0 space-y-5", children: [
|
|
1418
2045
|
entries.map(
|
|
1419
2046
|
([key, control]) => renderControl(key, control, "folder")
|
|
1420
2047
|
),
|
|
@@ -1436,7 +2063,7 @@ var ControlPanel = () => {
|
|
|
1436
2063
|
height: "auto",
|
|
1437
2064
|
flex: "0 0 auto"
|
|
1438
2065
|
};
|
|
1439
|
-
if (isHydrated) {
|
|
2066
|
+
if (isHydrated && !isControlsOnlyView) {
|
|
1440
2067
|
if (isDesktop) {
|
|
1441
2068
|
Object.assign(panelStyle, {
|
|
1442
2069
|
position: "absolute",
|
|
@@ -1453,47 +2080,87 @@ var ControlPanel = () => {
|
|
|
1453
2080
|
});
|
|
1454
2081
|
}
|
|
1455
2082
|
}
|
|
1456
|
-
return /* @__PURE__ */ (0,
|
|
2083
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1457
2084
|
"div",
|
|
1458
2085
|
{
|
|
1459
2086
|
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"}`,
|
|
1460
2087
|
onPointerDown: (e) => e.stopPropagation(),
|
|
1461
2088
|
onTouchStart: (e) => e.stopPropagation(),
|
|
1462
2089
|
style: panelStyle,
|
|
1463
|
-
children: /* @__PURE__ */ (0,
|
|
1464
|
-
/* @__PURE__ */ (0,
|
|
1465
|
-
/* @__PURE__ */ (0,
|
|
2090
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("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: [
|
|
2091
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "space-y-1", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("h1", { className: "text-lg text-stone-100 font-semibold", children: config?.mainLabel ?? "Controls" }) }),
|
|
2092
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "space-y-6", children: [
|
|
1466
2093
|
topFolderSections,
|
|
1467
|
-
hasRootButtonControls && /* @__PURE__ */ (0,
|
|
2094
|
+
hasRootButtonControls && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "flex flex-wrap gap-2", children: rootButtonControls.map(
|
|
1468
2095
|
([key, control]) => renderButtonControl(key, control, "root")
|
|
1469
2096
|
) }),
|
|
1470
2097
|
advancedPaletteControlNode,
|
|
2098
|
+
mediaUploadControlNode,
|
|
1471
2099
|
rootNormalControls.map(
|
|
1472
2100
|
([key, control]) => renderControl(key, control, "root")
|
|
1473
2101
|
),
|
|
1474
2102
|
bottomFolderSections,
|
|
1475
|
-
|
|
2103
|
+
hasCodeSnippet && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "border border-stone-700/60 rounded-lg bg-stone-900/70", children: [
|
|
2104
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
2105
|
+
"button",
|
|
2106
|
+
{
|
|
2107
|
+
type: "button",
|
|
2108
|
+
onClick: handleToggleCodeVisibility,
|
|
2109
|
+
className: "w-full flex items-center justify-between px-4 py-3 text-left font-semibold text-stone-200 tracking-wide",
|
|
2110
|
+
"aria-expanded": isCodeVisible,
|
|
2111
|
+
children: [
|
|
2112
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { children: isCodeVisible ? "Hide Code" : "Show Code" }),
|
|
2113
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2114
|
+
import_lucide_react4.ChevronDown,
|
|
2115
|
+
{
|
|
2116
|
+
className: `w-4 h-4 transition-transform duration-200 ${isCodeVisible ? "rotate-180" : ""}`
|
|
2117
|
+
}
|
|
2118
|
+
)
|
|
2119
|
+
]
|
|
2120
|
+
}
|
|
2121
|
+
),
|
|
2122
|
+
isCodeVisible && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "relative border-t border-stone-700/60 bg-stone-950/60 px-4 py-4 rounded-b-lg", children: [
|
|
2123
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2124
|
+
"button",
|
|
2125
|
+
{
|
|
2126
|
+
type: "button",
|
|
2127
|
+
onClick: handleCodeCopy,
|
|
2128
|
+
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",
|
|
2129
|
+
children: codeCopied ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
|
|
2130
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react4.Check, { className: "h-3.5 w-3.5" }),
|
|
2131
|
+
"Copied"
|
|
2132
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
|
|
2133
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react4.Copy, { className: "h-3.5 w-3.5" }),
|
|
2134
|
+
"Copy"
|
|
2135
|
+
] })
|
|
2136
|
+
}
|
|
2137
|
+
),
|
|
2138
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("pre", { className: "whitespace-pre overflow-x-auto text-xs md:text-sm text-stone-200 pr-14", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("code", { className: "block text-stone-200", children: highlightedCode ?? formattedCode }) })
|
|
2139
|
+
] })
|
|
2140
|
+
] }),
|
|
2141
|
+
shouldShowCopyButton && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "flex-1 pt-4", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1476
2142
|
"button",
|
|
1477
2143
|
{
|
|
1478
2144
|
onClick: () => {
|
|
1479
|
-
|
|
1480
|
-
|
|
2145
|
+
const copyPayload = formattedCode || baseSnippet;
|
|
2146
|
+
if (!copyPayload) return;
|
|
2147
|
+
navigator.clipboard.writeText(copyPayload);
|
|
1481
2148
|
setCopied(true);
|
|
1482
2149
|
setTimeout(() => setCopied(false), 5e3);
|
|
1483
2150
|
},
|
|
1484
2151
|
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",
|
|
1485
|
-
children: copied ? /* @__PURE__ */ (0,
|
|
1486
|
-
/* @__PURE__ */ (0,
|
|
2152
|
+
children: copied ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
|
|
2153
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react4.Check, { className: "w-4 h-4" }),
|
|
1487
2154
|
"Copied"
|
|
1488
|
-
] }) : /* @__PURE__ */ (0,
|
|
1489
|
-
/* @__PURE__ */ (0,
|
|
2155
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
|
|
2156
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react4.Copy, { className: "w-4 h-4" }),
|
|
1490
2157
|
"Copy to Clipboard"
|
|
1491
2158
|
] })
|
|
1492
2159
|
}
|
|
1493
2160
|
) }, "control-panel-jsx")
|
|
1494
2161
|
] }),
|
|
1495
|
-
previewUrl && /* @__PURE__ */ (0,
|
|
1496
|
-
/* @__PURE__ */ (0,
|
|
2162
|
+
previewUrl && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex flex-col gap-2", children: [
|
|
2163
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Button, { asChild: true, className: "w-full", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
1497
2164
|
"a",
|
|
1498
2165
|
{
|
|
1499
2166
|
href: previewUrl,
|
|
@@ -1501,12 +2168,12 @@ var ControlPanel = () => {
|
|
|
1501
2168
|
rel: "noopener noreferrer",
|
|
1502
2169
|
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",
|
|
1503
2170
|
children: [
|
|
1504
|
-
/* @__PURE__ */ (0,
|
|
2171
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react4.SquareArrowOutUpRight, {}),
|
|
1505
2172
|
" Open in a New Tab"
|
|
1506
2173
|
]
|
|
1507
2174
|
}
|
|
1508
2175
|
) }),
|
|
1509
|
-
config?.showPresentationButton && presentationUrl && /* @__PURE__ */ (0,
|
|
2176
|
+
config?.showPresentationButton && presentationUrl && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
1510
2177
|
Button,
|
|
1511
2178
|
{
|
|
1512
2179
|
type: "button",
|
|
@@ -1514,7 +2181,7 @@ var ControlPanel = () => {
|
|
|
1514
2181
|
variant: "secondary",
|
|
1515
2182
|
className: "w-full bg-stone-800 text-white hover:bg-stone-700 border border-stone-700",
|
|
1516
2183
|
children: [
|
|
1517
|
-
/* @__PURE__ */ (0,
|
|
2184
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react4.Presentation, {}),
|
|
1518
2185
|
" Presentation Mode"
|
|
1519
2186
|
]
|
|
1520
2187
|
}
|
|
@@ -1526,16 +2193,16 @@ var ControlPanel = () => {
|
|
|
1526
2193
|
};
|
|
1527
2194
|
var ControlPanel_default = ControlPanel;
|
|
1528
2195
|
|
|
1529
|
-
// src/components/PreviewContainer
|
|
1530
|
-
var
|
|
2196
|
+
// src/components/PreviewContainer.tsx
|
|
2197
|
+
var import_react7 = require("react");
|
|
1531
2198
|
|
|
1532
|
-
// src/components/Grid
|
|
1533
|
-
var
|
|
2199
|
+
// src/components/Grid.tsx
|
|
2200
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
1534
2201
|
function Grid() {
|
|
1535
|
-
return /* @__PURE__ */ (0,
|
|
2202
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1536
2203
|
"div",
|
|
1537
2204
|
{
|
|
1538
|
-
className: "absolute inset-0 w-
|
|
2205
|
+
className: "absolute inset-0 w-full h-full z-[0] blur-[1px]",
|
|
1539
2206
|
style: {
|
|
1540
2207
|
backgroundImage: `
|
|
1541
2208
|
linear-gradient(to right,rgb(13, 13, 13) 1px, transparent 1px),
|
|
@@ -1549,40 +2216,40 @@ function Grid() {
|
|
|
1549
2216
|
}
|
|
1550
2217
|
var Grid_default = Grid;
|
|
1551
2218
|
|
|
1552
|
-
// src/components/PreviewContainer
|
|
1553
|
-
var
|
|
2219
|
+
// src/components/PreviewContainer.tsx
|
|
2220
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
1554
2221
|
var PreviewContainer = ({ children, hideControls }) => {
|
|
1555
2222
|
const { config } = useControlsContext();
|
|
1556
2223
|
const { leftPanelWidth, isDesktop, isHydrated, containerRef } = useResizableLayout();
|
|
1557
|
-
const previewRef = (0,
|
|
1558
|
-
return /* @__PURE__ */ (0,
|
|
2224
|
+
const previewRef = (0, import_react7.useRef)(null);
|
|
2225
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1559
2226
|
"div",
|
|
1560
2227
|
{
|
|
1561
2228
|
ref: previewRef,
|
|
1562
|
-
className: "order-1 md:order-2 flex-1 bg-black overflow-auto flex items-center justify-center relative",
|
|
2229
|
+
className: "order-1 md:order-2 flex-1 md:flex-none bg-black overflow-auto flex items-center justify-center relative",
|
|
1563
2230
|
style: isHydrated && isDesktop && !hideControls ? {
|
|
1564
2231
|
width: `${100 - leftPanelWidth}%`,
|
|
1565
2232
|
marginLeft: `${leftPanelWidth}%`
|
|
1566
2233
|
} : {},
|
|
1567
|
-
children: /* @__PURE__ */ (0,
|
|
1568
|
-
config?.showGrid && /* @__PURE__ */ (0,
|
|
1569
|
-
/* @__PURE__ */ (0,
|
|
2234
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "w-full h-screen", children: [
|
|
2235
|
+
config?.showGrid && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Grid_default, {}),
|
|
2236
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "w-full h-full flex items-center justify-center relative", children })
|
|
1570
2237
|
] })
|
|
1571
2238
|
}
|
|
1572
2239
|
);
|
|
1573
2240
|
};
|
|
1574
2241
|
var PreviewContainer_default = PreviewContainer;
|
|
1575
2242
|
|
|
1576
|
-
// src/components/Playground
|
|
1577
|
-
var
|
|
1578
|
-
var HiddenPreview = ({ children }) => /* @__PURE__ */ (0,
|
|
2243
|
+
// src/components/Playground.tsx
|
|
2244
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
2245
|
+
var HiddenPreview = ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { "aria-hidden": "true", className: "hidden", children });
|
|
1579
2246
|
function Playground({ children }) {
|
|
1580
|
-
const [isHydrated, setIsHydrated] = (0,
|
|
1581
|
-
const [copied, setCopied] = (0,
|
|
1582
|
-
(0,
|
|
2247
|
+
const [isHydrated, setIsHydrated] = (0, import_react8.useState)(false);
|
|
2248
|
+
const [copied, setCopied] = (0, import_react8.useState)(false);
|
|
2249
|
+
(0, import_react8.useEffect)(() => {
|
|
1583
2250
|
setIsHydrated(true);
|
|
1584
2251
|
}, []);
|
|
1585
|
-
const { showControls, isPresentationMode, isControlsOnly } = (0,
|
|
2252
|
+
const { showControls, isPresentationMode, isControlsOnly } = (0, import_react8.useMemo)(() => {
|
|
1586
2253
|
if (typeof window === "undefined") {
|
|
1587
2254
|
return {
|
|
1588
2255
|
showControls: true,
|
|
@@ -1609,54 +2276,54 @@ function Playground({ children }) {
|
|
|
1609
2276
|
setTimeout(() => setCopied(false), 2e3);
|
|
1610
2277
|
};
|
|
1611
2278
|
if (!isHydrated) return null;
|
|
1612
|
-
return /* @__PURE__ */ (0,
|
|
1613
|
-
shouldShowShareButton && /* @__PURE__ */ (0,
|
|
2279
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ResizableLayout, { hideControls: layoutHideControls, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(ControlsProvider, { children: [
|
|
2280
|
+
shouldShowShareButton && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
1614
2281
|
"button",
|
|
1615
2282
|
{
|
|
1616
2283
|
onClick: handleCopy,
|
|
1617
2284
|
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",
|
|
1618
2285
|
children: [
|
|
1619
|
-
copied ? /* @__PURE__ */ (0,
|
|
2286
|
+
copied ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react5.Check, { size: 16 }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react5.Copy, { size: 16 }),
|
|
1620
2287
|
copied ? "Copied!" : "Share"
|
|
1621
2288
|
]
|
|
1622
2289
|
}
|
|
1623
2290
|
),
|
|
1624
|
-
isControlsOnly ? /* @__PURE__ */ (0,
|
|
1625
|
-
showControls && /* @__PURE__ */ (0,
|
|
2291
|
+
isControlsOnly ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(HiddenPreview, { children }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(PreviewContainer_default, { hideControls: layoutHideControls, children }),
|
|
2292
|
+
showControls && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ControlPanel_default, {})
|
|
1626
2293
|
] }) });
|
|
1627
2294
|
}
|
|
1628
2295
|
|
|
1629
2296
|
// src/hooks/useAdvancedPaletteControls.ts
|
|
1630
|
-
var
|
|
2297
|
+
var import_react9 = require("react");
|
|
1631
2298
|
var cloneForCallbacks = (palette) => clonePalette(palette);
|
|
1632
2299
|
var useAdvancedPaletteControls = (options = {}) => {
|
|
1633
|
-
const resolvedDefaultPalette = (0,
|
|
2300
|
+
const resolvedDefaultPalette = (0, import_react9.useMemo)(
|
|
1634
2301
|
() => createAdvancedPalette(options.defaultPalette),
|
|
1635
2302
|
[options.defaultPalette]
|
|
1636
2303
|
);
|
|
1637
|
-
const resolvedFallbackPalette = (0,
|
|
2304
|
+
const resolvedFallbackPalette = (0, import_react9.useMemo)(
|
|
1638
2305
|
() => options.fallbackPalette ? createAdvancedPalette(options.fallbackPalette) : resolvedDefaultPalette,
|
|
1639
2306
|
[options.fallbackPalette, resolvedDefaultPalette]
|
|
1640
2307
|
);
|
|
1641
|
-
const [palette, setPaletteState] = (0,
|
|
2308
|
+
const [palette, setPaletteState] = (0, import_react9.useState)(
|
|
1642
2309
|
() => clonePalette(resolvedDefaultPalette)
|
|
1643
2310
|
);
|
|
1644
|
-
const defaultSignatureRef = (0,
|
|
2311
|
+
const defaultSignatureRef = (0, import_react9.useRef)(
|
|
1645
2312
|
createPaletteSignature(resolvedDefaultPalette)
|
|
1646
2313
|
);
|
|
1647
|
-
(0,
|
|
2314
|
+
(0, import_react9.useEffect)(() => {
|
|
1648
2315
|
const nextSignature = createPaletteSignature(resolvedDefaultPalette);
|
|
1649
2316
|
if (defaultSignatureRef.current === nextSignature) return;
|
|
1650
2317
|
defaultSignatureRef.current = nextSignature;
|
|
1651
2318
|
setPaletteState(clonePalette(resolvedDefaultPalette));
|
|
1652
2319
|
}, [resolvedDefaultPalette]);
|
|
1653
|
-
const notifyChange = (0,
|
|
2320
|
+
const notifyChange = (0, import_react9.useCallback)(
|
|
1654
2321
|
(nextPalette) => {
|
|
1655
2322
|
options.onChange?.(cloneForCallbacks(nextPalette));
|
|
1656
2323
|
},
|
|
1657
2324
|
[options.onChange]
|
|
1658
2325
|
);
|
|
1659
|
-
const setPalette = (0,
|
|
2326
|
+
const setPalette = (0, import_react9.useCallback)(
|
|
1660
2327
|
(source) => {
|
|
1661
2328
|
const nextPalette = createAdvancedPalette(
|
|
1662
2329
|
source ?? resolvedDefaultPalette
|
|
@@ -1666,7 +2333,7 @@ var useAdvancedPaletteControls = (options = {}) => {
|
|
|
1666
2333
|
},
|
|
1667
2334
|
[notifyChange, resolvedDefaultPalette]
|
|
1668
2335
|
);
|
|
1669
|
-
const updatePalette = (0,
|
|
2336
|
+
const updatePalette = (0, import_react9.useCallback)(
|
|
1670
2337
|
(updater) => {
|
|
1671
2338
|
setPaletteState((current) => {
|
|
1672
2339
|
const nextSource = updater(clonePalette(current));
|
|
@@ -1679,18 +2346,18 @@ var useAdvancedPaletteControls = (options = {}) => {
|
|
|
1679
2346
|
},
|
|
1680
2347
|
[notifyChange, resolvedDefaultPalette]
|
|
1681
2348
|
);
|
|
1682
|
-
const resetPalette = (0,
|
|
2349
|
+
const resetPalette = (0, import_react9.useCallback)(() => {
|
|
1683
2350
|
setPaletteState(clonePalette(resolvedDefaultPalette));
|
|
1684
2351
|
notifyChange(resolvedDefaultPalette);
|
|
1685
2352
|
}, [notifyChange, resolvedDefaultPalette]);
|
|
1686
|
-
const handleControlPaletteChange = (0,
|
|
2353
|
+
const handleControlPaletteChange = (0, import_react9.useCallback)(
|
|
1687
2354
|
(nextPalette) => {
|
|
1688
2355
|
setPaletteState(clonePalette(nextPalette));
|
|
1689
2356
|
notifyChange(nextPalette);
|
|
1690
2357
|
},
|
|
1691
2358
|
[notifyChange]
|
|
1692
2359
|
);
|
|
1693
|
-
const controlConfig = (0,
|
|
2360
|
+
const controlConfig = (0, import_react9.useMemo)(
|
|
1694
2361
|
() => ({
|
|
1695
2362
|
...options.control ?? {},
|
|
1696
2363
|
defaultPalette: resolvedDefaultPalette,
|
|
@@ -1698,7 +2365,7 @@ var useAdvancedPaletteControls = (options = {}) => {
|
|
|
1698
2365
|
}),
|
|
1699
2366
|
[handleControlPaletteChange, options.control, resolvedDefaultPalette]
|
|
1700
2367
|
);
|
|
1701
|
-
const hexColors = (0,
|
|
2368
|
+
const hexColors = (0, import_react9.useMemo)(
|
|
1702
2369
|
() => advancedPaletteToHexColors(palette, {
|
|
1703
2370
|
sectionOrder: options.sectionOrder,
|
|
1704
2371
|
fallbackPalette: resolvedFallbackPalette,
|
|
@@ -1711,11 +2378,11 @@ var useAdvancedPaletteControls = (options = {}) => {
|
|
|
1711
2378
|
resolvedFallbackPalette
|
|
1712
2379
|
]
|
|
1713
2380
|
);
|
|
1714
|
-
const paletteSignature = (0,
|
|
2381
|
+
const paletteSignature = (0, import_react9.useMemo)(
|
|
1715
2382
|
() => createPaletteSignature(palette),
|
|
1716
2383
|
[palette]
|
|
1717
2384
|
);
|
|
1718
|
-
const paletteGradient = (0,
|
|
2385
|
+
const paletteGradient = (0, import_react9.useMemo)(
|
|
1719
2386
|
() => computePaletteGradient(palette, options.gradientSteps),
|
|
1720
2387
|
[options.gradientSteps, palette]
|
|
1721
2388
|
);
|