@newtonedev/components 0.1.6 → 0.1.8
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/composites/actions/Button/Button.d.ts.map +1 -1
- package/dist/composites/form-controls/Select/Select.styles.d.ts.map +1 -1
- package/dist/composites/form-controls/TextInput/TextInput.styles.d.ts.map +1 -1
- package/dist/composites/form-controls/Toggle/Toggle.styles.d.ts.map +1 -1
- package/dist/composites/range-inputs/ColorScaleSlider/ColorScaleSlider.styles.d.ts.map +1 -1
- package/dist/composites/range-inputs/HueSlider/HueSlider.styles.d.ts.map +1 -1
- package/dist/composites/range-inputs/Slider/Slider.styles.d.ts.map +1 -1
- package/dist/fonts/GoogleFontLoader.d.ts +5 -4
- package/dist/fonts/GoogleFontLoader.d.ts.map +1 -1
- package/dist/fonts/SelfHostedFontLoader.d.ts +14 -0
- package/dist/fonts/SelfHostedFontLoader.d.ts.map +1 -0
- package/dist/fonts/buildGoogleFontsUrl.d.ts +1 -16
- package/dist/fonts/buildGoogleFontsUrl.d.ts.map +1 -1
- package/dist/fonts/measureFont.d.ts +18 -0
- package/dist/fonts/measureFont.d.ts.map +1 -0
- package/dist/fonts/reportQueue.d.ts +7 -0
- package/dist/fonts/reportQueue.d.ts.map +1 -0
- package/dist/fonts/useLocalCalibration.d.ts +19 -0
- package/dist/fonts/useLocalCalibration.d.ts.map +1 -0
- package/dist/fonts/useTypographyCalibrations.d.ts +11 -0
- package/dist/fonts/useTypographyCalibrations.d.ts.map +1 -0
- package/dist/index.cjs +863 -437
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +9 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +801 -391
- package/dist/index.js.map +1 -1
- package/dist/primitives/Icon/Icon.d.ts +1 -1
- package/dist/primitives/Icon/Icon.d.ts.map +1 -1
- package/dist/primitives/Icon/Icon.types.d.ts +8 -13
- package/dist/primitives/Icon/Icon.types.d.ts.map +1 -1
- package/dist/primitives/Text/Text.d.ts +33 -8
- package/dist/primitives/Text/Text.d.ts.map +1 -1
- package/dist/primitives/Text/Text.spans.d.ts +22 -0
- package/dist/primitives/Text/Text.spans.d.ts.map +1 -0
- package/dist/primitives/Text/Text.types.d.ts +75 -27
- package/dist/primitives/Text/Text.types.d.ts.map +1 -1
- package/dist/primitives/Text/index.d.ts +23 -2
- package/dist/primitives/Text/index.d.ts.map +1 -1
- package/dist/primitives/index.d.ts +1 -1
- package/dist/primitives/index.d.ts.map +1 -1
- package/dist/registry/codegen.d.ts.map +1 -1
- package/dist/registry/icons.d.ts +7 -0
- package/dist/registry/icons.d.ts.map +1 -0
- package/dist/registry/index.d.ts +2 -0
- package/dist/registry/index.d.ts.map +1 -1
- package/dist/registry/registry.d.ts.map +1 -1
- package/dist/registry/types.d.ts +3 -1
- package/dist/registry/types.d.ts.map +1 -1
- package/dist/theme/NewtoneProvider.d.ts +9 -1
- package/dist/theme/NewtoneProvider.d.ts.map +1 -1
- package/dist/theme/defaults.d.ts +1 -0
- package/dist/theme/defaults.d.ts.map +1 -1
- package/dist/theme/types.d.ts +48 -32
- package/dist/theme/types.d.ts.map +1 -1
- package/dist/theme/useBreakpoint.d.ts +9 -0
- package/dist/theme/useBreakpoint.d.ts.map +1 -0
- package/dist/tokens/computeTokens.d.ts +9 -22
- package/dist/tokens/computeTokens.d.ts.map +1 -1
- package/dist/tokens/types.d.ts +40 -22
- package/dist/tokens/types.d.ts.map +1 -1
- package/package.json +2 -1
- package/src/composites/actions/Button/Button.styles.ts +3 -3
- package/src/composites/actions/Button/Button.tsx +3 -2
- package/src/composites/form-controls/Select/Select.styles.ts +8 -8
- package/src/composites/form-controls/Select/Select.tsx +1 -1
- package/src/composites/form-controls/Select/SelectOption.tsx +3 -3
- package/src/composites/form-controls/TextInput/TextInput.styles.ts +5 -5
- package/src/composites/form-controls/Toggle/Toggle.styles.ts +3 -3
- package/src/composites/range-inputs/ColorScaleSlider/ColorScaleSlider.styles.ts +6 -6
- package/src/composites/range-inputs/HueSlider/HueSlider.styles.ts +9 -9
- package/src/composites/range-inputs/Slider/Slider.styles.ts +9 -9
- package/src/fonts/GoogleFontLoader.tsx +25 -10
- package/src/fonts/SelfHostedFontLoader.tsx +44 -0
- package/src/fonts/buildGoogleFontsUrl.ts +2 -31
- package/src/fonts/measureFont.ts +42 -0
- package/src/fonts/reportQueue.ts +54 -0
- package/src/fonts/useLocalCalibration.ts +97 -0
- package/src/fonts/useTypographyCalibrations.ts +15 -0
- package/src/index.ts +18 -7
- package/src/primitives/Frame/Frame.tsx +3 -3
- package/src/primitives/Icon/Icon.tsx +5 -7
- package/src/primitives/Icon/Icon.types.ts +8 -15
- package/src/primitives/Text/Text.spans.ts +57 -0
- package/src/primitives/Text/Text.tsx +205 -53
- package/src/primitives/Text/Text.types.ts +80 -27
- package/src/primitives/Text/index.ts +27 -3
- package/src/primitives/index.ts +3 -2
- package/src/registry/codegen.ts +1 -0
- package/src/registry/icons.ts +111 -0
- package/src/registry/index.ts +3 -0
- package/src/registry/registry.ts +67 -70
- package/src/registry/types.ts +3 -1
- package/src/theme/NewtoneProvider.tsx +18 -2
- package/src/theme/defaults.ts +8 -28
- package/src/theme/types.ts +63 -33
- package/src/theme/useBreakpoint.ts +14 -0
- package/src/tokens/computeTokens.ts +23 -19
- package/src/tokens/types.ts +10 -24
- package/dist/fonts/googleFonts.d.ts +0 -20
- package/dist/fonts/googleFonts.d.ts.map +0 -1
- package/src/fonts/googleFonts.ts +0 -87
package/src/registry/registry.ts
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import type { CategoryMeta, ComponentMeta } from './types';
|
|
2
2
|
|
|
3
3
|
export const CATEGORIES: readonly CategoryMeta[] = [
|
|
4
|
-
{ id: '
|
|
5
|
-
{ id: '
|
|
6
|
-
{ id: '
|
|
7
|
-
{ id: '
|
|
8
|
-
{ id: '
|
|
9
|
-
{ id: 'overlays', name: 'Overlays', description: 'Floating and portal-based UI elements' },
|
|
4
|
+
{ id: 'colors', name: 'Colors', description: 'Color palettes and token visualization', icon: 'palette' },
|
|
5
|
+
{ id: 'typography', name: 'Typography', description: 'Text roles, scopes, and weight control', icon: 'text_fields' },
|
|
6
|
+
{ id: 'symbols', name: 'Symbols', description: 'Material Symbols icon browser', icon: 'grid_view' },
|
|
7
|
+
{ id: 'layout', name: 'Layout', description: 'Structural containers — Frame and Wrapper', icon: 'grid_on' },
|
|
8
|
+
{ id: 'components', name: 'Components', description: 'Interactive UI components', icon: 'widgets' },
|
|
10
9
|
];
|
|
11
10
|
|
|
12
11
|
export const COMPONENTS: readonly ComponentMeta[] = [
|
|
@@ -14,7 +13,7 @@ export const COMPONENTS: readonly ComponentMeta[] = [
|
|
|
14
13
|
id: 'button',
|
|
15
14
|
name: 'Button',
|
|
16
15
|
importName: 'Button',
|
|
17
|
-
categoryId: '
|
|
16
|
+
categoryId: 'components',
|
|
18
17
|
description: 'Interactive button with multiple variants, sizes, and optional icon',
|
|
19
18
|
hasChildren: true,
|
|
20
19
|
variants: [
|
|
@@ -96,7 +95,7 @@ export const COMPONENTS: readonly ComponentMeta[] = [
|
|
|
96
95
|
id: 'text-input',
|
|
97
96
|
name: 'TextInput',
|
|
98
97
|
importName: 'TextInput',
|
|
99
|
-
categoryId: '
|
|
98
|
+
categoryId: 'components',
|
|
100
99
|
description: 'Text input field with label support',
|
|
101
100
|
hasChildren: false,
|
|
102
101
|
variants: [
|
|
@@ -123,7 +122,7 @@ export const COMPONENTS: readonly ComponentMeta[] = [
|
|
|
123
122
|
id: 'select',
|
|
124
123
|
name: 'Select',
|
|
125
124
|
importName: 'Select',
|
|
126
|
-
categoryId: '
|
|
125
|
+
categoryId: 'components',
|
|
127
126
|
description: 'Dropdown selector with options',
|
|
128
127
|
hasChildren: false,
|
|
129
128
|
variants: [
|
|
@@ -170,7 +169,7 @@ export const COMPONENTS: readonly ComponentMeta[] = [
|
|
|
170
169
|
id: 'toggle',
|
|
171
170
|
name: 'Toggle',
|
|
172
171
|
importName: 'Toggle',
|
|
173
|
-
categoryId: '
|
|
172
|
+
categoryId: 'components',
|
|
174
173
|
description: 'Binary switch component',
|
|
175
174
|
hasChildren: false,
|
|
176
175
|
variants: [
|
|
@@ -197,7 +196,7 @@ export const COMPONENTS: readonly ComponentMeta[] = [
|
|
|
197
196
|
id: 'slider',
|
|
198
197
|
name: 'Slider',
|
|
199
198
|
importName: 'Slider',
|
|
200
|
-
categoryId: '
|
|
199
|
+
categoryId: 'components',
|
|
201
200
|
description: 'Numeric range slider',
|
|
202
201
|
hasChildren: false,
|
|
203
202
|
variants: [
|
|
@@ -241,7 +240,7 @@ export const COMPONENTS: readonly ComponentMeta[] = [
|
|
|
241
240
|
id: 'hue-slider',
|
|
242
241
|
name: 'HueSlider',
|
|
243
242
|
importName: 'HueSlider',
|
|
244
|
-
categoryId: '
|
|
243
|
+
categoryId: 'components',
|
|
245
244
|
description: 'Specialized slider for hue selection (0-360\u00b0)',
|
|
246
245
|
hasChildren: false,
|
|
247
246
|
variants: [
|
|
@@ -377,7 +376,7 @@ export const COMPONENTS: readonly ComponentMeta[] = [
|
|
|
377
376
|
id: 'card',
|
|
378
377
|
name: 'Card',
|
|
379
378
|
importName: 'Card',
|
|
380
|
-
categoryId: '
|
|
379
|
+
categoryId: 'components',
|
|
381
380
|
description: 'Surface container with elevation levels',
|
|
382
381
|
hasChildren: true,
|
|
383
382
|
variants: [
|
|
@@ -410,45 +409,59 @@ export const COMPONENTS: readonly ComponentMeta[] = [
|
|
|
410
409
|
id: 'text',
|
|
411
410
|
name: 'Text',
|
|
412
411
|
importName: 'Text',
|
|
413
|
-
categoryId: '
|
|
414
|
-
description: 'Typography primitive with semantic
|
|
412
|
+
categoryId: 'typography',
|
|
413
|
+
description: 'Typography primitive with semantic scope (font family) and role (purpose)',
|
|
415
414
|
hasChildren: true,
|
|
415
|
+
previewLayout: 'list',
|
|
416
416
|
variants: [
|
|
417
|
-
{ id: '
|
|
418
|
-
{ id: '
|
|
419
|
-
{ id: '
|
|
420
|
-
{ id: '
|
|
421
|
-
{ id: '
|
|
422
|
-
{ id: '
|
|
423
|
-
{ id: '
|
|
417
|
+
{ id: 'body', label: 'Body', props: { role: 'body' } },
|
|
418
|
+
{ id: 'headline', label: 'Headline', props: { role: 'headline', scope: 'display' } },
|
|
419
|
+
{ id: 'title', label: 'Title', props: { role: 'title', scope: 'display' } },
|
|
420
|
+
{ id: 'heading', label: 'Heading', props: { role: 'heading' } },
|
|
421
|
+
{ id: 'subheading', label: 'Subheading', props: { role: 'subheading' } },
|
|
422
|
+
{ id: 'label', label: 'Label', props: { role: 'label' } },
|
|
423
|
+
{ id: 'caption', label: 'Caption', props: { role: 'caption', color: 'secondary' } },
|
|
424
|
+
{ id: 'mono', label: 'Monospace', props: { scope: 'mono', role: 'body' } },
|
|
425
|
+
{ id: 'currency', label: 'Currency', props: { scope: 'currency', role: 'body' } },
|
|
424
426
|
],
|
|
425
427
|
editableProps: [
|
|
426
428
|
{
|
|
427
|
-
name: '
|
|
428
|
-
label: '
|
|
429
|
+
name: 'scope',
|
|
430
|
+
label: 'Scope',
|
|
429
431
|
control: 'select',
|
|
430
432
|
options: [
|
|
431
|
-
{ label: '
|
|
432
|
-
{ label: '
|
|
433
|
-
{ label: '
|
|
434
|
-
{ label: '
|
|
435
|
-
{ label: 'Large', value: 'lg' },
|
|
436
|
-
{ label: 'Extra Large', value: 'xl' },
|
|
437
|
-
{ label: 'XXL', value: 'xxl' },
|
|
433
|
+
{ label: 'Main', value: 'main' },
|
|
434
|
+
{ label: 'Display', value: 'display' },
|
|
435
|
+
{ label: 'Mono', value: 'mono' },
|
|
436
|
+
{ label: 'Currency', value: 'currency' },
|
|
438
437
|
],
|
|
439
|
-
defaultValue: '
|
|
438
|
+
defaultValue: 'main',
|
|
440
439
|
},
|
|
441
440
|
{
|
|
442
|
-
name: '
|
|
443
|
-
label: '
|
|
441
|
+
name: 'role',
|
|
442
|
+
label: 'Role',
|
|
444
443
|
control: 'select',
|
|
445
444
|
options: [
|
|
446
|
-
{ label: '
|
|
447
|
-
{ label: '
|
|
448
|
-
{ label: '
|
|
449
|
-
{ label: '
|
|
445
|
+
{ label: 'Headline', value: 'headline' },
|
|
446
|
+
{ label: 'Title', value: 'title' },
|
|
447
|
+
{ label: 'Heading', value: 'heading' },
|
|
448
|
+
{ label: 'Subheading', value: 'subheading' },
|
|
449
|
+
{ label: 'Body', value: 'body' },
|
|
450
|
+
{ label: 'Label', value: 'label' },
|
|
451
|
+
{ label: 'Caption', value: 'caption' },
|
|
452
|
+
],
|
|
453
|
+
defaultValue: 'body',
|
|
454
|
+
},
|
|
455
|
+
{
|
|
456
|
+
name: 'size',
|
|
457
|
+
label: 'Size',
|
|
458
|
+
control: 'select',
|
|
459
|
+
options: [
|
|
460
|
+
{ label: 'Small', value: 'sm' },
|
|
461
|
+
{ label: 'Medium', value: 'md' },
|
|
462
|
+
{ label: 'Large', value: 'lg' },
|
|
450
463
|
],
|
|
451
|
-
defaultValue: '
|
|
464
|
+
defaultValue: 'md',
|
|
452
465
|
},
|
|
453
466
|
{
|
|
454
467
|
name: 'color',
|
|
@@ -466,58 +479,42 @@ export const COMPONENTS: readonly ComponentMeta[] = [
|
|
|
466
479
|
],
|
|
467
480
|
defaultValue: 'primary',
|
|
468
481
|
},
|
|
469
|
-
{
|
|
470
|
-
name: 'font',
|
|
471
|
-
label: 'Font',
|
|
472
|
-
control: 'select',
|
|
473
|
-
options: [
|
|
474
|
-
{ label: 'Default', value: 'default' },
|
|
475
|
-
{ label: 'Display', value: 'display' },
|
|
476
|
-
{ label: 'Mono', value: 'mono' },
|
|
477
|
-
],
|
|
478
|
-
defaultValue: 'default',
|
|
479
|
-
},
|
|
480
482
|
],
|
|
481
483
|
},
|
|
482
484
|
{
|
|
483
485
|
id: 'icon',
|
|
484
486
|
name: 'Icon',
|
|
485
487
|
importName: 'Icon',
|
|
486
|
-
categoryId: '
|
|
487
|
-
description: 'Material Symbols icon with size
|
|
488
|
+
categoryId: 'symbols',
|
|
489
|
+
description: 'Material Symbols icon with size and fill',
|
|
488
490
|
hasChildren: false,
|
|
489
491
|
variants: [
|
|
490
|
-
{ id: '
|
|
491
|
-
{ id: 'settings', label: 'Settings', props: { name: 'settings' } },
|
|
492
|
-
{ id: 'check', label: 'Check', props: { name: 'check' } },
|
|
493
|
-
{ id: 'add', label: 'Add', props: { name: 'add' } },
|
|
494
|
-
{ id: 'delete', label: 'Delete', props: { name: 'delete' } },
|
|
495
|
-
{ id: 'search', label: 'Search', props: { name: 'search' } },
|
|
496
|
-
{ id: 'filled', label: 'Filled Icon', props: { name: 'favorite', fill: 1 } },
|
|
497
|
-
{ id: 'large', label: 'Large Icon', props: { name: 'star', size: 32 } },
|
|
492
|
+
{ id: 'default', label: 'Default', props: { name: 'add' } },
|
|
498
493
|
],
|
|
499
494
|
editableProps: [
|
|
500
495
|
{
|
|
501
496
|
name: 'name',
|
|
502
497
|
label: 'Icon Name',
|
|
503
498
|
control: 'text',
|
|
504
|
-
defaultValue: '
|
|
499
|
+
defaultValue: 'add',
|
|
505
500
|
},
|
|
506
501
|
{
|
|
507
502
|
name: 'size',
|
|
508
503
|
label: 'Size',
|
|
509
|
-
control: '
|
|
504
|
+
control: 'discrete-slider',
|
|
505
|
+
options: [
|
|
506
|
+
{ label: '20', value: 20 },
|
|
507
|
+
{ label: '24', value: 24 },
|
|
508
|
+
{ label: '40', value: 40 },
|
|
509
|
+
{ label: '48', value: 48 },
|
|
510
|
+
],
|
|
510
511
|
defaultValue: 24,
|
|
511
512
|
},
|
|
512
513
|
{
|
|
513
514
|
name: 'fill',
|
|
514
515
|
label: 'Fill',
|
|
515
|
-
control: '
|
|
516
|
-
|
|
517
|
-
{ label: 'Outlined', value: 0 },
|
|
518
|
-
{ label: 'Filled', value: 1 },
|
|
519
|
-
],
|
|
520
|
-
defaultValue: 0,
|
|
516
|
+
control: 'toggle',
|
|
517
|
+
defaultValue: false,
|
|
521
518
|
},
|
|
522
519
|
],
|
|
523
520
|
},
|
|
@@ -525,7 +522,7 @@ export const COMPONENTS: readonly ComponentMeta[] = [
|
|
|
525
522
|
id: 'wrapper',
|
|
526
523
|
name: 'Wrapper',
|
|
527
524
|
importName: 'Wrapper',
|
|
528
|
-
categoryId: '
|
|
525
|
+
categoryId: 'layout',
|
|
529
526
|
description: 'Lightweight layout container with direction, spacing, and alignment (no theming)',
|
|
530
527
|
hasChildren: true,
|
|
531
528
|
variants: [
|
|
@@ -599,7 +596,7 @@ export const COMPONENTS: readonly ComponentMeta[] = [
|
|
|
599
596
|
id: 'color-scale-slider',
|
|
600
597
|
name: 'ColorScaleSlider',
|
|
601
598
|
importName: 'ColorScaleSlider',
|
|
602
|
-
categoryId: '
|
|
599
|
+
categoryId: 'components',
|
|
603
600
|
description: 'Interactive palette preview slider with color segments',
|
|
604
601
|
hasChildren: false,
|
|
605
602
|
variants: [
|
package/src/registry/types.ts
CHANGED
|
@@ -2,6 +2,7 @@ export interface CategoryMeta {
|
|
|
2
2
|
readonly id: string;
|
|
3
3
|
readonly name: string;
|
|
4
4
|
readonly description: string;
|
|
5
|
+
readonly icon?: string;
|
|
5
6
|
}
|
|
6
7
|
|
|
7
8
|
export interface VariantMeta {
|
|
@@ -18,7 +19,7 @@ export interface EditablePropOption {
|
|
|
18
19
|
export interface EditableProp {
|
|
19
20
|
readonly name: string;
|
|
20
21
|
readonly label: string;
|
|
21
|
-
readonly control: 'select' | 'text' | 'toggle' | 'number';
|
|
22
|
+
readonly control: 'select' | 'text' | 'toggle' | 'number' | 'discrete-slider';
|
|
22
23
|
readonly options?: readonly EditablePropOption[];
|
|
23
24
|
readonly defaultValue: string | number | boolean;
|
|
24
25
|
}
|
|
@@ -30,6 +31,7 @@ export interface ComponentMeta {
|
|
|
30
31
|
readonly categoryId: string;
|
|
31
32
|
readonly description: string;
|
|
32
33
|
readonly hasChildren: boolean;
|
|
34
|
+
readonly previewLayout?: 'grid' | 'list';
|
|
33
35
|
readonly variants: readonly VariantMeta[];
|
|
34
36
|
readonly editableProps: readonly EditableProp[];
|
|
35
37
|
}
|
|
@@ -2,6 +2,7 @@ import React, { createContext, useState, useMemo, useContext } from 'react';
|
|
|
2
2
|
import type { NewtoneThemeConfig, NewtoneThemeContext, ColorMode } from './types';
|
|
3
3
|
import { DEFAULT_THEME_CONFIG } from './defaults';
|
|
4
4
|
import { GoogleFontLoader } from '../fonts/GoogleFontLoader';
|
|
5
|
+
import { SelfHostedFontLoader } from '../fonts/SelfHostedFontLoader';
|
|
5
6
|
import { IconFontLoader } from '../fonts/IconFontLoader';
|
|
6
7
|
|
|
7
8
|
const ThemeContext = createContext<NewtoneThemeContext | null>(null);
|
|
@@ -10,6 +11,14 @@ export interface NewtoneProviderProps {
|
|
|
10
11
|
readonly config?: NewtoneThemeConfig;
|
|
11
12
|
readonly initialMode?: ColorMode;
|
|
12
13
|
readonly children: React.ReactNode;
|
|
14
|
+
/** Optional URL for typography telemetry. When set, adaptive Text instances report observations. */
|
|
15
|
+
readonly reportingEndpoint?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Self-hosted @font-face CSS from the theme API.
|
|
18
|
+
* When provided, injects this CSS instead of loading from Google CDN.
|
|
19
|
+
* Falls back to Google CDN when absent or null.
|
|
20
|
+
*/
|
|
21
|
+
readonly fontFaceCss?: string | null;
|
|
13
22
|
}
|
|
14
23
|
|
|
15
24
|
/**
|
|
@@ -28,6 +37,8 @@ export function NewtoneProvider({
|
|
|
28
37
|
config = DEFAULT_THEME_CONFIG,
|
|
29
38
|
initialMode = 'light',
|
|
30
39
|
children,
|
|
40
|
+
reportingEndpoint,
|
|
41
|
+
fontFaceCss,
|
|
31
42
|
}: NewtoneProviderProps) {
|
|
32
43
|
const [mode, setMode] = useState<ColorMode>(initialMode);
|
|
33
44
|
|
|
@@ -36,13 +47,18 @@ export function NewtoneProvider({
|
|
|
36
47
|
config,
|
|
37
48
|
mode,
|
|
38
49
|
setMode,
|
|
50
|
+
reportingEndpoint,
|
|
39
51
|
}),
|
|
40
|
-
[config, mode]
|
|
52
|
+
[config, mode, reportingEndpoint]
|
|
41
53
|
);
|
|
42
54
|
|
|
43
55
|
return (
|
|
44
56
|
<ThemeContext.Provider value={value}>
|
|
45
|
-
|
|
57
|
+
{fontFaceCss ? (
|
|
58
|
+
<SelfHostedFontLoader fontFaceCss={fontFaceCss} />
|
|
59
|
+
) : (
|
|
60
|
+
<GoogleFontLoader fonts={config.typography.fonts} />
|
|
61
|
+
)}
|
|
46
62
|
<IconFontLoader icons={config.icons} />
|
|
47
63
|
{children}
|
|
48
64
|
</ThemeContext.Provider>
|
package/src/theme/defaults.ts
CHANGED
|
@@ -11,6 +11,10 @@ import {
|
|
|
11
11
|
DEFAULT_ERROR_HUE,
|
|
12
12
|
DEFAULT_ERROR_SATURATION,
|
|
13
13
|
} from 'newtone';
|
|
14
|
+
import { DEFAULT_FONT_SLOTS, DEFAULT_FONT_SIZES, DEFAULT_LINE_HEIGHTS, DEFAULT_ROLE_SCALES } from '@newtonedev/fonts';
|
|
15
|
+
|
|
16
|
+
// Re-export typography defaults from @newtonedev/fonts (canonical source)
|
|
17
|
+
export { DEFAULT_FONT_SIZES, DEFAULT_LINE_HEIGHTS, DEFAULT_ROLE_SCALES } from '@newtonedev/fonts';
|
|
14
18
|
|
|
15
19
|
/**
|
|
16
20
|
* Default theme configuration matching playground defaults.
|
|
@@ -54,34 +58,10 @@ export const DEFAULT_THEME_CONFIG: NewtoneThemeConfig = {
|
|
|
54
58
|
pill: 999,
|
|
55
59
|
},
|
|
56
60
|
typography: {
|
|
57
|
-
fonts:
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
fallback: 'SFMono-Regular, Menlo, Monaco, Consolas, monospace',
|
|
62
|
-
},
|
|
63
|
-
display: {
|
|
64
|
-
type: 'system',
|
|
65
|
-
family: 'system-ui',
|
|
66
|
-
fallback: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
|
|
67
|
-
},
|
|
68
|
-
default: {
|
|
69
|
-
type: 'system',
|
|
70
|
-
family: 'system-ui',
|
|
71
|
-
fallback: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
|
|
72
|
-
},
|
|
73
|
-
},
|
|
74
|
-
scale: {
|
|
75
|
-
xs: 10, // 16 / 1.25^2
|
|
76
|
-
sm: 13, // 16 / 1.25
|
|
77
|
-
base: 16,
|
|
78
|
-
md: 20, // 16 * 1.25
|
|
79
|
-
lg: 25, // 16 * 1.25^2
|
|
80
|
-
xl: 31, // 16 * 1.25^3
|
|
81
|
-
xxl: 39, // 16 * 1.25^4
|
|
82
|
-
},
|
|
83
|
-
lineHeight: { tight: 1.25, normal: 1.5, relaxed: 1.75 },
|
|
84
|
-
fontWeight: { regular: 400, medium: 500, semibold: 600, bold: 700 },
|
|
61
|
+
fonts: DEFAULT_FONT_SLOTS,
|
|
62
|
+
fontSizes: DEFAULT_FONT_SIZES,
|
|
63
|
+
lineHeights: DEFAULT_LINE_HEIGHTS,
|
|
64
|
+
roles: DEFAULT_ROLE_SCALES,
|
|
85
65
|
},
|
|
86
66
|
icons: {
|
|
87
67
|
variant: 'rounded', // Material Design 3 aesthetic
|
package/src/theme/types.ts
CHANGED
|
@@ -1,20 +1,27 @@
|
|
|
1
1
|
import type { DynamicRange, PaletteConfig } from 'newtone';
|
|
2
2
|
|
|
3
|
+
// Re-export font/typography types from @newtonedev/fonts (canonical source)
|
|
4
|
+
export type {
|
|
5
|
+
FontConfig,
|
|
6
|
+
FontWeights,
|
|
7
|
+
FontSlot,
|
|
8
|
+
FontSizeScale,
|
|
9
|
+
LineHeightScale,
|
|
10
|
+
RoleSizeStep,
|
|
11
|
+
RoleScale,
|
|
12
|
+
RoleScales,
|
|
13
|
+
BreakpointKey,
|
|
14
|
+
Breakpoints,
|
|
15
|
+
BreakpointRoleScales,
|
|
16
|
+
FontRuntimeMetrics,
|
|
17
|
+
} from '@newtonedev/fonts';
|
|
18
|
+
import type { FontSlot, FontSizeScale, LineHeightScale, RoleScales, BreakpointRoleScales, FontRuntimeMetrics, TextRole } from '@newtonedev/fonts';
|
|
19
|
+
|
|
3
20
|
/**
|
|
4
21
|
* Color mode: light or dark
|
|
5
22
|
*/
|
|
6
23
|
export type ColorMode = 'light' | 'dark';
|
|
7
24
|
|
|
8
|
-
/**
|
|
9
|
-
* Font configuration for a single font slot
|
|
10
|
-
*/
|
|
11
|
-
export interface FontConfig {
|
|
12
|
-
readonly type: 'system' | 'google' | 'custom';
|
|
13
|
-
readonly family: string; // 'ui-monospace' | 'Roboto' | custom name
|
|
14
|
-
readonly customUrl?: string; // Supabase Storage URL for custom fonts
|
|
15
|
-
readonly fallback: string; // CSS fallback stack
|
|
16
|
-
}
|
|
17
|
-
|
|
18
25
|
/**
|
|
19
26
|
* Elevation levels for surfaces (internal)
|
|
20
27
|
* 0 = sunken, 1 = default, 2 = elevated
|
|
@@ -118,30 +125,46 @@ export interface NewtoneThemeConfig {
|
|
|
118
125
|
};
|
|
119
126
|
readonly typography: {
|
|
120
127
|
readonly fonts: {
|
|
121
|
-
readonly
|
|
122
|
-
readonly display:
|
|
123
|
-
readonly
|
|
124
|
-
|
|
125
|
-
readonly scale: {
|
|
126
|
-
readonly xs: number; // baseSize / ratio^2
|
|
127
|
-
readonly sm: number; // baseSize / ratio
|
|
128
|
-
readonly base: number; // baseSize
|
|
129
|
-
readonly md: number; // baseSize * ratio
|
|
130
|
-
readonly lg: number; // baseSize * ratio^2
|
|
131
|
-
readonly xl: number; // baseSize * ratio^3
|
|
132
|
-
readonly xxl: number; // baseSize * ratio^4
|
|
133
|
-
};
|
|
134
|
-
readonly lineHeight: {
|
|
135
|
-
readonly tight: number; // 1.25
|
|
136
|
-
readonly normal: number; // 1.5
|
|
137
|
-
readonly relaxed: number; // 1.75
|
|
138
|
-
};
|
|
139
|
-
readonly fontWeight: {
|
|
140
|
-
readonly regular: number; // 400
|
|
141
|
-
readonly medium: number; // 500
|
|
142
|
-
readonly semibold: number; // 600
|
|
143
|
-
readonly bold: number; // 700
|
|
128
|
+
readonly main: FontSlot; // Default/body font (fallback for all scopes)
|
|
129
|
+
readonly display: FontSlot; // Headlines, titles, large display text
|
|
130
|
+
readonly mono: FontSlot; // Code snippets, technical content
|
|
131
|
+
readonly currency: FontSlot; // Monetary amounts, financial data
|
|
144
132
|
};
|
|
133
|
+
/** Primitive font size scale — numbered tokens ('01'-'16'), values in px. */
|
|
134
|
+
readonly fontSizes: FontSizeScale;
|
|
135
|
+
/** Primitive line height scale — numbered tokens ('01'-'16'), values in px. */
|
|
136
|
+
readonly lineHeights: LineHeightScale;
|
|
137
|
+
/** Role mapping — pairs fontSizes and lineHeights for each role x size combination. */
|
|
138
|
+
readonly roles: RoleScales;
|
|
139
|
+
/**
|
|
140
|
+
* Per-font avgCharWidth ratios, keyed by font family name.
|
|
141
|
+
* Measured with canvas at editor publish time (Layer 1 calibration).
|
|
142
|
+
* Used by resolveResponsiveSize to improve line break estimation accuracy.
|
|
143
|
+
* Falls back to 0.55 when absent.
|
|
144
|
+
*/
|
|
145
|
+
readonly calibrations?: Record<string, number>;
|
|
146
|
+
/**
|
|
147
|
+
* Pre-computed role scales for each viewport breakpoint (sm/md/lg).
|
|
148
|
+
* Enables CSS-only consumers to generate @media rules from the theme JSON
|
|
149
|
+
* without importing newtone-fonts. Runtime components use useBreakpoint
|
|
150
|
+
* instead and compute scaling on the fly.
|
|
151
|
+
*/
|
|
152
|
+
readonly breakpointRoles?: BreakpointRoleScales;
|
|
153
|
+
/**
|
|
154
|
+
* Per-font OpenType-derived metrics, keyed by font family name.
|
|
155
|
+
* Extracted from font binaries at upload time, looked up at publish time.
|
|
156
|
+
* Used by Text for line height correction (adjustLineHeight),
|
|
157
|
+
* vertical centering (verticalCenterOffset), and font feature validation.
|
|
158
|
+
* Falls back to Inter-equivalent defaults when absent.
|
|
159
|
+
*/
|
|
160
|
+
readonly fontMetrics?: Readonly<Record<string, FontRuntimeMetrics>>;
|
|
161
|
+
/**
|
|
162
|
+
* Per-role font weight (CSS font-weight 100–900).
|
|
163
|
+
* Primary weight path — the Text component uses these values directly.
|
|
164
|
+
* When populated via toThemeConfig, defaults are merged with user overrides.
|
|
165
|
+
* Per-instance weight prop still takes priority.
|
|
166
|
+
*/
|
|
167
|
+
readonly roleWeights?: Partial<Record<TextRole, number>>;
|
|
145
168
|
};
|
|
146
169
|
readonly icons: {
|
|
147
170
|
readonly variant: 'outlined' | 'rounded' | 'sharp';
|
|
@@ -158,4 +181,11 @@ export interface NewtoneThemeContext {
|
|
|
158
181
|
readonly config: NewtoneThemeConfig;
|
|
159
182
|
readonly mode: ColorMode;
|
|
160
183
|
readonly setMode: (mode: ColorMode) => void;
|
|
184
|
+
/**
|
|
185
|
+
* Optional URL for the typography telemetry reporting endpoint.
|
|
186
|
+
* When set, the Text component (in responsive mode) will batch and POST
|
|
187
|
+
* ObserverPayload observations to this URL for cross-site aggregation.
|
|
188
|
+
* When absent, no telemetry is sent (opt-in).
|
|
189
|
+
*/
|
|
190
|
+
readonly reportingEndpoint?: string;
|
|
161
191
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { useWindowDimensions } from 'react-native';
|
|
2
|
+
import { getBreakpointForWidth } from '@newtonedev/fonts';
|
|
3
|
+
import type { BreakpointKey } from '@newtonedev/fonts';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Returns the current viewport breakpoint key ('sm' | 'md' | 'lg').
|
|
7
|
+
*
|
|
8
|
+
* Uses `useWindowDimensions` from react-native (cross-platform — works
|
|
9
|
+
* on web via react-native-web) and re-evaluates on window resize.
|
|
10
|
+
*/
|
|
11
|
+
export function useBreakpoint(): BreakpointKey {
|
|
12
|
+
const { width } = useWindowDimensions();
|
|
13
|
+
return getBreakpointForWidth(width);
|
|
14
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { getColor } from 'newtone';
|
|
2
2
|
import type { PaletteConfig } from 'newtone';
|
|
3
|
-
import
|
|
3
|
+
import { fontConfigToFamily } from '@newtonedev/fonts';
|
|
4
|
+
import type { ColorSystemConfig, ColorMode, ElevationLevel, FontSlot, TokenOverrides } from '../theme/types';
|
|
4
5
|
import type { ResolvedTokens, PaletteTokens } from './types';
|
|
5
6
|
|
|
6
7
|
/**
|
|
@@ -115,14 +116,6 @@ export const ERROR_DEFAULTS: PaletteDefaults = {
|
|
|
115
116
|
},
|
|
116
117
|
};
|
|
117
118
|
|
|
118
|
-
/**
|
|
119
|
-
* Convert FontConfig to CSS font-family string
|
|
120
|
-
*/
|
|
121
|
-
function fontConfigToFamily(font: FontConfig): string {
|
|
122
|
-
const family = font.family.includes(' ') ? `"${font.family}"` : font.family;
|
|
123
|
-
return `${family}, ${font.fallback}`;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
119
|
const clamp = (n: number) => Math.max(0, Math.min(1, n));
|
|
127
120
|
|
|
128
121
|
/**
|
|
@@ -262,10 +255,9 @@ export function computeTokens(
|
|
|
262
255
|
spacing: { readonly '00': number; readonly '02': number; readonly '04': number; readonly '06': number; readonly '08': number; readonly '10': number; readonly '12': number; readonly '16': number; readonly '20': number; readonly '24': number; readonly '32': number; readonly '40': number; readonly '48': number },
|
|
263
256
|
radius: { readonly none: number; readonly sm: number; readonly md: number; readonly lg: number; readonly xl: number; readonly pill: 999 },
|
|
264
257
|
typography: {
|
|
265
|
-
readonly fonts: { readonly
|
|
266
|
-
readonly
|
|
267
|
-
readonly
|
|
268
|
-
readonly fontWeight: { readonly regular: number; readonly medium: number; readonly semibold: number; readonly bold: number };
|
|
258
|
+
readonly fonts: { readonly main: FontSlot; readonly display: FontSlot; readonly mono: FontSlot; readonly currency: FontSlot };
|
|
259
|
+
readonly fontSizes: { readonly [key: string]: number };
|
|
260
|
+
readonly lineHeights: { readonly [key: string]: number };
|
|
269
261
|
},
|
|
270
262
|
icons: {
|
|
271
263
|
readonly variant: 'outlined' | 'rounded' | 'sharp';
|
|
@@ -493,13 +485,25 @@ export function computeTokens(
|
|
|
493
485
|
radius,
|
|
494
486
|
typography: {
|
|
495
487
|
fonts: {
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
488
|
+
main: {
|
|
489
|
+
family: fontConfigToFamily(typography.fonts.main.config),
|
|
490
|
+
weights: typography.fonts.main.weights,
|
|
491
|
+
},
|
|
492
|
+
display: {
|
|
493
|
+
family: fontConfigToFamily(typography.fonts.display.config),
|
|
494
|
+
weights: typography.fonts.display.weights,
|
|
495
|
+
},
|
|
496
|
+
mono: {
|
|
497
|
+
family: fontConfigToFamily(typography.fonts.mono.config),
|
|
498
|
+
weights: typography.fonts.mono.weights,
|
|
499
|
+
},
|
|
500
|
+
currency: {
|
|
501
|
+
family: fontConfigToFamily(typography.fonts.currency.config),
|
|
502
|
+
weights: typography.fonts.currency.weights,
|
|
503
|
+
},
|
|
499
504
|
},
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
weight: typography.fontWeight,
|
|
505
|
+
fontSizes: typography.fontSizes,
|
|
506
|
+
lineHeights: typography.lineHeights,
|
|
503
507
|
},
|
|
504
508
|
icons: {
|
|
505
509
|
variant: icons.variant,
|
package/src/tokens/types.ts
CHANGED
|
@@ -123,33 +123,19 @@ export interface ResolvedTokens {
|
|
|
123
123
|
readonly xl: number;
|
|
124
124
|
readonly pill: 999;
|
|
125
125
|
};
|
|
126
|
-
/** Typography tokens for fonts
|
|
126
|
+
/** Typography tokens for fonts (per-scope) and primitive size/lineHeight scales */
|
|
127
127
|
readonly typography: {
|
|
128
|
+
/** Per-scope font family + weight mapping */
|
|
128
129
|
readonly fonts: {
|
|
129
|
-
readonly
|
|
130
|
-
readonly display: string;
|
|
131
|
-
readonly
|
|
132
|
-
|
|
133
|
-
readonly size: {
|
|
134
|
-
readonly xs: number;
|
|
135
|
-
readonly sm: number;
|
|
136
|
-
readonly base: number;
|
|
137
|
-
readonly md: number;
|
|
138
|
-
readonly lg: number;
|
|
139
|
-
readonly xl: number;
|
|
140
|
-
readonly xxl: number;
|
|
141
|
-
};
|
|
142
|
-
readonly lineHeight: {
|
|
143
|
-
readonly tight: number;
|
|
144
|
-
readonly normal: number;
|
|
145
|
-
readonly relaxed: number;
|
|
146
|
-
};
|
|
147
|
-
readonly weight: {
|
|
148
|
-
readonly regular: number;
|
|
149
|
-
readonly medium: number;
|
|
150
|
-
readonly semibold: number;
|
|
151
|
-
readonly bold: number;
|
|
130
|
+
readonly main: { readonly family: string; readonly weights: { readonly regular: number; readonly medium: number; readonly bold: number; } };
|
|
131
|
+
readonly display: { readonly family: string; readonly weights: { readonly regular: number; readonly medium: number; readonly bold: number; } };
|
|
132
|
+
readonly mono: { readonly family: string; readonly weights: { readonly regular: number; readonly medium: number; readonly bold: number; } };
|
|
133
|
+
readonly currency: { readonly family: string; readonly weights: { readonly regular: number; readonly medium: number; readonly bold: number; } };
|
|
152
134
|
};
|
|
135
|
+
/** Primitive font size scale — numbered tokens ('01'–'16'), values in px */
|
|
136
|
+
readonly fontSizes: { readonly [key: string]: number };
|
|
137
|
+
/** Primitive line height scale — numbered tokens ('01'–'16'), values in px */
|
|
138
|
+
readonly lineHeights: { readonly [key: string]: number };
|
|
153
139
|
};
|
|
154
140
|
/** Icon tokens for Material Symbols configuration */
|
|
155
141
|
readonly icons: {
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
export interface GoogleFontEntry {
|
|
2
|
-
readonly family: string;
|
|
3
|
-
readonly category: 'sans-serif' | 'serif' | 'monospace' | 'display';
|
|
4
|
-
readonly fallback: string;
|
|
5
|
-
}
|
|
6
|
-
/**
|
|
7
|
-
* Curated list of popular Google Fonts organized by category.
|
|
8
|
-
* Used by the font picker UI and the GoogleFontLoader.
|
|
9
|
-
*/
|
|
10
|
-
export declare const GOOGLE_FONTS: readonly GoogleFontEntry[];
|
|
11
|
-
export interface SystemFontEntry {
|
|
12
|
-
readonly family: string;
|
|
13
|
-
readonly category: 'sans-serif' | 'serif' | 'monospace';
|
|
14
|
-
readonly fallback: string;
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* System font options that don't require external loading.
|
|
18
|
-
*/
|
|
19
|
-
export declare const SYSTEM_FONTS: readonly SystemFontEntry[];
|
|
20
|
-
//# sourceMappingURL=googleFonts.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"googleFonts.d.ts","sourceRoot":"","sources":["../../src/fonts/googleFonts.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO,GAAG,WAAW,GAAG,SAAS,CAAC;IACpE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED;;;GAGG;AACH,eAAO,MAAM,YAAY,EAAE,SAAS,eAAe,EAiDlD,CAAC;AAEF,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO,GAAG,WAAW,CAAC;IACxD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED;;GAEG;AACH,eAAO,MAAM,YAAY,EAAE,SAAS,eAAe,EAgBlD,CAAC"}
|