@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.
- package/dist/Editor.d.ts.map +1 -1
- package/dist/components/CodeBlock.d.ts.map +1 -1
- package/dist/components/PresetSelector.d.ts.map +1 -1
- package/dist/components/PreviewWindow.d.ts +3 -2
- package/dist/components/PreviewWindow.d.ts.map +1 -1
- package/dist/components/RightSidebar.d.ts +4 -1
- package/dist/components/RightSidebar.d.ts.map +1 -1
- package/dist/components/Sidebar.d.ts.map +1 -1
- package/dist/components/sections/DynamicRangeSection.d.ts.map +1 -1
- package/dist/hooks/useEditorState.d.ts +1 -3
- package/dist/hooks/useEditorState.d.ts.map +1 -1
- package/dist/index.cjs +686 -346
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +689 -348
- package/dist/index.js.map +1 -1
- package/dist/preview/ComponentDetailView.d.ts +3 -2
- package/dist/preview/ComponentDetailView.d.ts.map +1 -1
- package/dist/preview/ComponentRenderer.d.ts.map +1 -1
- package/dist/preview/IconBrowserView.d.ts +7 -0
- package/dist/preview/IconBrowserView.d.ts.map +1 -0
- package/dist/types.d.ts +0 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/Editor.tsx +19 -9
- package/src/components/CodeBlock.tsx +42 -14
- package/src/components/EditorHeader.tsx +3 -3
- package/src/components/EditorShell.tsx +2 -2
- package/src/components/FontPicker.tsx +1 -1
- package/src/components/PresetSelector.tsx +11 -36
- package/src/components/PreviewWindow.tsx +6 -3
- package/src/components/RightSidebar.tsx +105 -42
- package/src/components/Sidebar.tsx +12 -92
- package/src/components/TableOfContents.tsx +1 -1
- package/src/components/sections/ColorsSection.tsx +2 -2
- package/src/components/sections/DynamicRangeSection.tsx +226 -3
- package/src/hooks/useEditorState.ts +14 -19
- package/src/index.ts +0 -2
- package/src/preview/CategoryView.tsx +1 -1
- package/src/preview/ComponentDetailView.tsx +47 -8
- package/src/preview/ComponentRenderer.tsx +51 -0
- package/src/preview/IconBrowserView.tsx +187 -0
- package/src/preview/OverviewView.tsx +1 -1
- package/src/types.ts +0 -2
- package/dist/components/ThemeBar.d.ts +0 -8
- package/dist/components/ThemeBar.d.ts.map +0 -1
- package/src/components/ThemeBar.tsx +0 -76
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
interface ComponentDetailViewProps {
|
|
2
2
|
readonly componentId: string;
|
|
3
3
|
readonly selectedVariantId: string | null;
|
|
4
|
-
readonly propOverrides?: Record<string, unknown>;
|
|
5
4
|
readonly onSelectVariant: (variantId: string) => void;
|
|
5
|
+
readonly propOverrides?: Record<string, unknown>;
|
|
6
|
+
readonly onPropOverride?: (name: string, value: unknown) => void;
|
|
6
7
|
}
|
|
7
|
-
export declare function ComponentDetailView({ componentId, selectedVariantId, propOverrides,
|
|
8
|
+
export declare function ComponentDetailView({ componentId, selectedVariantId, onSelectVariant, propOverrides, onPropOverride, }: ComponentDetailViewProps): import("react/jsx-runtime").JSX.Element | null;
|
|
8
9
|
export {};
|
|
9
10
|
//# sourceMappingURL=ComponentDetailView.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ComponentDetailView.d.ts","sourceRoot":"","sources":["../../src/preview/ComponentDetailView.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ComponentDetailView.d.ts","sourceRoot":"","sources":["../../src/preview/ComponentDetailView.tsx"],"names":[],"mappings":"AAOA,UAAU,wBAAwB;IAChC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1C,QAAQ,CAAC,eAAe,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACtD,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjD,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CAClE;AAED,wBAAgB,mBAAmB,CAAC,EAClC,WAAW,EACX,iBAAiB,EACjB,eAAe,EACf,aAAa,EACb,cAAc,GACf,EAAE,wBAAwB,kDA+I1B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ComponentRenderer.d.ts","sourceRoot":"","sources":["../../src/preview/ComponentRenderer.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ComponentRenderer.d.ts","sourceRoot":"","sources":["../../src/preview/ComponentRenderer.tsx"],"names":[],"mappings":"AAiBA,UAAU,sBAAsB;IAC9B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACzC;AA2ED,wBAAgB,iBAAiB,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE,sBAAsB,kDA8D/E"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
interface IconBrowserViewProps {
|
|
2
|
+
readonly selectedIconName: string;
|
|
3
|
+
readonly onIconSelect: (name: string) => void;
|
|
4
|
+
}
|
|
5
|
+
export declare function IconBrowserView({ selectedIconName, onIconSelect, }: IconBrowserViewProps): import("react/jsx-runtime").JSX.Element;
|
|
6
|
+
export {};
|
|
7
|
+
//# sourceMappingURL=IconBrowserView.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IconBrowserView.d.ts","sourceRoot":"","sources":["../../src/preview/IconBrowserView.tsx"],"names":[],"mappings":"AAIA,UAAU,oBAAoB;IAC5B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC/C;AAED,wBAAgB,eAAe,CAAC,EAC9B,gBAAgB,EAChB,YAAY,GACb,EAAE,oBAAoB,2CA8KtB"}
|
package/dist/types.d.ts
CHANGED
|
@@ -8,7 +8,6 @@ export interface Preset {
|
|
|
8
8
|
readonly published_state: ConfiguratorState | null;
|
|
9
9
|
}
|
|
10
10
|
export type SaveStatus = "saved" | "saving" | "unsaved" | "error";
|
|
11
|
-
export type ThemeName = "neutral" | "primary" | "secondary" | "strong";
|
|
12
11
|
export type PreviewView = {
|
|
13
12
|
readonly kind: "overview";
|
|
14
13
|
} | {
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIvC,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,iBAAiB,CAAC;IACxC,QAAQ,CAAC,eAAe,EAAE,iBAAiB,GAAG,IAAI,CAAC;CACpD;AAID,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC;AAElE,MAAM,MAAM,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/Editor.tsx
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { useMemo } from "react";
|
|
1
2
|
import { NewtoneProvider } from "@newtonedev/components";
|
|
3
|
+
import type { NewtoneThemeConfig } from "@newtonedev/components";
|
|
2
4
|
import { useEditorState } from "./hooks/useEditorState";
|
|
3
5
|
import { EditorShell } from "./components/EditorShell";
|
|
4
6
|
import { Sidebar } from "./components/Sidebar";
|
|
5
7
|
import { EditorHeader } from "./components/EditorHeader";
|
|
6
|
-
import { ThemeBar } from "./components/ThemeBar";
|
|
7
8
|
import { TableOfContents } from "./components/TableOfContents";
|
|
8
9
|
import { PreviewWindow } from "./components/PreviewWindow";
|
|
9
10
|
import { RightSidebar } from "./components/RightSidebar";
|
|
@@ -34,6 +35,17 @@ export function Editor({
|
|
|
34
35
|
initialPreviewView,
|
|
35
36
|
});
|
|
36
37
|
|
|
38
|
+
// Merge token overrides from chrome config into the preview config.
|
|
39
|
+
// Token overrides (from Token Tuner) are stored separately from configurator
|
|
40
|
+
// state, but should apply to the preview so components render accurately.
|
|
41
|
+
const previewConfig: NewtoneThemeConfig = useMemo(
|
|
42
|
+
() =>
|
|
43
|
+
chromeThemeConfig.tokenOverrides
|
|
44
|
+
? { ...editor.themeConfig, tokenOverrides: chromeThemeConfig.tokenOverrides }
|
|
45
|
+
: editor.themeConfig,
|
|
46
|
+
[editor.themeConfig, chromeThemeConfig.tokenOverrides],
|
|
47
|
+
);
|
|
48
|
+
|
|
37
49
|
return (
|
|
38
50
|
<NewtoneProvider config={chromeThemeConfig}>
|
|
39
51
|
<EditorShell
|
|
@@ -90,22 +102,18 @@ export function Editor({
|
|
|
90
102
|
}}
|
|
91
103
|
>
|
|
92
104
|
<NewtoneProvider
|
|
93
|
-
config={
|
|
105
|
+
config={previewConfig}
|
|
94
106
|
initialMode={editor.colorMode}
|
|
95
|
-
|
|
96
|
-
key={`${editor.colorMode}-${editor.activeTheme}`}
|
|
107
|
+
key={editor.colorMode}
|
|
97
108
|
>
|
|
98
|
-
<ThemeBar
|
|
99
|
-
activeTheme={editor.activeTheme}
|
|
100
|
-
onThemeChange={editor.handleThemeChange}
|
|
101
|
-
/>
|
|
102
109
|
<div style={{ flex: 1, overflowY: "auto", minWidth: 0 }}>
|
|
103
110
|
<PreviewWindow
|
|
104
111
|
view={editor.previewView}
|
|
105
112
|
selectedVariantId={editor.selectedVariantId}
|
|
106
|
-
propOverrides={editor.propOverrides}
|
|
107
113
|
onNavigate={editor.handlePreviewNavigate}
|
|
108
114
|
onSelectVariant={editor.handleSelectVariant}
|
|
115
|
+
propOverrides={editor.propOverrides}
|
|
116
|
+
onPropOverride={editor.handlePropOverride}
|
|
109
117
|
/>
|
|
110
118
|
</div>
|
|
111
119
|
</NewtoneProvider>
|
|
@@ -120,6 +128,8 @@ export function Editor({
|
|
|
120
128
|
onResetOverrides={editor.handleResetOverrides}
|
|
121
129
|
onClose={editor.handleCloseSidebar}
|
|
122
130
|
onScopeToComponent={editor.handleScopeToComponent}
|
|
131
|
+
previewConfig={previewConfig}
|
|
132
|
+
colorMode={editor.colorMode}
|
|
123
133
|
/>
|
|
124
134
|
}
|
|
125
135
|
/>
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { useState, useCallback } from "react";
|
|
2
|
-
import { useTokens,
|
|
2
|
+
import { useTokens, Icon } from "@newtonedev/components";
|
|
3
3
|
import { srgbToHex } from "newtone";
|
|
4
4
|
|
|
5
5
|
export function CopyButton({ text }: { readonly text: string }) {
|
|
6
|
+
const tokens = useTokens();
|
|
6
7
|
const [copied, setCopied] = useState(false);
|
|
7
8
|
|
|
8
9
|
const handleCopy = useCallback(async () => {
|
|
@@ -12,9 +13,31 @@ export function CopyButton({ text }: { readonly text: string }) {
|
|
|
12
13
|
}, [text]);
|
|
13
14
|
|
|
14
15
|
return (
|
|
15
|
-
<
|
|
16
|
-
{
|
|
17
|
-
|
|
16
|
+
<button
|
|
17
|
+
onClick={handleCopy}
|
|
18
|
+
aria-label={copied ? "Copied" : "Copy code"}
|
|
19
|
+
style={{
|
|
20
|
+
background: "none",
|
|
21
|
+
border: "none",
|
|
22
|
+
cursor: "pointer",
|
|
23
|
+
padding: 4,
|
|
24
|
+
display: "flex",
|
|
25
|
+
alignItems: "center",
|
|
26
|
+
justifyContent: "center",
|
|
27
|
+
color: srgbToHex(
|
|
28
|
+
copied ? tokens.accent.fill.srgb : tokens.textTertiary.srgb,
|
|
29
|
+
),
|
|
30
|
+
transition: "color 150ms ease",
|
|
31
|
+
}}
|
|
32
|
+
>
|
|
33
|
+
<Icon
|
|
34
|
+
name={copied ? "check" : "content_copy"}
|
|
35
|
+
size={16}
|
|
36
|
+
color={srgbToHex(
|
|
37
|
+
copied ? tokens.accent.fill.srgb : tokens.textTertiary.srgb,
|
|
38
|
+
)}
|
|
39
|
+
/>
|
|
40
|
+
</button>
|
|
18
41
|
);
|
|
19
42
|
}
|
|
20
43
|
|
|
@@ -26,24 +49,29 @@ export function CodeBlock({
|
|
|
26
49
|
const tokens = useTokens();
|
|
27
50
|
|
|
28
51
|
return (
|
|
29
|
-
<div
|
|
52
|
+
<div
|
|
53
|
+
style={{
|
|
54
|
+
backgroundColor: srgbToHex(tokens.backgroundSunken.srgb),
|
|
55
|
+
border: `1px solid ${srgbToHex(tokens.border.srgb)}`,
|
|
56
|
+
borderRadius: 8,
|
|
57
|
+
overflow: "hidden",
|
|
58
|
+
}}
|
|
59
|
+
>
|
|
30
60
|
<div
|
|
31
61
|
style={{
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
62
|
+
display: "flex",
|
|
63
|
+
justifyContent: "flex-end",
|
|
64
|
+
padding: "4px 8px",
|
|
65
|
+
borderBottom: `1px solid ${srgbToHex(tokens.border.srgb)}`,
|
|
35
66
|
}}
|
|
36
67
|
>
|
|
37
68
|
<CopyButton text={code} />
|
|
38
69
|
</div>
|
|
39
70
|
<pre
|
|
40
71
|
style={{
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
padding: 16,
|
|
45
|
-
paddingRight: 80,
|
|
46
|
-
overflow: "auto",
|
|
72
|
+
padding: "12px 16px",
|
|
73
|
+
whiteSpace: "pre-wrap",
|
|
74
|
+
wordBreak: "break-word",
|
|
47
75
|
fontSize: 13,
|
|
48
76
|
lineHeight: 1.5,
|
|
49
77
|
fontFamily: "'SF Mono', 'Fira Code', 'Fira Mono', Menlo, monospace",
|
|
@@ -34,10 +34,10 @@ export function EditorHeader({
|
|
|
34
34
|
const borderColor = srgbToHex(tokens.border.srgb);
|
|
35
35
|
|
|
36
36
|
const statusColor: Record<SaveStatus, string> = {
|
|
37
|
-
saved: srgbToHex(tokens.success.srgb),
|
|
38
|
-
saving: srgbToHex(tokens.warning.srgb),
|
|
37
|
+
saved: srgbToHex(tokens.success.fill.srgb),
|
|
38
|
+
saving: srgbToHex(tokens.warning.fill.srgb),
|
|
39
39
|
unsaved: srgbToHex(tokens.textSecondary.srgb),
|
|
40
|
-
error: srgbToHex(tokens.error.srgb),
|
|
40
|
+
error: srgbToHex(tokens.error.fill.srgb),
|
|
41
41
|
};
|
|
42
42
|
|
|
43
43
|
return (
|
|
@@ -23,7 +23,7 @@ export function EditorShell({
|
|
|
23
23
|
<div
|
|
24
24
|
style={{
|
|
25
25
|
display: "flex",
|
|
26
|
-
height: "
|
|
26
|
+
height: "100%",
|
|
27
27
|
overflow: "hidden",
|
|
28
28
|
backgroundColor: srgbToHex(tokens.background.srgb),
|
|
29
29
|
}}
|
|
@@ -33,7 +33,7 @@ export function EditorShell({
|
|
|
33
33
|
flex: 1,
|
|
34
34
|
display: "flex",
|
|
35
35
|
flexDirection: "column",
|
|
36
|
-
height: "
|
|
36
|
+
height: "100%",
|
|
37
37
|
overflow: "hidden",
|
|
38
38
|
minWidth: 0,
|
|
39
39
|
}}
|
|
@@ -84,7 +84,7 @@ export function FontPicker({
|
|
|
84
84
|
const bgColor = srgbToHex(tokens.backgroundElevated.srgb);
|
|
85
85
|
const borderColor = srgbToHex(tokens.border.srgb);
|
|
86
86
|
const hoverColor = srgbToHex(tokens.backgroundSunken.srgb);
|
|
87
|
-
const interactiveColor = srgbToHex(tokens.
|
|
87
|
+
const interactiveColor = srgbToHex(tokens.accent.fill.srgb);
|
|
88
88
|
|
|
89
89
|
useEffect(() => {
|
|
90
90
|
if (!isOpen) return;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useState, useRef, useEffect, useCallback } from "react";
|
|
2
|
-
import { useTokens } from "@newtonedev/components";
|
|
2
|
+
import { useTokens, Icon } from "@newtonedev/components";
|
|
3
3
|
import { srgbToHex } from "newtone";
|
|
4
4
|
import type { Preset } from "../types";
|
|
5
5
|
import { presetHasUnpublishedChanges } from "../utils/presets";
|
|
@@ -44,9 +44,9 @@ export function PresetSelector({
|
|
|
44
44
|
const bgColor = srgbToHex(tokens.background.srgb);
|
|
45
45
|
const textPrimary = srgbToHex(tokens.textPrimary.srgb);
|
|
46
46
|
const textSecondary = srgbToHex(tokens.textSecondary.srgb);
|
|
47
|
-
const interactiveColor = srgbToHex(tokens.
|
|
48
|
-
const warningColor = srgbToHex(tokens.warning.srgb);
|
|
49
|
-
const errorColor = srgbToHex(tokens.error.srgb);
|
|
47
|
+
const interactiveColor = srgbToHex(tokens.accent.fill.srgb);
|
|
48
|
+
const warningColor = srgbToHex(tokens.warning.fill.srgb);
|
|
49
|
+
const errorColor = srgbToHex(tokens.error.fill.srgb);
|
|
50
50
|
const hoverBg = `${borderColor}18`;
|
|
51
51
|
const activeBg = `${interactiveColor}14`;
|
|
52
52
|
|
|
@@ -145,21 +145,15 @@ export function PresetSelector({
|
|
|
145
145
|
>
|
|
146
146
|
{activePreset?.name ?? "Default"}
|
|
147
147
|
</span>
|
|
148
|
-
<
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
viewBox="0 0 24 24"
|
|
152
|
-
fill="none"
|
|
153
|
-
stroke="currentColor"
|
|
154
|
-
strokeWidth={2}
|
|
148
|
+
<Icon
|
|
149
|
+
name="expand_more"
|
|
150
|
+
size={14}
|
|
155
151
|
style={{
|
|
156
152
|
transform: isOpen ? "rotate(180deg)" : "none",
|
|
157
153
|
transition: "transform 150ms ease",
|
|
158
154
|
flexShrink: 0,
|
|
159
|
-
}}
|
|
160
|
-
|
|
161
|
-
<polyline points="6 9 12 15 18 9" />
|
|
162
|
-
</svg>
|
|
155
|
+
} as any}
|
|
156
|
+
/>
|
|
163
157
|
</button>
|
|
164
158
|
|
|
165
159
|
{isOpen && (
|
|
@@ -303,16 +297,7 @@ export function PresetSelector({
|
|
|
303
297
|
flexShrink: 0,
|
|
304
298
|
}}
|
|
305
299
|
>
|
|
306
|
-
<
|
|
307
|
-
width={14}
|
|
308
|
-
height={14}
|
|
309
|
-
viewBox="0 0 24 24"
|
|
310
|
-
fill="currentColor"
|
|
311
|
-
>
|
|
312
|
-
<circle cx={12} cy={5} r={2} />
|
|
313
|
-
<circle cx={12} cy={12} r={2} />
|
|
314
|
-
<circle cx={12} cy={19} r={2} />
|
|
315
|
-
</svg>
|
|
300
|
+
<Icon name="more_vert" size={14} color={textSecondary} />
|
|
316
301
|
</button>
|
|
317
302
|
)}
|
|
318
303
|
</>
|
|
@@ -435,17 +420,7 @@ export function PresetSelector({
|
|
|
435
420
|
cursor: "pointer",
|
|
436
421
|
}}
|
|
437
422
|
>
|
|
438
|
-
<
|
|
439
|
-
width={14}
|
|
440
|
-
height={14}
|
|
441
|
-
viewBox="0 0 24 24"
|
|
442
|
-
fill="none"
|
|
443
|
-
stroke="currentColor"
|
|
444
|
-
strokeWidth={2}
|
|
445
|
-
>
|
|
446
|
-
<line x1={12} y1={5} x2={12} y2={19} />
|
|
447
|
-
<line x1={5} y1={12} x2={19} y2={12} />
|
|
448
|
-
</svg>
|
|
423
|
+
<Icon name="add" size={14} color={textSecondary} />
|
|
449
424
|
New preset
|
|
450
425
|
</button>
|
|
451
426
|
</div>
|
|
@@ -9,17 +9,19 @@ import type { PreviewView } from "../types";
|
|
|
9
9
|
interface PreviewWindowProps {
|
|
10
10
|
readonly view: PreviewView;
|
|
11
11
|
readonly selectedVariantId: string | null;
|
|
12
|
-
readonly propOverrides?: Record<string, unknown>;
|
|
13
12
|
readonly onNavigate: (view: PreviewView) => void;
|
|
14
13
|
readonly onSelectVariant: (variantId: string) => void;
|
|
14
|
+
readonly propOverrides?: Record<string, unknown>;
|
|
15
|
+
readonly onPropOverride?: (name: string, value: unknown) => void;
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
export function PreviewWindow({
|
|
18
19
|
view,
|
|
19
20
|
selectedVariantId,
|
|
20
|
-
propOverrides,
|
|
21
21
|
onNavigate,
|
|
22
22
|
onSelectVariant,
|
|
23
|
+
propOverrides,
|
|
24
|
+
onPropOverride,
|
|
23
25
|
}: PreviewWindowProps) {
|
|
24
26
|
const tokens = useTokens();
|
|
25
27
|
|
|
@@ -59,8 +61,9 @@ export function PreviewWindow({
|
|
|
59
61
|
<ComponentDetailView
|
|
60
62
|
componentId={view.componentId}
|
|
61
63
|
selectedVariantId={selectedVariantId}
|
|
62
|
-
propOverrides={propOverrides}
|
|
63
64
|
onSelectVariant={onSelectVariant}
|
|
65
|
+
propOverrides={propOverrides}
|
|
66
|
+
onPropOverride={onPropOverride}
|
|
64
67
|
/>
|
|
65
68
|
)}
|
|
66
69
|
</div>
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { useCallback, type KeyboardEvent } from "react";
|
|
2
|
-
import { useTokens, getComponent, generateComponentCode, Select } from "@newtonedev/components";
|
|
3
|
-
import type { EditableProp } from "@newtonedev/components";
|
|
2
|
+
import { useTokens, getComponent, generateComponentCode, Select, NewtoneProvider, Icon } from "@newtonedev/components";
|
|
3
|
+
import type { EditableProp, NewtoneThemeConfig, ColorMode } from "@newtonedev/components";
|
|
4
4
|
import { srgbToHex } from "newtone";
|
|
5
5
|
import { CodeBlock } from "./CodeBlock";
|
|
6
|
+
import { ComponentRenderer } from "../preview/ComponentRenderer";
|
|
6
7
|
import type { SidebarSelection } from "../types";
|
|
7
8
|
|
|
8
9
|
interface RightSidebarProps {
|
|
@@ -12,6 +13,8 @@ interface RightSidebarProps {
|
|
|
12
13
|
readonly onResetOverrides: () => void;
|
|
13
14
|
readonly onClose: () => void;
|
|
14
15
|
readonly onScopeToComponent: () => void;
|
|
16
|
+
readonly previewConfig: NewtoneThemeConfig;
|
|
17
|
+
readonly colorMode: ColorMode;
|
|
15
18
|
}
|
|
16
19
|
|
|
17
20
|
export function RightSidebar({
|
|
@@ -21,6 +24,8 @@ export function RightSidebar({
|
|
|
21
24
|
onResetOverrides,
|
|
22
25
|
onClose,
|
|
23
26
|
onScopeToComponent,
|
|
27
|
+
previewConfig,
|
|
28
|
+
colorMode,
|
|
24
29
|
}: RightSidebarProps) {
|
|
25
30
|
const tokens = useTokens();
|
|
26
31
|
const visible = selection !== null;
|
|
@@ -79,19 +84,7 @@ export function RightSidebar({
|
|
|
79
84
|
alignItems: "center",
|
|
80
85
|
}}
|
|
81
86
|
>
|
|
82
|
-
<
|
|
83
|
-
width={16}
|
|
84
|
-
height={16}
|
|
85
|
-
viewBox="0 0 24 24"
|
|
86
|
-
fill="none"
|
|
87
|
-
stroke="currentColor"
|
|
88
|
-
strokeWidth={2}
|
|
89
|
-
strokeLinecap="round"
|
|
90
|
-
strokeLinejoin="round"
|
|
91
|
-
>
|
|
92
|
-
<line x1="19" y1="12" x2="5" y2="12" />
|
|
93
|
-
<polyline points="12 19 5 12 12 5" />
|
|
94
|
-
</svg>
|
|
87
|
+
<Icon name="arrow_back" size={16} color={srgbToHex(tokens.textSecondary.srgb)} />
|
|
95
88
|
</button>
|
|
96
89
|
{selection.scope === "variant" && variant ? (
|
|
97
90
|
<>
|
|
@@ -105,7 +98,7 @@ export function RightSidebar({
|
|
|
105
98
|
padding: 0,
|
|
106
99
|
fontSize: 14,
|
|
107
100
|
fontWeight: 500,
|
|
108
|
-
color: srgbToHex(tokens.
|
|
101
|
+
color: srgbToHex(tokens.accent.fill.srgb),
|
|
109
102
|
whiteSpace: "nowrap",
|
|
110
103
|
}}
|
|
111
104
|
>
|
|
@@ -154,6 +147,27 @@ export function RightSidebar({
|
|
|
154
147
|
padding: 16,
|
|
155
148
|
}}
|
|
156
149
|
>
|
|
150
|
+
{/* Live Preview */}
|
|
151
|
+
<div
|
|
152
|
+
style={{
|
|
153
|
+
marginBottom: 20,
|
|
154
|
+
borderRadius: 8,
|
|
155
|
+
border: `1px solid ${srgbToHex(tokens.border.srgb)}`,
|
|
156
|
+
overflow: "hidden",
|
|
157
|
+
}}
|
|
158
|
+
>
|
|
159
|
+
<NewtoneProvider
|
|
160
|
+
config={previewConfig}
|
|
161
|
+
initialMode={colorMode}
|
|
162
|
+
key={colorMode}
|
|
163
|
+
>
|
|
164
|
+
<PreviewSurface
|
|
165
|
+
componentId={selection.componentId}
|
|
166
|
+
propOverrides={propOverrides}
|
|
167
|
+
/>
|
|
168
|
+
</NewtoneProvider>
|
|
169
|
+
</div>
|
|
170
|
+
|
|
157
171
|
<h3
|
|
158
172
|
style={{
|
|
159
173
|
fontSize: 13,
|
|
@@ -222,6 +236,31 @@ export function RightSidebar({
|
|
|
222
236
|
);
|
|
223
237
|
}
|
|
224
238
|
|
|
239
|
+
function PreviewSurface({
|
|
240
|
+
componentId,
|
|
241
|
+
propOverrides,
|
|
242
|
+
}: {
|
|
243
|
+
readonly componentId: string;
|
|
244
|
+
readonly propOverrides: Record<string, unknown>;
|
|
245
|
+
}) {
|
|
246
|
+
const previewTokens = useTokens();
|
|
247
|
+
|
|
248
|
+
return (
|
|
249
|
+
<div
|
|
250
|
+
style={{
|
|
251
|
+
display: "flex",
|
|
252
|
+
alignItems: "center",
|
|
253
|
+
justifyContent: "center",
|
|
254
|
+
padding: 24,
|
|
255
|
+
height: 120,
|
|
256
|
+
backgroundColor: srgbToHex(previewTokens.backgroundElevated.srgb),
|
|
257
|
+
}}
|
|
258
|
+
>
|
|
259
|
+
<ComponentRenderer componentId={componentId} props={propOverrides} />
|
|
260
|
+
</div>
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
|
|
225
264
|
function PropControl({
|
|
226
265
|
prop,
|
|
227
266
|
value,
|
|
@@ -257,14 +296,7 @@ function PropControl({
|
|
|
257
296
|
|
|
258
297
|
return (
|
|
259
298
|
<div>
|
|
260
|
-
<div
|
|
261
|
-
style={{
|
|
262
|
-
display: "flex",
|
|
263
|
-
alignItems: "center",
|
|
264
|
-
justifyContent: "space-between",
|
|
265
|
-
marginBottom: 4,
|
|
266
|
-
}}
|
|
267
|
-
>
|
|
299
|
+
<div style={{ marginBottom: 4 }}>
|
|
268
300
|
<span
|
|
269
301
|
style={{
|
|
270
302
|
fontSize: 12,
|
|
@@ -274,15 +306,6 @@ function PropControl({
|
|
|
274
306
|
>
|
|
275
307
|
{prop.label}
|
|
276
308
|
</span>
|
|
277
|
-
<span
|
|
278
|
-
style={{
|
|
279
|
-
fontSize: 11,
|
|
280
|
-
color: srgbToHex(tokens.textSecondary.srgb),
|
|
281
|
-
fontFamily: "'SF Mono', 'Fira Code', Menlo, monospace",
|
|
282
|
-
}}
|
|
283
|
-
>
|
|
284
|
-
{prop.control}
|
|
285
|
-
</span>
|
|
286
309
|
</div>
|
|
287
310
|
|
|
288
311
|
{prop.control === "select" && prop.options && (
|
|
@@ -318,6 +341,54 @@ function PropControl({
|
|
|
318
341
|
/>
|
|
319
342
|
)}
|
|
320
343
|
|
|
344
|
+
{prop.control === "discrete-slider" && prop.options && (() => {
|
|
345
|
+
const options = prop.options!;
|
|
346
|
+
const currentIndex = options.findIndex((o) => o.value === value);
|
|
347
|
+
const idx = currentIndex >= 0 ? currentIndex : 0;
|
|
348
|
+
|
|
349
|
+
return (
|
|
350
|
+
<div>
|
|
351
|
+
<input
|
|
352
|
+
type="range"
|
|
353
|
+
min={0}
|
|
354
|
+
max={options.length - 1}
|
|
355
|
+
step={1}
|
|
356
|
+
value={idx}
|
|
357
|
+
onChange={(e) => onChange(options[Number(e.target.value)].value)}
|
|
358
|
+
aria-label={prop.label}
|
|
359
|
+
style={{
|
|
360
|
+
width: "100%",
|
|
361
|
+
accentColor: srgbToHex(tokens.accent.fill.srgb),
|
|
362
|
+
cursor: "pointer",
|
|
363
|
+
}}
|
|
364
|
+
/>
|
|
365
|
+
<div
|
|
366
|
+
style={{
|
|
367
|
+
display: "flex",
|
|
368
|
+
justifyContent: "space-between",
|
|
369
|
+
marginTop: 2,
|
|
370
|
+
}}
|
|
371
|
+
>
|
|
372
|
+
{options.map((o) => (
|
|
373
|
+
<span
|
|
374
|
+
key={String(o.value)}
|
|
375
|
+
style={{
|
|
376
|
+
fontSize: 11,
|
|
377
|
+
fontFamily: "'SF Mono', 'Fira Code', Menlo, monospace",
|
|
378
|
+
color: o.value === value
|
|
379
|
+
? srgbToHex(tokens.textPrimary.srgb)
|
|
380
|
+
: srgbToHex(tokens.textTertiary.srgb),
|
|
381
|
+
fontWeight: o.value === value ? 600 : 400,
|
|
382
|
+
}}
|
|
383
|
+
>
|
|
384
|
+
{o.label}
|
|
385
|
+
</span>
|
|
386
|
+
))}
|
|
387
|
+
</div>
|
|
388
|
+
</div>
|
|
389
|
+
);
|
|
390
|
+
})()}
|
|
391
|
+
|
|
321
392
|
{prop.control === "toggle" && (
|
|
322
393
|
<div
|
|
323
394
|
role="switch"
|
|
@@ -339,7 +410,7 @@ function PropControl({
|
|
|
339
410
|
height: 20,
|
|
340
411
|
borderRadius: 10,
|
|
341
412
|
backgroundColor: value
|
|
342
|
-
? srgbToHex(tokens.
|
|
413
|
+
? srgbToHex(tokens.accent.fill.srgb)
|
|
343
414
|
: srgbToHex(tokens.border.srgb),
|
|
344
415
|
position: "relative",
|
|
345
416
|
transition: "background-color 150ms ease",
|
|
@@ -359,14 +430,6 @@ function PropControl({
|
|
|
359
430
|
}}
|
|
360
431
|
/>
|
|
361
432
|
</div>
|
|
362
|
-
<span
|
|
363
|
-
style={{
|
|
364
|
-
fontSize: 12,
|
|
365
|
-
color: srgbToHex(tokens.textSecondary.srgb),
|
|
366
|
-
}}
|
|
367
|
-
>
|
|
368
|
-
{value ? "true" : "false"}
|
|
369
|
-
</span>
|
|
370
433
|
</div>
|
|
371
434
|
)}
|
|
372
435
|
</div>
|