@newtonedev/editor 0.1.4 → 0.1.6

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.
Files changed (48) hide show
  1. package/dist/Editor.d.ts.map +1 -1
  2. package/dist/components/CodeBlock.d.ts.map +1 -1
  3. package/dist/components/PresetSelector.d.ts.map +1 -1
  4. package/dist/components/PreviewWindow.d.ts +3 -2
  5. package/dist/components/PreviewWindow.d.ts.map +1 -1
  6. package/dist/components/RightSidebar.d.ts +4 -1
  7. package/dist/components/RightSidebar.d.ts.map +1 -1
  8. package/dist/components/Sidebar.d.ts.map +1 -1
  9. package/dist/components/sections/DynamicRangeSection.d.ts.map +1 -1
  10. package/dist/hooks/useEditorState.d.ts +1 -3
  11. package/dist/hooks/useEditorState.d.ts.map +1 -1
  12. package/dist/index.cjs +686 -346
  13. package/dist/index.cjs.map +1 -1
  14. package/dist/index.d.ts +1 -2
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +689 -348
  17. package/dist/index.js.map +1 -1
  18. package/dist/preview/ComponentDetailView.d.ts +3 -2
  19. package/dist/preview/ComponentDetailView.d.ts.map +1 -1
  20. package/dist/preview/ComponentRenderer.d.ts.map +1 -1
  21. package/dist/preview/IconBrowserView.d.ts +7 -0
  22. package/dist/preview/IconBrowserView.d.ts.map +1 -0
  23. package/dist/types.d.ts +0 -1
  24. package/dist/types.d.ts.map +1 -1
  25. package/package.json +1 -1
  26. package/src/Editor.tsx +19 -9
  27. package/src/components/CodeBlock.tsx +42 -14
  28. package/src/components/EditorHeader.tsx +3 -3
  29. package/src/components/EditorShell.tsx +2 -2
  30. package/src/components/FontPicker.tsx +1 -1
  31. package/src/components/PresetSelector.tsx +11 -36
  32. package/src/components/PreviewWindow.tsx +6 -3
  33. package/src/components/RightSidebar.tsx +105 -42
  34. package/src/components/Sidebar.tsx +12 -92
  35. package/src/components/TableOfContents.tsx +1 -1
  36. package/src/components/sections/ColorsSection.tsx +2 -2
  37. package/src/components/sections/DynamicRangeSection.tsx +226 -3
  38. package/src/hooks/useEditorState.ts +14 -19
  39. package/src/index.ts +0 -2
  40. package/src/preview/CategoryView.tsx +1 -1
  41. package/src/preview/ComponentDetailView.tsx +47 -8
  42. package/src/preview/ComponentRenderer.tsx +51 -0
  43. package/src/preview/IconBrowserView.tsx +187 -0
  44. package/src/preview/OverviewView.tsx +1 -1
  45. package/src/types.ts +0 -2
  46. package/dist/components/ThemeBar.d.ts +0 -8
  47. package/dist/components/ThemeBar.d.ts.map +0 -1
  48. package/src/components/ThemeBar.tsx +0 -76
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { useState, useCallback, useRef, useMemo, useEffect } from 'react';
2
- import { getComponent, useTokens, ColorScaleSlider, TextInput, HueSlider, Slider, Select, Toggle, GOOGLE_FONTS, SYSTEM_FONTS, Button, CATEGORIES, getComponentsByCategory, getCategory, generateComponentCode, NewtoneProvider, Card } from '@newtonedev/components';
2
+ import { getComponent, useTokens, ColorScaleSlider, TextInput, HueSlider, Slider, Select, Toggle, GOOGLE_FONTS, SYSTEM_FONTS, Icon, Button, CATEGORIES, getComponentsByCategory, Text, getCategory, generateComponentCode, NewtoneProvider, Wrapper, Frame, Card, ICON_CATALOG } from '@newtonedev/components';
3
3
  import { useConfigurator, usePreviewColors, SEMANTIC_HUE_RANGES, useWcagValidation, traditionalHueToOklch, hexToPaletteParams } from '@newtonedev/configurator';
4
- import { srgbToHex } from 'newtone';
4
+ import { srgbToHex, resolveLightness, findMaxChromaInGamut, clampSrgb, oklchToSrgb, HUE_GRADING_STRENGTH_HARD, HUE_GRADING_STRENGTH_MEDIUM, HUE_GRADING_STRENGTH_LOW, HUE_GRADING_EASING_POWER } from 'newtone';
5
5
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
6
6
 
7
7
  // src/utils/presets.ts
