@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.js CHANGED
@@ -49,9 +49,9 @@ __export(src_exports, {
49
49
  });
50
50
  module.exports = __toCommonJS(src_exports);
51
51
 
52
- // src/components/Playground/Playground.tsx
53
- var import_react7 = require("react");
54
- var import_lucide_react4 = require("lucide-react");
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");
@@ -472,17 +472,30 @@ var ControlsProvider = ({ children }) => {
472
472
  setComponentName(opts.componentName);
473
473
  }
474
474
  if (opts?.config) {
475
- const { addAdvancedPaletteControl, ...otherConfig } = opts.config;
476
- setConfig((prev) => ({
477
- ...prev,
478
- ...otherConfig,
479
- ...Object.prototype.hasOwnProperty.call(
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(
480
486
  opts.config,
481
487
  "addAdvancedPaletteControl"
482
- ) ? {
483
- addAdvancedPaletteControl: addAdvancedPaletteControl ? resolveAdvancedPaletteConfig(addAdvancedPaletteControl) : void 0
484
- } : {}
485
- }));
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
+ });
486
499
  }
487
500
  setSchema((prevSchema) => ({ ...prevSchema, ...newSchema }));
488
501
  setValues((prevValues) => {
@@ -647,7 +660,7 @@ var useControls = (schema, options) => {
647
660
  resolvedAdvancedConfig.onPaletteChange(clonePalette(palette));
648
661
  }, [ctx.values, resolvedAdvancedConfig]);
649
662
  const typedValues = ctx.values;
650
- const jsx14 = (0, import_react2.useCallback)(() => {
663
+ const jsx15 = (0, import_react2.useCallback)(() => {
651
664
  if (!options?.componentName) return "";
652
665
  const props = Object.entries(typedValues).map(([key, val]) => {
653
666
  if (typeof val === "string") return `${key}="${val}"`;
@@ -661,14 +674,14 @@ var useControls = (schema, options) => {
661
674
  controls: ctx.values,
662
675
  schema: ctx.schema,
663
676
  setValue: ctx.setValue,
664
- jsx: jsx14
677
+ jsx: jsx15
665
678
  };
666
679
  };
667
680
  var useUrlSyncedControls = useControls;
668
681
 
669
- // src/components/ControlPanel/ControlPanel.tsx
670
- var import_react5 = require("react");
671
- var import_lucide_react3 = require("lucide-react");
682
+ // src/components/ControlPanel.tsx
683
+ var import_react6 = require("react");
684
+ var import_lucide_react4 = require("lucide-react");
672
685
 
673
686
  // src/hooks/usePreviewUrl.ts
674
687
  var import_react3 = require("react");
@@ -943,7 +956,7 @@ Button.displayName = "Button";
943
956
  // src/constants/layout.ts
944
957
  var MOBILE_CONTROL_PANEL_PEEK = 112;
945
958
 
946
- // src/components/AdvancedPaletteControl/AdvancedPaletteControl.tsx
959
+ // src/components/AdvancedPaletteControl.tsx
947
960
  var import_react4 = require("react");
948
961
  var import_jsx_runtime9 = require("react/jsx-runtime");
949
962
  var AdvancedPaletteControl = ({
@@ -1091,8 +1104,309 @@ var AdvancedPaletteControl = ({
1091
1104
  };
1092
1105
  var AdvancedPaletteControl_default = AdvancedPaletteControl;
1093
1106
 
1094
- // src/components/ControlPanel/ControlPanel.tsx
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
1095
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");
1096
1410
  var splitPropsString = (input) => {
1097
1411
  const props = [];
1098
1412
  let current = "";
@@ -1299,23 +1613,23 @@ var highlightJsx = (input) => {
1299
1613
  nodes.push(token.value);
1300
1614
  } else {
1301
1615
  nodes.push(
1302
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: TOKEN_CLASS_MAP[token.type], children: token.value }, `token-${index}`)
1616
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: TOKEN_CLASS_MAP[token.type], children: token.value }, `token-${index}`)
1303
1617
  );
1304
1618
  }
1305
1619
  });
1306
1620
  return nodes;
1307
1621
  };
1308
1622
  var ControlPanel = () => {
1309
- const [copied, setCopied] = (0, import_react5.useState)(false);
1310
- const [codeCopied, setCodeCopied] = (0, import_react5.useState)(false);
1311
- const [isCodeVisible, setIsCodeVisible] = (0, import_react5.useState)(false);
1312
- const [folderStates, setFolderStates] = (0, import_react5.useState)({});
1313
- const codeCopyTimeoutRef = (0, import_react5.useRef)(null);
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);
1314
1628
  const { leftPanelWidth, isDesktop, isHydrated } = useResizableLayout();
1315
1629
  const { schema, setValue, values, componentName, config } = useControlsContext();
1316
1630
  const isControlsOnlyView = typeof window !== "undefined" && new URLSearchParams(window.location.search).get(CONTROLS_ONLY_PARAM) === "true";
1317
1631
  const previewUrl = usePreviewUrl(values);
1318
- const buildUrl = (0, import_react5.useCallback)(
1632
+ const buildUrl = (0, import_react6.useCallback)(
1319
1633
  (modifier) => {
1320
1634
  if (!previewUrl) return "";
1321
1635
  const [path, search = ""] = previewUrl.split("?");
@@ -1326,13 +1640,13 @@ var ControlPanel = () => {
1326
1640
  },
1327
1641
  [previewUrl]
1328
1642
  );
1329
- const presentationUrl = (0, import_react5.useMemo)(() => {
1643
+ const presentationUrl = (0, import_react6.useMemo)(() => {
1330
1644
  if (!previewUrl) return "";
1331
1645
  return buildUrl((params) => {
1332
1646
  params.set(PRESENTATION_PARAM, "true");
1333
1647
  });
1334
1648
  }, [buildUrl, previewUrl]);
1335
- const controlsOnlyUrl = (0, import_react5.useMemo)(() => {
1649
+ const controlsOnlyUrl = (0, import_react6.useMemo)(() => {
1336
1650
  if (!previewUrl) return "";
1337
1651
  return buildUrl((params) => {
1338
1652
  params.delete(NO_CONTROLS_PARAM);
@@ -1340,7 +1654,7 @@ var ControlPanel = () => {
1340
1654
  params.set(CONTROLS_ONLY_PARAM, "true");
1341
1655
  });
1342
1656
  }, [buildUrl, previewUrl]);
1343
- const handlePresentationClick = (0, import_react5.useCallback)(() => {
1657
+ const handlePresentationClick = (0, import_react6.useCallback)(() => {
1344
1658
  if (typeof window === "undefined" || !presentationUrl) return;
1345
1659
  window.open(presentationUrl, "_blank", "noopener,noreferrer");
1346
1660
  if (controlsOnlyUrl) {
@@ -1348,10 +1662,7 @@ var ControlPanel = () => {
1348
1662
  const viewportHeight = window.innerHeight || 900;
1349
1663
  const controlsWidth = Math.max(
1350
1664
  320,
1351
- Math.min(
1352
- 600,
1353
- Math.round(viewportWidth * leftPanelWidth / 100)
1354
- )
1665
+ Math.min(600, Math.round(viewportWidth * leftPanelWidth / 100))
1355
1666
  );
1356
1667
  const controlsHeight = Math.max(600, viewportHeight);
1357
1668
  const controlsFeatures = [
@@ -1367,7 +1678,7 @@ var ControlPanel = () => {
1367
1678
  window.open(controlsOnlyUrl, "v0-controls", controlsFeatures);
1368
1679
  }
1369
1680
  }, [controlsOnlyUrl, leftPanelWidth, presentationUrl]);
1370
- const jsx14 = (0, import_react5.useMemo)(() => {
1681
+ const jsx15 = (0, import_react6.useMemo)(() => {
1371
1682
  if (!componentName) return "";
1372
1683
  const props = Object.entries(values).map(([key, val]) => {
1373
1684
  if (typeof val === "string") return `${key}="${val}"`;
@@ -1412,7 +1723,7 @@ var ControlPanel = () => {
1412
1723
  const advancedConfig = config?.addAdvancedPaletteControl;
1413
1724
  let advancedPaletteControlNode = null;
1414
1725
  if (advancedConfig) {
1415
- const advancedNode = /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1726
+ const advancedNode = /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1416
1727
  AdvancedPaletteControl_default,
1417
1728
  {
1418
1729
  config: advancedConfig
@@ -1438,12 +1749,52 @@ var ControlPanel = () => {
1438
1749
  advancedPaletteControlNode = advancedNode;
1439
1750
  }
1440
1751
  }
1441
- const rootButtonControls = rootControls.filter(
1442
- ([, control]) => control.type === "button"
1443
- );
1444
- const rootNormalControls = rootControls.filter(
1445
- ([, control]) => control.type !== "button"
1446
- );
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
+ });
1447
1798
  const folderGroups = folderOrder.map((folder) => ({
1448
1799
  folder,
1449
1800
  entries: folderControls.get(folder) ?? [],
@@ -1452,7 +1803,7 @@ var ControlPanel = () => {
1452
1803
  })).filter((group) => group.entries.length > 0 || group.extras.length > 0);
1453
1804
  const hasRootButtonControls = rootButtonControls.length > 0;
1454
1805
  const hasAnyFolders = folderGroups.length > 0;
1455
- const jsonToComponentString = (0, import_react5.useCallback)(
1806
+ const jsonToComponentString = (0, import_react6.useCallback)(
1456
1807
  ({
1457
1808
  componentName: componentNameOverride,
1458
1809
  props
@@ -1483,40 +1834,40 @@ var ControlPanel = () => {
1483
1834
  componentName,
1484
1835
  values,
1485
1836
  schema,
1486
- jsx: jsx14,
1837
+ jsx: jsx15,
1487
1838
  jsonToComponentString
1488
- }) ?? jsx14;
1839
+ }) ?? jsx15;
1489
1840
  const shouldShowCopyButton = config?.showCopyButton !== false && Boolean(copyText);
1490
- const baseSnippet = copyText || jsx14;
1491
- const formattedCode = (0, import_react5.useMemo)(
1841
+ const baseSnippet = copyText || jsx15;
1842
+ const formattedCode = (0, import_react6.useMemo)(
1492
1843
  () => formatJsxCodeSnippet(baseSnippet),
1493
1844
  [baseSnippet]
1494
1845
  );
1495
1846
  const hasCodeSnippet = Boolean(config?.showCodeSnippet && formattedCode);
1496
- const highlightedCode = (0, import_react5.useMemo)(
1847
+ const highlightedCode = (0, import_react6.useMemo)(
1497
1848
  () => formattedCode ? highlightJsx(formattedCode) : null,
1498
1849
  [formattedCode]
1499
1850
  );
1500
- (0, import_react5.useEffect)(() => {
1851
+ (0, import_react6.useEffect)(() => {
1501
1852
  if (!hasCodeSnippet) {
1502
1853
  setIsCodeVisible(false);
1503
1854
  }
1504
1855
  }, [hasCodeSnippet]);
1505
- (0, import_react5.useEffect)(() => {
1856
+ (0, import_react6.useEffect)(() => {
1506
1857
  setCodeCopied(false);
1507
1858
  if (codeCopyTimeoutRef.current) {
1508
1859
  clearTimeout(codeCopyTimeoutRef.current);
1509
1860
  codeCopyTimeoutRef.current = null;
1510
1861
  }
1511
1862
  }, [formattedCode]);
1512
- (0, import_react5.useEffect)(() => {
1863
+ (0, import_react6.useEffect)(() => {
1513
1864
  return () => {
1514
1865
  if (codeCopyTimeoutRef.current) {
1515
1866
  clearTimeout(codeCopyTimeoutRef.current);
1516
1867
  }
1517
1868
  };
1518
1869
  }, []);
1519
- const handleToggleCodeVisibility = (0, import_react5.useCallback)(() => {
1870
+ const handleToggleCodeVisibility = (0, import_react6.useCallback)(() => {
1520
1871
  setIsCodeVisible((prev) => {
1521
1872
  const next = !prev;
1522
1873
  if (!next) {
@@ -1529,7 +1880,7 @@ var ControlPanel = () => {
1529
1880
  return next;
1530
1881
  });
1531
1882
  }, []);
1532
- const handleCodeCopy = (0, import_react5.useCallback)(() => {
1883
+ const handleCodeCopy = (0, import_react6.useCallback)(() => {
1533
1884
  if (!formattedCode) return;
1534
1885
  if (typeof navigator === "undefined" || !navigator.clipboard || typeof navigator.clipboard.writeText !== "function") {
1535
1886
  return;
@@ -1547,11 +1898,11 @@ var ControlPanel = () => {
1547
1898
  });
1548
1899
  }, [formattedCode]);
1549
1900
  const labelize = (key) => key.replace(/([A-Z])/g, " $1").replace(/[\-_]/g, " ").replace(/\s+/g, " ").trim().replace(/(^|\s)\S/g, (s) => s.toUpperCase());
1550
- const renderButtonControl = (key, control, variant) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1901
+ const renderButtonControl = (key, control, variant) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1551
1902
  "div",
1552
1903
  {
1553
1904
  className: variant === "root" ? "flex-1 [&_[data-slot=button]]:w-full" : "[&_[data-slot=button]]:w-full",
1554
- children: control.render ? control.render() : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1905
+ children: control.render ? control.render() : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1555
1906
  "button",
1556
1907
  {
1557
1908
  onClick: control.onClick,
@@ -1569,9 +1920,9 @@ var ControlPanel = () => {
1569
1920
  const value = values[key];
1570
1921
  switch (control.type) {
1571
1922
  case "boolean":
1572
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center justify-between", children: [
1573
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Label, { htmlFor: key, className: "cursor-pointer", children: labelize(key) }),
1574
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
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)(
1575
1926
  Switch,
1576
1927
  {
1577
1928
  id: key,
@@ -1582,10 +1933,10 @@ var ControlPanel = () => {
1582
1933
  )
1583
1934
  ] }, key);
1584
1935
  case "number":
1585
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "space-y-3 w-full", children: [
1586
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center justify-between", children: [
1587
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Label, { className: "text-stone-300", htmlFor: key, children: labelize(key) }),
1588
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
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)(
1589
1940
  Input,
1590
1941
  {
1591
1942
  type: "number",
@@ -1602,7 +1953,7 @@ var ControlPanel = () => {
1602
1953
  }
1603
1954
  )
1604
1955
  ] }),
1605
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1956
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1606
1957
  Slider,
1607
1958
  {
1608
1959
  id: key,
@@ -1616,9 +1967,9 @@ var ControlPanel = () => {
1616
1967
  )
1617
1968
  ] }, key);
1618
1969
  case "string":
1619
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "space-y-2 w-full", children: [
1620
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Label, { className: "text-stone-300", htmlFor: key, children: labelize(key) }),
1621
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
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)(
1622
1973
  Input,
1623
1974
  {
1624
1975
  id: key,
@@ -1630,9 +1981,9 @@ var ControlPanel = () => {
1630
1981
  )
1631
1982
  ] }, key);
1632
1983
  case "color":
1633
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "space-y-2 w-full", children: [
1634
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Label, { className: "text-stone-300", htmlFor: key, children: labelize(key) }),
1635
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
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)(
1636
1987
  "input",
1637
1988
  {
1638
1989
  type: "color",
@@ -1644,11 +1995,11 @@ var ControlPanel = () => {
1644
1995
  )
1645
1996
  ] }, key);
1646
1997
  case "select":
1647
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "space-y-2", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center gap-3", children: [
1648
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Label, { className: "min-w-fit", htmlFor: key, children: labelize(key) }),
1649
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Select, { value, onValueChange: (val) => setValue(key, val), children: [
1650
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(SelectTrigger, { className: "flex-1 cursor-pointer", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(SelectValue, { placeholder: "Select option" }) }),
1651
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(SelectContent, { className: "cursor-pointer z-[9999]", children: Object.entries(control.options).map(([label]) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
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)(
1652
2003
  SelectItem,
1653
2004
  {
1654
2005
  value: label,
@@ -1665,12 +2016,12 @@ var ControlPanel = () => {
1665
2016
  };
1666
2017
  const renderFolder = (folder, entries, extras = []) => {
1667
2018
  const isOpen = folderStates[folder] ?? true;
1668
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2019
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
1669
2020
  "div",
1670
2021
  {
1671
2022
  className: "border border-stone-700/60 rounded-lg bg-stone-900/70",
1672
2023
  children: [
1673
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2024
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
1674
2025
  "button",
1675
2026
  {
1676
2027
  type: "button",
@@ -1680,9 +2031,9 @@ var ControlPanel = () => {
1680
2031
  })),
1681
2032
  className: "w-full flex items-center justify-between px-4 py-3 text-left font-semibold text-stone-200 tracking-wide",
1682
2033
  children: [
1683
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: folder }),
1684
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1685
- import_lucide_react3.ChevronDown,
2034
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { children: folder }),
2035
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2036
+ import_lucide_react4.ChevronDown,
1686
2037
  {
1687
2038
  className: `w-4 h-4 transition-transform duration-200 ${isOpen ? "rotate-180" : ""}`
1688
2039
  }
@@ -1690,7 +2041,7 @@ var ControlPanel = () => {
1690
2041
  ]
1691
2042
  }
1692
2043
  ),
1693
- isOpen && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "px-4 pb-4 pt-0 space-y-5", children: [
2044
+ isOpen && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "px-4 pb-4 pt-0 space-y-5", children: [
1694
2045
  entries.map(
1695
2046
  ([key, control]) => renderControl(key, control, "folder")
1696
2047
  ),
@@ -1729,27 +2080,28 @@ var ControlPanel = () => {
1729
2080
  });
1730
2081
  }
1731
2082
  }
1732
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2083
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1733
2084
  "div",
1734
2085
  {
1735
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"}`,
1736
2087
  onPointerDown: (e) => e.stopPropagation(),
1737
2088
  onTouchStart: (e) => e.stopPropagation(),
1738
2089
  style: panelStyle,
1739
- children: /* @__PURE__ */ (0, import_jsx_runtime10.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: [
1740
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "space-y-1", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h1", { className: "text-lg text-stone-100 font-semibold", children: config?.mainLabel ?? "Controls" }) }),
1741
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "space-y-6", children: [
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: [
1742
2093
  topFolderSections,
1743
- hasRootButtonControls && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "flex flex-wrap gap-2", children: rootButtonControls.map(
2094
+ hasRootButtonControls && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "flex flex-wrap gap-2", children: rootButtonControls.map(
1744
2095
  ([key, control]) => renderButtonControl(key, control, "root")
1745
2096
  ) }),
1746
2097
  advancedPaletteControlNode,
2098
+ mediaUploadControlNode,
1747
2099
  rootNormalControls.map(
1748
2100
  ([key, control]) => renderControl(key, control, "root")
1749
2101
  ),
1750
2102
  bottomFolderSections,
1751
- hasCodeSnippet && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "border border-stone-700/60 rounded-lg bg-stone-900/70", children: [
1752
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
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)(
1753
2105
  "button",
1754
2106
  {
1755
2107
  type: "button",
@@ -1757,9 +2109,9 @@ var ControlPanel = () => {
1757
2109
  className: "w-full flex items-center justify-between px-4 py-3 text-left font-semibold text-stone-200 tracking-wide",
1758
2110
  "aria-expanded": isCodeVisible,
1759
2111
  children: [
1760
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: isCodeVisible ? "Hide Code" : "Show Code" }),
1761
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1762
- import_lucide_react3.ChevronDown,
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,
1763
2115
  {
1764
2116
  className: `w-4 h-4 transition-transform duration-200 ${isCodeVisible ? "rotate-180" : ""}`
1765
2117
  }
@@ -1767,26 +2119,26 @@ var ControlPanel = () => {
1767
2119
  ]
1768
2120
  }
1769
2121
  ),
1770
- isCodeVisible && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "relative border-t border-stone-700/60 bg-stone-950/60 px-4 py-4 rounded-b-lg", children: [
1771
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
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)(
1772
2124
  "button",
1773
2125
  {
1774
2126
  type: "button",
1775
2127
  onClick: handleCodeCopy,
1776
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",
1777
- children: codeCopied ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
1778
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react3.Check, { className: "h-3.5 w-3.5" }),
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" }),
1779
2131
  "Copied"
1780
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
1781
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react3.Copy, { className: "h-3.5 w-3.5" }),
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" }),
1782
2134
  "Copy"
1783
2135
  ] })
1784
2136
  }
1785
2137
  ),
1786
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("pre", { className: "whitespace-pre overflow-x-auto text-xs md:text-sm text-stone-200 pr-14", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("code", { className: "block text-stone-200", children: highlightedCode ?? formattedCode }) })
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 }) })
1787
2139
  ] })
1788
2140
  ] }),
1789
- shouldShowCopyButton && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "flex-1 pt-4", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2141
+ shouldShowCopyButton && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "flex-1 pt-4", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1790
2142
  "button",
1791
2143
  {
1792
2144
  onClick: () => {
@@ -1797,18 +2149,18 @@ var ControlPanel = () => {
1797
2149
  setTimeout(() => setCopied(false), 5e3);
1798
2150
  },
1799
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",
1800
- children: copied ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
1801
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react3.Check, { className: "w-4 h-4" }),
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" }),
1802
2154
  "Copied"
1803
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
1804
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react3.Copy, { className: "w-4 h-4" }),
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" }),
1805
2157
  "Copy to Clipboard"
1806
2158
  ] })
1807
2159
  }
1808
2160
  ) }, "control-panel-jsx")
1809
2161
  ] }),
1810
- previewUrl && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-col gap-2", children: [
1811
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Button, { asChild: true, className: "w-full", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
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)(
1812
2164
  "a",
1813
2165
  {
1814
2166
  href: previewUrl,
@@ -1816,12 +2168,12 @@ var ControlPanel = () => {
1816
2168
  rel: "noopener noreferrer",
1817
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",
1818
2170
  children: [
1819
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react3.SquareArrowOutUpRight, {}),
2171
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react4.SquareArrowOutUpRight, {}),
1820
2172
  " Open in a New Tab"
1821
2173
  ]
1822
2174
  }
1823
2175
  ) }),
1824
- config?.showPresentationButton && presentationUrl && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2176
+ config?.showPresentationButton && presentationUrl && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
1825
2177
  Button,
1826
2178
  {
1827
2179
  type: "button",
@@ -1829,7 +2181,7 @@ var ControlPanel = () => {
1829
2181
  variant: "secondary",
1830
2182
  className: "w-full bg-stone-800 text-white hover:bg-stone-700 border border-stone-700",
1831
2183
  children: [
1832
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react3.Presentation, {}),
2184
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react4.Presentation, {}),
1833
2185
  " Presentation Mode"
1834
2186
  ]
1835
2187
  }
@@ -1841,16 +2193,16 @@ var ControlPanel = () => {
1841
2193
  };
1842
2194
  var ControlPanel_default = ControlPanel;
1843
2195
 
1844
- // src/components/PreviewContainer/PreviewContainer.tsx
1845
- var import_react6 = require("react");
2196
+ // src/components/PreviewContainer.tsx
2197
+ var import_react7 = require("react");
1846
2198
 
1847
- // src/components/Grid/Grid.tsx
1848
- var import_jsx_runtime11 = require("react/jsx-runtime");
2199
+ // src/components/Grid.tsx
2200
+ var import_jsx_runtime12 = require("react/jsx-runtime");
1849
2201
  function Grid() {
1850
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2202
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1851
2203
  "div",
1852
2204
  {
1853
- className: "absolute inset-0 w-screen h-screen z-[0] blur-[1px]",
2205
+ className: "absolute inset-0 w-full h-full z-[0] blur-[1px]",
1854
2206
  style: {
1855
2207
  backgroundImage: `
1856
2208
  linear-gradient(to right,rgb(13, 13, 13) 1px, transparent 1px),
@@ -1864,40 +2216,40 @@ function Grid() {
1864
2216
  }
1865
2217
  var Grid_default = Grid;
1866
2218
 
1867
- // src/components/PreviewContainer/PreviewContainer.tsx
1868
- var import_jsx_runtime12 = require("react/jsx-runtime");
2219
+ // src/components/PreviewContainer.tsx
2220
+ var import_jsx_runtime13 = require("react/jsx-runtime");
1869
2221
  var PreviewContainer = ({ children, hideControls }) => {
1870
2222
  const { config } = useControlsContext();
1871
2223
  const { leftPanelWidth, isDesktop, isHydrated, containerRef } = useResizableLayout();
1872
- const previewRef = (0, import_react6.useRef)(null);
1873
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2224
+ const previewRef = (0, import_react7.useRef)(null);
2225
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1874
2226
  "div",
1875
2227
  {
1876
2228
  ref: previewRef,
1877
- 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",
1878
2230
  style: isHydrated && isDesktop && !hideControls ? {
1879
2231
  width: `${100 - leftPanelWidth}%`,
1880
2232
  marginLeft: `${leftPanelWidth}%`
1881
2233
  } : {},
1882
- children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "w-screen h-screen", children: [
1883
- config?.showGrid && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Grid_default, {}),
1884
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "w-screen h-screen flex items-center justify-center relative", children })
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 })
1885
2237
  ] })
1886
2238
  }
1887
2239
  );
1888
2240
  };
1889
2241
  var PreviewContainer_default = PreviewContainer;
1890
2242
 
1891
- // src/components/Playground/Playground.tsx
1892
- var import_jsx_runtime13 = require("react/jsx-runtime");
1893
- var HiddenPreview = ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { "aria-hidden": "true", className: "hidden", children });
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 });
1894
2246
  function Playground({ children }) {
1895
- const [isHydrated, setIsHydrated] = (0, import_react7.useState)(false);
1896
- const [copied, setCopied] = (0, import_react7.useState)(false);
1897
- (0, import_react7.useEffect)(() => {
2247
+ const [isHydrated, setIsHydrated] = (0, import_react8.useState)(false);
2248
+ const [copied, setCopied] = (0, import_react8.useState)(false);
2249
+ (0, import_react8.useEffect)(() => {
1898
2250
  setIsHydrated(true);
1899
2251
  }, []);
1900
- const { showControls, isPresentationMode, isControlsOnly } = (0, import_react7.useMemo)(() => {
2252
+ const { showControls, isPresentationMode, isControlsOnly } = (0, import_react8.useMemo)(() => {
1901
2253
  if (typeof window === "undefined") {
1902
2254
  return {
1903
2255
  showControls: true,
@@ -1924,54 +2276,54 @@ function Playground({ children }) {
1924
2276
  setTimeout(() => setCopied(false), 2e3);
1925
2277
  };
1926
2278
  if (!isHydrated) return null;
1927
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ResizableLayout, { hideControls: layoutHideControls, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(ControlsProvider, { children: [
1928
- shouldShowShareButton && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
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)(
1929
2281
  "button",
1930
2282
  {
1931
2283
  onClick: handleCopy,
1932
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",
1933
2285
  children: [
1934
- copied ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react4.Check, { size: 16 }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react4.Copy, { size: 16 }),
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 }),
1935
2287
  copied ? "Copied!" : "Share"
1936
2288
  ]
1937
2289
  }
1938
2290
  ),
1939
- isControlsOnly ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(HiddenPreview, { children }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(PreviewContainer_default, { hideControls: layoutHideControls, children }),
1940
- showControls && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ControlPanel_default, {})
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, {})
1941
2293
  ] }) });
1942
2294
  }
1943
2295
 
1944
2296
  // src/hooks/useAdvancedPaletteControls.ts
1945
- var import_react8 = require("react");
2297
+ var import_react9 = require("react");
1946
2298
  var cloneForCallbacks = (palette) => clonePalette(palette);
1947
2299
  var useAdvancedPaletteControls = (options = {}) => {
1948
- const resolvedDefaultPalette = (0, import_react8.useMemo)(
2300
+ const resolvedDefaultPalette = (0, import_react9.useMemo)(
1949
2301
  () => createAdvancedPalette(options.defaultPalette),
1950
2302
  [options.defaultPalette]
1951
2303
  );
1952
- const resolvedFallbackPalette = (0, import_react8.useMemo)(
2304
+ const resolvedFallbackPalette = (0, import_react9.useMemo)(
1953
2305
  () => options.fallbackPalette ? createAdvancedPalette(options.fallbackPalette) : resolvedDefaultPalette,
1954
2306
  [options.fallbackPalette, resolvedDefaultPalette]
1955
2307
  );
1956
- const [palette, setPaletteState] = (0, import_react8.useState)(
2308
+ const [palette, setPaletteState] = (0, import_react9.useState)(
1957
2309
  () => clonePalette(resolvedDefaultPalette)
1958
2310
  );
1959
- const defaultSignatureRef = (0, import_react8.useRef)(
2311
+ const defaultSignatureRef = (0, import_react9.useRef)(
1960
2312
  createPaletteSignature(resolvedDefaultPalette)
1961
2313
  );
1962
- (0, import_react8.useEffect)(() => {
2314
+ (0, import_react9.useEffect)(() => {
1963
2315
  const nextSignature = createPaletteSignature(resolvedDefaultPalette);
1964
2316
  if (defaultSignatureRef.current === nextSignature) return;
1965
2317
  defaultSignatureRef.current = nextSignature;
1966
2318
  setPaletteState(clonePalette(resolvedDefaultPalette));
1967
2319
  }, [resolvedDefaultPalette]);
1968
- const notifyChange = (0, import_react8.useCallback)(
2320
+ const notifyChange = (0, import_react9.useCallback)(
1969
2321
  (nextPalette) => {
1970
2322
  options.onChange?.(cloneForCallbacks(nextPalette));
1971
2323
  },
1972
2324
  [options.onChange]
1973
2325
  );
1974
- const setPalette = (0, import_react8.useCallback)(
2326
+ const setPalette = (0, import_react9.useCallback)(
1975
2327
  (source) => {
1976
2328
  const nextPalette = createAdvancedPalette(
1977
2329
  source ?? resolvedDefaultPalette
@@ -1981,7 +2333,7 @@ var useAdvancedPaletteControls = (options = {}) => {
1981
2333
  },
1982
2334
  [notifyChange, resolvedDefaultPalette]
1983
2335
  );
1984
- const updatePalette = (0, import_react8.useCallback)(
2336
+ const updatePalette = (0, import_react9.useCallback)(
1985
2337
  (updater) => {
1986
2338
  setPaletteState((current) => {
1987
2339
  const nextSource = updater(clonePalette(current));
@@ -1994,18 +2346,18 @@ var useAdvancedPaletteControls = (options = {}) => {
1994
2346
  },
1995
2347
  [notifyChange, resolvedDefaultPalette]
1996
2348
  );
1997
- const resetPalette = (0, import_react8.useCallback)(() => {
2349
+ const resetPalette = (0, import_react9.useCallback)(() => {
1998
2350
  setPaletteState(clonePalette(resolvedDefaultPalette));
1999
2351
  notifyChange(resolvedDefaultPalette);
2000
2352
  }, [notifyChange, resolvedDefaultPalette]);
2001
- const handleControlPaletteChange = (0, import_react8.useCallback)(
2353
+ const handleControlPaletteChange = (0, import_react9.useCallback)(
2002
2354
  (nextPalette) => {
2003
2355
  setPaletteState(clonePalette(nextPalette));
2004
2356
  notifyChange(nextPalette);
2005
2357
  },
2006
2358
  [notifyChange]
2007
2359
  );
2008
- const controlConfig = (0, import_react8.useMemo)(
2360
+ const controlConfig = (0, import_react9.useMemo)(
2009
2361
  () => ({
2010
2362
  ...options.control ?? {},
2011
2363
  defaultPalette: resolvedDefaultPalette,
@@ -2013,7 +2365,7 @@ var useAdvancedPaletteControls = (options = {}) => {
2013
2365
  }),
2014
2366
  [handleControlPaletteChange, options.control, resolvedDefaultPalette]
2015
2367
  );
2016
- const hexColors = (0, import_react8.useMemo)(
2368
+ const hexColors = (0, import_react9.useMemo)(
2017
2369
  () => advancedPaletteToHexColors(palette, {
2018
2370
  sectionOrder: options.sectionOrder,
2019
2371
  fallbackPalette: resolvedFallbackPalette,
@@ -2026,11 +2378,11 @@ var useAdvancedPaletteControls = (options = {}) => {
2026
2378
  resolvedFallbackPalette
2027
2379
  ]
2028
2380
  );
2029
- const paletteSignature = (0, import_react8.useMemo)(
2381
+ const paletteSignature = (0, import_react9.useMemo)(
2030
2382
  () => createPaletteSignature(palette),
2031
2383
  [palette]
2032
2384
  );
2033
- const paletteGradient = (0, import_react8.useMemo)(
2385
+ const paletteGradient = (0, import_react9.useMemo)(
2034
2386
  () => computePaletteGradient(palette, options.gradientSteps),
2035
2387
  [options.gradientSteps, palette]
2036
2388
  );