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