@@ -214,9 +214,6 @@ function useEditorState({
214
214
  const [colorMode, setColorMode] = useState(
215
215
  initialState.preview.mode
216
216
  );
217
- const [activeTheme, setActiveTheme] = useState(
218
- initialState.preview.theme || "neutral"
219
- );
220
217
  const [previewView, setPreviewView] = useState(
221
218
  initialPreviewView ?? { kind: "overview" }
222
219
  );
@@ -339,9 +336,19 @@ function useEditorState({
339
336
  initOverridesFromVariant(sidebarSelection.componentId);
340
337
  }
341
338
  }, [sidebarSelection, initOverridesFromVariant]);
342
- const handlePropOverride = useCallback((propName, value) => {
343
- setPropOverrides((prev) => ({ ...prev, [propName]: value }));
344
- }, []);
339
+ const handlePropOverride = useCallback(
340
+ (propName, value) => {
341
+ setPropOverrides((prev) => ({ ...prev, [propName]: value }));
342
+ setSidebarSelection((prev) => {
343
+ if (prev !== null) return prev;
344
+ if (previewView.kind === "component") {
345
+ return { scope: "component", componentId: previewView.componentId };
346
+ }
347
+ return prev;
348
+ });
349
+ },
350
+ [previewView]
351
+ );
345
352
  const handleResetOverrides = useCallback(() => {
346
353
  if (sidebarSelection?.scope === "variant") {
347
354
  initOverridesFromVariant(
@@ -378,13 +385,6 @@ function useEditorState({
378
385
  setIsPublished(false);
379
386
  scheduleSave();
380
387
  }, [configuratorState, scheduleSave]);
381
- const handleThemeChange = useCallback(
382
- (theme) => {
383
- setActiveTheme(theme);
384
- dispatch({ type: "SET_PREVIEW_THEME", theme });
385
- },
386
- [dispatch]
387
- );
388
388
  const handleColorModeChange = useCallback(
389
389
  (mode) => {
390
390
  setColorMode(mode);
@@ -446,10 +446,8 @@ function useEditorState({
446
446
  // Preview
447
447
  previewView,
448
448
  colorMode,
449
- activeTheme,
450
449
  handlePreviewNavigate,
451
450
  handleSelectVariant,
452
- handleThemeChange,
453
451
  handleColorModeChange,
454
452
  // Sidebar
455
453
  sidebarSelection,
@@ -489,7 +487,7 @@ function EditorShell({
489
487
  {
490
488
  style: {
491
489
  display: "flex",
492
- height: "100vh",
490
+ height: "100%",
493
491
  overflow: "hidden",
494
492
  backgroundColor: srgbToHex(tokens.background.srgb)
495
493
  },
@@ -501,7 +499,7 @@ function EditorShell({
501
499
  flex: 1,
502
500
  display: "flex",
503
501
  flexDirection: "column",
504
- height: "100vh",
502
+ height: "100%",
505
503
  overflow: "hidden",
506
504
  minWidth: 0
507
505
  },
@@ -564,7 +562,7 @@ function ColorsSection({
564
562
  const palette = state.palettes[activePaletteIndex];
565
563
  const hueRange = SEMANTIC_HUE_RANGES[activePaletteIndex];
566
564
  const isNeutral = activePaletteIndex === 0;
567
- const activeColor = srgbToHex(tokens.interactive.srgb);
565
+ const activeColor = srgbToHex(tokens.accent.fill.srgb);
568
566
  const borderColor = srgbToHex(tokens.border.srgb);
569
567
  const effectiveKeyColor = colorMode === "dark" ? palette.keyColorDark : palette.keyColor;
570
568
  const setKeyColorAction = colorMode === "dark" ? "SET_PALETTE_KEY_COLOR_DARK" : "SET_PALETTE_KEY_COLOR";
@@ -796,7 +794,7 @@ function ColorsSection({
796
794
  style: {
797
795
  fontSize: 12,
798
796
  fontWeight: 500,
799
- color: srgbToHex(tokens.error.srgb)
797
+ color: srgbToHex(tokens.error.fill.srgb)
800
798
  },
801
799
  children: hexError
802
800
  }
@@ -955,7 +953,7 @@ function DualRangeSlider({
955
953
  const tokens = useTokens();
956
954
  const trackRef = useRef(null);
957
955
  const [activeThumb, setActiveThumb] = useState(null);
958
- const interactiveColor = srgbToHex(tokens.interactive.srgb);
956
+ const interactiveColor = srgbToHex(tokens.accent.fill.srgb);
959
957
  const borderColor = srgbToHex(tokens.border.srgb);
960
958
  const wDisplay = internalToDisplay(whitesValue);
961
959
  const bDisplay = internalToDisplay(blacksValue);
@@ -1126,6 +1124,154 @@ function RangeInput({ display, onCommit, toInternal }) {
1126
1124
  }
1127
1125
  );
1128
1126
  }
1127
+ var GRAPH_HEIGHT = 80;
1128
+ var GRAPH_COLS = 256;
1129
+ var GRAPH_ROWS = 64;
1130
+ function strengthToFactor(strength) {
1131
+ switch (strength) {
1132
+ case "none":
1133
+ return 0;
1134
+ case "low":
1135
+ return HUE_GRADING_STRENGTH_LOW;
1136
+ case "medium":
1137
+ return HUE_GRADING_STRENGTH_MEDIUM;
1138
+ case "hard":
1139
+ return HUE_GRADING_STRENGTH_HARD;
1140
+ }
1141
+ }
1142
+ function blendHues(lightHue, darkHue, wLight, wDark) {
1143
+ const totalW = wLight + wDark;
1144
+ if (totalW === 0) return 0;
1145
+ const delta = ((darkHue - lightHue + 180) % 360 + 360) % 360 - 180;
1146
+ const t = wDark / totalW;
1147
+ const result = lightHue + delta * t;
1148
+ return (result % 360 + 360) % 360;
1149
+ }
1150
+ function computeGraphData(state) {
1151
+ const { dynamicRange, globalHueGrading } = state;
1152
+ const lightActive = globalHueGrading.light.strength !== "none";
1153
+ const darkActive = globalHueGrading.dark.strength !== "none";
1154
+ const lightOklchHue = traditionalHueToOklch(globalHueGrading.light.hue);
1155
+ const darkOklchHue = traditionalHueToOklch(globalHueGrading.dark.hue);
1156
+ const lightFactor = strengthToFactor(globalHueGrading.light.strength);
1157
+ const darkFactor = strengthToFactor(globalHueGrading.dark.strength);
1158
+ const buffer = new Uint8ClampedArray(GRAPH_COLS * GRAPH_ROWS * 4);
1159
+ for (let col = 0; col < GRAPH_COLS; col++) {
1160
+ const nv = 1 - col / (GRAPH_COLS - 1);
1161
+ const L = resolveLightness(dynamicRange, nv);
1162
+ const wLight = lightActive ? Math.pow(nv, HUE_GRADING_EASING_POWER) : 0;
1163
+ const wDark = darkActive ? Math.pow(1 - nv, HUE_GRADING_EASING_POWER) : 0;
1164
+ const totalW = wLight + wDark;
1165
+ let topHue;
1166
+ let topChroma;
1167
+ if (totalW === 0) {
1168
+ topHue = 0;
1169
+ topChroma = 0;
1170
+ } else {
1171
+ if (!lightActive) {
1172
+ topHue = darkOklchHue;
1173
+ } else if (!darkActive) {
1174
+ topHue = lightOklchHue;
1175
+ } else {
1176
+ topHue = blendHues(lightOklchHue, darkOklchHue, wLight, wDark);
1177
+ }
1178
+ topChroma = findMaxChromaInGamut(L, topHue) * Math.min(totalW, 1);
1179
+ }
1180
+ for (let row = 0; row < GRAPH_ROWS; row++) {
1181
+ const gradingIntensity = row / (GRAPH_ROWS - 1);
1182
+ const C = topChroma * gradingIntensity;
1183
+ const srgb = clampSrgb(oklchToSrgb({ L, C, h: topHue }));
1184
+ const canvasY = GRAPH_ROWS - 1 - row;
1185
+ const idx = (canvasY * GRAPH_COLS + col) * 4;
1186
+ buffer[idx] = Math.round(srgb.r * 255);
1187
+ buffer[idx + 1] = Math.round(srgb.g * 255);
1188
+ buffer[idx + 2] = Math.round(srgb.b * 255);
1189
+ buffer[idx + 3] = 255;
1190
+ }
1191
+ }
1192
+ const curvePoints = [];
1193
+ for (let i = 0; i < 26; i++) {
1194
+ const nv = 1 - i / 25;
1195
+ const x = i / 25 * (GRAPH_COLS - 1);
1196
+ const lightContrib = Math.pow(nv, HUE_GRADING_EASING_POWER) * (lightFactor / HUE_GRADING_STRENGTH_HARD);
1197
+ const darkContrib = Math.pow(1 - nv, HUE_GRADING_EASING_POWER) * (darkFactor / HUE_GRADING_STRENGTH_HARD);
1198
+ const y = clamp(lightContrib + darkContrib, 0, 1);
1199
+ curvePoints.push({ x, y });
1200
+ }
1201
+ return { buffer, curvePoints };
1202
+ }
1203
+ function DynamicRangeGraph({ state }) {
1204
+ const tokens = useTokens();
1205
+ const canvasRef = useRef(null);
1206
+ const graphData = useMemo(
1207
+ () => computeGraphData(state),
1208
+ [
1209
+ state.dynamicRange.lightest,
1210
+ state.dynamicRange.darkest,
1211
+ state.globalHueGrading.light.strength,
1212
+ state.globalHueGrading.light.hue,
1213
+ state.globalHueGrading.dark.strength,
1214
+ state.globalHueGrading.dark.hue
1215
+ ]
1216
+ );
1217
+ useEffect(() => {
1218
+ const canvas = canvasRef.current;
1219
+ if (!canvas) return;
1220
+ canvas.width = GRAPH_COLS;
1221
+ canvas.height = GRAPH_ROWS;
1222
+ const ctx = canvas.getContext("2d");
1223
+ if (!ctx) return;
1224
+ const imageData = ctx.createImageData(GRAPH_COLS, GRAPH_ROWS);
1225
+ imageData.data.set(graphData.buffer);
1226
+ ctx.putImageData(imageData, 0, 0);
1227
+ const curveColor = srgbToHex(tokens.accent.fill.srgb);
1228
+ const { curvePoints } = graphData;
1229
+ if (curvePoints.length < 2) return;
1230
+ const mapped = curvePoints.map((p) => ({
1231
+ cx: p.x,
1232
+ cy: (1 - p.y) * (GRAPH_ROWS - 1)
1233
+ }));
1234
+ ctx.beginPath();
1235
+ ctx.strokeStyle = curveColor;
1236
+ ctx.lineWidth = 1.5;
1237
+ ctx.lineJoin = "round";
1238
+ ctx.lineCap = "round";
1239
+ ctx.moveTo(mapped[0].cx, mapped[0].cy);
1240
+ for (let i = 0; i < mapped.length - 1; i++) {
1241
+ const p0 = mapped[Math.max(0, i - 1)];
1242
+ const p1 = mapped[i];
1243
+ const p2 = mapped[i + 1];
1244
+ const p3 = mapped[Math.min(mapped.length - 1, i + 2)];
1245
+ const cp1x = p1.cx + (p2.cx - p0.cx) / 6;
1246
+ const cp1y = p1.cy + (p2.cy - p0.cy) / 6;
1247
+ const cp2x = p2.cx - (p3.cx - p1.cx) / 6;
1248
+ const cp2y = p2.cy - (p3.cy - p1.cy) / 6;
1249
+ ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, p2.cx, p2.cy);
1250
+ }
1251
+ ctx.stroke();
1252
+ ctx.fillStyle = curveColor;
1253
+ for (const p of mapped) {
1254
+ ctx.beginPath();
1255
+ ctx.arc(p.cx, p.cy, 2, 0, Math.PI * 2);
1256
+ ctx.fill();
1257
+ }
1258
+ }, [graphData, tokens]);
1259
+ const borderColor = srgbToHex(tokens.border.srgb);
1260
+ return /* @__PURE__ */ jsx(
1261
+ "canvas",
1262
+ {
1263
+ ref: canvasRef,
1264
+ style: {
1265
+ width: "100%",
1266
+ height: GRAPH_HEIGHT,
1267
+ borderRadius: 6,
1268
+ border: `1px solid ${borderColor}`,
1269
+ display: "block",
1270
+ overflow: "hidden"
1271
+ }
1272
+ }
1273
+ );
1274
+ }
1129
1275
  function DynamicRangeSection({
1130
1276
  state,
1131
1277
  dispatch
@@ -1142,6 +1288,7 @@ function DynamicRangeSection({
1142
1288
  const wDisplay = internalToDisplay(state.dynamicRange.lightest);
1143
1289
  const bDisplay = internalToDisplay(state.dynamicRange.darkest);
1144
1290
  return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 12 }, children: [
1291
+ /* @__PURE__ */ jsx(DynamicRangeGraph, { state }),
1145
1292
  /* @__PURE__ */ jsxs(
1146
1293
  "div",
1147
1294
  {
@@ -1348,7 +1495,7 @@ function FontPicker({
1348
1495
  const bgColor = srgbToHex(tokens.backgroundElevated.srgb);
1349
1496
  const borderColor = srgbToHex(tokens.border.srgb);
1350
1497
  const hoverColor = srgbToHex(tokens.backgroundSunken.srgb);
1351
- const interactiveColor = srgbToHex(tokens.interactive.srgb);
1498
+ const interactiveColor = srgbToHex(tokens.accent.fill.srgb);
1352
1499
  useEffect(() => {
1353
1500
  if (!isOpen) return;
1354
1501
  function handleMouseDown(e) {
@@ -1791,9 +1938,9 @@ function PresetSelector({
1791
1938
  const bgColor = srgbToHex(tokens.background.srgb);
1792
1939
  const textPrimary = srgbToHex(tokens.textPrimary.srgb);
1793
1940
  const textSecondary = srgbToHex(tokens.textSecondary.srgb);
1794
- const interactiveColor = srgbToHex(tokens.interactive.srgb);
1795
- const warningColor = srgbToHex(tokens.warning.srgb);
1796
- const errorColor = srgbToHex(tokens.error.srgb);
1941
+ const interactiveColor = srgbToHex(tokens.accent.fill.srgb);
1942
+ const warningColor = srgbToHex(tokens.warning.fill.srgb);
1943
+ const errorColor = srgbToHex(tokens.error.fill.srgb);
1797
1944
  const hoverBg = `${borderColor}18`;
1798
1945
  const activeBg = `${interactiveColor}14`;
1799
1946
  useEffect(() => {
@@ -1885,20 +2032,15 @@ function PresetSelector({
1885
2032
  }
1886
2033
  ),
1887
2034
  /* @__PURE__ */ jsx(
1888
- "svg",
2035
+ Icon,
1889
2036
  {
1890
- width: 10,
1891
- height: 10,
1892
- viewBox: "0 0 24 24",
1893
- fill: "none",
1894
- stroke: "currentColor",
1895
- strokeWidth: 2,
2037
+ name: "expand_more",
2038
+ size: 14,
1896
2039
  style: {
1897
2040
  transform: isOpen ? "rotate(180deg)" : "none",
1898
2041
  transition: "transform 150ms ease",
1899
2042
  flexShrink: 0
1900
- },
1901
- children: /* @__PURE__ */ jsx("polyline", { points: "6 9 12 15 18 9" })
2043
+ }
1902
2044
  }
1903
2045
  )
1904
2046
  ]
@@ -2046,20 +2188,7 @@ function PresetSelector({
2046
2188
  borderRadius: 4,
2047
2189
  flexShrink: 0
2048
2190
  },
2049
- children: /* @__PURE__ */ jsxs(
2050
- "svg",
2051
- {
2052
- width: 14,
2053
- height: 14,
2054
- viewBox: "0 0 24 24",
2055
- fill: "currentColor",
2056
- children: [
2057
- /* @__PURE__ */ jsx("circle", { cx: 12, cy: 5, r: 2 }),
2058
- /* @__PURE__ */ jsx("circle", { cx: 12, cy: 12, r: 2 }),
2059
- /* @__PURE__ */ jsx("circle", { cx: 12, cy: 19, r: 2 })
2060
- ]
2061
- }
2062
- )
2191
+ children: /* @__PURE__ */ jsx(Icon, { name: "more_vert", size: 14, color: textSecondary })
2063
2192
  }
2064
2193
  )
2065
2194
  ] }),
@@ -2178,21 +2307,7 @@ function PresetSelector({
2178
2307
  cursor: "pointer"
2179
2308
  },
2180
2309
  children: [
2181
- /* @__PURE__ */ jsxs(
2182
- "svg",
2183
- {
2184
- width: 14,
2185
- height: 14,
2186
- viewBox: "0 0 24 24",
2187
- fill: "none",
2188
- stroke: "currentColor",
2189
- strokeWidth: 2,
2190
- children: [
2191
- /* @__PURE__ */ jsx("line", { x1: 12, y1: 5, x2: 12, y2: 19 }),
2192
- /* @__PURE__ */ jsx("line", { x1: 5, y1: 12, x2: 19, y2: 12 })
2193
- ]
2194
- }
2195
- ),
2310
+ /* @__PURE__ */ jsx(Icon, { name: "add", size: 14, color: textSecondary }),
2196
2311
  "New preset"
2197
2312
  ]
2198
2313
  }
@@ -2204,67 +2319,12 @@ function PresetSelector({
2204
2319
  }
2205
2320
  var SIDEBAR_WIDTH2 = 360;
2206
2321
  var ACCORDION_SECTIONS = [
2207
- { id: "dynamic-range", label: "Dynamic Range" },
2208
- { id: "colors", label: "Colors" },
2209
- { id: "fonts", label: "Fonts" },
2210
- { id: "icons", label: "Icons" },
2211
- { id: "others", label: "Others" }
2322
+ { id: "dynamic-range", label: "Dynamic Range", icon: "contrast" },
2323
+ { id: "colors", label: "Colors", icon: "palette" },
2324
+ { id: "fonts", label: "Fonts", icon: "text_fields" },
2325
+ { id: "icons", label: "Icons", icon: "grid_view" },
2326
+ { id: "others", label: "Others", icon: "tune" }
2212
2327
  ];
2213
- function SectionIcon({ id }) {
2214
- const props = {
2215
- width: 16,
2216
- height: 16,
2217
- viewBox: "0 0 24 24",
2218
- fill: "none",
2219
- stroke: "currentColor",
2220
- strokeWidth: 2,
2221
- strokeLinecap: "round",
2222
- strokeLinejoin: "round"
2223
- };
2224
- switch (id) {
2225
- case "dynamic-range":
2226
- return /* @__PURE__ */ jsxs("svg", { ...props, children: [
2227
- /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "5" }),
2228
- /* @__PURE__ */ jsx("line", { x1: "12", y1: "1", x2: "12", y2: "3" }),
2229
- /* @__PURE__ */ jsx("line", { x1: "12", y1: "21", x2: "12", y2: "23" }),
2230
- /* @__PURE__ */ jsx("line", { x1: "4.22", y1: "4.22", x2: "5.64", y2: "5.64" }),
2231
- /* @__PURE__ */ jsx("line", { x1: "18.36", y1: "18.36", x2: "19.78", y2: "19.78" }),
2232
- /* @__PURE__ */ jsx("line", { x1: "1", y1: "12", x2: "3", y2: "12" }),
2233
- /* @__PURE__ */ jsx("line", { x1: "21", y1: "12", x2: "23", y2: "12" }),
2234
- /* @__PURE__ */ jsx("line", { x1: "4.22", y1: "19.78", x2: "5.64", y2: "18.36" }),
2235
- /* @__PURE__ */ jsx("line", { x1: "18.36", y1: "5.64", x2: "19.78", y2: "4.22" })
2236
- ] });
2237
- case "colors":
2238
- return /* @__PURE__ */ jsx("svg", { ...props, children: /* @__PURE__ */ jsx("path", { d: "M12 2.69l5.66 5.66a8 8 0 1 1-11.31 0z" }) });
2239
- case "fonts":
2240
- return /* @__PURE__ */ jsxs("svg", { ...props, children: [
2241
- /* @__PURE__ */ jsx("polyline", { points: "4 7 4 4 20 4 20 7" }),
2242
- /* @__PURE__ */ jsx("line", { x1: "9", y1: "20", x2: "15", y2: "20" }),
2243
- /* @__PURE__ */ jsx("line", { x1: "12", y1: "4", x2: "12", y2: "20" })
2244
- ] });
2245
- case "icons":
2246
- return /* @__PURE__ */ jsxs("svg", { ...props, children: [
2247
- /* @__PURE__ */ jsx("rect", { x: "3", y: "3", width: "7", height: "7" }),
2248
- /* @__PURE__ */ jsx("rect", { x: "14", y: "3", width: "7", height: "7" }),
2249
- /* @__PURE__ */ jsx("rect", { x: "3", y: "14", width: "7", height: "7" }),
2250
- /* @__PURE__ */ jsx("rect", { x: "14", y: "14", width: "7", height: "7" })
2251
- ] });
2252
- case "others":
2253
- return /* @__PURE__ */ jsxs("svg", { ...props, children: [
2254
- /* @__PURE__ */ jsx("line", { x1: "4", y1: "21", x2: "4", y2: "14" }),
2255
- /* @__PURE__ */ jsx("line", { x1: "4", y1: "10", x2: "4", y2: "3" }),
2256
- /* @__PURE__ */ jsx("line", { x1: "12", y1: "21", x2: "12", y2: "12" }),
2257
- /* @__PURE__ */ jsx("line", { x1: "12", y1: "8", x2: "12", y2: "3" }),
2258
- /* @__PURE__ */ jsx("line", { x1: "20", y1: "21", x2: "20", y2: "16" }),
2259
- /* @__PURE__ */ jsx("line", { x1: "20", y1: "12", x2: "20", y2: "3" }),
2260
- /* @__PURE__ */ jsx("line", { x1: "1", y1: "14", x2: "7", y2: "14" }),
2261
- /* @__PURE__ */ jsx("line", { x1: "9", y1: "8", x2: "15", y2: "8" }),
2262
- /* @__PURE__ */ jsx("line", { x1: "17", y1: "16", x2: "23", y2: "16" })
2263
- ] });
2264
- default:
2265
- return null;
2266
- }
2267
- }
2268
2328
  function Sidebar({
2269
2329
  state,
2270
2330
  dispatch,
@@ -2412,23 +2472,18 @@ function Sidebar({
2412
2472
  },
2413
2473
  children: [
2414
2474
  /* @__PURE__ */ jsxs("span", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
2415
- /* @__PURE__ */ jsx(SectionIcon, { id: section.id }),
2475
+ /* @__PURE__ */ jsx(Icon, { name: section.icon, size: 16 }),
2416
2476
  section.label
2417
2477
  ] }),
2418
2478
  /* @__PURE__ */ jsx(
2419
- "svg",
2479
+ Icon,
2420
2480
  {
2421
- width: 12,
2422
- height: 12,
2423
- viewBox: "0 0 24 24",
2424
- fill: "none",
2425
- stroke: "currentColor",
2426
- strokeWidth: 2,
2481
+ name: "expand_more",
2482
+ size: 16,
2427
2483
  style: {
2428
2484
  transform: isOpen ? "rotate(180deg)" : "none",
2429
2485
  transition: "transform 150ms ease"
2430
- },
2431
- children: /* @__PURE__ */ jsx("polyline", { points: "6 9 12 15 18 9" })
2486
+ }
2432
2487
  }
2433
2488
  )
2434
2489
  ]
@@ -2502,10 +2557,10 @@ function EditorHeader({
2502
2557
  const tokens = useTokens();
2503
2558
  const borderColor = srgbToHex(tokens.border.srgb);
2504
2559
  const statusColor = {
2505
- saved: srgbToHex(tokens.success.srgb),
2506
- saving: srgbToHex(tokens.warning.srgb),
2560
+ saved: srgbToHex(tokens.success.fill.srgb),
2561
+ saving: srgbToHex(tokens.warning.fill.srgb),
2507
2562
  unsaved: srgbToHex(tokens.textSecondary.srgb),
2508
- error: srgbToHex(tokens.error.srgb)
2563
+ error: srgbToHex(tokens.error.fill.srgb)
2509
2564
  };
2510
2565
  return /* @__PURE__ */ jsxs(
2511
2566
  "div",
@@ -2551,59 +2606,6 @@ function EditorHeader({
2551
2606
  }
2552
2607
  );
2553
2608
  }
2554
- var THEME_CHIPS = [
2555
- { id: "neutral", label: "Neutral" },
2556
- { id: "primary", label: "Primary" },
2557
- { id: "secondary", label: "Secondary" },
2558
- { id: "strong", label: "Strong" }
2559
- ];
2560
- function ThemeBar({ activeTheme, onThemeChange }) {
2561
- const tokens = useTokens();
2562
- const [hoveredChipId, setHoveredChipId] = useState(null);
2563
- const borderColor = srgbToHex(tokens.border.srgb);
2564
- const interactiveColor = srgbToHex(tokens.interactive.srgb);
2565
- return /* @__PURE__ */ jsx(
2566
- "div",
2567
- {
2568
- style: {
2569
- display: "flex",
2570
- alignItems: "center",
2571
- padding: "8px 24px",
2572
- borderBottom: `1px solid ${borderColor}`,
2573
- backgroundColor: srgbToHex(tokens.background.srgb),
2574
- flexShrink: 0
2575
- },
2576
- children: /* @__PURE__ */ jsx("div", { style: { display: "flex", gap: 8 }, role: "group", "aria-label": "Theme", children: THEME_CHIPS.map((chip) => {
2577
- const isActive = chip.id === activeTheme;
2578
- const isHovered = hoveredChipId === chip.id;
2579
- return /* @__PURE__ */ jsx(
2580
- "button",
2581
- {
2582
- onClick: () => onThemeChange(chip.id),
2583
- onMouseEnter: () => setHoveredChipId(chip.id),
2584
- onMouseLeave: () => setHoveredChipId(null),
2585
- "aria-pressed": isActive,
2586
- style: {
2587
- padding: "4px 12px",
2588
- borderRadius: 16,
2589
- border: `1px solid ${srgbToHex(
2590
- isActive ? tokens.interactive.srgb : tokens.border.srgb
2591
- )}`,
2592
- backgroundColor: isActive ? interactiveColor : isHovered ? `${interactiveColor}10` : "transparent",
2593
- color: isActive ? "#fff" : srgbToHex(tokens.textPrimary.srgb),
2594
- fontSize: 12,
2595
- fontWeight: 500,
2596
- cursor: "pointer",
2597
- transition: "background-color 150ms ease"
2598
- },
2599
- children: chip.label
2600
- },
2601
- chip.id
2602
- );
2603
- }) })
2604
- }
2605
- );
2606
- }
2607
2609
  var TOC_WIDTH = 220;
2608
2610
  function TableOfContents({
2609
2611
  activeView,
@@ -2613,7 +2615,7 @@ function TableOfContents({
2613
2615
  const tokens = useTokens();
2614
2616
  const [hoveredId, setHoveredId] = useState(null);
2615
2617
  const borderColor = srgbToHex(tokens.border.srgb);
2616
- const activeColor = srgbToHex(tokens.interactive.srgb);
2618
+ const activeColor = srgbToHex(tokens.accent.fill.srgb);
2617
2619
  const textPrimary = srgbToHex(tokens.textPrimary.srgb);
2618
2620
  const textSecondary = srgbToHex(tokens.textSecondary.srgb);
2619
2621
  const hoverBg = `${borderColor}20`;
@@ -2768,6 +2770,16 @@ function CardPreview(props) {
2768
2770
  )
2769
2771
  ] });
2770
2772
  }
2773
+ function FramePreview(props) {
2774
+ return /* @__PURE__ */ jsx(Frame, { ...props, style: { minWidth: 200, minHeight: 60 }, children: /* @__PURE__ */ jsx(Text, { size: "sm", children: "Frame content" }) });
2775
+ }
2776
+ function WrapperPreview(props) {
2777
+ return /* @__PURE__ */ jsxs(Wrapper, { ...props, style: { minWidth: 200 }, children: [
2778
+ /* @__PURE__ */ jsx(Text, { size: "sm", children: "Item 1" }),
2779
+ /* @__PURE__ */ jsx(Text, { size: "sm", children: "Item 2" }),
2780
+ /* @__PURE__ */ jsx(Text, { size: "sm", children: "Item 3" })
2781
+ ] });
2782
+ }
2771
2783
  function ComponentRenderer({ componentId, props }) {
2772
2784
  const noop = useCallback(() => {
2773
2785
  }, []);
@@ -2778,9 +2790,11 @@ function ComponentRenderer({ componentId, props }) {
2778
2790
  Button,
2779
2791
  {
2780
2792
  variant: props.variant,
2793
+ semantic: props.semantic,
2781
2794
  size: props.size,
2782
2795
  icon,
2783
2796
  iconPosition: props.iconPosition,
2797
+ disabled: props.disabled,
2784
2798
  onPress: noop,
2785
2799
  children: "Button"
2786
2800
  }
@@ -2798,6 +2812,30 @@ function ComponentRenderer({ componentId, props }) {
2798
2812
  return /* @__PURE__ */ jsx(StatefulHueSlider, { ...props });
2799
2813
  case "card":
2800
2814
  return /* @__PURE__ */ jsx(CardPreview, { ...props });
2815
+ case "text":
2816
+ return /* @__PURE__ */ jsx(
2817
+ Text,
2818
+ {
2819
+ size: props.size,
2820
+ weight: props.weight,
2821
+ color: props.color,
2822
+ font: props.font,
2823
+ children: "The quick brown fox"
2824
+ }
2825
+ );
2826
+ case "icon":
2827
+ return /* @__PURE__ */ jsx(
2828
+ Icon,
2829
+ {
2830
+ name: props.name ?? "home",
2831
+ size: props.size,
2832
+ fill: props.fill
2833
+ }
2834
+ );
2835
+ case "frame":
2836
+ return /* @__PURE__ */ jsx(FramePreview, { ...props });
2837
+ case "wrapper":
2838
+ return /* @__PURE__ */ jsx(WrapperPreview, { ...props });
2801
2839
  default:
2802
2840
  return null;
2803
2841
  }
@@ -2921,7 +2959,7 @@ function ComponentCard({
2921
2959
  padding: 20,
2922
2960
  borderRadius: 12,
2923
2961
  border: `1px solid ${srgbToHex(
2924
- isHovered ? tokens.interactive.srgb : tokens.border.srgb
2962
+ isHovered ? tokens.accent.fill.srgb : tokens.border.srgb
2925
2963
  )}`,
2926
2964
  backgroundColor: srgbToHex(tokens.backgroundElevated.srgb),
2927
2965
  cursor: "pointer",
@@ -3031,7 +3069,7 @@ function CategoryView({
3031
3069
  padding: 24,
3032
3070
  borderRadius: 12,
3033
3071
  border: `1px solid ${srgbToHex(
3034
- isHovered ? tokens.interactive.srgb : tokens.border.srgb
3072
+ isHovered ? tokens.accent.fill.srgb : tokens.border.srgb
3035
3073
  )}`,
3036
3074
  backgroundColor: srgbToHex(tokens.backgroundElevated.srgb),
3037
3075
  cursor: "pointer",
@@ -3110,17 +3148,239 @@ function CategoryView({
3110
3148
  )
3111
3149
  ] });
3112
3150
  }
3151
+ function IconBrowserView({
3152
+ selectedIconName,
3153
+ onIconSelect
3154
+ }) {
3155
+ const tokens = useTokens();
3156
+ const [search, setSearch] = useState("");
3157
+ const [hoveredIcon, setHoveredIcon] = useState(null);
3158
+ const scrollRef = useRef(null);
3159
+ const filteredCategories = useMemo(() => {
3160
+ const q = search.toLowerCase().trim();
3161
+ if (!q) return ICON_CATALOG;
3162
+ return ICON_CATALOG.map((cat) => ({
3163
+ ...cat,
3164
+ icons: cat.icons.filter((name) => name.includes(q))
3165
+ })).filter((cat) => cat.icons.length > 0);
3166
+ }, [search]);
3167
+ useEffect(() => {
3168
+ if (!selectedIconName || !scrollRef.current) return;
3169
+ const el = scrollRef.current.querySelector(
3170
+ `[data-icon="${selectedIconName}"]`
3171
+ );
3172
+ if (el) {
3173
+ el.scrollIntoView({ behavior: "smooth", block: "nearest" });
3174
+ }
3175
+ }, [selectedIconName]);
3176
+ const accentColor = srgbToHex(tokens.accent.fill.srgb);
3177
+ return /* @__PURE__ */ jsxs(
3178
+ "div",
3179
+ {
3180
+ style: {
3181
+ display: "flex",
3182
+ flexDirection: "column",
3183
+ height: "100%",
3184
+ minHeight: 0
3185
+ },
3186
+ children: [
3187
+ /* @__PURE__ */ jsx("div", { style: { padding: "0 32px", flexShrink: 0 }, children: /* @__PURE__ */ jsxs("div", { style: { position: "relative" }, children: [
3188
+ /* @__PURE__ */ jsx(
3189
+ Icon,
3190
+ {
3191
+ name: "search",
3192
+ size: 18,
3193
+ color: srgbToHex(tokens.textTertiary.srgb),
3194
+ style: {
3195
+ position: "absolute",
3196
+ left: 10,
3197
+ top: 9,
3198
+ pointerEvents: "none"
3199
+ }
3200
+ }
3201
+ ),
3202
+ /* @__PURE__ */ jsx(
3203
+ "input",
3204
+ {
3205
+ type: "text",
3206
+ placeholder: "Search icons...",
3207
+ value: search,
3208
+ onChange: (e) => setSearch(e.target.value),
3209
+ style: {
3210
+ width: "100%",
3211
+ padding: "8px 12px 8px 34px",
3212
+ borderRadius: 8,
3213
+ border: `1px solid ${srgbToHex(tokens.border.srgb)}`,
3214
+ backgroundColor: srgbToHex(tokens.backgroundSunken.srgb),
3215
+ color: srgbToHex(tokens.textPrimary.srgb),
3216
+ fontSize: 13,
3217
+ boxSizing: "border-box",
3218
+ outline: "none"
3219
+ }
3220
+ }
3221
+ )
3222
+ ] }) }),
3223
+ /* @__PURE__ */ jsxs(
3224
+ "div",
3225
+ {
3226
+ ref: scrollRef,
3227
+ style: {
3228
+ flex: 1,
3229
+ overflowY: "auto",
3230
+ padding: "16px 32px 32px"
3231
+ },
3232
+ children: [
3233
+ filteredCategories.length === 0 && /* @__PURE__ */ jsx(
3234
+ "p",
3235
+ {
3236
+ style: {
3237
+ fontSize: 13,
3238
+ color: srgbToHex(tokens.textTertiary.srgb),
3239
+ textAlign: "center",
3240
+ marginTop: 32
3241
+ },
3242
+ children: "No icons found"
3243
+ }
3244
+ ),
3245
+ filteredCategories.map((category) => /* @__PURE__ */ jsxs("div", { style: { marginBottom: 24 }, children: [
3246
+ /* @__PURE__ */ jsx(
3247
+ "h3",
3248
+ {
3249
+ style: {
3250
+ fontSize: 12,
3251
+ fontWeight: 600,
3252
+ color: srgbToHex(tokens.textSecondary.srgb),
3253
+ textTransform: "uppercase",
3254
+ letterSpacing: 0.5,
3255
+ margin: "0 0 8px"
3256
+ },
3257
+ children: category.label
3258
+ }
3259
+ ),
3260
+ /* @__PURE__ */ jsx(
3261
+ "div",
3262
+ {
3263
+ style: {
3264
+ display: "grid",
3265
+ gridTemplateColumns: "repeat(auto-fill, minmax(80px, 1fr))",
3266
+ gap: 6
3267
+ },
3268
+ children: category.icons.map((name) => {
3269
+ const isSelected = selectedIconName === name;
3270
+ const isHovered = hoveredIcon === name;
3271
+ const borderColor = isSelected ? accentColor : isHovered ? `${accentColor}66` : "transparent";
3272
+ return /* @__PURE__ */ jsxs(
3273
+ "button",
3274
+ {
3275
+ "data-icon": name,
3276
+ onClick: () => onIconSelect(name),
3277
+ onMouseEnter: () => setHoveredIcon(name),
3278
+ onMouseLeave: () => setHoveredIcon(null),
3279
+ style: {
3280
+ display: "flex",
3281
+ flexDirection: "column",
3282
+ alignItems: "center",
3283
+ justifyContent: "center",
3284
+ gap: 4,
3285
+ padding: "8px 4px 6px",
3286
+ borderRadius: 8,
3287
+ border: `2px solid ${borderColor}`,
3288
+ backgroundColor: isSelected ? srgbToHex(tokens.backgroundElevated.srgb) : "transparent",
3289
+ cursor: "pointer",
3290
+ transition: "border-color 150ms ease"
3291
+ },
3292
+ children: [
3293
+ /* @__PURE__ */ jsx(Icon, { name, size: 40 }),
3294
+ /* @__PURE__ */ jsx(
3295
+ "span",
3296
+ {
3297
+ style: {
3298
+ fontSize: 10,
3299
+ color: isSelected ? accentColor : srgbToHex(tokens.textTertiary.srgb),
3300
+ fontWeight: isSelected ? 600 : 400,
3301
+ maxWidth: "100%",
3302
+ overflow: "hidden",
3303
+ textOverflow: "ellipsis",
3304
+ whiteSpace: "nowrap"
3305
+ },
3306
+ children: name
3307
+ }
3308
+ )
3309
+ ]
3310
+ },
3311
+ name
3312
+ );
3313
+ })
3314
+ }
3315
+ )
3316
+ ] }, category.id))
3317
+ ]
3318
+ }
3319
+ )
3320
+ ]
3321
+ }
3322
+ );
3323
+ }
3113
3324
  function ComponentDetailView({
3114
3325
  componentId,
3115
3326
  selectedVariantId,
3327
+ onSelectVariant,
3116
3328
  propOverrides,
3117
- onSelectVariant
3329
+ onPropOverride
3118
3330
  }) {
3119
3331
  const tokens = useTokens();
3120
3332
  const component = getComponent(componentId);
3121
3333
  const [hoveredId, setHoveredId] = useState(null);
3122
3334
  if (!component) return null;
3123
- const interactiveColor = srgbToHex(tokens.interactive.srgb);
3335
+ if (componentId === "icon" && propOverrides && onPropOverride) {
3336
+ return /* @__PURE__ */ jsxs(
3337
+ "div",
3338
+ {
3339
+ style: {
3340
+ padding: "32px 0 0",
3341
+ height: "100%",
3342
+ display: "flex",
3343
+ flexDirection: "column"
3344
+ },
3345
+ children: [
3346
+ /* @__PURE__ */ jsxs("div", { style: { padding: "0 32px", marginBottom: 24 }, children: [
3347
+ /* @__PURE__ */ jsx(
3348
+ "h2",
3349
+ {
3350
+ style: {
3351
+ fontSize: 22,
3352
+ fontWeight: 700,
3353
+ color: srgbToHex(tokens.textPrimary.srgb),
3354
+ margin: 0,
3355
+ marginBottom: 4
3356
+ },
3357
+ children: component.name
3358
+ }
3359
+ ),
3360
+ /* @__PURE__ */ jsx(
3361
+ "p",
3362
+ {
3363
+ style: {
3364
+ fontSize: 14,
3365
+ color: srgbToHex(tokens.textSecondary.srgb),
3366
+ margin: 0
3367
+ },
3368
+ children: component.description
3369
+ }
3370
+ )
3371
+ ] }),
3372
+ /* @__PURE__ */ jsx(
3373
+ IconBrowserView,
3374
+ {
3375
+ selectedIconName: propOverrides.name ?? "add",
3376
+ onIconSelect: (name) => onPropOverride("name", name)
3377
+ }
3378
+ )
3379
+ ]
3380
+ }
3381
+ );
3382
+ }
3383
+ const interactiveColor = srgbToHex(tokens.accent.fill.srgb);
3124
3384
  return /* @__PURE__ */ jsxs("div", { style: { padding: 32 }, children: [
3125
3385
  /* @__PURE__ */ jsx(
3126
3386
  "h2",
@@ -3195,7 +3455,7 @@ function ComponentDetailView({
3195
3455
  ComponentRenderer,
3196
3456
  {
3197
3457
  componentId,
3198
- props: isSelected && propOverrides ? { ...variant.props, ...propOverrides } : variant.props
3458
+ props: variant.props
3199
3459
  }
3200
3460
  )
3201
3461
  }
@@ -3223,9 +3483,10 @@ function ComponentDetailView({
3223
3483
  function PreviewWindow({
3224
3484
  view,
3225
3485
  selectedVariantId,
3226
- propOverrides,
3227
3486
  onNavigate,
3228
- onSelectVariant
3487
+ onSelectVariant,
3488
+ propOverrides,
3489
+ onPropOverride
3229
3490
  }) {
3230
3491
  const tokens = useTokens();
3231
3492
  const handleNavigateToCategory = useCallback(
@@ -3265,8 +3526,9 @@ function PreviewWindow({
3265
3526
  {
3266
3527
  componentId: view.componentId,
3267
3528
  selectedVariantId,
3529
+ onSelectVariant,
3268
3530
  propOverrides,
3269
- onSelectVariant
3531
+ onPropOverride
3270
3532
  }
3271
3533
  )
3272
3534
  ] })
@@ -3274,50 +3536,89 @@ function PreviewWindow({
3274
3536
  );
3275
3537
  }
3276
3538
  function CopyButton({ text }) {
3539
+ const tokens = useTokens();
3277
3540
  const [copied, setCopied] = useState(false);
3278
3541
  const handleCopy = useCallback(async () => {
3279
3542
  await navigator.clipboard.writeText(text);
3280
3543
  setCopied(true);
3281
3544
  setTimeout(() => setCopied(false), 2e3);
3282
3545
  }, [text]);
3283
- return /* @__PURE__ */ jsx(Button, { variant: "tertiary", semantic: "neutral", size: "sm", icon: copied ? "check" : "content_copy", onPress: handleCopy, children: copied ? "Copied!" : "Copy" });
3546
+ return /* @__PURE__ */ jsx(
3547
+ "button",
3548
+ {
3549
+ onClick: handleCopy,
3550
+ "aria-label": copied ? "Copied" : "Copy code",
3551
+ style: {
3552
+ background: "none",
3553
+ border: "none",
3554
+ cursor: "pointer",
3555
+ padding: 4,
3556
+ display: "flex",
3557
+ alignItems: "center",
3558
+ justifyContent: "center",
3559
+ color: srgbToHex(
3560
+ copied ? tokens.accent.fill.srgb : tokens.textTertiary.srgb
3561
+ ),
3562
+ transition: "color 150ms ease"
3563
+ },
3564
+ children: /* @__PURE__ */ jsx(
3565
+ Icon,
3566
+ {
3567
+ name: copied ? "check" : "content_copy",
3568
+ size: 16,
3569
+ color: srgbToHex(
3570
+ copied ? tokens.accent.fill.srgb : tokens.textTertiary.srgb
3571
+ )
3572
+ }
3573
+ )
3574
+ }
3575
+ );
3284
3576
  }
3285
3577
  function CodeBlock({
3286
3578
  code
3287
3579
  }) {
3288
3580
  const tokens = useTokens();
3289
- return /* @__PURE__ */ jsxs("div", { style: { position: "relative" }, children: [
3290
- /* @__PURE__ */ jsx(
3291
- "div",
3292
- {
3293
- style: {
3294
- position: "absolute",
3295
- top: 8,
3296
- right: 8
3297
- },
3298
- children: /* @__PURE__ */ jsx(CopyButton, { text: code })
3299
- }
3300
- ),
3301
- /* @__PURE__ */ jsx(
3302
- "pre",
3303
- {
3304
- style: {
3305
- backgroundColor: srgbToHex(tokens.backgroundSunken.srgb),
3306
- border: `1px solid ${srgbToHex(tokens.border.srgb)}`,
3307
- borderRadius: 8,
3308
- padding: 16,
3309
- paddingRight: 80,
3310
- overflow: "auto",
3311
- fontSize: 13,
3312
- lineHeight: 1.5,
3313
- fontFamily: "'SF Mono', 'Fira Code', 'Fira Mono', Menlo, monospace",
3314
- color: srgbToHex(tokens.textPrimary.srgb),
3315
- margin: 0
3316
- },
3317
- children: /* @__PURE__ */ jsx("code", { children: code })
3318
- }
3319
- )
3320
- ] });
3581
+ return /* @__PURE__ */ jsxs(
3582
+ "div",
3583
+ {
3584
+ style: {
3585
+ backgroundColor: srgbToHex(tokens.backgroundSunken.srgb),
3586
+ border: `1px solid ${srgbToHex(tokens.border.srgb)}`,
3587
+ borderRadius: 8,
3588
+ overflow: "hidden"
3589
+ },
3590
+ children: [
3591
+ /* @__PURE__ */ jsx(
3592
+ "div",
3593
+ {
3594
+ style: {
3595
+ display: "flex",
3596
+ justifyContent: "flex-end",
3597
+ padding: "4px 8px",
3598
+ borderBottom: `1px solid ${srgbToHex(tokens.border.srgb)}`
3599
+ },
3600
+ children: /* @__PURE__ */ jsx(CopyButton, { text: code })
3601
+ }
3602
+ ),
3603
+ /* @__PURE__ */ jsx(
3604
+ "pre",
3605
+ {
3606
+ style: {
3607
+ padding: "12px 16px",
3608
+ whiteSpace: "pre-wrap",
3609
+ wordBreak: "break-word",
3610
+ fontSize: 13,
3611
+ lineHeight: 1.5,
3612
+ fontFamily: "'SF Mono', 'Fira Code', 'Fira Mono', Menlo, monospace",
3613
+ color: srgbToHex(tokens.textPrimary.srgb),
3614
+ margin: 0
3615
+ },
3616
+ children: /* @__PURE__ */ jsx("code", { children: code })
3617
+ }
3618
+ )
3619
+ ]
3620
+ }
3621
+ );
3321
3622
  }
3322
3623
  function RightSidebar({
3323
3624
  selection,
@@ -3325,7 +3626,9 @@ function RightSidebar({
3325
3626
  onPropOverride,
3326
3627
  onResetOverrides,
3327
3628
  onClose,
3328
- onScopeToComponent
3629
+ onScopeToComponent,
3630
+ previewConfig,
3631
+ colorMode
3329
3632
  }) {
3330
3633
  const tokens = useTokens();
3331
3634
  const visible = selection !== null;
@@ -3378,23 +3681,7 @@ function RightSidebar({
3378
3681
  display: "flex",
3379
3682
  alignItems: "center"
3380
3683
  },
3381
- children: /* @__PURE__ */ jsxs(
3382
- "svg",
3383
- {
3384
- width: 16,
3385
- height: 16,
3386
- viewBox: "0 0 24 24",
3387
- fill: "none",
3388
- stroke: "currentColor",
3389
- strokeWidth: 2,
3390
- strokeLinecap: "round",
3391
- strokeLinejoin: "round",
3392
- children: [
3393
- /* @__PURE__ */ jsx("line", { x1: "19", y1: "12", x2: "5", y2: "12" }),
3394
- /* @__PURE__ */ jsx("polyline", { points: "12 19 5 12 12 5" })
3395
- ]
3396
- }
3397
- )
3684
+ children: /* @__PURE__ */ jsx(Icon, { name: "arrow_back", size: 16, color: srgbToHex(tokens.textSecondary.srgb) })
3398
3685
  }
3399
3686
  ),
3400
3687
  selection.scope === "variant" && variant ? /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -3410,7 +3697,7 @@ function RightSidebar({
3410
3697
  padding: 0,
3411
3698
  fontSize: 14,
3412
3699
  fontWeight: 500,
3413
- color: srgbToHex(tokens.interactive.srgb),
3700
+ color: srgbToHex(tokens.accent.fill.srgb),
3414
3701
  whiteSpace: "nowrap"
3415
3702
  },
3416
3703
  children: component.name
@@ -3463,6 +3750,32 @@ function RightSidebar({
3463
3750
  padding: 16
3464
3751
  },
3465
3752
  children: [
3753
+ /* @__PURE__ */ jsx(
3754
+ "div",
3755
+ {
3756
+ style: {
3757
+ marginBottom: 20,
3758
+ borderRadius: 8,
3759
+ border: `1px solid ${srgbToHex(tokens.border.srgb)}`,
3760
+ overflow: "hidden"
3761
+ },
3762
+ children: /* @__PURE__ */ jsx(
3763
+ NewtoneProvider,
3764
+ {
3765
+ config: previewConfig,
3766
+ initialMode: colorMode,
3767
+ children: /* @__PURE__ */ jsx(
3768
+ PreviewSurface,
3769
+ {
3770
+ componentId: selection.componentId,
3771
+ propOverrides
3772
+ }
3773
+ )
3774
+ },
3775
+ colorMode
3776
+ )
3777
+ }
3778
+ ),
3466
3779
  /* @__PURE__ */ jsx(
3467
3780
  "h3",
3468
3781
  {
@@ -3530,6 +3843,26 @@ function RightSidebar({
3530
3843
  }
3531
3844
  );
3532
3845
  }
3846
+ function PreviewSurface({
3847
+ componentId,
3848
+ propOverrides
3849
+ }) {
3850
+ const previewTokens = useTokens();
3851
+ return /* @__PURE__ */ jsx(
3852
+ "div",
3853
+ {
3854
+ style: {
3855
+ display: "flex",
3856
+ alignItems: "center",
3857
+ justifyContent: "center",
3858
+ padding: 24,
3859
+ height: 120,
3860
+ backgroundColor: srgbToHex(previewTokens.backgroundElevated.srgb)
3861
+ },
3862
+ children: /* @__PURE__ */ jsx(ComponentRenderer, { componentId, props: propOverrides })
3863
+ }
3864
+ );
3865
+ }
3533
3866
  function PropControl({
3534
3867
  prop,
3535
3868
  value,
@@ -3557,41 +3890,17 @@ function PropControl({
3557
3890
  boxSizing: "border-box"
3558
3891
  };
3559
3892
  return /* @__PURE__ */ jsxs("div", { children: [
3560
- /* @__PURE__ */ jsxs(
3561
- "div",
3893
+ /* @__PURE__ */ jsx("div", { style: { marginBottom: 4 }, children: /* @__PURE__ */ jsx(
3894
+ "span",
3562
3895
  {
3563
3896
  style: {
3564
- display: "flex",
3565
- alignItems: "center",
3566
- justifyContent: "space-between",
3567
- marginBottom: 4
3897
+ fontSize: 12,
3898
+ fontWeight: 500,
3899
+ color: srgbToHex(tokens.textPrimary.srgb)
3568
3900
  },
3569
- children: [
3570
- /* @__PURE__ */ jsx(
3571
- "span",
3572
- {
3573
- style: {
3574
- fontSize: 12,
3575
- fontWeight: 500,
3576
- color: srgbToHex(tokens.textPrimary.srgb)
3577
- },
3578
- children: prop.label
3579
- }
3580
- ),
3581
- /* @__PURE__ */ jsx(
3582
- "span",
3583
- {
3584
- style: {
3585
- fontSize: 11,
3586
- color: srgbToHex(tokens.textSecondary.srgb),
3587
- fontFamily: "'SF Mono', 'Fira Code', Menlo, monospace"
3588
- },
3589
- children: prop.control
3590
- }
3591
- )
3592
- ]
3901
+ children: prop.label
3593
3902
  }
3594
- ),
3903
+ ) }),
3595
3904
  prop.control === "select" && prop.options && /* @__PURE__ */ jsx(
3596
3905
  Select,
3597
3906
  {
@@ -3625,7 +3934,54 @@ function PropControl({
3625
3934
  style: inputStyle
3626
3935
  }
3627
3936
  ),
3628
- prop.control === "toggle" && /* @__PURE__ */ jsxs(
3937
+ prop.control === "discrete-slider" && prop.options && (() => {
3938
+ const options = prop.options;
3939
+ const currentIndex = options.findIndex((o) => o.value === value);
3940
+ const idx = currentIndex >= 0 ? currentIndex : 0;
3941
+ return /* @__PURE__ */ jsxs("div", { children: [
3942
+ /* @__PURE__ */ jsx(
3943
+ "input",
3944
+ {
3945
+ type: "range",
3946
+ min: 0,
3947
+ max: options.length - 1,
3948
+ step: 1,
3949
+ value: idx,
3950
+ onChange: (e) => onChange(options[Number(e.target.value)].value),
3951
+ "aria-label": prop.label,
3952
+ style: {
3953
+ width: "100%",
3954
+ accentColor: srgbToHex(tokens.accent.fill.srgb),
3955
+ cursor: "pointer"
3956
+ }
3957
+ }
3958
+ ),
3959
+ /* @__PURE__ */ jsx(
3960
+ "div",
3961
+ {
3962
+ style: {
3963
+ display: "flex",
3964
+ justifyContent: "space-between",
3965
+ marginTop: 2
3966
+ },
3967
+ children: options.map((o) => /* @__PURE__ */ jsx(
3968
+ "span",
3969
+ {
3970
+ style: {
3971
+ fontSize: 11,
3972
+ fontFamily: "'SF Mono', 'Fira Code', Menlo, monospace",
3973
+ color: o.value === value ? srgbToHex(tokens.textPrimary.srgb) : srgbToHex(tokens.textTertiary.srgb),
3974
+ fontWeight: o.value === value ? 600 : 400
3975
+ },
3976
+ children: o.label
3977
+ },
3978
+ String(o.value)
3979
+ ))
3980
+ }
3981
+ )
3982
+ ] });
3983
+ })(),
3984
+ prop.control === "toggle" && /* @__PURE__ */ jsx(
3629
3985
  "div",
3630
3986
  {
3631
3987
  role: "switch",
@@ -3640,47 +3996,35 @@ function PropControl({
3640
3996
  gap: 8,
3641
3997
  cursor: "pointer"
3642
3998
  },
3643
- children: [
3644
- /* @__PURE__ */ jsx(
3645
- "div",
3646
- {
3647
- style: {
3648
- width: 36,
3649
- height: 20,
3650
- borderRadius: 10,
3651
- backgroundColor: value ? srgbToHex(tokens.interactive.srgb) : srgbToHex(tokens.border.srgb),
3652
- position: "relative",
3653
- transition: "background-color 150ms ease",
3654
- flexShrink: 0
3655
- },
3656
- children: /* @__PURE__ */ jsx(
3657
- "div",
3658
- {
3659
- style: {
3660
- width: 16,
3661
- height: 16,
3662
- borderRadius: 8,
3663
- backgroundColor: "#fff",
3664
- position: "absolute",
3665
- top: 2,
3666
- left: value ? 18 : 2,
3667
- transition: "left 150ms ease"
3668
- }
3999
+ children: /* @__PURE__ */ jsx(
4000
+ "div",
4001
+ {
4002
+ style: {
4003
+ width: 36,
4004
+ height: 20,
4005
+ borderRadius: 10,
4006
+ backgroundColor: value ? srgbToHex(tokens.accent.fill.srgb) : srgbToHex(tokens.border.srgb),
4007
+ position: "relative",
4008
+ transition: "background-color 150ms ease",
4009
+ flexShrink: 0
4010
+ },
4011
+ children: /* @__PURE__ */ jsx(
4012
+ "div",
4013
+ {
4014
+ style: {
4015
+ width: 16,
4016
+ height: 16,
4017
+ borderRadius: 8,
4018
+ backgroundColor: "#fff",
4019
+ position: "absolute",
4020
+ top: 2,
4021
+ left: value ? 18 : 2,
4022
+ transition: "left 150ms ease"
3669
4023
  }
3670
- )
3671
- }
3672
- ),
3673
- /* @__PURE__ */ jsx(
3674
- "span",
3675
- {
3676
- style: {
3677
- fontSize: 12,
3678
- color: srgbToHex(tokens.textSecondary.srgb)
3679
- },
3680
- children: value ? "true" : "false"
3681
- }
3682
- )
3683
- ]
4024
+ }
4025
+ )
4026
+ }
4027
+ )
3684
4028
  }
3685
4029
  )
3686
4030
  ] });
@@ -3709,6 +4053,10 @@ function Editor({
3709
4053
  onNavigate,
3710
4054
  initialPreviewView
3711
4055
  });
4056
+ const previewConfig = useMemo(
4057
+ () => chromeThemeConfig.tokenOverrides ? { ...editor.themeConfig, tokenOverrides: chromeThemeConfig.tokenOverrides } : editor.themeConfig,
4058
+ [editor.themeConfig, chromeThemeConfig.tokenOverrides]
4059
+ );
3712
4060
  return /* @__PURE__ */ jsx(NewtoneProvider, { config: chromeThemeConfig, children: /* @__PURE__ */ jsx(
3713
4061
  EditorShell,
3714
4062
  {
@@ -3771,33 +4119,24 @@ function Editor({
3771
4119
  overflow: "hidden",
3772
4120
  minWidth: 0
3773
4121
  },
3774
- children: /* @__PURE__ */ jsxs(
4122
+ children: /* @__PURE__ */ jsx(
3775
4123
  NewtoneProvider,
3776
4124
  {
3777
- config: editor.themeConfig,
4125
+ config: previewConfig,
3778
4126
  initialMode: editor.colorMode,
3779
- initialTheme: editor.activeTheme,
3780
- children: [
3781
- /* @__PURE__ */ jsx(
3782
- ThemeBar,
3783
- {
3784
- activeTheme: editor.activeTheme,
3785
- onThemeChange: editor.handleThemeChange
3786
- }
3787
- ),
3788
- /* @__PURE__ */ jsx("div", { style: { flex: 1, overflowY: "auto", minWidth: 0 }, children: /* @__PURE__ */ jsx(
3789
- PreviewWindow,
3790
- {
3791
- view: editor.previewView,
3792
- selectedVariantId: editor.selectedVariantId,
3793
- propOverrides: editor.propOverrides,
3794
- onNavigate: editor.handlePreviewNavigate,
3795
- onSelectVariant: editor.handleSelectVariant
3796
- }
3797
- ) })
3798
- ]
4127
+ children: /* @__PURE__ */ jsx("div", { style: { flex: 1, overflowY: "auto", minWidth: 0 }, children: /* @__PURE__ */ jsx(
4128
+ PreviewWindow,
4129
+ {
4130
+ view: editor.previewView,
4131
+ selectedVariantId: editor.selectedVariantId,
4132
+ onNavigate: editor.handlePreviewNavigate,
4133
+ onSelectVariant: editor.handleSelectVariant,
4134
+ propOverrides: editor.propOverrides,
4135
+ onPropOverride: editor.handlePropOverride
4136
+ }
4137
+ ) })
3799
4138
  },
3800
- `${editor.colorMode}-${editor.activeTheme}`
4139
+ editor.colorMode
3801
4140
  )
3802
4141
  }
3803
4142
  )
@@ -3812,13 +4151,15 @@ function Editor({
3812
4151
  onPropOverride: editor.handlePropOverride,
3813
4152
  onResetOverrides: editor.handleResetOverrides,
3814
4153
  onClose: editor.handleCloseSidebar,
3815
- onScopeToComponent: editor.handleScopeToComponent
4154
+ onScopeToComponent: editor.handleScopeToComponent,
4155
+ previewConfig,
4156
+ colorMode: editor.colorMode
3816
4157
  }
3817
4158
  )
3818
4159
  }
3819
4160
  ) });
3820
4161
  }
3821
4162
 
3822
- export { CategoryView, CodeBlock, ColorsSection, ComponentDetailView, ComponentRenderer, CopyButton, Editor, EditorHeader, EditorShell, FontPicker, FontsSection, IconsSection, OthersSection, OverviewView, PresetSelector, PreviewWindow, RightSidebar, Sidebar, TableOfContents, ThemeBar, findPreset, presetHasUnpublishedChanges, updatePresetInArray, useEditorState, useHover, usePresets };
4163
+ export { CategoryView, CodeBlock, ColorsSection, ComponentDetailView, ComponentRenderer, CopyButton, Editor, EditorHeader, EditorShell, FontPicker, FontsSection, IconsSection, OthersSection, OverviewView, PresetSelector, PreviewWindow, RightSidebar, Sidebar, TableOfContents, findPreset, presetHasUnpublishedChanges, updatePresetInArray, useEditorState, useHover, usePresets };
3823
4164
  //# sourceMappingURL=index.js.map
3824
4165
  //# sourceMappingURL=index.js.map