@toriistudio/v0-playground 0.7.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.mjs CHANGED
@@ -1,5 +1,5 @@
1
- // src/components/Playground/Playground.tsx
2
- import { useEffect as useEffect6, useMemo as useMemo4, useState as useState5 } from "react";
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
@@ -435,17 +435,30 @@ var ControlsProvider = ({ children }) => {
435
435
  setComponentName(opts.componentName);
436
436
  }
437
437
  if (opts?.config) {
438
- const { addAdvancedPaletteControl, ...otherConfig } = opts.config;
439
- setConfig((prev) => ({
440
- ...prev,
441
- ...otherConfig,
442
- ...Object.prototype.hasOwnProperty.call(
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(
443
449
  opts.config,
444
450
  "addAdvancedPaletteControl"
445
- ) ? {
446
- addAdvancedPaletteControl: addAdvancedPaletteControl ? resolveAdvancedPaletteConfig(addAdvancedPaletteControl) : void 0
447
- } : {}
448
- }));
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
+ });
449
462
  }
450
463
  setSchema((prevSchema) => ({ ...prevSchema, ...newSchema }));
451
464
  setValues((prevValues) => {
@@ -610,7 +623,7 @@ var useControls = (schema, options) => {
610
623
  resolvedAdvancedConfig.onPaletteChange(clonePalette(palette));
611
624
  }, [ctx.values, resolvedAdvancedConfig]);
612
625
  const typedValues = ctx.values;
613
- const jsx14 = useCallback(() => {
626
+ const jsx15 = useCallback(() => {
614
627
  if (!options?.componentName) return "";
615
628
  const props = Object.entries(typedValues).map(([key, val]) => {
616
629
  if (typeof val === "string") return `${key}="${val}"`;
@@ -624,13 +637,19 @@ var useControls = (schema, options) => {
624
637
  controls: ctx.values,
625
638
  schema: ctx.schema,
626
639
  setValue: ctx.setValue,
627
- jsx: jsx14
640
+ jsx: jsx15
628
641
  };
629
642
  };
630
643
  var useUrlSyncedControls = useControls;
631
644
 
632
- // src/components/ControlPanel/ControlPanel.tsx
633
- import { useState as useState4, useMemo as useMemo3, useCallback as useCallback3, useEffect as useEffect5, useRef as useRef4 } from "react";
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";
634
653
  import {
635
654
  Check as Check2,
636
655
  Copy,
@@ -912,7 +931,7 @@ Button.displayName = "Button";
912
931
  // src/constants/layout.ts
913
932
  var MOBILE_CONTROL_PANEL_PEEK = 112;
914
933
 
915
- // src/components/AdvancedPaletteControl/AdvancedPaletteControl.tsx
934
+ // src/components/AdvancedPaletteControl.tsx
916
935
  import {
917
936
  useCallback as useCallback2,
918
937
  useEffect as useEffect4,
@@ -1065,8 +1084,316 @@ var AdvancedPaletteControl = ({
1065
1084
  };
1066
1085
  var AdvancedPaletteControl_default = AdvancedPaletteControl;
1067
1086
 
1068
- // src/components/ControlPanel/ControlPanel.tsx
1069
- import { Fragment, jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
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";
1070
1397
  var splitPropsString = (input) => {
1071
1398
  const props = [];
1072
1399
  let current = "";
@@ -1273,7 +1600,7 @@ var highlightJsx = (input) => {
1273
1600
  nodes.push(token.value);
1274
1601
  } else {
1275
1602
  nodes.push(
1276
- /* @__PURE__ */ jsx10("span", { className: TOKEN_CLASS_MAP[token.type], children: token.value }, `token-${index}`)
1603
+ /* @__PURE__ */ jsx11("span", { className: TOKEN_CLASS_MAP[token.type], children: token.value }, `token-${index}`)
1277
1604
  );
1278
1605
  }
1279
1606
  });
@@ -1284,12 +1611,12 @@ var ControlPanel = () => {
1284
1611
  const [codeCopied, setCodeCopied] = useState4(false);
1285
1612
  const [isCodeVisible, setIsCodeVisible] = useState4(false);
1286
1613
  const [folderStates, setFolderStates] = useState4({});
1287
- const codeCopyTimeoutRef = useRef4(null);
1614
+ const codeCopyTimeoutRef = useRef5(null);
1288
1615
  const { leftPanelWidth, isDesktop, isHydrated } = useResizableLayout();
1289
1616
  const { schema, setValue, values, componentName, config } = useControlsContext();
1290
1617
  const isControlsOnlyView = typeof window !== "undefined" && new URLSearchParams(window.location.search).get(CONTROLS_ONLY_PARAM) === "true";
1291
1618
  const previewUrl = usePreviewUrl(values);
1292
- const buildUrl = useCallback3(
1619
+ const buildUrl = useCallback4(
1293
1620
  (modifier) => {
1294
1621
  if (!previewUrl) return "";
1295
1622
  const [path, search = ""] = previewUrl.split("?");
@@ -1300,13 +1627,13 @@ var ControlPanel = () => {
1300
1627
  },
1301
1628
  [previewUrl]
1302
1629
  );
1303
- const presentationUrl = useMemo3(() => {
1630
+ const presentationUrl = useMemo4(() => {
1304
1631
  if (!previewUrl) return "";
1305
1632
  return buildUrl((params) => {
1306
1633
  params.set(PRESENTATION_PARAM, "true");
1307
1634
  });
1308
1635
  }, [buildUrl, previewUrl]);
1309
- const controlsOnlyUrl = useMemo3(() => {
1636
+ const controlsOnlyUrl = useMemo4(() => {
1310
1637
  if (!previewUrl) return "";
1311
1638
  return buildUrl((params) => {
1312
1639
  params.delete(NO_CONTROLS_PARAM);
@@ -1314,7 +1641,7 @@ var ControlPanel = () => {
1314
1641
  params.set(CONTROLS_ONLY_PARAM, "true");
1315
1642
  });
1316
1643
  }, [buildUrl, previewUrl]);
1317
- const handlePresentationClick = useCallback3(() => {
1644
+ const handlePresentationClick = useCallback4(() => {
1318
1645
  if (typeof window === "undefined" || !presentationUrl) return;
1319
1646
  window.open(presentationUrl, "_blank", "noopener,noreferrer");
1320
1647
  if (controlsOnlyUrl) {
@@ -1322,10 +1649,7 @@ var ControlPanel = () => {
1322
1649
  const viewportHeight = window.innerHeight || 900;
1323
1650
  const controlsWidth = Math.max(
1324
1651
  320,
1325
- Math.min(
1326
- 600,
1327
- Math.round(viewportWidth * leftPanelWidth / 100)
1328
- )
1652
+ Math.min(600, Math.round(viewportWidth * leftPanelWidth / 100))
1329
1653
  );
1330
1654
  const controlsHeight = Math.max(600, viewportHeight);
1331
1655
  const controlsFeatures = [
@@ -1341,7 +1665,7 @@ var ControlPanel = () => {
1341
1665
  window.open(controlsOnlyUrl, "v0-controls", controlsFeatures);
1342
1666
  }
1343
1667
  }, [controlsOnlyUrl, leftPanelWidth, presentationUrl]);
1344
- const jsx14 = useMemo3(() => {
1668
+ const jsx15 = useMemo4(() => {
1345
1669
  if (!componentName) return "";
1346
1670
  const props = Object.entries(values).map(([key, val]) => {
1347
1671
  if (typeof val === "string") return `${key}="${val}"`;
@@ -1386,7 +1710,7 @@ var ControlPanel = () => {
1386
1710
  const advancedConfig = config?.addAdvancedPaletteControl;
1387
1711
  let advancedPaletteControlNode = null;
1388
1712
  if (advancedConfig) {
1389
- const advancedNode = /* @__PURE__ */ jsx10(
1713
+ const advancedNode = /* @__PURE__ */ jsx11(
1390
1714
  AdvancedPaletteControl_default,
1391
1715
  {
1392
1716
  config: advancedConfig
@@ -1412,12 +1736,52 @@ var ControlPanel = () => {
1412
1736
  advancedPaletteControlNode = advancedNode;
1413
1737
  }
1414
1738
  }
1415
- const rootButtonControls = rootControls.filter(
1416
- ([, control]) => control.type === "button"
1417
- );
1418
- const rootNormalControls = rootControls.filter(
1419
- ([, control]) => control.type !== "button"
1420
- );
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
+ });
1421
1785
  const folderGroups = folderOrder.map((folder) => ({
1422
1786
  folder,
1423
1787
  entries: folderControls.get(folder) ?? [],
@@ -1426,7 +1790,7 @@ var ControlPanel = () => {
1426
1790
  })).filter((group) => group.entries.length > 0 || group.extras.length > 0);
1427
1791
  const hasRootButtonControls = rootButtonControls.length > 0;
1428
1792
  const hasAnyFolders = folderGroups.length > 0;
1429
- const jsonToComponentString = useCallback3(
1793
+ const jsonToComponentString = useCallback4(
1430
1794
  ({
1431
1795
  componentName: componentNameOverride,
1432
1796
  props
@@ -1457,40 +1821,40 @@ var ControlPanel = () => {
1457
1821
  componentName,
1458
1822
  values,
1459
1823
  schema,
1460
- jsx: jsx14,
1824
+ jsx: jsx15,
1461
1825
  jsonToComponentString
1462
- }) ?? jsx14;
1826
+ }) ?? jsx15;
1463
1827
  const shouldShowCopyButton = config?.showCopyButton !== false && Boolean(copyText);
1464
- const baseSnippet = copyText || jsx14;
1465
- const formattedCode = useMemo3(
1828
+ const baseSnippet = copyText || jsx15;
1829
+ const formattedCode = useMemo4(
1466
1830
  () => formatJsxCodeSnippet(baseSnippet),
1467
1831
  [baseSnippet]
1468
1832
  );
1469
1833
  const hasCodeSnippet = Boolean(config?.showCodeSnippet && formattedCode);
1470
- const highlightedCode = useMemo3(
1834
+ const highlightedCode = useMemo4(
1471
1835
  () => formattedCode ? highlightJsx(formattedCode) : null,
1472
1836
  [formattedCode]
1473
1837
  );
1474
- useEffect5(() => {
1838
+ useEffect6(() => {
1475
1839
  if (!hasCodeSnippet) {
1476
1840
  setIsCodeVisible(false);
1477
1841
  }
1478
1842
  }, [hasCodeSnippet]);
1479
- useEffect5(() => {
1843
+ useEffect6(() => {
1480
1844
  setCodeCopied(false);
1481
1845
  if (codeCopyTimeoutRef.current) {
1482
1846
  clearTimeout(codeCopyTimeoutRef.current);
1483
1847
  codeCopyTimeoutRef.current = null;
1484
1848
  }
1485
1849
  }, [formattedCode]);
1486
- useEffect5(() => {
1850
+ useEffect6(() => {
1487
1851
  return () => {
1488
1852
  if (codeCopyTimeoutRef.current) {
1489
1853
  clearTimeout(codeCopyTimeoutRef.current);
1490
1854
  }
1491
1855
  };
1492
1856
  }, []);
1493
- const handleToggleCodeVisibility = useCallback3(() => {
1857
+ const handleToggleCodeVisibility = useCallback4(() => {
1494
1858
  setIsCodeVisible((prev) => {
1495
1859
  const next = !prev;
1496
1860
  if (!next) {
@@ -1503,7 +1867,7 @@ var ControlPanel = () => {
1503
1867
  return next;
1504
1868
  });
1505
1869
  }, []);
1506
- const handleCodeCopy = useCallback3(() => {
1870
+ const handleCodeCopy = useCallback4(() => {
1507
1871
  if (!formattedCode) return;
1508
1872
  if (typeof navigator === "undefined" || !navigator.clipboard || typeof navigator.clipboard.writeText !== "function") {
1509
1873
  return;
@@ -1521,11 +1885,11 @@ var ControlPanel = () => {
1521
1885
  });
1522
1886
  }, [formattedCode]);
1523
1887
  const labelize = (key) => key.replace(/([A-Z])/g, " $1").replace(/[\-_]/g, " ").replace(/\s+/g, " ").trim().replace(/(^|\s)\S/g, (s) => s.toUpperCase());
1524
- const renderButtonControl = (key, control, variant) => /* @__PURE__ */ jsx10(
1888
+ const renderButtonControl = (key, control, variant) => /* @__PURE__ */ jsx11(
1525
1889
  "div",
1526
1890
  {
1527
1891
  className: variant === "root" ? "flex-1 [&_[data-slot=button]]:w-full" : "[&_[data-slot=button]]:w-full",
1528
- children: control.render ? control.render() : /* @__PURE__ */ jsx10(
1892
+ children: control.render ? control.render() : /* @__PURE__ */ jsx11(
1529
1893
  "button",
1530
1894
  {
1531
1895
  onClick: control.onClick,
@@ -1543,9 +1907,9 @@ var ControlPanel = () => {
1543
1907
  const value = values[key];
1544
1908
  switch (control.type) {
1545
1909
  case "boolean":
1546
- return /* @__PURE__ */ jsxs5("div", { className: "flex items-center justify-between", children: [
1547
- /* @__PURE__ */ jsx10(Label, { htmlFor: key, className: "cursor-pointer", children: labelize(key) }),
1548
- /* @__PURE__ */ jsx10(
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(
1549
1913
  Switch,
1550
1914
  {
1551
1915
  id: key,
@@ -1556,10 +1920,10 @@ var ControlPanel = () => {
1556
1920
  )
1557
1921
  ] }, key);
1558
1922
  case "number":
1559
- return /* @__PURE__ */ jsxs5("div", { className: "space-y-3 w-full", children: [
1560
- /* @__PURE__ */ jsxs5("div", { className: "flex items-center justify-between", children: [
1561
- /* @__PURE__ */ jsx10(Label, { className: "text-stone-300", htmlFor: key, children: labelize(key) }),
1562
- /* @__PURE__ */ jsx10(
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(
1563
1927
  Input,
1564
1928
  {
1565
1929
  type: "number",
@@ -1576,7 +1940,7 @@ var ControlPanel = () => {
1576
1940
  }
1577
1941
  )
1578
1942
  ] }),
1579
- /* @__PURE__ */ jsx10(
1943
+ /* @__PURE__ */ jsx11(
1580
1944
  Slider,
1581
1945
  {
1582
1946
  id: key,
@@ -1590,9 +1954,9 @@ var ControlPanel = () => {
1590
1954
  )
1591
1955
  ] }, key);
1592
1956
  case "string":
1593
- return /* @__PURE__ */ jsxs5("div", { className: "space-y-2 w-full", children: [
1594
- /* @__PURE__ */ jsx10(Label, { className: "text-stone-300", htmlFor: key, children: labelize(key) }),
1595
- /* @__PURE__ */ jsx10(
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(
1596
1960
  Input,
1597
1961
  {
1598
1962
  id: key,
@@ -1604,9 +1968,9 @@ var ControlPanel = () => {
1604
1968
  )
1605
1969
  ] }, key);
1606
1970
  case "color":
1607
- return /* @__PURE__ */ jsxs5("div", { className: "space-y-2 w-full", children: [
1608
- /* @__PURE__ */ jsx10(Label, { className: "text-stone-300", htmlFor: key, children: labelize(key) }),
1609
- /* @__PURE__ */ jsx10(
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(
1610
1974
  "input",
1611
1975
  {
1612
1976
  type: "color",
@@ -1618,11 +1982,11 @@ var ControlPanel = () => {
1618
1982
  )
1619
1983
  ] }, key);
1620
1984
  case "select":
1621
- return /* @__PURE__ */ jsx10("div", { className: "space-y-2", children: /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-3", children: [
1622
- /* @__PURE__ */ jsx10(Label, { className: "min-w-fit", htmlFor: key, children: labelize(key) }),
1623
- /* @__PURE__ */ jsxs5(Select, { value, onValueChange: (val) => setValue(key, val), children: [
1624
- /* @__PURE__ */ jsx10(SelectTrigger, { className: "flex-1 cursor-pointer", children: /* @__PURE__ */ jsx10(SelectValue, { placeholder: "Select option" }) }),
1625
- /* @__PURE__ */ jsx10(SelectContent, { className: "cursor-pointer z-[9999]", children: Object.entries(control.options).map(([label]) => /* @__PURE__ */ jsx10(
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(
1626
1990
  SelectItem,
1627
1991
  {
1628
1992
  value: label,
@@ -1639,12 +2003,12 @@ var ControlPanel = () => {
1639
2003
  };
1640
2004
  const renderFolder = (folder, entries, extras = []) => {
1641
2005
  const isOpen = folderStates[folder] ?? true;
1642
- return /* @__PURE__ */ jsxs5(
2006
+ return /* @__PURE__ */ jsxs6(
1643
2007
  "div",
1644
2008
  {
1645
2009
  className: "border border-stone-700/60 rounded-lg bg-stone-900/70",
1646
2010
  children: [
1647
- /* @__PURE__ */ jsxs5(
2011
+ /* @__PURE__ */ jsxs6(
1648
2012
  "button",
1649
2013
  {
1650
2014
  type: "button",
@@ -1654,8 +2018,8 @@ var ControlPanel = () => {
1654
2018
  })),
1655
2019
  className: "w-full flex items-center justify-between px-4 py-3 text-left font-semibold text-stone-200 tracking-wide",
1656
2020
  children: [
1657
- /* @__PURE__ */ jsx10("span", { children: folder }),
1658
- /* @__PURE__ */ jsx10(
2021
+ /* @__PURE__ */ jsx11("span", { children: folder }),
2022
+ /* @__PURE__ */ jsx11(
1659
2023
  ChevronDown2,
1660
2024
  {
1661
2025
  className: `w-4 h-4 transition-transform duration-200 ${isOpen ? "rotate-180" : ""}`
@@ -1664,7 +2028,7 @@ var ControlPanel = () => {
1664
2028
  ]
1665
2029
  }
1666
2030
  ),
1667
- isOpen && /* @__PURE__ */ jsxs5("div", { className: "px-4 pb-4 pt-0 space-y-5", children: [
2031
+ isOpen && /* @__PURE__ */ jsxs6("div", { className: "px-4 pb-4 pt-0 space-y-5", children: [
1668
2032
  entries.map(
1669
2033
  ([key, control]) => renderControl(key, control, "folder")
1670
2034
  ),
@@ -1703,27 +2067,28 @@ var ControlPanel = () => {
1703
2067
  });
1704
2068
  }
1705
2069
  }
1706
- return /* @__PURE__ */ jsx10(
2070
+ return /* @__PURE__ */ jsx11(
1707
2071
  "div",
1708
2072
  {
1709
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"}`,
1710
2074
  onPointerDown: (e) => e.stopPropagation(),
1711
2075
  onTouchStart: (e) => e.stopPropagation(),
1712
2076
  style: panelStyle,
1713
- children: /* @__PURE__ */ jsxs5("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: [
1714
- /* @__PURE__ */ jsx10("div", { className: "space-y-1", children: /* @__PURE__ */ jsx10("h1", { className: "text-lg text-stone-100 font-semibold", children: config?.mainLabel ?? "Controls" }) }),
1715
- /* @__PURE__ */ jsxs5("div", { className: "space-y-6", children: [
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: [
1716
2080
  topFolderSections,
1717
- hasRootButtonControls && /* @__PURE__ */ jsx10("div", { className: "flex flex-wrap gap-2", children: rootButtonControls.map(
2081
+ hasRootButtonControls && /* @__PURE__ */ jsx11("div", { className: "flex flex-wrap gap-2", children: rootButtonControls.map(
1718
2082
  ([key, control]) => renderButtonControl(key, control, "root")
1719
2083
  ) }),
1720
2084
  advancedPaletteControlNode,
2085
+ mediaUploadControlNode,
1721
2086
  rootNormalControls.map(
1722
2087
  ([key, control]) => renderControl(key, control, "root")
1723
2088
  ),
1724
2089
  bottomFolderSections,
1725
- hasCodeSnippet && /* @__PURE__ */ jsxs5("div", { className: "border border-stone-700/60 rounded-lg bg-stone-900/70", children: [
1726
- /* @__PURE__ */ jsxs5(
2090
+ hasCodeSnippet && /* @__PURE__ */ jsxs6("div", { className: "border border-stone-700/60 rounded-lg bg-stone-900/70", children: [
2091
+ /* @__PURE__ */ jsxs6(
1727
2092
  "button",
1728
2093
  {
1729
2094
  type: "button",
@@ -1731,8 +2096,8 @@ var ControlPanel = () => {
1731
2096
  className: "w-full flex items-center justify-between px-4 py-3 text-left font-semibold text-stone-200 tracking-wide",
1732
2097
  "aria-expanded": isCodeVisible,
1733
2098
  children: [
1734
- /* @__PURE__ */ jsx10("span", { children: isCodeVisible ? "Hide Code" : "Show Code" }),
1735
- /* @__PURE__ */ jsx10(
2099
+ /* @__PURE__ */ jsx11("span", { children: isCodeVisible ? "Hide Code" : "Show Code" }),
2100
+ /* @__PURE__ */ jsx11(
1736
2101
  ChevronDown2,
1737
2102
  {
1738
2103
  className: `w-4 h-4 transition-transform duration-200 ${isCodeVisible ? "rotate-180" : ""}`
@@ -1741,26 +2106,26 @@ var ControlPanel = () => {
1741
2106
  ]
1742
2107
  }
1743
2108
  ),
1744
- isCodeVisible && /* @__PURE__ */ jsxs5("div", { className: "relative border-t border-stone-700/60 bg-stone-950/60 px-4 py-4 rounded-b-lg", children: [
1745
- /* @__PURE__ */ jsx10(
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(
1746
2111
  "button",
1747
2112
  {
1748
2113
  type: "button",
1749
2114
  onClick: handleCodeCopy,
1750
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",
1751
- children: codeCopied ? /* @__PURE__ */ jsxs5(Fragment, { children: [
1752
- /* @__PURE__ */ jsx10(Check2, { className: "h-3.5 w-3.5" }),
2116
+ children: codeCopied ? /* @__PURE__ */ jsxs6(Fragment, { children: [
2117
+ /* @__PURE__ */ jsx11(Check2, { className: "h-3.5 w-3.5" }),
1753
2118
  "Copied"
1754
- ] }) : /* @__PURE__ */ jsxs5(Fragment, { children: [
1755
- /* @__PURE__ */ jsx10(Copy, { className: "h-3.5 w-3.5" }),
2119
+ ] }) : /* @__PURE__ */ jsxs6(Fragment, { children: [
2120
+ /* @__PURE__ */ jsx11(Copy, { className: "h-3.5 w-3.5" }),
1756
2121
  "Copy"
1757
2122
  ] })
1758
2123
  }
1759
2124
  ),
1760
- /* @__PURE__ */ jsx10("pre", { className: "whitespace-pre overflow-x-auto text-xs md:text-sm text-stone-200 pr-14", children: /* @__PURE__ */ jsx10("code", { className: "block text-stone-200", children: highlightedCode ?? formattedCode }) })
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 }) })
1761
2126
  ] })
1762
2127
  ] }),
1763
- shouldShowCopyButton && /* @__PURE__ */ jsx10("div", { className: "flex-1 pt-4", children: /* @__PURE__ */ jsx10(
2128
+ shouldShowCopyButton && /* @__PURE__ */ jsx11("div", { className: "flex-1 pt-4", children: /* @__PURE__ */ jsx11(
1764
2129
  "button",
1765
2130
  {
1766
2131
  onClick: () => {
@@ -1771,18 +2136,18 @@ var ControlPanel = () => {
1771
2136
  setTimeout(() => setCopied(false), 5e3);
1772
2137
  },
1773
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",
1774
- children: copied ? /* @__PURE__ */ jsxs5(Fragment, { children: [
1775
- /* @__PURE__ */ jsx10(Check2, { className: "w-4 h-4" }),
2139
+ children: copied ? /* @__PURE__ */ jsxs6(Fragment, { children: [
2140
+ /* @__PURE__ */ jsx11(Check2, { className: "w-4 h-4" }),
1776
2141
  "Copied"
1777
- ] }) : /* @__PURE__ */ jsxs5(Fragment, { children: [
1778
- /* @__PURE__ */ jsx10(Copy, { className: "w-4 h-4" }),
2142
+ ] }) : /* @__PURE__ */ jsxs6(Fragment, { children: [
2143
+ /* @__PURE__ */ jsx11(Copy, { className: "w-4 h-4" }),
1779
2144
  "Copy to Clipboard"
1780
2145
  ] })
1781
2146
  }
1782
2147
  ) }, "control-panel-jsx")
1783
2148
  ] }),
1784
- previewUrl && /* @__PURE__ */ jsxs5("div", { className: "flex flex-col gap-2", children: [
1785
- /* @__PURE__ */ jsx10(Button, { asChild: true, className: "w-full", children: /* @__PURE__ */ jsxs5(
2149
+ previewUrl && /* @__PURE__ */ jsxs6("div", { className: "flex flex-col gap-2", children: [
2150
+ /* @__PURE__ */ jsx11(Button, { asChild: true, className: "w-full", children: /* @__PURE__ */ jsxs6(
1786
2151
  "a",
1787
2152
  {
1788
2153
  href: previewUrl,
@@ -1790,12 +2155,12 @@ var ControlPanel = () => {
1790
2155
  rel: "noopener noreferrer",
1791
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",
1792
2157
  children: [
1793
- /* @__PURE__ */ jsx10(SquareArrowOutUpRight, {}),
2158
+ /* @__PURE__ */ jsx11(SquareArrowOutUpRight, {}),
1794
2159
  " Open in a New Tab"
1795
2160
  ]
1796
2161
  }
1797
2162
  ) }),
1798
- config?.showPresentationButton && presentationUrl && /* @__PURE__ */ jsxs5(
2163
+ config?.showPresentationButton && presentationUrl && /* @__PURE__ */ jsxs6(
1799
2164
  Button,
1800
2165
  {
1801
2166
  type: "button",
@@ -1803,7 +2168,7 @@ var ControlPanel = () => {
1803
2168
  variant: "secondary",
1804
2169
  className: "w-full bg-stone-800 text-white hover:bg-stone-700 border border-stone-700",
1805
2170
  children: [
1806
- /* @__PURE__ */ jsx10(Presentation, {}),
2171
+ /* @__PURE__ */ jsx11(Presentation, {}),
1807
2172
  " Presentation Mode"
1808
2173
  ]
1809
2174
  }
@@ -1815,16 +2180,16 @@ var ControlPanel = () => {
1815
2180
  };
1816
2181
  var ControlPanel_default = ControlPanel;
1817
2182
 
1818
- // src/components/PreviewContainer/PreviewContainer.tsx
1819
- import { useRef as useRef5 } from "react";
2183
+ // src/components/PreviewContainer.tsx
2184
+ import { useRef as useRef6 } from "react";
1820
2185
 
1821
- // src/components/Grid/Grid.tsx
1822
- import { jsx as jsx11 } from "react/jsx-runtime";
2186
+ // src/components/Grid.tsx
2187
+ import { jsx as jsx12 } from "react/jsx-runtime";
1823
2188
  function Grid() {
1824
- return /* @__PURE__ */ jsx11(
2189
+ return /* @__PURE__ */ jsx12(
1825
2190
  "div",
1826
2191
  {
1827
- className: "absolute inset-0 w-screen h-screen z-[0] blur-[1px]",
2192
+ className: "absolute inset-0 w-full h-full z-[0] blur-[1px]",
1828
2193
  style: {
1829
2194
  backgroundImage: `
1830
2195
  linear-gradient(to right,rgb(13, 13, 13) 1px, transparent 1px),
@@ -1838,40 +2203,40 @@ function Grid() {
1838
2203
  }
1839
2204
  var Grid_default = Grid;
1840
2205
 
1841
- // src/components/PreviewContainer/PreviewContainer.tsx
1842
- import { jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
2206
+ // src/components/PreviewContainer.tsx
2207
+ import { jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
1843
2208
  var PreviewContainer = ({ children, hideControls }) => {
1844
2209
  const { config } = useControlsContext();
1845
2210
  const { leftPanelWidth, isDesktop, isHydrated, containerRef } = useResizableLayout();
1846
- const previewRef = useRef5(null);
1847
- return /* @__PURE__ */ jsx12(
2211
+ const previewRef = useRef6(null);
2212
+ return /* @__PURE__ */ jsx13(
1848
2213
  "div",
1849
2214
  {
1850
2215
  ref: previewRef,
1851
- 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",
1852
2217
  style: isHydrated && isDesktop && !hideControls ? {
1853
2218
  width: `${100 - leftPanelWidth}%`,
1854
2219
  marginLeft: `${leftPanelWidth}%`
1855
2220
  } : {},
1856
- children: /* @__PURE__ */ jsxs6("div", { className: "w-screen h-screen", children: [
1857
- config?.showGrid && /* @__PURE__ */ jsx12(Grid_default, {}),
1858
- /* @__PURE__ */ jsx12("div", { className: "w-screen h-screen flex items-center justify-center relative", children })
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 })
1859
2224
  ] })
1860
2225
  }
1861
2226
  );
1862
2227
  };
1863
2228
  var PreviewContainer_default = PreviewContainer;
1864
2229
 
1865
- // src/components/Playground/Playground.tsx
1866
- import { jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
1867
- var HiddenPreview = ({ children }) => /* @__PURE__ */ jsx13("div", { "aria-hidden": "true", className: "hidden", children });
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 });
1868
2233
  function Playground({ children }) {
1869
2234
  const [isHydrated, setIsHydrated] = useState5(false);
1870
2235
  const [copied, setCopied] = useState5(false);
1871
- useEffect6(() => {
2236
+ useEffect7(() => {
1872
2237
  setIsHydrated(true);
1873
2238
  }, []);
1874
- const { showControls, isPresentationMode, isControlsOnly } = useMemo4(() => {
2239
+ const { showControls, isPresentationMode, isControlsOnly } = useMemo5(() => {
1875
2240
  if (typeof window === "undefined") {
1876
2241
  return {
1877
2242
  showControls: true,
@@ -1898,54 +2263,54 @@ function Playground({ children }) {
1898
2263
  setTimeout(() => setCopied(false), 2e3);
1899
2264
  };
1900
2265
  if (!isHydrated) return null;
1901
- return /* @__PURE__ */ jsx13(ResizableLayout, { hideControls: layoutHideControls, children: /* @__PURE__ */ jsxs7(ControlsProvider, { children: [
1902
- shouldShowShareButton && /* @__PURE__ */ jsxs7(
2266
+ return /* @__PURE__ */ jsx14(ResizableLayout, { hideControls: layoutHideControls, children: /* @__PURE__ */ jsxs8(ControlsProvider, { children: [
2267
+ shouldShowShareButton && /* @__PURE__ */ jsxs8(
1903
2268
  "button",
1904
2269
  {
1905
2270
  onClick: handleCopy,
1906
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",
1907
2272
  children: [
1908
- copied ? /* @__PURE__ */ jsx13(Check3, { size: 16 }) : /* @__PURE__ */ jsx13(Copy2, { size: 16 }),
2273
+ copied ? /* @__PURE__ */ jsx14(Check3, { size: 16 }) : /* @__PURE__ */ jsx14(Copy2, { size: 16 }),
1909
2274
  copied ? "Copied!" : "Share"
1910
2275
  ]
1911
2276
  }
1912
2277
  ),
1913
- isControlsOnly ? /* @__PURE__ */ jsx13(HiddenPreview, { children }) : /* @__PURE__ */ jsx13(PreviewContainer_default, { hideControls: layoutHideControls, children }),
1914
- showControls && /* @__PURE__ */ jsx13(ControlPanel_default, {})
2278
+ isControlsOnly ? /* @__PURE__ */ jsx14(HiddenPreview, { children }) : /* @__PURE__ */ jsx14(PreviewContainer_default, { hideControls: layoutHideControls, children }),
2279
+ showControls && /* @__PURE__ */ jsx14(ControlPanel_default, {})
1915
2280
  ] }) });
1916
2281
  }
1917
2282
 
1918
2283
  // src/hooks/useAdvancedPaletteControls.ts
1919
- import { useCallback as useCallback4, useEffect as useEffect7, useMemo as useMemo5, useRef as useRef6, useState as useState6 } from "react";
2284
+ import { useCallback as useCallback5, useEffect as useEffect8, useMemo as useMemo6, useRef as useRef7, useState as useState6 } from "react";
1920
2285
  var cloneForCallbacks = (palette) => clonePalette(palette);
1921
2286
  var useAdvancedPaletteControls = (options = {}) => {
1922
- const resolvedDefaultPalette = useMemo5(
2287
+ const resolvedDefaultPalette = useMemo6(
1923
2288
  () => createAdvancedPalette(options.defaultPalette),
1924
2289
  [options.defaultPalette]
1925
2290
  );
1926
- const resolvedFallbackPalette = useMemo5(
2291
+ const resolvedFallbackPalette = useMemo6(
1927
2292
  () => options.fallbackPalette ? createAdvancedPalette(options.fallbackPalette) : resolvedDefaultPalette,
1928
2293
  [options.fallbackPalette, resolvedDefaultPalette]
1929
2294
  );
1930
2295
  const [palette, setPaletteState] = useState6(
1931
2296
  () => clonePalette(resolvedDefaultPalette)
1932
2297
  );
1933
- const defaultSignatureRef = useRef6(
2298
+ const defaultSignatureRef = useRef7(
1934
2299
  createPaletteSignature(resolvedDefaultPalette)
1935
2300
  );
1936
- useEffect7(() => {
2301
+ useEffect8(() => {
1937
2302
  const nextSignature = createPaletteSignature(resolvedDefaultPalette);
1938
2303
  if (defaultSignatureRef.current === nextSignature) return;
1939
2304
  defaultSignatureRef.current = nextSignature;
1940
2305
  setPaletteState(clonePalette(resolvedDefaultPalette));
1941
2306
  }, [resolvedDefaultPalette]);
1942
- const notifyChange = useCallback4(
2307
+ const notifyChange = useCallback5(
1943
2308
  (nextPalette) => {
1944
2309
  options.onChange?.(cloneForCallbacks(nextPalette));
1945
2310
  },
1946
2311
  [options.onChange]
1947
2312
  );
1948
- const setPalette = useCallback4(
2313
+ const setPalette = useCallback5(
1949
2314
  (source) => {
1950
2315
  const nextPalette = createAdvancedPalette(
1951
2316
  source ?? resolvedDefaultPalette
@@ -1955,7 +2320,7 @@ var useAdvancedPaletteControls = (options = {}) => {
1955
2320
  },
1956
2321
  [notifyChange, resolvedDefaultPalette]
1957
2322
  );
1958
- const updatePalette = useCallback4(
2323
+ const updatePalette = useCallback5(
1959
2324
  (updater) => {
1960
2325
  setPaletteState((current) => {
1961
2326
  const nextSource = updater(clonePalette(current));
@@ -1968,18 +2333,18 @@ var useAdvancedPaletteControls = (options = {}) => {
1968
2333
  },
1969
2334
  [notifyChange, resolvedDefaultPalette]
1970
2335
  );
1971
- const resetPalette = useCallback4(() => {
2336
+ const resetPalette = useCallback5(() => {
1972
2337
  setPaletteState(clonePalette(resolvedDefaultPalette));
1973
2338
  notifyChange(resolvedDefaultPalette);
1974
2339
  }, [notifyChange, resolvedDefaultPalette]);
1975
- const handleControlPaletteChange = useCallback4(
2340
+ const handleControlPaletteChange = useCallback5(
1976
2341
  (nextPalette) => {
1977
2342
  setPaletteState(clonePalette(nextPalette));
1978
2343
  notifyChange(nextPalette);
1979
2344
  },
1980
2345
  [notifyChange]
1981
2346
  );
1982
- const controlConfig = useMemo5(
2347
+ const controlConfig = useMemo6(
1983
2348
  () => ({
1984
2349
  ...options.control ?? {},
1985
2350
  defaultPalette: resolvedDefaultPalette,
@@ -1987,7 +2352,7 @@ var useAdvancedPaletteControls = (options = {}) => {
1987
2352
  }),
1988
2353
  [handleControlPaletteChange, options.control, resolvedDefaultPalette]
1989
2354
  );
1990
- const hexColors = useMemo5(
2355
+ const hexColors = useMemo6(
1991
2356
  () => advancedPaletteToHexColors(palette, {
1992
2357
  sectionOrder: options.sectionOrder,
1993
2358
  fallbackPalette: resolvedFallbackPalette,
@@ -2000,11 +2365,11 @@ var useAdvancedPaletteControls = (options = {}) => {
2000
2365
  resolvedFallbackPalette
2001
2366
  ]
2002
2367
  );
2003
- const paletteSignature = useMemo5(
2368
+ const paletteSignature = useMemo6(
2004
2369
  () => createPaletteSignature(palette),
2005
2370
  [palette]
2006
2371
  );
2007
- const paletteGradient = useMemo5(
2372
+ const paletteGradient = useMemo6(
2008
2373
  () => computePaletteGradient(palette, options.gradientSteps),
2009
2374
  [options.gradientSteps, palette]
2010
2375
  );