@newtonedev/editor 0.1.5 → 0.1.7
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 +1 -1
- package/dist/Editor.d.ts.map +1 -1
- package/dist/components/CodeBlock.d.ts.map +1 -1
- package/dist/components/ConfiguratorPanel.d.ts +17 -0
- package/dist/components/ConfiguratorPanel.d.ts.map +1 -0
- package/dist/components/FontPicker.d.ts +4 -2
- package/dist/components/FontPicker.d.ts.map +1 -1
- package/dist/components/PresetSelector.d.ts.map +1 -1
- package/dist/components/PreviewWindow.d.ts +9 -3
- package/dist/components/PreviewWindow.d.ts.map +1 -1
- package/dist/components/PrimaryNav.d.ts +7 -0
- package/dist/components/PrimaryNav.d.ts.map +1 -0
- package/dist/components/RightSidebar.d.ts +4 -1
- package/dist/components/RightSidebar.d.ts.map +1 -1
- package/dist/components/Sidebar.d.ts +1 -10
- package/dist/components/Sidebar.d.ts.map +1 -1
- package/dist/components/TableOfContents.d.ts +2 -1
- package/dist/components/TableOfContents.d.ts.map +1 -1
- package/dist/components/sections/DynamicRangeSection.d.ts.map +1 -1
- package/dist/components/sections/FontsSection.d.ts +3 -1
- package/dist/components/sections/FontsSection.d.ts.map +1 -1
- package/dist/hooks/useEditorState.d.ts +4 -1
- package/dist/hooks/useEditorState.d.ts.map +1 -1
- package/dist/index.cjs +2893 -2248
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2895 -2251
- package/dist/index.js.map +1 -1
- package/dist/preview/ComponentDetailView.d.ts +9 -2
- package/dist/preview/ComponentDetailView.d.ts.map +1 -1
- package/dist/preview/ComponentRenderer.d.ts +2 -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 +17 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/lookupFontMetrics.d.ts +19 -0
- package/dist/utils/lookupFontMetrics.d.ts.map +1 -0
- package/dist/utils/measureFonts.d.ts +18 -0
- package/dist/utils/measureFonts.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/Editor.tsx +57 -11
- package/src/components/CodeBlock.tsx +42 -14
- package/src/components/ConfiguratorPanel.tsx +77 -0
- package/src/components/FontPicker.tsx +38 -29
- package/src/components/PresetSelector.tsx +8 -33
- package/src/components/PreviewWindow.tsx +20 -4
- package/src/components/PrimaryNav.tsx +76 -0
- package/src/components/RightSidebar.tsx +103 -40
- package/src/components/Sidebar.tsx +4 -211
- package/src/components/TableOfContents.tsx +41 -78
- package/src/components/sections/DynamicRangeSection.tsx +2 -225
- package/src/components/sections/FontsSection.tsx +61 -93
- package/src/hooks/useEditorState.ts +68 -9
- package/src/index.ts +2 -0
- package/src/preview/ComponentDetailView.tsx +576 -73
- package/src/preview/ComponentRenderer.tsx +6 -4
- package/src/preview/IconBrowserView.tsx +187 -0
- package/src/types.ts +15 -0
- package/src/utils/lookupFontMetrics.ts +52 -0
- package/src/utils/measureFonts.ts +41 -0
|
@@ -1,9 +1,16 @@
|
|
|
1
|
+
import type { TextRole } from "@newtonedev/fonts";
|
|
2
|
+
import type { EditorFontEntry } from "../types";
|
|
1
3
|
interface ComponentDetailViewProps {
|
|
2
4
|
readonly componentId: string;
|
|
3
5
|
readonly selectedVariantId: string | null;
|
|
4
|
-
readonly propOverrides?: Record<string, unknown>;
|
|
5
6
|
readonly onSelectVariant: (variantId: string) => void;
|
|
7
|
+
readonly propOverrides?: Record<string, unknown>;
|
|
8
|
+
readonly onPropOverride?: (name: string, value: unknown) => void;
|
|
9
|
+
readonly roleWeights?: Partial<Record<TextRole, number>>;
|
|
10
|
+
readonly onRoleWeightChange?: (role: TextRole, weight: number) => void;
|
|
11
|
+
readonly fontCatalog?: readonly EditorFontEntry[];
|
|
12
|
+
readonly scopeFontMap?: Record<string, string>;
|
|
6
13
|
}
|
|
7
|
-
export declare function ComponentDetailView({ componentId, selectedVariantId, propOverrides,
|
|
14
|
+
export declare function ComponentDetailView({ componentId, selectedVariantId, onSelectVariant, propOverrides, onPropOverride, roleWeights, onRoleWeightChange, fontCatalog, scopeFontMap, }: ComponentDetailViewProps): import("react/jsx-runtime").JSX.Element | null;
|
|
8
15
|
export {};
|
|
9
16
|
//# 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":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAuC,MAAM,mBAAmB,CAAC;AAIvF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAahD,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;IACjE,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;IACzD,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACvE,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IAClD,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChD;AA+PD,wBAAgB,mBAAmB,CAAC,EAClC,WAAW,EACX,iBAAiB,EACjB,eAAe,EACf,aAAa,EACb,cAAc,EACd,WAAW,EACX,kBAAkB,EAClB,WAAW,EACX,YAAY,GACb,EAAE,wBAAwB,kDA4U1B"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
interface ComponentRendererProps {
|
|
2
2
|
readonly componentId: string;
|
|
3
3
|
readonly props: Record<string, unknown>;
|
|
4
|
+
readonly previewText?: string;
|
|
4
5
|
}
|
|
5
|
-
export declare function ComponentRenderer({ componentId, props }: ComponentRendererProps): import("react/jsx-runtime").JSX.Element | null;
|
|
6
|
+
export declare function ComponentRenderer({ componentId, props, previewText }: ComponentRendererProps): import("react/jsx-runtime").JSX.Element | null;
|
|
6
7
|
export {};
|
|
7
8
|
//# sourceMappingURL=ComponentRenderer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
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;
|
|
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;IACxC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AA2ED,wBAAgB,iBAAiB,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,sBAAsB,kDA+D5F"}
|
|
@@ -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
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
import type { ConfiguratorState } from "@newtonedev/configurator";
|
|
2
2
|
import type { NewtoneThemeConfig } from "@newtonedev/components";
|
|
3
|
+
import type { FontRuntimeMetrics, GoogleFontEntry } from "@newtonedev/fonts";
|
|
3
4
|
import type { ReactNode } from "react";
|
|
5
|
+
/** Font catalog entry enriched with weight metadata for the editor. */
|
|
6
|
+
export interface EditorFontEntry extends GoogleFontEntry {
|
|
7
|
+
readonly isVariable?: boolean;
|
|
8
|
+
readonly availableWeights?: readonly number[];
|
|
9
|
+
/** Weight axis range for variable fonts (from Google Fonts API wght axis). */
|
|
10
|
+
readonly weightAxisRange?: {
|
|
11
|
+
readonly min: number;
|
|
12
|
+
readonly max: number;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
4
15
|
export interface Preset {
|
|
5
16
|
readonly id: string;
|
|
6
17
|
readonly name: string;
|
|
@@ -38,6 +49,8 @@ export interface EditorPersistence {
|
|
|
38
49
|
readonly state: ConfiguratorState;
|
|
39
50
|
readonly presets: readonly Preset[];
|
|
40
51
|
readonly activePresetId: string;
|
|
52
|
+
readonly calibrations?: Record<string, number>;
|
|
53
|
+
readonly fontMetrics?: Record<string, FontRuntimeMetrics>;
|
|
41
54
|
}) => Promise<{
|
|
42
55
|
error?: unknown;
|
|
43
56
|
}>;
|
|
@@ -64,5 +77,9 @@ export interface EditorProps {
|
|
|
64
77
|
readonly headerSlots?: EditorHeaderSlots;
|
|
65
78
|
readonly onNavigate?: (view: PreviewView) => void;
|
|
66
79
|
readonly initialPreviewView?: PreviewView;
|
|
80
|
+
/** URL of the font manifest for metrics lookup at publish time. */
|
|
81
|
+
readonly manifestUrl?: string;
|
|
82
|
+
/** Curated fonts available in the font picker, enriched with weight metadata. */
|
|
83
|
+
readonly fontCatalog?: readonly EditorFontEntry[];
|
|
67
84
|
}
|
|
68
85
|
//# sourceMappingURL=types.d.ts.map
|
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;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { FontScope } from '@newtonedev/fonts';
|
|
2
|
+
import type { FontSlot } from '@newtonedev/components';
|
|
3
|
+
import type { FontRuntimeMetrics } from '@newtonedev/fonts';
|
|
4
|
+
/**
|
|
5
|
+
* Look up FontRuntimeMetrics for all font scopes from the font manifest.
|
|
6
|
+
*
|
|
7
|
+
* Called at publish time alongside measureFontCalibrations. Fetches the
|
|
8
|
+
* manifest JSON from the given URL and extracts metrics for each unique
|
|
9
|
+
* font family in the current typography configuration.
|
|
10
|
+
*
|
|
11
|
+
* Deduplicates by family name so a font used in multiple scopes is
|
|
12
|
+
* looked up only once. Returns empty object if manifest is unavailable.
|
|
13
|
+
*
|
|
14
|
+
* @param fonts - The typography.fonts record from ConfiguratorState.
|
|
15
|
+
* @param manifestUrl - URL of the font manifest (e.g., Supabase Storage public URL).
|
|
16
|
+
* @returns Map of fontFamily → FontRuntimeMetrics.
|
|
17
|
+
*/
|
|
18
|
+
export declare function lookupFontMetrics(fonts: Record<FontScope, FontSlot> | undefined, manifestUrl: string | undefined): Promise<Record<string, FontRuntimeMetrics>>;
|
|
19
|
+
//# sourceMappingURL=lookupFontMetrics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lookupFontMetrics.d.ts","sourceRoot":"","sources":["../../src/utils/lookupFontMetrics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAE5D;;;;;;;;;;;;;GAaG;AACH,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC,GAAG,SAAS,EAC9C,WAAW,EAAE,MAAM,GAAG,SAAS,GAC9B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC,CA8B7C"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { FontScope } from '@newtonedev/fonts';
|
|
2
|
+
import type { FontSlot } from '@newtonedev/components';
|
|
3
|
+
/**
|
|
4
|
+
* Measure avgCharWidth ratios for all font scopes at publish time.
|
|
5
|
+
*
|
|
6
|
+
* Deduplicates by font family name so a font used in multiple scopes is
|
|
7
|
+
* measured only once. Waits for fonts to load via `document.fonts.ready`
|
|
8
|
+
* before measuring, since the editor always preloads fonts for preview.
|
|
9
|
+
*
|
|
10
|
+
* Called in `handlePublish` before writing to persistence so that calibration
|
|
11
|
+
* data is included in the published config served to consumer sites.
|
|
12
|
+
*
|
|
13
|
+
* @param fonts - The typography.fonts record from ConfiguratorState.
|
|
14
|
+
* @returns Map of fontFamily → avgCharWidthRatio (e.g. `{ "Inter": 0.52 }`).
|
|
15
|
+
* Returns empty object if called outside a browser context.
|
|
16
|
+
*/
|
|
17
|
+
export declare function measureFontCalibrations(fonts: Record<FontScope, FontSlot> | undefined): Promise<Record<string, number>>;
|
|
18
|
+
//# sourceMappingURL=measureFonts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"measureFonts.d.ts","sourceRoot":"","sources":["../../src/utils/measureFonts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAGvD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,uBAAuB,CAC3C,KAAK,EAAE,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC,GAAG,SAAS,GAC7C,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAoBjC"}
|
package/package.json
CHANGED
package/src/Editor.tsx
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
import { useMemo } from "react";
|
|
1
|
+
import { useMemo, useCallback } from "react";
|
|
2
2
|
import { NewtoneProvider } from "@newtonedev/components";
|
|
3
3
|
import type { NewtoneThemeConfig } from "@newtonedev/components";
|
|
4
|
+
import type { TextRole } from "@newtonedev/fonts";
|
|
4
5
|
import { useEditorState } from "./hooks/useEditorState";
|
|
5
6
|
import { EditorShell } from "./components/EditorShell";
|
|
6
7
|
import { Sidebar } from "./components/Sidebar";
|
|
7
8
|
import { EditorHeader } from "./components/EditorHeader";
|
|
9
|
+
import { PrimaryNav } from "./components/PrimaryNav";
|
|
10
|
+
import { ConfiguratorPanel } from "./components/ConfiguratorPanel";
|
|
8
11
|
import { TableOfContents } from "./components/TableOfContents";
|
|
9
12
|
import { PreviewWindow } from "./components/PreviewWindow";
|
|
10
13
|
import { RightSidebar } from "./components/RightSidebar";
|
|
@@ -22,6 +25,8 @@ export function Editor({
|
|
|
22
25
|
headerSlots,
|
|
23
26
|
onNavigate,
|
|
24
27
|
initialPreviewView,
|
|
28
|
+
manifestUrl,
|
|
29
|
+
fontCatalog,
|
|
25
30
|
}: EditorProps) {
|
|
26
31
|
const editor = useEditorState({
|
|
27
32
|
initialState,
|
|
@@ -33,8 +38,30 @@ export function Editor({
|
|
|
33
38
|
persistence,
|
|
34
39
|
onNavigate,
|
|
35
40
|
initialPreviewView,
|
|
41
|
+
manifestUrl,
|
|
36
42
|
});
|
|
37
43
|
|
|
44
|
+
// Per-role weight state and handler
|
|
45
|
+
const roleWeights = editor.configuratorState.typography?.roleWeights;
|
|
46
|
+
const handleRoleWeightChange = useCallback(
|
|
47
|
+
(role: TextRole, weight: number) => {
|
|
48
|
+
editor.dispatch({ type: "SET_ROLE_WEIGHT", role, weight });
|
|
49
|
+
},
|
|
50
|
+
[editor.dispatch],
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
// Map font scopes to family names for weight metadata lookup
|
|
54
|
+
const scopeFontMap = useMemo((): Record<string, string> => {
|
|
55
|
+
const fonts = editor.configuratorState.typography?.fonts;
|
|
56
|
+
if (!fonts) return {};
|
|
57
|
+
const map: Record<string, string> = {};
|
|
58
|
+
if (fonts.main?.config?.family) map.main = fonts.main.config.family;
|
|
59
|
+
if (fonts.display?.config?.family) map.display = fonts.display.config.family;
|
|
60
|
+
if (fonts.mono?.config?.family) map.mono = fonts.mono.config.family;
|
|
61
|
+
if (fonts.currency?.config?.family) map.currency = fonts.currency.config.family;
|
|
62
|
+
return map;
|
|
63
|
+
}, [editor.configuratorState.typography?.fonts]);
|
|
64
|
+
|
|
38
65
|
// Merge token overrides from chrome config into the preview config.
|
|
39
66
|
// Token overrides (from Token Tuner) are stored separately from configurator
|
|
40
67
|
// state, but should apply to the preview so components render accurately.
|
|
@@ -51,9 +78,6 @@ export function Editor({
|
|
|
51
78
|
<EditorShell
|
|
52
79
|
sidebar={
|
|
53
80
|
<Sidebar
|
|
54
|
-
state={editor.configuratorState}
|
|
55
|
-
dispatch={editor.dispatch}
|
|
56
|
-
previewColors={editor.previewColors}
|
|
57
81
|
isDirty={editor.isDirty}
|
|
58
82
|
onRevert={editor.handleRevert}
|
|
59
83
|
presets={editor.presets}
|
|
@@ -64,8 +88,6 @@ export function Editor({
|
|
|
64
88
|
onRenamePreset={editor.renamePreset}
|
|
65
89
|
onDeletePreset={editor.deletePreset}
|
|
66
90
|
onDuplicatePreset={editor.duplicatePreset}
|
|
67
|
-
colorMode={editor.colorMode}
|
|
68
|
-
onColorModeChange={editor.handleColorModeChange}
|
|
69
91
|
/>
|
|
70
92
|
}
|
|
71
93
|
navbar={
|
|
@@ -87,11 +109,28 @@ export function Editor({
|
|
|
87
109
|
minWidth: 0,
|
|
88
110
|
}}
|
|
89
111
|
>
|
|
90
|
-
<
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
onNavigate={editor.handlePreviewNavigate}
|
|
112
|
+
<PrimaryNav
|
|
113
|
+
activeSectionId={editor.activeSectionId}
|
|
114
|
+
onSelectSection={editor.handleSectionChange}
|
|
94
115
|
/>
|
|
116
|
+
{editor.activeSectionId === "components" ? (
|
|
117
|
+
<TableOfContents
|
|
118
|
+
activeSectionId={editor.activeSectionId}
|
|
119
|
+
activeView={editor.previewView}
|
|
120
|
+
selectedComponentId={editor.selectedComponentId}
|
|
121
|
+
onNavigate={editor.handlePreviewNavigate}
|
|
122
|
+
/>
|
|
123
|
+
) : (
|
|
124
|
+
<ConfiguratorPanel
|
|
125
|
+
activeSectionId={editor.activeSectionId}
|
|
126
|
+
state={editor.configuratorState}
|
|
127
|
+
dispatch={editor.dispatch}
|
|
128
|
+
previewColors={editor.previewColors}
|
|
129
|
+
colorMode={editor.colorMode}
|
|
130
|
+
onColorModeChange={editor.handleColorModeChange}
|
|
131
|
+
fontCatalog={fontCatalog}
|
|
132
|
+
/>
|
|
133
|
+
)}
|
|
95
134
|
<div
|
|
96
135
|
style={{
|
|
97
136
|
flex: 1,
|
|
@@ -110,9 +149,14 @@ export function Editor({
|
|
|
110
149
|
<PreviewWindow
|
|
111
150
|
view={editor.previewView}
|
|
112
151
|
selectedVariantId={editor.selectedVariantId}
|
|
113
|
-
propOverrides={editor.propOverrides}
|
|
114
152
|
onNavigate={editor.handlePreviewNavigate}
|
|
115
153
|
onSelectVariant={editor.handleSelectVariant}
|
|
154
|
+
propOverrides={editor.propOverrides}
|
|
155
|
+
onPropOverride={editor.handlePropOverride}
|
|
156
|
+
roleWeights={roleWeights}
|
|
157
|
+
onRoleWeightChange={handleRoleWeightChange}
|
|
158
|
+
fontCatalog={fontCatalog}
|
|
159
|
+
scopeFontMap={scopeFontMap}
|
|
116
160
|
/>
|
|
117
161
|
</div>
|
|
118
162
|
</NewtoneProvider>
|
|
@@ -127,6 +171,8 @@ export function Editor({
|
|
|
127
171
|
onResetOverrides={editor.handleResetOverrides}
|
|
128
172
|
onClose={editor.handleCloseSidebar}
|
|
129
173
|
onScopeToComponent={editor.handleScopeToComponent}
|
|
174
|
+
previewConfig={previewConfig}
|
|
175
|
+
colorMode={editor.colorMode}
|
|
130
176
|
/>
|
|
131
177
|
}
|
|
132
178
|
/>
|
|
@@ -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",
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { useTokens } from "@newtonedev/components";
|
|
2
|
+
import type { ColorMode } from "@newtonedev/components";
|
|
3
|
+
import { srgbToHex } from "newtone";
|
|
4
|
+
import type { ColorResult } from "newtone";
|
|
5
|
+
import type { ConfiguratorState } from "@newtonedev/configurator";
|
|
6
|
+
import type { ConfiguratorAction } from "@newtonedev/configurator";
|
|
7
|
+
import type { GoogleFontEntry } from "@newtonedev/fonts";
|
|
8
|
+
import {
|
|
9
|
+
ColorsSection,
|
|
10
|
+
DynamicRangeSection,
|
|
11
|
+
IconsSection,
|
|
12
|
+
FontsSection,
|
|
13
|
+
OthersSection,
|
|
14
|
+
} from "./sections";
|
|
15
|
+
|
|
16
|
+
interface ConfiguratorPanelProps {
|
|
17
|
+
readonly activeSectionId: string;
|
|
18
|
+
readonly state: ConfiguratorState;
|
|
19
|
+
readonly dispatch: (action: ConfiguratorAction) => void;
|
|
20
|
+
readonly previewColors: readonly (readonly ColorResult[])[];
|
|
21
|
+
readonly colorMode: ColorMode;
|
|
22
|
+
readonly onColorModeChange: (mode: ColorMode) => void;
|
|
23
|
+
readonly fontCatalog?: readonly GoogleFontEntry[];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const PANEL_WIDTH = 280;
|
|
27
|
+
|
|
28
|
+
export function ConfiguratorPanel({
|
|
29
|
+
activeSectionId,
|
|
30
|
+
state,
|
|
31
|
+
dispatch,
|
|
32
|
+
previewColors,
|
|
33
|
+
colorMode,
|
|
34
|
+
onColorModeChange,
|
|
35
|
+
fontCatalog,
|
|
36
|
+
}: ConfiguratorPanelProps) {
|
|
37
|
+
const tokens = useTokens();
|
|
38
|
+
const borderColor = srgbToHex(tokens.border.srgb);
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<div
|
|
42
|
+
style={{
|
|
43
|
+
width: PANEL_WIDTH,
|
|
44
|
+
flexShrink: 0,
|
|
45
|
+
overflowY: "auto",
|
|
46
|
+
borderRight: `1px solid ${borderColor}`,
|
|
47
|
+
padding: 20,
|
|
48
|
+
backgroundColor: srgbToHex(tokens.background.srgb),
|
|
49
|
+
display: "flex",
|
|
50
|
+
flexDirection: "column",
|
|
51
|
+
gap: 24,
|
|
52
|
+
}}
|
|
53
|
+
>
|
|
54
|
+
{activeSectionId === "colors" && (
|
|
55
|
+
<>
|
|
56
|
+
<DynamicRangeSection state={state} dispatch={dispatch} />
|
|
57
|
+
<ColorsSection
|
|
58
|
+
state={state}
|
|
59
|
+
dispatch={dispatch}
|
|
60
|
+
previewColors={previewColors}
|
|
61
|
+
colorMode={colorMode}
|
|
62
|
+
onColorModeChange={onColorModeChange}
|
|
63
|
+
/>
|
|
64
|
+
</>
|
|
65
|
+
)}
|
|
66
|
+
{activeSectionId === "typography" && (
|
|
67
|
+
<FontsSection state={state} dispatch={dispatch} fontCatalog={fontCatalog} />
|
|
68
|
+
)}
|
|
69
|
+
{activeSectionId === "symbols" && (
|
|
70
|
+
<IconsSection state={state} dispatch={dispatch} />
|
|
71
|
+
)}
|
|
72
|
+
{activeSectionId === "layout" && (
|
|
73
|
+
<OthersSection state={state} dispatch={dispatch} />
|
|
74
|
+
)}
|
|
75
|
+
</div>
|
|
76
|
+
);
|
|
77
|
+
}
|
|
@@ -1,27 +1,29 @@
|
|
|
1
1
|
import { useState, useRef, useEffect, useMemo, useCallback } from "react";
|
|
2
2
|
import { useTokens } from "@newtonedev/components";
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
} from "@newtonedev/components";
|
|
7
|
-
import type { GoogleFontEntry, SystemFontEntry, FontConfig } from "@newtonedev/components";
|
|
3
|
+
import type { FontConfig } from "@newtonedev/components";
|
|
4
|
+
import { SYSTEM_FONTS } from "@newtonedev/fonts";
|
|
5
|
+
import type { GoogleFontEntry, SystemFontEntry } from "@newtonedev/fonts";
|
|
8
6
|
import { srgbToHex } from "newtone";
|
|
9
7
|
|
|
10
|
-
type FontSlot = "default" | "display" | "mono";
|
|
8
|
+
type FontSlot = "default" | "display" | "mono" | "currency";
|
|
11
9
|
|
|
12
10
|
interface FontPickerProps {
|
|
13
11
|
readonly label: string;
|
|
14
12
|
readonly slot: FontSlot;
|
|
15
13
|
readonly currentFont: FontConfig;
|
|
16
14
|
readonly onSelect: (font: FontConfig) => void;
|
|
15
|
+
readonly fontCatalog?: readonly GoogleFontEntry[];
|
|
17
16
|
}
|
|
18
17
|
|
|
19
|
-
/** Preload
|
|
20
|
-
let
|
|
21
|
-
function preloadFontsForPreview() {
|
|
22
|
-
if (
|
|
23
|
-
|
|
24
|
-
const
|
|
18
|
+
/** Preload curated Google Fonts for preview on first dropdown open. */
|
|
19
|
+
let previewLoadedKey = "";
|
|
20
|
+
function preloadFontsForPreview(catalog: readonly GoogleFontEntry[]) {
|
|
21
|
+
if (catalog.length === 0 || typeof document === "undefined") return;
|
|
22
|
+
// Re-preload if the catalog changes (e.g. new fonts curated)
|
|
23
|
+
const key = catalog.map((f) => f.family).join(",");
|
|
24
|
+
if (key === previewLoadedKey) return;
|
|
25
|
+
previewLoadedKey = key;
|
|
26
|
+
const families = catalog.map(
|
|
25
27
|
(f) => `family=${f.family.replace(/ /g, "+")}:wght@400`,
|
|
26
28
|
).join("&");
|
|
27
29
|
const url = `https://fonts.googleapis.com/css2?${families}&display=swap`;
|
|
@@ -60,18 +62,13 @@ const CATEGORY_ORDER: readonly string[] = [
|
|
|
60
62
|
"monospace",
|
|
61
63
|
"display",
|
|
62
64
|
];
|
|
63
|
-
const MONO_CATEGORY_ORDER: readonly string[] = [
|
|
64
|
-
"monospace",
|
|
65
|
-
"sans-serif",
|
|
66
|
-
"serif",
|
|
67
|
-
"display",
|
|
68
|
-
];
|
|
69
65
|
|
|
70
66
|
export function FontPicker({
|
|
71
67
|
label,
|
|
72
68
|
slot,
|
|
73
69
|
currentFont,
|
|
74
70
|
onSelect,
|
|
71
|
+
fontCatalog = [],
|
|
75
72
|
}: FontPickerProps) {
|
|
76
73
|
const tokens = useTokens();
|
|
77
74
|
const [isOpen, setIsOpen] = useState(false);
|
|
@@ -103,35 +100,47 @@ export function FontPicker({
|
|
|
103
100
|
|
|
104
101
|
useEffect(() => {
|
|
105
102
|
if (isOpen) {
|
|
106
|
-
preloadFontsForPreview();
|
|
103
|
+
preloadFontsForPreview(fontCatalog);
|
|
107
104
|
requestAnimationFrame(() => searchInputRef.current?.focus());
|
|
108
105
|
}
|
|
109
|
-
}, [isOpen]);
|
|
110
|
-
|
|
111
|
-
const categoryOrder = slot === "mono" ? MONO_CATEGORY_ORDER : CATEGORY_ORDER;
|
|
106
|
+
}, [isOpen, fontCatalog]);
|
|
112
107
|
|
|
113
108
|
const filteredGoogleFonts = useMemo(() => {
|
|
114
109
|
const query = search.toLowerCase().trim();
|
|
115
|
-
|
|
116
|
-
?
|
|
117
|
-
:
|
|
110
|
+
let fonts: readonly GoogleFontEntry[] = query
|
|
111
|
+
? fontCatalog.filter((f) => f.family.toLowerCase().includes(query))
|
|
112
|
+
: fontCatalog;
|
|
113
|
+
|
|
114
|
+
if (slot === "mono") {
|
|
115
|
+
fonts = fonts.filter((f) => f.category === "monospace");
|
|
116
|
+
} else if (slot === "currency") {
|
|
117
|
+
fonts = fonts.filter((f) => f.category === "monospace" || f.category === "sans-serif");
|
|
118
|
+
}
|
|
118
119
|
|
|
119
120
|
const grouped: Record<string, GoogleFontEntry[]> = {};
|
|
120
|
-
for (const cat of
|
|
121
|
+
for (const cat of CATEGORY_ORDER) {
|
|
121
122
|
const inCategory = fonts.filter((f) => f.category === cat);
|
|
122
123
|
if (inCategory.length > 0) {
|
|
123
124
|
grouped[cat] = inCategory;
|
|
124
125
|
}
|
|
125
126
|
}
|
|
126
127
|
return grouped;
|
|
127
|
-
}, [search,
|
|
128
|
+
}, [search, slot, fontCatalog]);
|
|
128
129
|
|
|
129
130
|
const filteredSystemFonts = useMemo(() => {
|
|
130
131
|
const query = search.toLowerCase().trim();
|
|
131
|
-
|
|
132
|
+
let fonts = query
|
|
132
133
|
? SYSTEM_FONTS.filter((f) => f.family.toLowerCase().includes(query))
|
|
133
134
|
: [...SYSTEM_FONTS];
|
|
134
|
-
|
|
135
|
+
|
|
136
|
+
if (slot === "mono") {
|
|
137
|
+
fonts = fonts.filter((f) => f.category === "monospace");
|
|
138
|
+
} else if (slot === "currency") {
|
|
139
|
+
fonts = fonts.filter((f) => f.category !== "serif");
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return fonts;
|
|
143
|
+
}, [search, slot]);
|
|
135
144
|
|
|
136
145
|
const handleSelect = useCallback(
|
|
137
146
|
(font: FontConfig) => {
|
|
@@ -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";
|
|
@@ -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>
|