@newtonedev/components 0.1.13 → 0.1.15
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 +17 -20
- package/dist/composites/actions/Button/Button.d.ts.map +1 -1
- package/dist/composites/actions/Button/Button.styles.d.ts +12 -24
- package/dist/composites/actions/Button/Button.styles.d.ts.map +1 -1
- package/dist/composites/actions/Button/Button.types.d.ts +14 -13
- package/dist/composites/actions/Button/Button.types.d.ts.map +1 -1
- package/dist/composites/actions/Button/index.d.ts +1 -1
- package/dist/composites/actions/Button/index.d.ts.map +1 -1
- package/dist/composites/branding/LogoMonogram/LogoMonogram.d.ts +10 -0
- package/dist/composites/branding/LogoMonogram/LogoMonogram.d.ts.map +1 -0
- package/dist/composites/branding/LogoMonogram/LogoMonogram.types.d.ts +35 -0
- package/dist/composites/branding/LogoMonogram/LogoMonogram.types.d.ts.map +1 -0
- package/dist/composites/branding/LogoMonogram/index.d.ts +3 -0
- package/dist/composites/branding/LogoMonogram/index.d.ts.map +1 -0
- package/dist/composites/branding/LogoWordmark/LogoWordmark.d.ts +9 -0
- package/dist/composites/branding/LogoWordmark/LogoWordmark.d.ts.map +1 -0
- package/dist/composites/branding/LogoWordmark/LogoWordmark.types.d.ts +26 -0
- package/dist/composites/branding/LogoWordmark/LogoWordmark.types.d.ts.map +1 -0
- package/dist/composites/branding/LogoWordmark/index.d.ts +3 -0
- package/dist/composites/branding/LogoWordmark/index.d.ts.map +1 -0
- package/dist/composites/display/Chip/Chip.d.ts +25 -0
- package/dist/composites/display/Chip/Chip.d.ts.map +1 -0
- package/dist/composites/display/Chip/Chip.styles.d.ts +29 -0
- package/dist/composites/display/Chip/Chip.styles.d.ts.map +1 -0
- package/dist/composites/display/Chip/Chip.types.d.ts +63 -0
- package/dist/composites/display/Chip/Chip.types.d.ts.map +1 -0
- package/dist/composites/display/Chip/index.d.ts +3 -0
- package/dist/composites/display/Chip/index.d.ts.map +1 -0
- package/dist/composites/form-controls/Select/Select.d.ts.map +1 -1
- package/dist/composites/form-controls/Select/Select.styles.d.ts +2 -2
- package/dist/composites/form-controls/Select/Select.styles.d.ts.map +1 -1
- package/dist/composites/form-controls/Select/SelectOption.d.ts.map +1 -1
- package/dist/composites/form-controls/TextInput/TextInput.d.ts.map +1 -1
- package/dist/composites/form-controls/TextInput/TextInput.styles.d.ts +2 -2
- package/dist/composites/form-controls/TextInput/TextInput.styles.d.ts.map +1 -1
- package/dist/composites/form-controls/Toggle/Toggle.d.ts.map +1 -1
- package/dist/composites/form-controls/Toggle/Toggle.styles.d.ts +2 -2
- package/dist/composites/form-controls/Toggle/Toggle.styles.d.ts.map +1 -1
- package/dist/composites/layout/AppShell/AppShell.d.ts.map +1 -1
- package/dist/composites/layout/AppShell/AppShell.styles.d.ts +2 -2
- package/dist/composites/layout/AppShell/AppShell.styles.d.ts.map +1 -1
- package/dist/composites/layout/Card/Card.d.ts.map +1 -1
- package/dist/composites/layout/Card/Card.styles.d.ts +2 -2
- package/dist/composites/layout/Card/Card.styles.d.ts.map +1 -1
- package/dist/composites/layout/ContentCard/ContentCard.d.ts +33 -0
- package/dist/composites/layout/ContentCard/ContentCard.d.ts.map +1 -0
- package/dist/composites/layout/ContentCard/ContentCard.styles.d.ts +10 -0
- package/dist/composites/layout/ContentCard/ContentCard.styles.d.ts.map +1 -0
- package/dist/composites/layout/ContentCard/ContentCard.types.d.ts +52 -0
- package/dist/composites/layout/ContentCard/ContentCard.types.d.ts.map +1 -0
- package/dist/composites/layout/ContentCard/index.d.ts +3 -0
- package/dist/composites/layout/ContentCard/index.d.ts.map +1 -0
- package/dist/composites/layout/Divider/Divider.d.ts +25 -0
- package/dist/composites/layout/Divider/Divider.d.ts.map +1 -0
- package/dist/composites/layout/Divider/Divider.styles.d.ts +8 -0
- package/dist/composites/layout/Divider/Divider.styles.d.ts.map +1 -0
- package/dist/composites/layout/Divider/Divider.types.d.ts +25 -0
- package/dist/composites/layout/Divider/Divider.types.d.ts.map +1 -0
- package/dist/composites/layout/Divider/index.d.ts +3 -0
- package/dist/composites/layout/Divider/index.d.ts.map +1 -0
- package/dist/composites/layout/Navbar/Navbar.d.ts.map +1 -1
- package/dist/composites/layout/Navbar/Navbar.styles.d.ts +4 -3
- package/dist/composites/layout/Navbar/Navbar.styles.d.ts.map +1 -1
- package/dist/composites/layout/Sidebar/Sidebar.d.ts.map +1 -1
- package/dist/composites/layout/Sidebar/Sidebar.styles.d.ts +4 -3
- package/dist/composites/layout/Sidebar/Sidebar.styles.d.ts.map +1 -1
- package/dist/composites/overlays/Popover/Popover.d.ts.map +1 -1
- package/dist/composites/overlays/Popover/Popover.styles.d.ts +2 -2
- package/dist/composites/overlays/Popover/Popover.styles.d.ts.map +1 -1
- package/dist/composites/range-inputs/ColorScaleSlider/ColorScaleSlider.d.ts.map +1 -1
- package/dist/composites/range-inputs/ColorScaleSlider/ColorScaleSlider.styles.d.ts +2 -2
- package/dist/composites/range-inputs/ColorScaleSlider/ColorScaleSlider.styles.d.ts.map +1 -1
- package/dist/composites/range-inputs/HueSlider/HueSlider.styles.d.ts +2 -2
- package/dist/composites/range-inputs/HueSlider/HueSlider.styles.d.ts.map +1 -1
- package/dist/composites/range-inputs/Slider/Slider.styles.d.ts +2 -2
- package/dist/composites/range-inputs/Slider/Slider.styles.d.ts.map +1 -1
- package/dist/index.cjs +935 -523
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +13 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +860 -473
- package/dist/index.js.map +1 -1
- package/dist/primitives/Frame/Frame.d.ts +1 -35
- package/dist/primitives/Frame/Frame.d.ts.map +1 -1
- package/dist/primitives/Frame/Frame.styles.d.ts +13 -4
- package/dist/primitives/Frame/Frame.styles.d.ts.map +1 -1
- package/dist/primitives/Frame/Frame.types.d.ts +99 -1
- package/dist/primitives/Frame/Frame.types.d.ts.map +1 -1
- package/dist/primitives/Frame/index.d.ts +1 -1
- package/dist/primitives/Frame/index.d.ts.map +1 -1
- package/dist/primitives/Icon/Icon.d.ts.map +1 -1
- package/dist/primitives/Icon/Icon.types.d.ts +2 -2
- package/dist/primitives/Icon/Icon.types.d.ts.map +1 -1
- package/dist/primitives/Text/Text.d.ts +5 -3
- package/dist/primitives/Text/Text.d.ts.map +1 -1
- package/dist/primitives/Text/Text.spans.d.ts.map +1 -1
- package/dist/primitives/Text/Text.types.d.ts +3 -6
- package/dist/primitives/Text/Text.types.d.ts.map +1 -1
- package/dist/primitives/Wrapper/Wrapper.d.ts +1 -1
- package/dist/primitives/Wrapper/Wrapper.d.ts.map +1 -1
- package/dist/primitives/Wrapper/Wrapper.styles.d.ts +9 -1
- package/dist/primitives/Wrapper/Wrapper.styles.d.ts.map +1 -1
- package/dist/primitives/Wrapper/Wrapper.types.d.ts +31 -1
- package/dist/primitives/Wrapper/Wrapper.types.d.ts.map +1 -1
- package/dist/registry/registry.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/composites/actions/Button/Button.styles.ts +90 -182
- package/src/composites/actions/Button/Button.tsx +37 -33
- package/src/composites/actions/Button/Button.types.ts +16 -15
- package/src/composites/actions/Button/index.ts +1 -1
- package/src/composites/branding/LogoMonogram/LogoMonogram.tsx +29 -0
- package/src/composites/branding/LogoMonogram/LogoMonogram.types.ts +35 -0
- package/src/composites/branding/LogoMonogram/index.ts +2 -0
- package/src/composites/branding/LogoWordmark/LogoWordmark.tsx +29 -0
- package/src/composites/branding/LogoWordmark/LogoWordmark.types.ts +25 -0
- package/src/composites/branding/LogoWordmark/index.ts +2 -0
- package/src/composites/display/Chip/Chip.styles.ts +189 -0
- package/src/composites/display/Chip/Chip.tsx +97 -0
- package/src/composites/display/Chip/Chip.types.ts +74 -0
- package/src/composites/display/Chip/index.ts +2 -0
- package/src/composites/form-controls/Select/Select.styles.ts +10 -10
- package/src/composites/form-controls/Select/Select.tsx +9 -6
- package/src/composites/form-controls/Select/SelectOption.tsx +10 -7
- package/src/composites/form-controls/TextInput/TextInput.styles.ts +12 -8
- package/src/composites/form-controls/TextInput/TextInput.tsx +7 -4
- package/src/composites/form-controls/Toggle/Toggle.styles.ts +10 -7
- package/src/composites/form-controls/Toggle/Toggle.tsx +4 -3
- package/src/composites/layout/AppShell/AppShell.styles.ts +8 -3
- package/src/composites/layout/AppShell/AppShell.tsx +6 -2
- package/src/composites/layout/Card/Card.styles.ts +10 -4
- package/src/composites/layout/Card/Card.tsx +4 -3
- package/src/composites/layout/ContentCard/ContentCard.styles.ts +44 -0
- package/src/composites/layout/ContentCard/ContentCard.tsx +71 -0
- package/src/composites/layout/ContentCard/ContentCard.types.ts +60 -0
- package/src/composites/layout/ContentCard/index.ts +2 -0
- package/src/composites/layout/Divider/Divider.styles.ts +30 -0
- package/src/composites/layout/Divider/Divider.tsx +46 -0
- package/src/composites/layout/Divider/Divider.types.ts +28 -0
- package/src/composites/layout/Divider/index.ts +2 -0
- package/src/composites/layout/Navbar/Navbar.styles.ts +7 -5
- package/src/composites/layout/Navbar/Navbar.tsx +4 -3
- package/src/composites/layout/Sidebar/Sidebar.styles.ts +7 -5
- package/src/composites/layout/Sidebar/Sidebar.tsx +4 -3
- package/src/composites/overlays/Popover/Popover.styles.ts +7 -5
- package/src/composites/overlays/Popover/Popover.tsx +4 -3
- package/src/composites/range-inputs/ColorScaleSlider/ColorScaleSlider.styles.ts +5 -5
- package/src/composites/range-inputs/ColorScaleSlider/ColorScaleSlider.tsx +4 -3
- package/src/composites/range-inputs/HueSlider/HueSlider.styles.ts +7 -7
- package/src/composites/range-inputs/HueSlider/HueSlider.tsx +1 -1
- package/src/composites/range-inputs/Slider/Slider.styles.ts +9 -9
- package/src/composites/range-inputs/Slider/Slider.tsx +1 -1
- package/src/index.ts +49 -10
- package/src/primitives/Frame/Frame.styles.ts +55 -12
- package/src/primitives/Frame/Frame.tsx +139 -140
- package/src/primitives/Frame/Frame.types.ts +119 -1
- package/src/primitives/Frame/index.ts +4 -0
- package/src/primitives/Icon/Icon.tsx +9 -6
- package/src/primitives/Icon/Icon.types.ts +2 -2
- package/src/primitives/Text/Text.spans.ts +9 -5
- package/src/primitives/Text/Text.tsx +26 -15
- package/src/primitives/Text/Text.types.ts +3 -6
- package/src/primitives/Wrapper/Wrapper.styles.ts +32 -0
- package/src/primitives/Wrapper/Wrapper.tsx +22 -3
- package/src/primitives/Wrapper/Wrapper.types.ts +45 -0
- package/src/registry/registry.ts +5 -21
- package/dist/_COMPONENT_TEMPLATE/ComponentName.d.ts +0 -70
- package/dist/_COMPONENT_TEMPLATE/ComponentName.d.ts.map +0 -1
- package/dist/_COMPONENT_TEMPLATE/ComponentName.styles.d.ts +0 -23
- package/dist/_COMPONENT_TEMPLATE/ComponentName.styles.d.ts.map +0 -1
- package/dist/_COMPONENT_TEMPLATE/ComponentName.types.d.ts +0 -45
- package/dist/_COMPONENT_TEMPLATE/ComponentName.types.d.ts.map +0 -1
- package/dist/_COMPONENT_TEMPLATE/index.d.ts +0 -3
- package/dist/_COMPONENT_TEMPLATE/index.d.ts.map +0 -1
|
@@ -2,19 +2,15 @@ import React, { useMemo } from 'react';
|
|
|
2
2
|
import { View, Pressable, Text } from 'react-native';
|
|
3
3
|
import type { ViewStyle, TextStyle } from 'react-native';
|
|
4
4
|
import type { FrameProps } from './Frame.types';
|
|
5
|
-
import type { ElevationLevel, FrameElevation } from 'newtone-api';
|
|
5
|
+
import type { ElevationLevel, FrameElevation, ElevationName, ThemeName, AppearanceName } from 'newtone-api';
|
|
6
6
|
import { FrameContext, useFrameContext } from 'newtone-api';
|
|
7
|
-
import { useNewtoneTheme } from 'newtone-api';
|
|
7
|
+
import { useNewtoneTheme, _ThemeContext } from 'newtone-api';
|
|
8
8
|
import { computeTokens } from 'newtone-api';
|
|
9
9
|
import { getFrameStyles } from './Frame.styles';
|
|
10
10
|
import { useFocusVisible } from '../useFocusVisible';
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Wrap raw string/number children in <Text> so they display correctly.
|
|
14
|
-
*
|
|
15
|
-
* In React Native, raw text like <View>"hello"</View> will crash on native
|
|
16
|
-
* and show console warnings on web. All text must be inside a <Text> element.
|
|
17
|
-
* This helper scans children and auto-wraps any bare strings or numbers.
|
|
18
14
|
*/
|
|
19
15
|
function wrapTextChildren(
|
|
20
16
|
children: React.ReactNode,
|
|
@@ -28,16 +24,15 @@ function wrapTextChildren(
|
|
|
28
24
|
});
|
|
29
25
|
}
|
|
30
26
|
|
|
27
|
+
/** Map numeric elevation levels to named elevations for the swatches layer. */
|
|
28
|
+
const ELEVATION_MAP: Record<ElevationLevel, ElevationName> = {
|
|
29
|
+
0: 'sunken',
|
|
30
|
+
1: 'grounded',
|
|
31
|
+
2: 'elevated',
|
|
32
|
+
};
|
|
33
|
+
|
|
31
34
|
/**
|
|
32
35
|
* Convert user-facing FrameElevation (-2..2) to internal ElevationLevel (0..2).
|
|
33
|
-
*
|
|
34
|
-
* | Frame | Internal | Background |
|
|
35
|
-
* |:-----:|:--------:|:-----------|
|
|
36
|
-
* | -2 | 0 | Sunken |
|
|
37
|
-
* | -1 | 0 | Sunken |
|
|
38
|
-
* | 0 | 1 | Default |
|
|
39
|
-
* | 1 | 2 | Elevated |
|
|
40
|
-
* | 2 | 2 | Elevated |
|
|
41
36
|
*/
|
|
42
37
|
function toElevationLevel(frameElevation: FrameElevation): ElevationLevel {
|
|
43
38
|
if (frameElevation <= -1) return 0;
|
|
@@ -53,45 +48,16 @@ function toElevationLevel(frameElevation: FrameElevation): ElevationLevel {
|
|
|
53
48
|
* and interactivity capabilities.
|
|
54
49
|
*
|
|
55
50
|
* Frames can be nested. Inner frames override outer frames for their subtree.
|
|
56
|
-
* Unspecified props inherit from the nearest parent Frame.
|
|
57
|
-
*
|
|
58
|
-
* @example
|
|
59
|
-
* ```tsx
|
|
60
|
-
* // Basic layout
|
|
61
|
-
* <Frame direction="horizontal" gap="md" padding="lg" align="center">
|
|
62
|
-
* <Button onPress={() => {}}>Save</Button>
|
|
63
|
-
* <Button variant="tertiary" onPress={() => {}}>Cancel</Button>
|
|
64
|
-
* </Frame>
|
|
65
|
-
* ```
|
|
66
|
-
*
|
|
67
|
-
* @example
|
|
68
|
-
* ```tsx
|
|
69
|
-
* // Card-like frame
|
|
70
|
-
* <Frame
|
|
71
|
-
* elevation={2}
|
|
72
|
-
* radius="lg"
|
|
73
|
-
* padding="xl"
|
|
74
|
-
* bordered
|
|
75
|
-
* onPress={() => navigate('/details')}
|
|
76
|
-
* >
|
|
77
|
-
* <Text>Clickable card</Text>
|
|
78
|
-
* </Frame>
|
|
79
|
-
* ```
|
|
80
|
-
*
|
|
81
|
-
* @example
|
|
82
|
-
* ```tsx
|
|
83
|
-
* // Grid layout (web)
|
|
84
|
-
* <Frame layout="grid" columns={3} gap="md" padding="lg">
|
|
85
|
-
* <Frame radius="md" padding="md" bordered>Cell 1</Frame>
|
|
86
|
-
* <Frame radius="md" padding="md" bordered>Cell 2</Frame>
|
|
87
|
-
* <Frame radius="md" padding="md" bordered>Cell 3</Frame>
|
|
88
|
-
* </Frame>
|
|
89
|
-
* ```
|
|
90
51
|
*/
|
|
91
52
|
export function Frame({
|
|
92
53
|
children,
|
|
93
54
|
// Elevation
|
|
94
55
|
elevation,
|
|
56
|
+
// Scheme
|
|
57
|
+
scheme,
|
|
58
|
+
// Theme / Appearance
|
|
59
|
+
theme,
|
|
60
|
+
appearance,
|
|
95
61
|
// Layout
|
|
96
62
|
layout,
|
|
97
63
|
direction,
|
|
@@ -112,6 +78,16 @@ export function Frame({
|
|
|
112
78
|
maxWidth,
|
|
113
79
|
minHeight,
|
|
114
80
|
maxHeight,
|
|
81
|
+
// Positioning
|
|
82
|
+
position,
|
|
83
|
+
top,
|
|
84
|
+
right,
|
|
85
|
+
bottom,
|
|
86
|
+
left,
|
|
87
|
+
zIndex,
|
|
88
|
+
overflow,
|
|
89
|
+
pointerEvents,
|
|
90
|
+
opacity,
|
|
115
91
|
// Appearance
|
|
116
92
|
radius,
|
|
117
93
|
bordered,
|
|
@@ -129,45 +105,55 @@ export function Frame({
|
|
|
129
105
|
// Style override
|
|
130
106
|
style,
|
|
131
107
|
}: FrameProps) {
|
|
132
|
-
|
|
133
|
-
const {
|
|
134
|
-
// Read the elevation from the nearest parent Frame (if nested).
|
|
108
|
+
const themeCtx = useNewtoneTheme();
|
|
109
|
+
const { mode, gamut } = themeCtx;
|
|
135
110
|
const parentFrameCtx = useFrameContext();
|
|
136
111
|
|
|
137
|
-
//
|
|
112
|
+
// Resolve which config to use: explicit scheme > inherited from parent > default.
|
|
113
|
+
const resolvedConfig = useMemo(() => {
|
|
114
|
+
if (scheme && themeCtx.schemes) {
|
|
115
|
+
const schemeConfig = themeCtx.schemes[scheme];
|
|
116
|
+
if (schemeConfig) return schemeConfig;
|
|
117
|
+
}
|
|
118
|
+
return themeCtx.config;
|
|
119
|
+
}, [scheme, themeCtx.schemes, themeCtx.config]);
|
|
120
|
+
|
|
121
|
+
// Track whether this Frame switches the scheme (needs theme context override).
|
|
122
|
+
const isSchemeOverride = resolvedConfig !== themeCtx.config;
|
|
123
|
+
|
|
124
|
+
// Resolve theme/appearance: explicit prop > parent Frame > defaults.
|
|
125
|
+
const resolvedTheme: ThemeName = theme ?? parentFrameCtx?.theme ?? 'primary';
|
|
126
|
+
const resolvedAppearance: AppearanceName = appearance ?? parentFrameCtx?.appearance ?? 'main';
|
|
127
|
+
|
|
138
128
|
const resolvedFrameElevation: FrameElevation = elevation ?? 0;
|
|
139
129
|
|
|
140
|
-
// Convert user-facing elevation to internal level (0-2) for token computation.
|
|
141
|
-
// When no elevation is set, inherit from parent Frame or default to 1.
|
|
142
130
|
const resolvedElevation: ElevationLevel = elevation !== undefined
|
|
143
131
|
? toElevationLevel(elevation)
|
|
144
132
|
: parentFrameCtx?.elevation ?? 1;
|
|
145
133
|
|
|
146
|
-
//
|
|
147
|
-
// Frame computes its own tokens instead of using useTokens() because
|
|
148
|
-
// useTokens() reads from FrameContext — but this Frame IS the provider,
|
|
149
|
-
// so it needs to compute fresh tokens from the resolved theme/elevation.
|
|
150
|
-
// Wrapped in useMemo so it only recalculates when the theme/mode/elevation changes.
|
|
134
|
+
// Compute tokens with gamut pre-applied (no [gamut] indexing needed downstream).
|
|
151
135
|
const tokens = useMemo(() => {
|
|
152
136
|
return computeTokens(
|
|
153
|
-
|
|
137
|
+
resolvedConfig.colorSystem,
|
|
154
138
|
mode,
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
139
|
+
gamut,
|
|
140
|
+
ELEVATION_MAP[resolvedElevation],
|
|
141
|
+
resolvedConfig.spacing,
|
|
142
|
+
resolvedConfig.radius,
|
|
143
|
+
resolvedConfig.typography,
|
|
144
|
+
resolvedConfig.icons,
|
|
145
|
+
resolvedConfig.themeMappings,
|
|
146
|
+
resolvedConfig.swatchDefaults,
|
|
147
|
+
resolvedConfig.relativeSwatchDefaults,
|
|
161
148
|
);
|
|
162
|
-
}, [
|
|
149
|
+
}, [resolvedConfig, mode, gamut, resolvedElevation]);
|
|
163
150
|
|
|
164
|
-
// Calculate all visual styles (background, layout, border, shadow, etc.).
|
|
165
|
-
// Only recalculates when one of the style-related props changes.
|
|
166
151
|
const styles = useMemo(
|
|
167
152
|
() => getFrameStyles({
|
|
168
153
|
tokens,
|
|
169
|
-
gamut,
|
|
170
154
|
frameElevation: resolvedFrameElevation,
|
|
155
|
+
theme: resolvedTheme,
|
|
156
|
+
appearance: resolvedAppearance,
|
|
171
157
|
layout,
|
|
172
158
|
direction,
|
|
173
159
|
wrap,
|
|
@@ -184,29 +170,53 @@ export function Frame({
|
|
|
184
170
|
maxWidth,
|
|
185
171
|
minHeight,
|
|
186
172
|
maxHeight,
|
|
173
|
+
position,
|
|
174
|
+
top,
|
|
175
|
+
right,
|
|
176
|
+
bottom,
|
|
177
|
+
left,
|
|
178
|
+
zIndex,
|
|
179
|
+
overflow,
|
|
180
|
+
opacity,
|
|
187
181
|
radius,
|
|
188
182
|
bordered,
|
|
189
183
|
disabled,
|
|
190
184
|
}),
|
|
191
185
|
[
|
|
192
|
-
tokens,
|
|
186
|
+
tokens, resolvedFrameElevation, resolvedTheme, resolvedAppearance,
|
|
193
187
|
layout, direction, wrap, reverse, columns, rows,
|
|
194
188
|
align, justify, padding, gap,
|
|
195
189
|
width, height, minWidth, maxWidth, minHeight, maxHeight,
|
|
190
|
+
position, top, right, bottom, left, zIndex, overflow, opacity,
|
|
196
191
|
radius, bordered, disabled,
|
|
197
192
|
],
|
|
198
193
|
);
|
|
199
194
|
|
|
200
|
-
//
|
|
201
|
-
|
|
195
|
+
// Resolved scheme name: explicit prop > inherited from parent Frame.
|
|
196
|
+
const resolvedScheme = scheme ?? parentFrameCtx?.scheme;
|
|
197
|
+
|
|
202
198
|
const contextValue = useMemo(
|
|
203
|
-
() => ({
|
|
204
|
-
|
|
199
|
+
() => ({
|
|
200
|
+
elevation: resolvedElevation,
|
|
201
|
+
tokens,
|
|
202
|
+
scheme: resolvedScheme,
|
|
203
|
+
theme: resolvedTheme,
|
|
204
|
+
appearance: resolvedAppearance,
|
|
205
|
+
}),
|
|
206
|
+
[resolvedElevation, tokens, resolvedScheme, resolvedTheme, resolvedAppearance],
|
|
205
207
|
);
|
|
206
208
|
|
|
207
|
-
//
|
|
208
|
-
//
|
|
209
|
-
|
|
209
|
+
// When this Frame switches the scheme, override ThemeContext so that
|
|
210
|
+
// useNewtoneTheme().config returns the scheme's config for descendants.
|
|
211
|
+
const schemeThemeCtx = useMemo(() => {
|
|
212
|
+
if (!isSchemeOverride) return null;
|
|
213
|
+
return {
|
|
214
|
+
...themeCtx,
|
|
215
|
+
config: resolvedConfig,
|
|
216
|
+
activeScheme: scheme ?? themeCtx.activeScheme,
|
|
217
|
+
};
|
|
218
|
+
}, [isSchemeOverride, themeCtx, resolvedConfig, scheme]);
|
|
219
|
+
|
|
210
220
|
const webOverrides: ViewStyle[] = [];
|
|
211
221
|
if (styles.gridWebStyle) {
|
|
212
222
|
webOverrides.push(styles.gridWebStyle as unknown as ViewStyle);
|
|
@@ -215,94 +225,83 @@ export function Frame({
|
|
|
215
225
|
webOverrides.push({ boxShadow: styles.insetBoxShadow } as unknown as ViewStyle);
|
|
216
226
|
}
|
|
217
227
|
|
|
218
|
-
// Normalize user's custom styles into an array for merging.
|
|
219
228
|
const userStyles = Array.isArray(style) ? style : style ? [style] : [];
|
|
220
229
|
|
|
221
|
-
|
|
222
|
-
// In that case we render a Pressable (tappable); otherwise a plain View.
|
|
230
|
+
|
|
223
231
|
const isInteractive = onPress !== undefined || href !== undefined;
|
|
224
232
|
|
|
225
|
-
// Detect keyboard-only focus (Tab, arrows) vs mouse/touch focus.
|
|
226
|
-
// Only shows a visible focus ring when the user navigated via keyboard,
|
|
227
|
-
// matching the browser's native :focus-visible behavior.
|
|
228
233
|
const { isFocusVisible, focusProps } = useFocusVisible();
|
|
229
234
|
|
|
230
|
-
// Focus ring
|
|
231
|
-
// offset by 2px so it doesn't overlap the Frame's border.
|
|
232
|
-
// Uses CSS outline properties — silently ignored on native platforms.
|
|
235
|
+
// Focus ring: uses the emphasis background of the resolved theme as the outline color.
|
|
233
236
|
const focusRingStyle = isFocusVisible && !disabled ? {
|
|
234
237
|
outlineWidth: 2,
|
|
235
238
|
outlineStyle: 'solid',
|
|
236
|
-
outlineColor: tokens.
|
|
239
|
+
outlineColor: tokens.colors[resolvedTheme].emphasis.background,
|
|
237
240
|
outlineOffset: 2,
|
|
238
|
-
} as unknown as ViewStyle : undefined;
|
|
241
|
+
} as unknown as ViewStyle : undefined;
|
|
239
242
|
|
|
240
|
-
|
|
241
|
-
// handlers supported by react-native-web — silently ignored on native.
|
|
242
|
-
const webFocusProps = isInteractive ? focusProps as any : {}; // web-only
|
|
243
|
+
const webFocusProps = isInteractive ? focusProps as any : {};
|
|
243
244
|
|
|
244
|
-
// Default text style for any raw strings/numbers passed as children.
|
|
245
|
-
// Uses the theme's primary text color, default font, and base size.
|
|
246
245
|
const textStyle = useMemo<TextStyle>(
|
|
247
246
|
() => ({
|
|
248
|
-
color: tokens.
|
|
247
|
+
color: tokens.colors[resolvedTheme][resolvedAppearance].fontPrimary,
|
|
249
248
|
fontSize: tokens.typography.fontSizes['05'],
|
|
250
249
|
fontFamily: tokens.typography.fonts.main.family,
|
|
251
250
|
lineHeight: tokens.typography.lineHeights['06'],
|
|
252
251
|
}),
|
|
253
|
-
[tokens],
|
|
252
|
+
[tokens, resolvedTheme, resolvedAppearance],
|
|
254
253
|
);
|
|
255
|
-
// Auto-wrap bare text ("hello") in <Text> elements (required by React Native).
|
|
256
|
-
// Wrapped in useMemo so it only re-scans children when they or the text style changes.
|
|
257
254
|
const wrappedChildren = useMemo(
|
|
258
255
|
() => wrapTextChildren(children, textStyle),
|
|
259
256
|
[children, textStyle],
|
|
260
257
|
);
|
|
261
258
|
|
|
262
|
-
|
|
263
|
-
|
|
259
|
+
const content = isInteractive ? (
|
|
260
|
+
<Pressable
|
|
261
|
+
ref={ref}
|
|
262
|
+
testID={testID}
|
|
263
|
+
nativeID={nativeID}
|
|
264
|
+
pointerEvents={pointerEvents}
|
|
265
|
+
accessibilityLabel={accessibilityLabel}
|
|
266
|
+
accessibilityHint={accessibilityHint}
|
|
267
|
+
accessibilityState={disabled ? { disabled: true } : undefined}
|
|
268
|
+
onPress={onPress}
|
|
269
|
+
disabled={disabled}
|
|
270
|
+
{...(href ? { href, accessibilityRole: 'link' as const } : { accessibilityRole: 'button' as const })}
|
|
271
|
+
{...webFocusProps}
|
|
272
|
+
style={({ pressed }) => [
|
|
273
|
+
styles.container,
|
|
274
|
+
pressed && !disabled && styles.pressed,
|
|
275
|
+
focusRingStyle,
|
|
276
|
+
...webOverrides,
|
|
277
|
+
...userStyles,
|
|
278
|
+
]}
|
|
279
|
+
>
|
|
280
|
+
{wrappedChildren}
|
|
281
|
+
</Pressable>
|
|
282
|
+
) : (
|
|
283
|
+
<View
|
|
284
|
+
ref={ref}
|
|
285
|
+
testID={testID}
|
|
286
|
+
nativeID={nativeID}
|
|
287
|
+
pointerEvents={pointerEvents}
|
|
288
|
+
accessibilityLabel={accessibilityLabel}
|
|
289
|
+
accessibilityHint={accessibilityHint}
|
|
290
|
+
style={[styles.container, ...webOverrides, ...userStyles]}
|
|
291
|
+
>
|
|
292
|
+
{wrappedChildren}
|
|
293
|
+
</View>
|
|
294
|
+
);
|
|
295
|
+
|
|
296
|
+
const wrappedContent = schemeThemeCtx ? (
|
|
297
|
+
<_ThemeContext.Provider value={schemeThemeCtx}>
|
|
298
|
+
{content}
|
|
299
|
+
</_ThemeContext.Provider>
|
|
300
|
+
) : content;
|
|
301
|
+
|
|
264
302
|
return (
|
|
265
303
|
<FrameContext.Provider value={contextValue}>
|
|
266
|
-
{
|
|
267
|
-
// Pressable handles taps. When href is set, react-native-web renders
|
|
268
|
-
// it as an <a> tag so it works like a regular link on the web.
|
|
269
|
-
<Pressable
|
|
270
|
-
ref={ref}
|
|
271
|
-
testID={testID}
|
|
272
|
-
nativeID={nativeID}
|
|
273
|
-
accessibilityLabel={accessibilityLabel}
|
|
274
|
-
accessibilityHint={accessibilityHint}
|
|
275
|
-
// Tell screen readers this is disabled so assistive technology can announce it.
|
|
276
|
-
accessibilityState={disabled ? { disabled: true } : undefined}
|
|
277
|
-
onPress={onPress}
|
|
278
|
-
disabled={disabled}
|
|
279
|
-
{...(href ? { href, accessibilityRole: 'link' as const } : { accessibilityRole: 'button' as const })}
|
|
280
|
-
{...webFocusProps}
|
|
281
|
-
// The style callback receives { pressed: true/false } so we can
|
|
282
|
-
// change the background when the user is actively pressing.
|
|
283
|
-
style={({ pressed }) => [
|
|
284
|
-
styles.container,
|
|
285
|
-
pressed && !disabled && styles.pressed,
|
|
286
|
-
focusRingStyle,
|
|
287
|
-
...webOverrides,
|
|
288
|
-
...userStyles,
|
|
289
|
-
]}
|
|
290
|
-
>
|
|
291
|
-
{wrappedChildren}
|
|
292
|
-
</Pressable>
|
|
293
|
-
) : (
|
|
294
|
-
// Non-interactive Frame: just a plain View with no tap handling.
|
|
295
|
-
<View
|
|
296
|
-
ref={ref}
|
|
297
|
-
testID={testID}
|
|
298
|
-
nativeID={nativeID}
|
|
299
|
-
accessibilityLabel={accessibilityLabel}
|
|
300
|
-
accessibilityHint={accessibilityHint}
|
|
301
|
-
style={[styles.container, ...webOverrides, ...userStyles]}
|
|
302
|
-
>
|
|
303
|
-
{wrappedChildren}
|
|
304
|
-
</View>
|
|
305
|
-
)}
|
|
304
|
+
{wrappedContent}
|
|
306
305
|
</FrameContext.Provider>
|
|
307
306
|
);
|
|
308
307
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { View, ViewStyle, GestureResponderEvent } from 'react-native';
|
|
2
|
-
import type { FrameElevation } from 'newtone-api';
|
|
2
|
+
import type { FrameElevation, ThemeName, AppearanceName } from 'newtone-api';
|
|
3
3
|
|
|
4
4
|
// ── Spacing Types ──────────────────────────────────────────────
|
|
5
5
|
|
|
@@ -76,6 +76,20 @@ export interface RadiusCorners {
|
|
|
76
76
|
*/
|
|
77
77
|
export type RadiusProp = RadiusValue | RadiusCorners;
|
|
78
78
|
|
|
79
|
+
// ── Positioning Types ──────────────────────────────────────────
|
|
80
|
+
|
|
81
|
+
/** CSS position mode. `'fixed'` and `'sticky'` are web-only (via react-native-web). */
|
|
82
|
+
export type PositionType = 'absolute' | 'relative' | 'fixed' | 'sticky';
|
|
83
|
+
|
|
84
|
+
/** Position offset value: pixels (number) or percentage string (e.g. `'50%'`). */
|
|
85
|
+
export type OffsetValue = number | string;
|
|
86
|
+
|
|
87
|
+
/** Overflow clipping mode. */
|
|
88
|
+
export type OverflowMode = 'visible' | 'hidden' | 'scroll';
|
|
89
|
+
|
|
90
|
+
/** Pointer-events mode (View prop, not a style). */
|
|
91
|
+
export type PointerEventsMode = 'auto' | 'none' | 'box-none' | 'box-only';
|
|
92
|
+
|
|
79
93
|
// ── Sizing Types ───────────────────────────────────────────────
|
|
80
94
|
|
|
81
95
|
/**
|
|
@@ -159,6 +173,23 @@ export interface FrameProps {
|
|
|
159
173
|
*/
|
|
160
174
|
readonly elevation?: FrameElevation;
|
|
161
175
|
|
|
176
|
+
/**
|
|
177
|
+
* Named scheme to use for this Frame's subtree.
|
|
178
|
+
* Looks up the scheme's config from the ancestor NewtoneProvider's `schemes` map
|
|
179
|
+
* and uses it instead of the default for token computation and context.
|
|
180
|
+
* Ignored when the provider is in single-config mode.
|
|
181
|
+
*
|
|
182
|
+
* @example
|
|
183
|
+
* ```tsx
|
|
184
|
+
* <NewtoneProvider schemes={{ Default: config1, Dark: config2 }} defaultScheme="Default">
|
|
185
|
+
* <Frame scheme="Dark">
|
|
186
|
+
* {/* Children here get the "Dark" scheme's tokens */}
|
|
187
|
+
* </Frame>
|
|
188
|
+
* </NewtoneProvider>
|
|
189
|
+
* ```
|
|
190
|
+
*/
|
|
191
|
+
readonly scheme?: string;
|
|
192
|
+
|
|
162
193
|
// ── Layout ──
|
|
163
194
|
|
|
164
195
|
/** Layout mode. @default 'flex' */
|
|
@@ -248,8 +279,95 @@ export interface FrameProps {
|
|
|
248
279
|
/** Maximum height in pixels. */
|
|
249
280
|
readonly maxHeight?: number;
|
|
250
281
|
|
|
282
|
+
// ── Positioning ──
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* CSS position mode.
|
|
286
|
+
*
|
|
287
|
+
* `'fixed'` and `'sticky'` are web-only (supported via react-native-web).
|
|
288
|
+
* React Native natively supports `'absolute'` and `'relative'`.
|
|
289
|
+
*/
|
|
290
|
+
readonly position?: PositionType;
|
|
291
|
+
|
|
292
|
+
/** Offset from the top edge. Accepts pixels (number) or percentage string. */
|
|
293
|
+
readonly top?: OffsetValue;
|
|
294
|
+
|
|
295
|
+
/** Offset from the right edge. Accepts pixels (number) or percentage string. */
|
|
296
|
+
readonly right?: OffsetValue;
|
|
297
|
+
|
|
298
|
+
/** Offset from the bottom edge. Accepts pixels (number) or percentage string. */
|
|
299
|
+
readonly bottom?: OffsetValue;
|
|
300
|
+
|
|
301
|
+
/** Offset from the left edge. Accepts pixels (number) or percentage string. */
|
|
302
|
+
readonly left?: OffsetValue;
|
|
303
|
+
|
|
304
|
+
/** Stacking order. Higher values render above lower values. */
|
|
305
|
+
readonly zIndex?: number;
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Content overflow behavior.
|
|
309
|
+
*
|
|
310
|
+
* When `radius` is set with positive values, Frame auto-applies `overflow: 'hidden'`
|
|
311
|
+
* to clip content at rounded corners. Setting `overflow` explicitly overrides this.
|
|
312
|
+
*/
|
|
313
|
+
readonly overflow?: OverflowMode;
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Controls whether the element can be the target of touch/pointer events.
|
|
317
|
+
*
|
|
318
|
+
* - `'auto'` — default, element and children receive events
|
|
319
|
+
* - `'none'` — element and children are invisible to events (pass through)
|
|
320
|
+
* - `'box-none'` — element ignores events but children can receive them
|
|
321
|
+
* - `'box-only'` — element receives events but children cannot
|
|
322
|
+
*/
|
|
323
|
+
readonly pointerEvents?: PointerEventsMode;
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Opacity of the element (0 = fully transparent, 1 = fully opaque).
|
|
327
|
+
*
|
|
328
|
+
* When set explicitly, overrides the automatic `0.5` opacity applied by `disabled`.
|
|
329
|
+
*/
|
|
330
|
+
readonly opacity?: number;
|
|
331
|
+
|
|
251
332
|
// ── Appearance ──
|
|
252
333
|
|
|
334
|
+
/**
|
|
335
|
+
* Color theme for this Frame's visual rendering (background, border, text).
|
|
336
|
+
*
|
|
337
|
+
* Selects which of the 6 themes to use from the resolved tokens.
|
|
338
|
+
* Does not affect scheme selection — use `scheme` for that.
|
|
339
|
+
*
|
|
340
|
+
* @default 'primary'
|
|
341
|
+
*
|
|
342
|
+
* @example
|
|
343
|
+
* ```tsx
|
|
344
|
+
* <Frame theme="error" appearance="tinted">
|
|
345
|
+
* <Text>Error banner</Text>
|
|
346
|
+
* </Frame>
|
|
347
|
+
* ```
|
|
348
|
+
*/
|
|
349
|
+
readonly theme?: ThemeName;
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* Appearance variant within the selected theme.
|
|
353
|
+
*
|
|
354
|
+
* Controls the visual emphasis of the Frame's chrome (background, border):
|
|
355
|
+
* - `'main'` — default surface (passive contrast)
|
|
356
|
+
* - `'emphasis'` — prominent, filled surface (active contrast)
|
|
357
|
+
* - `'tinted'` — subtle tinted surface
|
|
358
|
+
* - `'strong'` — bold, high-contrast variant
|
|
359
|
+
*
|
|
360
|
+
* @default 'main'
|
|
361
|
+
*
|
|
362
|
+
* @example
|
|
363
|
+
* ```tsx
|
|
364
|
+
* <Frame theme="primary" appearance="emphasis">
|
|
365
|
+
* <Text>CTA section</Text>
|
|
366
|
+
* </Frame>
|
|
367
|
+
* ```
|
|
368
|
+
*/
|
|
369
|
+
readonly appearance?: AppearanceName;
|
|
370
|
+
|
|
253
371
|
/**
|
|
254
372
|
* Border radius.
|
|
255
373
|
*
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { useMemo } from 'react';
|
|
2
2
|
import { Text, type TextStyle } from 'react-native';
|
|
3
|
-
import { useTokens } from 'newtone-api';
|
|
3
|
+
import { useTokens, useFrameContext } from 'newtone-api';
|
|
4
4
|
import type { IconProps } from './Icon.types';
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -17,8 +17,8 @@ import type { IconProps } from './Icon.types';
|
|
|
17
17
|
* ```
|
|
18
18
|
*/
|
|
19
19
|
export function Icon({
|
|
20
|
-
name,
|
|
21
|
-
size,
|
|
20
|
+
name = 'add',
|
|
21
|
+
size = 24,
|
|
22
22
|
opticalSize,
|
|
23
23
|
fill = 0,
|
|
24
24
|
color,
|
|
@@ -32,6 +32,9 @@ export function Icon({
|
|
|
32
32
|
}: IconProps) {
|
|
33
33
|
// Inherit tokens from nearest parent Frame via FrameContext.
|
|
34
34
|
const tokens = useTokens();
|
|
35
|
+
const frameCtx = useFrameContext();
|
|
36
|
+
const resolvedTheme = frameCtx?.theme ?? 'primary';
|
|
37
|
+
const resolvedAppearance = frameCtx?.appearance ?? 'main';
|
|
35
38
|
|
|
36
39
|
// Build the icon's style from the theme tokens and props.
|
|
37
40
|
// Wrapped in useMemo so it only recalculates when the inputs change,
|
|
@@ -53,8 +56,8 @@ export function Icon({
|
|
|
53
56
|
// Use explicit opticalSize if provided, otherwise auto-calculate from fontSize.
|
|
54
57
|
const opsz = opticalSize ?? getOpticalSize(fontSize);
|
|
55
58
|
|
|
56
|
-
// Use the provided color, or fall back to the theme
|
|
57
|
-
const iconColor = color ?? tokens.
|
|
59
|
+
// Use the provided color, or fall back to the inherited theme/appearance text color.
|
|
60
|
+
const iconColor = color ?? tokens.colors[resolvedTheme][resolvedAppearance].fontPrimary;
|
|
58
61
|
|
|
59
62
|
// Build the font family name from the theme's icon variant setting.
|
|
60
63
|
// Example: variant 'rounded' → 'Material Symbols Rounded'
|
|
@@ -80,7 +83,7 @@ export function Icon({
|
|
|
80
83
|
fontVariationSettings, // web-only: controls the variable font axes listed above
|
|
81
84
|
...style,
|
|
82
85
|
} as TextStyle; // Cast needed because web-only properties aren't in RN's type definitions
|
|
83
|
-
}, [tokens, size, opticalSize, fill, color, style]);
|
|
86
|
+
}, [tokens, size, opticalSize, fill, color, style, resolvedTheme, resolvedAppearance]);
|
|
84
87
|
|
|
85
88
|
// Material Symbols renders icons as text ligatures — the icon name (like "home")
|
|
86
89
|
// is passed as text content, and the font renders it as the icon glyph.
|
|
@@ -23,9 +23,9 @@ export interface IconProps {
|
|
|
23
23
|
* @example `'home'`, `'settings'`, `'check'`, `'expand_more'`, `'delete'`, `'add'`, `'search'`
|
|
24
24
|
* @see {@link https://fonts.google.com/icons Browse all icons}
|
|
25
25
|
*/
|
|
26
|
-
readonly name
|
|
26
|
+
readonly name?: string;
|
|
27
27
|
|
|
28
|
-
/** Font size in pixels. @default
|
|
28
|
+
/** Font size in pixels. @default 24 */
|
|
29
29
|
readonly size?: number;
|
|
30
30
|
|
|
31
31
|
/** Optical size for variable font axis. Adjusts stroke weight for readability at small sizes. @default same as size */
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import React, { useContext, useMemo } from 'react';
|
|
2
2
|
import { Text as RNText } from 'react-native';
|
|
3
3
|
import type { TextStyle } from 'react-native';
|
|
4
|
-
import { useTokens } from 'newtone-api';
|
|
4
|
+
import { useTokens, useFrameContext } from 'newtone-api';
|
|
5
|
+
import type { ThemeName, AppearanceName } from 'newtone-api';
|
|
5
6
|
import { TextScopeContext, resolveTextColor } from './Text';
|
|
6
7
|
import type { TextSpanProps, TextWeight } from './Text.types';
|
|
7
8
|
|
|
@@ -11,18 +12,21 @@ import type { TextSpanProps, TextWeight } from './Text.types';
|
|
|
11
12
|
* Only inline formatting properties (color, weight, italic, underline, highlight) are exposed.
|
|
12
13
|
*/
|
|
13
14
|
export function TextSpan({ children, color, weight, italic, underline, highlight, style }: TextSpanProps) {
|
|
14
|
-
const tokens = useTokens(
|
|
15
|
+
const tokens = useTokens();
|
|
15
16
|
const scopeCtx = useContext(TextScopeContext);
|
|
17
|
+
const frameCtx = useFrameContext();
|
|
18
|
+
const resolvedTheme: ThemeName = frameCtx?.theme ?? 'primary';
|
|
19
|
+
const resolvedAppearance: AppearanceName = frameCtx?.appearance ?? 'main';
|
|
16
20
|
|
|
17
21
|
const spanStyle = useMemo<TextStyle>(() => {
|
|
18
22
|
const s: TextStyle = {};
|
|
19
|
-
if (color) s.color = resolveTextColor(color, tokens);
|
|
23
|
+
if (color) s.color = resolveTextColor(color, tokens, resolvedTheme, resolvedAppearance);
|
|
20
24
|
if (weight && scopeCtx) s.fontWeight = String(scopeCtx.weights[weight]) as TextStyle['fontWeight'];
|
|
21
25
|
if (italic) s.fontStyle = 'italic';
|
|
22
26
|
if (underline) s.textDecorationLine = 'underline';
|
|
23
|
-
if (highlight) s.backgroundColor = resolveTextColor(highlight, tokens);
|
|
27
|
+
if (highlight) s.backgroundColor = resolveTextColor(highlight, tokens, resolvedTheme, resolvedAppearance);
|
|
24
28
|
return s;
|
|
25
|
-
}, [tokens, scopeCtx, color, weight, italic, underline, highlight]);
|
|
29
|
+
}, [tokens, scopeCtx, color, weight, italic, underline, highlight, resolvedTheme, resolvedAppearance]);
|
|
26
30
|
|
|
27
31
|
return React.createElement(
|
|
28
32
|
RNText,
|