@newtonedev/editor 0.1.6 → 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.
Files changed (52) hide show
  1. package/dist/Editor.d.ts +1 -1
  2. package/dist/Editor.d.ts.map +1 -1
  3. package/dist/components/ConfiguratorPanel.d.ts +17 -0
  4. package/dist/components/ConfiguratorPanel.d.ts.map +1 -0
  5. package/dist/components/FontPicker.d.ts +4 -2
  6. package/dist/components/FontPicker.d.ts.map +1 -1
  7. package/dist/components/PreviewWindow.d.ts +7 -2
  8. package/dist/components/PreviewWindow.d.ts.map +1 -1
  9. package/dist/components/PrimaryNav.d.ts +7 -0
  10. package/dist/components/PrimaryNav.d.ts.map +1 -0
  11. package/dist/components/Sidebar.d.ts +1 -10
  12. package/dist/components/Sidebar.d.ts.map +1 -1
  13. package/dist/components/TableOfContents.d.ts +2 -1
  14. package/dist/components/TableOfContents.d.ts.map +1 -1
  15. package/dist/components/sections/DynamicRangeSection.d.ts.map +1 -1
  16. package/dist/components/sections/FontsSection.d.ts +3 -1
  17. package/dist/components/sections/FontsSection.d.ts.map +1 -1
  18. package/dist/hooks/useEditorState.d.ts +4 -1
  19. package/dist/hooks/useEditorState.d.ts.map +1 -1
  20. package/dist/index.cjs +2464 -2046
  21. package/dist/index.cjs.map +1 -1
  22. package/dist/index.d.ts +2 -1
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +2466 -2049
  25. package/dist/index.js.map +1 -1
  26. package/dist/preview/ComponentDetailView.d.ts +7 -1
  27. package/dist/preview/ComponentDetailView.d.ts.map +1 -1
  28. package/dist/preview/ComponentRenderer.d.ts +2 -1
  29. package/dist/preview/ComponentRenderer.d.ts.map +1 -1
  30. package/dist/types.d.ts +17 -0
  31. package/dist/types.d.ts.map +1 -1
  32. package/dist/utils/lookupFontMetrics.d.ts +19 -0
  33. package/dist/utils/lookupFontMetrics.d.ts.map +1 -0
  34. package/dist/utils/measureFonts.d.ts +18 -0
  35. package/dist/utils/measureFonts.d.ts.map +1 -0
  36. package/package.json +1 -1
  37. package/src/Editor.tsx +53 -10
  38. package/src/components/ConfiguratorPanel.tsx +77 -0
  39. package/src/components/FontPicker.tsx +38 -29
  40. package/src/components/PreviewWindow.tsx +14 -1
  41. package/src/components/PrimaryNav.tsx +76 -0
  42. package/src/components/Sidebar.tsx +5 -132
  43. package/src/components/TableOfContents.tsx +41 -78
  44. package/src/components/sections/DynamicRangeSection.tsx +2 -225
  45. package/src/components/sections/FontsSection.tsx +61 -93
  46. package/src/hooks/useEditorState.ts +54 -6
  47. package/src/index.ts +2 -0
  48. package/src/preview/ComponentDetailView.tsx +531 -67
  49. package/src/preview/ComponentRenderer.tsx +6 -4
  50. package/src/types.ts +15 -0
  51. package/src/utils/lookupFontMetrics.ts +52 -0
  52. package/src/utils/measureFonts.ts +41 -0
package/src/types.ts CHANGED
@@ -1,7 +1,16 @@
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";
4
5
 
6
+ /** Font catalog entry enriched with weight metadata for the editor. */
7
+ export interface EditorFontEntry extends GoogleFontEntry {
8
+ readonly isVariable?: boolean;
9
+ readonly availableWeights?: readonly number[];
10
+ /** Weight axis range for variable fonts (from Google Fonts API wght axis). */
11
+ readonly weightAxisRange?: { readonly min: number; readonly max: number };
12
+ }
13
+
5
14
  // --- Data types ---
6
15
 
7
16
  export interface Preset {
@@ -43,6 +52,8 @@ export interface EditorPersistence {
43
52
  readonly state: ConfiguratorState;
44
53
  readonly presets: readonly Preset[];
45
54
  readonly activePresetId: string;
55
+ readonly calibrations?: Record<string, number>;
56
+ readonly fontMetrics?: Record<string, FontRuntimeMetrics>;
46
57
  }) => Promise<{ error?: unknown }>;
47
58
 
48
59
  /** Persist preset metadata (used by preset CRUD operations). */
