@newtonedev/components 0.1.18 → 0.1.19
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/actions/Button/Button.styles.d.ts +1 -0
- package/dist/composites/actions/Button/Button.styles.d.ts.map +1 -1
- package/dist/index.cjs +850 -509
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +11 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +808 -470
- package/dist/index.js.map +1 -1
- package/dist/layout/Page/Page.d.ts +30 -0
- package/dist/layout/Page/Page.d.ts.map +1 -0
- package/dist/layout/Page/Page.types.d.ts +60 -0
- package/dist/layout/Page/Page.types.d.ts.map +1 -0
- package/dist/layout/Page/index.d.ts +3 -0
- package/dist/layout/Page/index.d.ts.map +1 -0
- package/dist/layout/Section/Section.d.ts +23 -0
- package/dist/layout/Section/Section.d.ts.map +1 -0
- package/dist/layout/Section/Section.styles.d.ts +20 -0
- package/dist/layout/Section/Section.styles.d.ts.map +1 -0
- package/dist/layout/Section/Section.types.d.ts +74 -0
- package/dist/layout/Section/Section.types.d.ts.map +1 -0
- package/dist/layout/Section/index.d.ts +3 -0
- package/dist/layout/Section/index.d.ts.map +1 -0
- package/dist/layout/Viewport/Viewport.d.ts +22 -0
- package/dist/layout/Viewport/Viewport.d.ts.map +1 -0
- package/dist/layout/Viewport/Viewport.types.d.ts +34 -0
- package/dist/layout/Viewport/Viewport.types.d.ts.map +1 -0
- package/dist/layout/Viewport/index.d.ts +3 -0
- package/dist/layout/Viewport/index.d.ts.map +1 -0
- package/dist/{primitives → layout}/Wrapper/Wrapper.d.ts +1 -16
- package/dist/layout/Wrapper/Wrapper.d.ts.map +1 -0
- package/dist/{primitives → layout}/Wrapper/Wrapper.styles.d.ts +1 -2
- package/dist/layout/Wrapper/Wrapper.styles.d.ts.map +1 -0
- package/dist/{primitives → layout}/Wrapper/Wrapper.types.d.ts +1 -3
- package/dist/layout/Wrapper/Wrapper.types.d.ts.map +1 -0
- package/dist/layout/Wrapper/index.d.ts.map +1 -0
- package/dist/layout/index.d.ts +9 -0
- package/dist/layout/index.d.ts.map +1 -0
- package/dist/primitives/Card/Card.d.ts +15 -0
- package/dist/primitives/Card/Card.d.ts.map +1 -0
- package/dist/primitives/Card/Card.styles.d.ts +40 -0
- package/dist/primitives/Card/Card.styles.d.ts.map +1 -0
- package/dist/primitives/Card/Card.types.d.ts +101 -0
- package/dist/primitives/Card/Card.types.d.ts.map +1 -0
- package/dist/primitives/Card/index.d.ts +3 -0
- package/dist/primitives/Card/index.d.ts.map +1 -0
- package/dist/primitives/Frame/Frame.d.ts +1 -1
- package/dist/primitives/Frame/Frame.d.ts.map +1 -1
- package/dist/primitives/Frame/Frame.styles.d.ts +0 -6
- package/dist/primitives/Frame/Frame.styles.d.ts.map +1 -1
- package/dist/primitives/Frame/Frame.types.d.ts +1 -15
- package/dist/primitives/Frame/Frame.types.d.ts.map +1 -1
- package/dist/primitives/index.d.ts +2 -2
- package/dist/primitives/index.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/composites/actions/Button/Button.styles.ts +58 -19
- package/src/composites/actions/Button/Button.tsx +18 -3
- package/src/composites/display/Chip/Chip.tsx +1 -1
- package/src/composites/form-controls/TextInput/TextInput.styles.ts +4 -4
- package/src/index.ts +18 -5
- package/src/layout/Page/Page.tsx +103 -0
- package/src/layout/Page/Page.types.ts +69 -0
- package/src/layout/Page/index.ts +2 -0
- package/src/layout/Section/Section.styles.ts +90 -0
- package/src/layout/Section/Section.tsx +57 -0
- package/src/layout/Section/Section.types.ts +85 -0
- package/src/layout/Section/index.ts +2 -0
- package/src/layout/Viewport/Viewport.tsx +52 -0
- package/src/layout/Viewport/Viewport.types.ts +40 -0
- package/src/layout/Viewport/index.ts +2 -0
- package/src/{primitives → layout}/Wrapper/Wrapper.styles.ts +2 -20
- package/src/{primitives → layout}/Wrapper/Wrapper.tsx +1 -31
- package/src/{primitives → layout}/Wrapper/Wrapper.types.ts +1 -4
- package/src/layout/index.ts +15 -0
- package/src/primitives/Card/Card.styles.ts +182 -0
- package/src/primitives/Card/Card.tsx +197 -0
- package/src/primitives/Card/Card.types.ts +155 -0
- package/src/primitives/Card/index.ts +2 -0
- package/src/primitives/Frame/Frame.styles.ts +0 -32
- package/src/primitives/Frame/Frame.tsx +5 -52
- package/src/primitives/Frame/Frame.types.ts +1 -22
- package/src/primitives/Text/Text.tsx +1 -1
- package/src/primitives/index.ts +3 -3
- package/dist/primitives/Wrapper/Wrapper.d.ts.map +0 -1
- package/dist/primitives/Wrapper/Wrapper.styles.d.ts.map +0 -1
- package/dist/primitives/Wrapper/Wrapper.types.d.ts.map +0 -1
- package/dist/primitives/Wrapper/index.d.ts.map +0 -1
- /package/dist/{primitives → layout}/Wrapper/index.d.ts +0 -0
- /package/src/{primitives → layout}/Wrapper/index.ts +0 -0
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
|
+
import { Pressable, Text } from 'react-native';
|
|
3
|
+
import type { TextStyle } from 'react-native';
|
|
4
|
+
import type { CardProps } from './Card.types';
|
|
5
|
+
import type { ElevationLevel, ElevationName, ThemeName, AppearanceName } from 'newtone-api';
|
|
6
|
+
import { FrameContext, useFrameContext } from 'newtone-api';
|
|
7
|
+
import { useNewtoneTheme } from 'newtone-api';
|
|
8
|
+
import { computeTokens } from 'newtone-api';
|
|
9
|
+
import { getCardStyles } from './Card.styles';
|
|
10
|
+
import { useFocusVisible } from '../useFocusVisible';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Wrap raw string/number children in <Text> so they display correctly.
|
|
14
|
+
*/
|
|
15
|
+
function wrapTextChildren(
|
|
16
|
+
children: React.ReactNode,
|
|
17
|
+
textStyle: TextStyle,
|
|
18
|
+
): React.ReactNode {
|
|
19
|
+
return React.Children.map(children, (child) => {
|
|
20
|
+
if (typeof child === 'string' || typeof child === 'number') {
|
|
21
|
+
return <Text style={textStyle}>{child}</Text>;
|
|
22
|
+
}
|
|
23
|
+
return child;
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** Cards are always elevated. */
|
|
28
|
+
const CARD_ELEVATION: ElevationLevel = 2;
|
|
29
|
+
const CARD_ELEVATION_NAME: ElevationName = 'elevated';
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Card — An elevated, bordered, pressable surface.
|
|
33
|
+
*
|
|
34
|
+
* Card inherits its theme from the parent Frame context. It is always
|
|
35
|
+
* rendered at the elevated level with a border and drop shadow.
|
|
36
|
+
* It handles press and navigation interactions, making it ideal for
|
|
37
|
+
* clickable content tiles, list items, and action surfaces.
|
|
38
|
+
*
|
|
39
|
+
* Cards can be nested inside Frames. They inherit the theme but provide
|
|
40
|
+
* their own elevated FrameContext to descendants.
|
|
41
|
+
*/
|
|
42
|
+
export function Card({
|
|
43
|
+
children,
|
|
44
|
+
// Appearance
|
|
45
|
+
appearance,
|
|
46
|
+
radius,
|
|
47
|
+
// Layout
|
|
48
|
+
direction,
|
|
49
|
+
wrap,
|
|
50
|
+
reverse,
|
|
51
|
+
// Alignment
|
|
52
|
+
align,
|
|
53
|
+
justify,
|
|
54
|
+
// Spacing
|
|
55
|
+
padding,
|
|
56
|
+
gap,
|
|
57
|
+
// Sizing
|
|
58
|
+
width,
|
|
59
|
+
height,
|
|
60
|
+
minWidth,
|
|
61
|
+
maxWidth,
|
|
62
|
+
minHeight,
|
|
63
|
+
maxHeight,
|
|
64
|
+
// Positioning
|
|
65
|
+
pointerEvents,
|
|
66
|
+
// Interactivity
|
|
67
|
+
onPress,
|
|
68
|
+
href,
|
|
69
|
+
disabled = false,
|
|
70
|
+
// Accessibility
|
|
71
|
+
accessibilityLabel,
|
|
72
|
+
accessibilityHint,
|
|
73
|
+
// Testing & platform
|
|
74
|
+
testID,
|
|
75
|
+
nativeID,
|
|
76
|
+
ref,
|
|
77
|
+
// Style override
|
|
78
|
+
style,
|
|
79
|
+
}: CardProps) {
|
|
80
|
+
const themeCtx = useNewtoneTheme();
|
|
81
|
+
const { mode, gamut } = themeCtx;
|
|
82
|
+
const parentFrameCtx = useFrameContext();
|
|
83
|
+
|
|
84
|
+
// Inherit theme from parent Frame context (Card never overrides theme).
|
|
85
|
+
const resolvedTheme: ThemeName = parentFrameCtx?.theme ?? 'primary';
|
|
86
|
+
const resolvedAppearance: AppearanceName = appearance ?? parentFrameCtx?.appearance ?? 'main';
|
|
87
|
+
|
|
88
|
+
// Compute tokens at the elevated level.
|
|
89
|
+
const tokens = useMemo(() => {
|
|
90
|
+
return computeTokens(
|
|
91
|
+
themeCtx.config.colorSystem,
|
|
92
|
+
mode,
|
|
93
|
+
gamut,
|
|
94
|
+
CARD_ELEVATION_NAME,
|
|
95
|
+
themeCtx.config.spacing,
|
|
96
|
+
themeCtx.config.radius,
|
|
97
|
+
themeCtx.config.typography,
|
|
98
|
+
themeCtx.config.icons,
|
|
99
|
+
themeCtx.config.themeMappings,
|
|
100
|
+
themeCtx.config.swatchDefaults,
|
|
101
|
+
themeCtx.config.relativeSwatchDefaults,
|
|
102
|
+
);
|
|
103
|
+
}, [themeCtx.config, mode, gamut]);
|
|
104
|
+
|
|
105
|
+
const styles = useMemo(
|
|
106
|
+
() => getCardStyles({
|
|
107
|
+
tokens,
|
|
108
|
+
theme: resolvedTheme,
|
|
109
|
+
appearance: resolvedAppearance,
|
|
110
|
+
direction,
|
|
111
|
+
wrap,
|
|
112
|
+
reverse,
|
|
113
|
+
align,
|
|
114
|
+
justify,
|
|
115
|
+
padding,
|
|
116
|
+
gap,
|
|
117
|
+
width,
|
|
118
|
+
height,
|
|
119
|
+
minWidth,
|
|
120
|
+
maxWidth,
|
|
121
|
+
minHeight,
|
|
122
|
+
maxHeight,
|
|
123
|
+
radius,
|
|
124
|
+
disabled,
|
|
125
|
+
}),
|
|
126
|
+
[
|
|
127
|
+
tokens, resolvedTheme, resolvedAppearance,
|
|
128
|
+
direction, wrap, reverse,
|
|
129
|
+
align, justify, padding, gap,
|
|
130
|
+
width, height, minWidth, maxWidth, minHeight, maxHeight,
|
|
131
|
+
radius, disabled,
|
|
132
|
+
],
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
const contextValue = useMemo(
|
|
136
|
+
() => ({
|
|
137
|
+
elevation: CARD_ELEVATION,
|
|
138
|
+
tokens,
|
|
139
|
+
scheme: parentFrameCtx?.scheme,
|
|
140
|
+
theme: resolvedTheme,
|
|
141
|
+
appearance: resolvedAppearance,
|
|
142
|
+
}),
|
|
143
|
+
[tokens, parentFrameCtx?.scheme, resolvedTheme, resolvedAppearance],
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
const userStyles = Array.isArray(style) ? style : style ? [style] : [];
|
|
147
|
+
|
|
148
|
+
const { isFocusVisible, focusProps } = useFocusVisible();
|
|
149
|
+
|
|
150
|
+
// Focus ring: uses the emphasis background of the inherited theme as the outline color.
|
|
151
|
+
const focusRingStyle = isFocusVisible && !disabled ? {
|
|
152
|
+
outlineWidth: 2,
|
|
153
|
+
outlineStyle: 'solid',
|
|
154
|
+
outlineColor: tokens.colors[resolvedTheme].emphasis.background,
|
|
155
|
+
outlineOffset: 2,
|
|
156
|
+
} as unknown as import('react-native').ViewStyle : undefined;
|
|
157
|
+
|
|
158
|
+
const textStyle = useMemo<TextStyle>(
|
|
159
|
+
() => ({
|
|
160
|
+
color: tokens.colors[resolvedTheme][resolvedAppearance].fontPrimary,
|
|
161
|
+
fontSize: tokens.typography.fontSizes['05'],
|
|
162
|
+
fontFamily: tokens.typography.fonts.main.family,
|
|
163
|
+
lineHeight: tokens.typography.lineHeights['06'],
|
|
164
|
+
}),
|
|
165
|
+
[tokens, resolvedTheme, resolvedAppearance],
|
|
166
|
+
);
|
|
167
|
+
const wrappedChildren = useMemo(
|
|
168
|
+
() => wrapTextChildren(children, textStyle),
|
|
169
|
+
[children, textStyle],
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
return (
|
|
173
|
+
<FrameContext.Provider value={contextValue}>
|
|
174
|
+
<Pressable
|
|
175
|
+
ref={ref}
|
|
176
|
+
testID={testID}
|
|
177
|
+
nativeID={nativeID}
|
|
178
|
+
pointerEvents={pointerEvents}
|
|
179
|
+
accessibilityLabel={accessibilityLabel}
|
|
180
|
+
accessibilityHint={accessibilityHint}
|
|
181
|
+
accessibilityState={disabled ? { disabled: true } : undefined}
|
|
182
|
+
onPress={onPress}
|
|
183
|
+
disabled={disabled}
|
|
184
|
+
{...(href ? { href, accessibilityRole: 'link' as const } : { accessibilityRole: 'button' as const })}
|
|
185
|
+
{...(focusProps as any)}
|
|
186
|
+
style={({ pressed }) => [
|
|
187
|
+
styles.container,
|
|
188
|
+
pressed && !disabled && styles.pressed,
|
|
189
|
+
focusRingStyle,
|
|
190
|
+
...userStyles,
|
|
191
|
+
]}
|
|
192
|
+
>
|
|
193
|
+
{wrappedChildren}
|
|
194
|
+
</Pressable>
|
|
195
|
+
</FrameContext.Provider>
|
|
196
|
+
);
|
|
197
|
+
}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import type { View, ViewStyle, GestureResponderEvent } from 'react-native';
|
|
2
|
+
import type { AppearanceName } from 'newtone-api';
|
|
3
|
+
import type {
|
|
4
|
+
PaddingProp,
|
|
5
|
+
GapProp,
|
|
6
|
+
SizingMode,
|
|
7
|
+
Direction,
|
|
8
|
+
Alignment,
|
|
9
|
+
Justification,
|
|
10
|
+
RadiusProp,
|
|
11
|
+
PointerEventsMode,
|
|
12
|
+
} from '../Frame/Frame.types';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Props for Card — an elevated, bordered, pressable surface.
|
|
16
|
+
*
|
|
17
|
+
* Card inherits its theme from the parent Frame context and is always
|
|
18
|
+
* rendered at elevated level with a border. It handles press and
|
|
19
|
+
* navigation interactions, making it ideal for clickable content tiles.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```tsx
|
|
23
|
+
* <Card padding="lg" onPress={() => navigate('/details')}>
|
|
24
|
+
* <Text>Tap to open</Text>
|
|
25
|
+
* </Card>
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```tsx
|
|
30
|
+
* <Card padding="md" gap="sm" href="/settings" appearance="tinted">
|
|
31
|
+
* <Icon name="settings" />
|
|
32
|
+
* <Text>Settings</Text>
|
|
33
|
+
* </Card>
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export interface CardProps {
|
|
37
|
+
/** Child elements. Raw strings/numbers are auto-wrapped in themed `<Text>`. */
|
|
38
|
+
readonly children: React.ReactNode;
|
|
39
|
+
|
|
40
|
+
// ── Appearance ──
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Appearance variant within the inherited theme.
|
|
44
|
+
*
|
|
45
|
+
* Controls the visual emphasis of the Card's chrome (background, border):
|
|
46
|
+
* - `'main'` — default surface (passive contrast)
|
|
47
|
+
* - `'emphasis'` — prominent, filled surface (active contrast)
|
|
48
|
+
* - `'tinted'` — subtle tinted surface
|
|
49
|
+
* - `'strong'` — bold, high-contrast variant
|
|
50
|
+
*
|
|
51
|
+
* @default 'main'
|
|
52
|
+
*/
|
|
53
|
+
readonly appearance?: AppearanceName;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Border radius.
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```tsx
|
|
60
|
+
* <Card radius="md" /> // uniform token
|
|
61
|
+
* <Card radius={8} /> // uniform px
|
|
62
|
+
* <Card radius={{ topLeft: 'lg', topRight: 'lg' }} /> // per-corner
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
readonly radius?: RadiusProp;
|
|
66
|
+
|
|
67
|
+
// ── Layout ──
|
|
68
|
+
|
|
69
|
+
/** Flex direction. @default 'vertical' */
|
|
70
|
+
readonly direction?: Direction;
|
|
71
|
+
|
|
72
|
+
/** Enable flex wrap. @default false */
|
|
73
|
+
readonly wrap?: boolean;
|
|
74
|
+
|
|
75
|
+
/** Reverse flex direction. @default false */
|
|
76
|
+
readonly reverse?: boolean;
|
|
77
|
+
|
|
78
|
+
// ── Alignment ──
|
|
79
|
+
|
|
80
|
+
/** Cross-axis alignment of children. */
|
|
81
|
+
readonly align?: Alignment;
|
|
82
|
+
|
|
83
|
+
/** Main-axis justification of children. */
|
|
84
|
+
readonly justify?: Justification;
|
|
85
|
+
|
|
86
|
+
// ── Spacing ──
|
|
87
|
+
|
|
88
|
+
/** Padding inside the card. */
|
|
89
|
+
readonly padding?: PaddingProp;
|
|
90
|
+
|
|
91
|
+
/** Gap between children. */
|
|
92
|
+
readonly gap?: GapProp;
|
|
93
|
+
|
|
94
|
+
// ── Sizing ──
|
|
95
|
+
|
|
96
|
+
/** Width sizing: `'hug'`, `'fill'`, or fixed px. */
|
|
97
|
+
readonly width?: SizingMode;
|
|
98
|
+
|
|
99
|
+
/** Height sizing: `'hug'`, `'fill'`, or fixed px. */
|
|
100
|
+
readonly height?: SizingMode;
|
|
101
|
+
|
|
102
|
+
/** Minimum width in pixels. */
|
|
103
|
+
readonly minWidth?: number;
|
|
104
|
+
|
|
105
|
+
/** Maximum width in pixels. */
|
|
106
|
+
readonly maxWidth?: number;
|
|
107
|
+
|
|
108
|
+
/** Minimum height in pixels. */
|
|
109
|
+
readonly minHeight?: number;
|
|
110
|
+
|
|
111
|
+
/** Maximum height in pixels. */
|
|
112
|
+
readonly maxHeight?: number;
|
|
113
|
+
|
|
114
|
+
// ── Positioning ──
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Controls whether the element can be the target of touch/pointer events.
|
|
118
|
+
*/
|
|
119
|
+
readonly pointerEvents?: PointerEventsMode;
|
|
120
|
+
|
|
121
|
+
// ── Interactivity ──
|
|
122
|
+
|
|
123
|
+
/** Press handler. */
|
|
124
|
+
readonly onPress?: (event: GestureResponderEvent) => void;
|
|
125
|
+
|
|
126
|
+
/** Navigation URL — renders as a link. */
|
|
127
|
+
readonly href?: string;
|
|
128
|
+
|
|
129
|
+
/** Disable interaction. @default false */
|
|
130
|
+
readonly disabled?: boolean;
|
|
131
|
+
|
|
132
|
+
// ── Accessibility ──
|
|
133
|
+
|
|
134
|
+
/** Accessible label read by screen readers. */
|
|
135
|
+
readonly accessibilityLabel?: string;
|
|
136
|
+
|
|
137
|
+
/** Additional hint read after the label. */
|
|
138
|
+
readonly accessibilityHint?: string;
|
|
139
|
+
|
|
140
|
+
// ── Testing & Platform ──
|
|
141
|
+
|
|
142
|
+
/** Test identifier — maps to `data-testid` on web. */
|
|
143
|
+
readonly testID?: string;
|
|
144
|
+
|
|
145
|
+
/** DOM id — maps to `id` attribute on web. */
|
|
146
|
+
readonly nativeID?: string;
|
|
147
|
+
|
|
148
|
+
/** Ref to the underlying Pressable element. */
|
|
149
|
+
readonly ref?: React.Ref<View>;
|
|
150
|
+
|
|
151
|
+
// ── Style override ──
|
|
152
|
+
|
|
153
|
+
/** Custom style overrides (applied last). */
|
|
154
|
+
readonly style?: ViewStyle | ViewStyle[];
|
|
155
|
+
}
|
|
@@ -68,12 +68,9 @@ export interface FrameStyleInput {
|
|
|
68
68
|
readonly left?: OffsetValue;
|
|
69
69
|
readonly zIndex?: number;
|
|
70
70
|
readonly overflow?: OverflowMode;
|
|
71
|
-
readonly opacity?: number;
|
|
72
71
|
|
|
73
72
|
// Appearance
|
|
74
73
|
readonly radius?: RadiusProp;
|
|
75
|
-
readonly bordered?: boolean;
|
|
76
|
-
readonly disabled?: boolean;
|
|
77
74
|
}
|
|
78
75
|
|
|
79
76
|
// ── Output ───────────────────────────────────────────────────────
|
|
@@ -81,8 +78,6 @@ export interface FrameStyleInput {
|
|
|
81
78
|
export interface FrameStyles {
|
|
82
79
|
/** Main container style (ViewStyle) */
|
|
83
80
|
readonly container: ViewStyle;
|
|
84
|
-
/** Style applied when pressed (background shift) */
|
|
85
|
-
readonly pressed: ViewStyle;
|
|
86
81
|
/** Web-only CSS Grid properties (cast to ViewStyle at render) */
|
|
87
82
|
readonly gridWebStyle: React.CSSProperties | null;
|
|
88
83
|
/** Web-only inset box-shadow string for elevation -2 */
|
|
@@ -96,7 +91,6 @@ export interface FrameStyles {
|
|
|
96
91
|
*
|
|
97
92
|
* Takes the Frame's props + design tokens and produces:
|
|
98
93
|
* - container: the main style (background, layout, spacing, border, shadow, etc.)
|
|
99
|
-
* - pressed: style override applied when the user is pressing/clicking
|
|
100
94
|
* - gridWebStyle: CSS Grid properties (only works on web, null otherwise)
|
|
101
95
|
* - insetBoxShadow: inner shadow CSS string for sunken frames (web-only)
|
|
102
96
|
*/
|
|
@@ -129,10 +123,7 @@ export function getFrameStyles(input: FrameStyleInput): FrameStyles {
|
|
|
129
123
|
left,
|
|
130
124
|
zIndex,
|
|
131
125
|
overflow,
|
|
132
|
-
opacity,
|
|
133
126
|
radius,
|
|
134
|
-
bordered = false,
|
|
135
|
-
disabled = false,
|
|
136
127
|
} = input;
|
|
137
128
|
|
|
138
129
|
// We build styles as a plain object first, then validate it through
|
|
@@ -229,13 +220,6 @@ export function getFrameStyles(input: FrameStyleInput): FrameStyles {
|
|
|
229
220
|
// Explicit overflow prop overrides the auto-overflow from radius.
|
|
230
221
|
if (overflow) container.overflow = overflow;
|
|
231
222
|
|
|
232
|
-
// ── Border ──
|
|
233
|
-
// Add a thin border using the theme's border color.
|
|
234
|
-
if (bordered) {
|
|
235
|
-
container.borderWidth = 1;
|
|
236
|
-
container.borderColor = appearanceTokens.fontTertiary;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
223
|
// ── Outer shadow (elevation 2) ──
|
|
240
224
|
// Add a subtle drop shadow to make the Frame look raised above the surface.
|
|
241
225
|
// These are React Native shadow properties — react-native-web converts them
|
|
@@ -248,21 +232,6 @@ export function getFrameStyles(input: FrameStyleInput): FrameStyles {
|
|
|
248
232
|
container.elevation = 4; // Android-specific shadow depth
|
|
249
233
|
}
|
|
250
234
|
|
|
251
|
-
// ── Opacity ──
|
|
252
|
-
// Explicit opacity takes precedence over the disabled fade.
|
|
253
|
-
if (opacity !== undefined) {
|
|
254
|
-
container.opacity = opacity;
|
|
255
|
-
} else if (disabled) {
|
|
256
|
-
container.opacity = 0.5;
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
// ── Pressed state ──
|
|
260
|
-
// When the user is pressing an interactive Frame, shift the background
|
|
261
|
-
// to a darker "sunken" shade to give visual feedback.
|
|
262
|
-
const pressed = StyleSheet.create({
|
|
263
|
-
s: { backgroundColor: appearanceTokens.fontSecondary },
|
|
264
|
-
}).s;
|
|
265
|
-
|
|
266
235
|
// ── Grid web style (web-only) ──
|
|
267
236
|
// CSS Grid only works in web browsers. On native platforms this stays null,
|
|
268
237
|
// and the flex fallback (set above) handles the layout instead.
|
|
@@ -287,7 +256,6 @@ export function getFrameStyles(input: FrameStyleInput): FrameStyles {
|
|
|
287
256
|
// Validate and optimize the container styles through StyleSheet.create(),
|
|
288
257
|
// then extract the single style object with `.c`.
|
|
289
258
|
container: StyleSheet.create({ c: container as ViewStyle }).c,
|
|
290
|
-
pressed,
|
|
291
259
|
gridWebStyle,
|
|
292
260
|
insetBoxShadow,
|
|
293
261
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useMemo } from 'react';
|
|
2
|
-
import { View,
|
|
2
|
+
import { View, Text } from 'react-native';
|
|
3
3
|
import type { ViewStyle, TextStyle } from 'react-native';
|
|
4
4
|
import type { FrameProps } from './Frame.types';
|
|
5
5
|
import type { ElevationLevel, FrameElevation, ElevationName, ThemeName, AppearanceName } from 'newtone-api';
|
|
@@ -7,7 +7,7 @@ import { FrameContext, useFrameContext } from 'newtone-api';
|
|
|
7
7
|
import { useNewtoneTheme, _ThemeContext } from 'newtone-api';
|
|
8
8
|
import { computeTokens } from 'newtone-api';
|
|
9
9
|
import { getFrameStyles } from './Frame.styles';
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Wrap raw string/number children in <Text> so they display correctly.
|
|
@@ -87,14 +87,8 @@ export function Frame({
|
|
|
87
87
|
zIndex,
|
|
88
88
|
overflow,
|
|
89
89
|
pointerEvents,
|
|
90
|
-
opacity,
|
|
91
90
|
// Appearance
|
|
92
91
|
radius,
|
|
93
|
-
bordered,
|
|
94
|
-
// Interactivity
|
|
95
|
-
onPress,
|
|
96
|
-
href,
|
|
97
|
-
disabled = false,
|
|
98
92
|
// Accessibility
|
|
99
93
|
accessibilityLabel,
|
|
100
94
|
accessibilityHint,
|
|
@@ -177,18 +171,15 @@ export function Frame({
|
|
|
177
171
|
left,
|
|
178
172
|
zIndex,
|
|
179
173
|
overflow,
|
|
180
|
-
opacity,
|
|
181
174
|
radius,
|
|
182
|
-
bordered,
|
|
183
|
-
disabled,
|
|
184
175
|
}),
|
|
185
176
|
[
|
|
186
177
|
tokens, resolvedFrameElevation, resolvedTheme, resolvedAppearance,
|
|
187
178
|
layout, direction, wrap, reverse, columns, rows,
|
|
188
179
|
align, justify, padding, gap,
|
|
189
180
|
width, height, minWidth, maxWidth, minHeight, maxHeight,
|
|
190
|
-
position, top, right, bottom, left, zIndex, overflow,
|
|
191
|
-
radius,
|
|
181
|
+
position, top, right, bottom, left, zIndex, overflow,
|
|
182
|
+
radius,
|
|
192
183
|
],
|
|
193
184
|
);
|
|
194
185
|
|
|
@@ -227,21 +218,6 @@ export function Frame({
|
|
|
227
218
|
|
|
228
219
|
const userStyles = Array.isArray(style) ? style : style ? [style] : [];
|
|
229
220
|
|
|
230
|
-
|
|
231
|
-
const isInteractive = onPress !== undefined || href !== undefined;
|
|
232
|
-
|
|
233
|
-
const { isFocusVisible, focusProps } = useFocusVisible();
|
|
234
|
-
|
|
235
|
-
// Focus ring: uses the emphasis background of the resolved theme as the outline color.
|
|
236
|
-
const focusRingStyle = isFocusVisible && !disabled ? {
|
|
237
|
-
outlineWidth: 2,
|
|
238
|
-
outlineStyle: 'solid',
|
|
239
|
-
outlineColor: tokens.colors[resolvedTheme].emphasis.background,
|
|
240
|
-
outlineOffset: 2,
|
|
241
|
-
} as unknown as ViewStyle : undefined;
|
|
242
|
-
|
|
243
|
-
const webFocusProps = isInteractive ? focusProps as any : {};
|
|
244
|
-
|
|
245
221
|
const textStyle = useMemo<TextStyle>(
|
|
246
222
|
() => ({
|
|
247
223
|
color: tokens.colors[resolvedTheme][resolvedAppearance].fontPrimary,
|
|
@@ -256,30 +232,7 @@ export function Frame({
|
|
|
256
232
|
[children, textStyle],
|
|
257
233
|
);
|
|
258
234
|
|
|
259
|
-
const content =
|
|
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
|
-
) : (
|
|
235
|
+
const content = (
|
|
283
236
|
<View
|
|
284
237
|
ref={ref}
|
|
285
238
|
testID={testID}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { View, ViewStyle
|
|
1
|
+
import type { View, ViewStyle } from 'react-native';
|
|
2
2
|
import type { FrameElevation, ThemeName, AppearanceName } from 'newtone-api';
|
|
3
3
|
|
|
4
4
|
// ── Spacing Types ──────────────────────────────────────────────
|
|
@@ -322,13 +322,6 @@ export interface FrameProps {
|
|
|
322
322
|
*/
|
|
323
323
|
readonly pointerEvents?: PointerEventsMode;
|
|
324
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
|
-
|
|
332
325
|
// ── Appearance ──
|
|
333
326
|
|
|
334
327
|
/**
|
|
@@ -381,20 +374,6 @@ export interface FrameProps {
|
|
|
381
374
|
*/
|
|
382
375
|
readonly radius?: RadiusProp;
|
|
383
376
|
|
|
384
|
-
/** Show 1px border using theme border color. @default false */
|
|
385
|
-
readonly bordered?: boolean;
|
|
386
|
-
|
|
387
|
-
// ── Interactivity ──
|
|
388
|
-
|
|
389
|
-
/** Press handler — switches rendering from View to Pressable. */
|
|
390
|
-
readonly onPress?: (event: GestureResponderEvent) => void;
|
|
391
|
-
|
|
392
|
-
/** Navigation URL — switches rendering to Pressable with link role. */
|
|
393
|
-
readonly href?: string;
|
|
394
|
-
|
|
395
|
-
/** Disable interaction. @default false */
|
|
396
|
-
readonly disabled?: boolean;
|
|
397
|
-
|
|
398
377
|
// ── Accessibility ──
|
|
399
378
|
|
|
400
379
|
/** Accessible label read by screen readers. Use for icon-only or non-textual frames. */
|
|
@@ -42,8 +42,8 @@ export function resolveTextColor(
|
|
|
42
42
|
case 'primary': return tokens.colors[theme][appearance].fontPrimary;
|
|
43
43
|
case 'secondary': return tokens.colors[theme][appearance].fontSecondary;
|
|
44
44
|
case 'tertiary': return tokens.colors[theme][appearance].fontTertiary;
|
|
45
|
-
case 'disabled': return tokens.colors[theme][appearance].fontDisabled;
|
|
46
45
|
case 'accent': return tokens.colors[theme][appearance][LARGE_TEXT_ROLES.has(role) ? 'accentLarge' : 'accentSmall'];
|
|
46
|
+
case 'disabled': return tokens.colors[theme][appearance].fontDisabled;
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
|
package/src/primitives/index.ts
CHANGED
|
@@ -29,9 +29,9 @@ export type { ResolvedCorners } from './Frame/Frame.utils';
|
|
|
29
29
|
export { Icon } from './Icon';
|
|
30
30
|
export type { IconProps } from './Icon';
|
|
31
31
|
|
|
32
|
-
//
|
|
33
|
-
export {
|
|
34
|
-
export type {
|
|
32
|
+
// Card
|
|
33
|
+
export { Card } from './Card';
|
|
34
|
+
export type { CardProps } from './Card';
|
|
35
35
|
|
|
36
36
|
// Text
|
|
37
37
|
export { Text } from './Text';
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Wrapper.d.ts","sourceRoot":"","sources":["../../../src/primitives/Wrapper/Wrapper.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAIpD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,OAAO,CAAC,EACtB,QAAQ,EACR,SAAS,EACT,IAAI,EACJ,OAAO,EACP,KAAK,EACL,OAAO,EACP,OAAO,EACP,GAAG,EACH,KAAK,EACL,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,SAAS,EAET,QAAQ,EACR,GAAG,EACH,KAAK,EACL,MAAM,EACN,IAAI,EACJ,MAAM,EACN,QAAQ,EACR,aAAa,EACb,OAAO,EACP,KAAK,EAEL,MAAM,EACN,QAAQ,EACR,GAAG,GACJ,EAAE,YAAY,qBA6Dd"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Wrapper.styles.d.ts","sourceRoot":"","sources":["../../../src/primitives/Wrapper/Wrapper.styles.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EACV,SAAS,EACT,SAAS,EACT,aAAa,EACb,WAAW,EACX,OAAO,EACP,UAAU,EACV,YAAY,EACZ,WAAW,EACX,YAAY,EACb,MAAM,sBAAsB,CAAC;AAU9B,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC;IAC/B,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,OAAO,CAAC,EAAE,aAAa,CAAC;IACjC,QAAQ,CAAC,OAAO,CAAC,EAAE,WAAW,CAAC;IAC/B,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC;IAC7B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAG5B,QAAQ,CAAC,QAAQ,CAAC,EAAE,YAAY,CAAC;IACjC,QAAQ,CAAC,GAAG,CAAC,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,KAAK,CAAC,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,IAAI,CAAC,EAAE,WAAW,CAAC;IAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,YAAY,CAAC;IACjC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,iBAAiB,GAAG,SAAS,CAuFpE"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Wrapper.types.d.ts","sourceRoot":"","sources":["../../../src/primitives/Wrapper/Wrapper.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,KAAK,EACV,SAAS,EACT,SAAS,EACT,aAAa,EACb,WAAW,EACX,OAAO,EACP,UAAU,EACV,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,iBAAiB,EAClB,MAAM,sBAAsB,CAAC;AAE9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,MAAM,WAAW,YAAY;IAC3B;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAIpC,0CAA0C;IAC1C,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC;IAE/B,uCAAuC;IACvC,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IAExB,6CAA6C;IAC7C,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAI3B,wCAAwC;IACxC,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,CAAC;IAE3B,2CAA2C;IAC3C,QAAQ,CAAC,OAAO,CAAC,EAAE,aAAa,CAAC;IAIjC;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,WAAW,CAAC;IAE/B;;;;;;;;;OASG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;IAIvB;;;;;;;OAOG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;IAE5B;;;;;;;OAOG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC;IAE7B,+BAA+B;IAC/B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAE3B,+BAA+B;IAC/B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAE3B,gCAAgC;IAChC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAE5B,gCAAgC;IAChC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAI5B;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,YAAY,CAAC;IAEjC,8EAA8E;IAC9E,QAAQ,CAAC,GAAG,CAAC,EAAE,WAAW,CAAC;IAE3B,gFAAgF;IAChF,QAAQ,CAAC,KAAK,CAAC,EAAE,WAAW,CAAC;IAE7B,iFAAiF;IACjF,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;IAE9B,+EAA+E;IAC/E,QAAQ,CAAC,IAAI,CAAC,EAAE,WAAW,CAAC;IAE5B,+DAA+D;IAC/D,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAEzB,iCAAiC;IACjC,QAAQ,CAAC,QAAQ,CAAC,EAAE,YAAY,CAAC;IAEjC;;;;;;;OAOG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,iBAAiB,CAAC;IAE3C,wEAAwE;IACxE,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAI1B,iFAAiF;IACjF,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAEzB,mFAAmF;IACnF,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAE3B,0CAA0C;IAC1C,QAAQ,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAI/B,6CAA6C;IAC7C,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,GAAG,SAAS,EAAE,CAAC;CAC1C"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/primitives/Wrapper/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,YAAY,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC"}
|
|
File without changes
|
|
File without changes
|