@@ -72,4 +83,8 @@ export interface EditorProps {
72
83
  readonly headerSlots?: EditorHeaderSlots;
73
84
  readonly onNavigate?: (view: PreviewView) => void;
74
85
  readonly initialPreviewView?: PreviewView;
86
+ /** URL of the font manifest for metrics lookup at publish time. */
87
+ readonly manifestUrl?: string;
88
+ /** Curated fonts available in the font picker, enriched with weight metadata. */
89
+ readonly fontCatalog?: readonly EditorFontEntry[];
75
90
  }
@@ -0,0 +1,52 @@
1
+ import type { FontScope } from '@newtonedev/fonts';
2
+ import type { FontSlot } from '@newtonedev/components';
3
+ import type { FontRuntimeMetrics } from '@newtonedev/fonts';
4
+
5
+ /**
6
+ * Look up FontRuntimeMetrics for all font scopes from the font manifest.
7
+ *
8
+ * Called at publish time alongside measureFontCalibrations. Fetches the
9
+ * manifest JSON from the given URL and extracts metrics for each unique
10
+ * font family in the current typography configuration.
11
+ *
12
+ * Deduplicates by family name so a font used in multiple scopes is
13
+ * looked up only once. Returns empty object if manifest is unavailable.
14
+ *
15
+ * @param fonts - The typography.fonts record from ConfiguratorState.
16
+ * @param manifestUrl - URL of the font manifest (e.g., Supabase Storage public URL).
17
+ * @returns Map of fontFamily → FontRuntimeMetrics.
18
+ */
19
+ export async function lookupFontMetrics(
20
+ fonts: Record<FontScope, FontSlot> | undefined,
21
+ manifestUrl: string | undefined,
22
+ ): Promise<Record<string, FontRuntimeMetrics>> {
23
+ if (!fonts || !manifestUrl) return {};
24
+
25
+ try {
26
+ const res = await fetch(manifestUrl);
27
+ if (!res.ok) return {};
28
+ const manifest = await res.json();
29
+
30
+ const result: Record<string, FontRuntimeMetrics> = {};
31
+ const seen = new Set<string>();
32
+
33
+ for (const slot of Object.values(fonts) as FontSlot[]) {
34
+ const family = slot.config.family;
35
+ if (seen.has(family)) continue;
36
+ seen.add(family);
37
+
38
+ const entry = manifest.families?.[family];
39
+ if (entry?.metrics) {
40
+ result[family] = {
41
+ naturalLineHeightRatio: entry.metrics.naturalLineHeightRatio,
42
+ verticalCenterOffset: entry.metrics.verticalCenterOffset,
43
+ features: entry.metrics.features ?? [],
44
+ };
45
+ }
46
+ }
47
+
48
+ return result;
49
+ } catch {
50
+ return {};
51
+ }
52
+ }
@@ -0,0 +1,41 @@
1
+ import type { FontScope } from '@newtonedev/fonts';
2
+ import type { FontSlot } from '@newtonedev/components';
3
+ import { measureAvgCharWidth } from '@newtonedev/components';
4
+
5
+ /**
6
+ * Measure avgCharWidth ratios for all font scopes at publish time.
7
+ *
8
+ * Deduplicates by font family name so a font used in multiple scopes is
9
+ * measured only once. Waits for fonts to load via `document.fonts.ready`
10
+ * before measuring, since the editor always preloads fonts for preview.
11
+ *
12
+ * Called in `handlePublish` before writing to persistence so that calibration
13
+ * data is included in the published config served to consumer sites.
14
+ *
15
+ * @param fonts - The typography.fonts record from ConfiguratorState.
16
+ * @returns Map of fontFamily → avgCharWidthRatio (e.g. `{ "Inter": 0.52 }`).
17
+ * Returns empty object if called outside a browser context.
18
+ */
19
+ export async function measureFontCalibrations(
20
+ fonts: Record<FontScope, FontSlot> | undefined,
21
+ ): Promise<Record<string, number>> {
22
+ if (!fonts || typeof document === 'undefined') return {};
23
+
24
+ const calibrations: Record<string, number> = {};
25
+ const seen = new Set<string>();
26
+
27
+ for (const slot of Object.values(fonts) as FontSlot[]) {
28
+ const { family, fallback } = slot.config;
29
+ if (seen.has(family)) continue;
30
+ seen.add(family);
31
+
32
+ const ratio = await measureAvgCharWidth(
33
+ family,
34
+ slot.weights.regular,
35
+ fallback,
36
+ );
37
+ calibrations[family] = ratio;
38
+ }
39
+
40
+ return calibrations;
41
+ }