@xaui/native 0.9.1-alpha.16 → 0.9.1-alpha.18
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/chunk-4K3LZS7M.js +448 -0
- package/dist/chunk-5SU7FXWH.cjs +448 -0
- package/dist/chunk-6PZF4PI7.js +100 -0
- package/dist/chunk-6VTBGBPP.cjs +100 -0
- package/dist/{chunk-KCUT47FY.cjs → chunk-BHAHJHAI.cjs} +5 -1
- package/dist/{chunk-UOJBK5Z4.js → chunk-L3AQNVRN.js} +1 -1
- package/dist/{chunk-BAACHVM4.cjs → chunk-M2VYRHVS.cjs} +2 -2
- package/dist/{chunk-E3756MJC.js → chunk-MBLPPOSO.js} +16 -15
- package/dist/{chunk-NLFE3CRM.cjs → chunk-ODH5WAVM.cjs} +24 -23
- package/dist/{chunk-PUER6Y4M.cjs → chunk-P5MKOLIW.cjs} +110 -409
- package/dist/chunk-VQPP6FCB.js +728 -0
- package/dist/{chunk-EHHSY2KB.js → chunk-XQE5PXOD.js} +5 -1
- package/dist/components/button/index.cjs +4 -3
- package/dist/components/button/index.d.cts +179 -178
- package/dist/components/button/index.d.ts +179 -178
- package/dist/components/button/index.js +3 -2
- package/dist/components/typography/index.cjs +12 -0
- package/dist/components/typography/index.d.cts +115 -0
- package/dist/components/typography/index.d.ts +115 -0
- package/dist/components/typography/index.js +12 -0
- package/dist/create-recipe-3_ElpCYt.d.cts +117 -0
- package/dist/create-recipe-DImq1AZA.d.ts +117 -0
- package/dist/index.cjs +17 -7
- package/dist/index.d.cts +4 -2
- package/dist/index.d.ts +4 -2
- package/dist/index.js +21 -11
- package/dist/pressable-feedback.type-UwqIG6ES.d.ts +195 -0
- package/dist/pressable-feedback.type-lgW5wQx5.d.cts +195 -0
- package/dist/system/index.cjs +5 -3
- package/dist/system/index.d.cts +10 -4
- package/dist/system/index.d.ts +10 -4
- package/dist/system/index.js +11 -9
- package/dist/theme/index.cjs +2 -2
- package/dist/theme/index.d.cts +2 -2
- package/dist/theme/index.d.ts +2 -2
- package/dist/theme/index.js +1 -1
- package/dist/{theme.type-C9bFJKFm.d.cts → theme.type-C2gNHpEx.d.cts} +1 -1
- package/dist/{theme.type-C9bFJKFm.d.ts → theme.type-C2gNHpEx.d.ts} +1 -1
- package/package.json +11 -1
- package/dist/chunk-64L44HEI.js +0 -1021
- package/dist/create-recipe-BcUu9b2I.d.cts +0 -280
- package/dist/create-recipe-DD9W6m9b.d.ts +0 -280
|
@@ -1,280 +0,0 @@
|
|
|
1
|
-
import { ComponentType, ReactNode } from 'react';
|
|
2
|
-
import { ImageStyle, TextStyle, ViewStyle, ImageSourcePropType, StyleProp, PressableProps } from 'react-native';
|
|
3
|
-
import { SharedValue } from 'react-native-reanimated';
|
|
4
|
-
import { g as XAUITheme, X as XAUIColors } from './theme.type-C9bFJKFm.cjs';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* R13 — React Native mirrors a layout under RTL through the Start/End properties and only
|
|
8
|
-
* those. A props API is exactly where someone writes `paddingLeft` without thinking, so
|
|
9
|
-
* the type removes the temptation instead of leaving it to a review.
|
|
10
|
-
*/
|
|
11
|
-
type DirectionalStyleKey = 'left' | 'right' | 'paddingLeft' | 'paddingRight' | 'marginLeft' | 'marginRight' | 'borderLeftWidth' | 'borderRightWidth' | 'borderLeftColor' | 'borderRightColor' | 'borderTopLeftRadius' | 'borderTopRightRadius' | 'borderBottomLeftRadius' | 'borderBottomRightRadius';
|
|
12
|
-
/**
|
|
13
|
-
* `pointerEvents` is a style key *and* a `View` prop. R14 says the component's own prop
|
|
14
|
-
* wins, so it stays the prop it has always been and is not exposed twice — the one name
|
|
15
|
-
* where the two vocabularies collide.
|
|
16
|
-
*/
|
|
17
|
-
type ComponentOwnedStyleKey = 'pointerEvents';
|
|
18
|
-
/**
|
|
19
|
-
* The style keys of a node, exposed as props (R14). Not a maintained list: it derives
|
|
20
|
-
* from the React Native type, minus what R13 forbids.
|
|
21
|
-
*
|
|
22
|
-
* ```ts
|
|
23
|
-
* type CardProps = ViewStyleProps & { variant?: CardVariant }
|
|
24
|
-
* ```
|
|
25
|
-
*/
|
|
26
|
-
type StyleProps<Style> = Omit<Style, DirectionalStyleKey | ComponentOwnedStyleKey>;
|
|
27
|
-
/** A root, or any slot that renders a view. */
|
|
28
|
-
type ViewStyleProps = StyleProps<ViewStyle>;
|
|
29
|
-
/** A text slot — `color`, `fontSize`, `letterSpacing`… */
|
|
30
|
-
type TextStyleProps = StyleProps<TextStyle>;
|
|
31
|
-
/** An image slot — `resizeMode`, `tintColor`… */
|
|
32
|
-
type ImageStyleProps = StyleProps<ImageStyle>;
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* The props Lucide, Ionicons and `react-native-vector-icons` all accept — the shape
|
|
36
|
-
* `as` is handed. It is a convention rather than an interface anyone published, which is
|
|
37
|
-
* exactly why `Icon` exists: without it every call site computes the two values by hand.
|
|
38
|
-
*/
|
|
39
|
-
type IconComponentProps = {
|
|
40
|
-
size?: number;
|
|
41
|
-
color?: string;
|
|
42
|
-
};
|
|
43
|
-
/**
|
|
44
|
-
* R14 reaches the **`source` form only**, exactly like `style` below and for the same
|
|
45
|
-
* reason: it is the one of the three forms where we render the node. On the other two,
|
|
46
|
-
* `size` and `color` are what shapes the icon.
|
|
47
|
-
*/
|
|
48
|
-
type IconProps = ImageStyleProps & {
|
|
49
|
-
/** An icon component. `size` and `color` are injected into it. */
|
|
50
|
-
as?: ComponentType<IconComponentProps>;
|
|
51
|
-
/** A raw `react-native-svg` element, cloned with the resolved size and colour. */
|
|
52
|
-
children?: ReactNode;
|
|
53
|
-
/** An image, tinted with the resolved colour. */
|
|
54
|
-
source?: ImageSourcePropType;
|
|
55
|
-
/** Overrides what the surrounding slot asked for. */
|
|
56
|
-
size?: number;
|
|
57
|
-
/** A raw value (R7), never a token. Overrides the slot's. */
|
|
58
|
-
color?: string;
|
|
59
|
-
/**
|
|
60
|
-
* The **`source` form only** — it is the one of the three where we render the view.
|
|
61
|
-
* `as` hands its props to a third-party component and the children form clones an
|
|
62
|
-
* element the caller made; neither is a view this can style, and wrapping them would
|
|
63
|
-
* add a level of depth to every icon in the library. `size` and `color` are the
|
|
64
|
-
* escape hatch there.
|
|
65
|
-
*/
|
|
66
|
-
style?: StyleProp<ImageStyle>;
|
|
67
|
-
};
|
|
68
|
-
/** What a component root publishes so the icons inside it need no props at all. */
|
|
69
|
-
type IconContextValue = {
|
|
70
|
-
size?: number;
|
|
71
|
-
color?: string;
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
type AnimationConfig = {
|
|
75
|
-
scale?: boolean;
|
|
76
|
-
highlight?: boolean;
|
|
77
|
-
ripple?: boolean;
|
|
78
|
-
};
|
|
79
|
-
/**
|
|
80
|
-
* `false` and `'disabled'` turn this component's animations off. `'disable-all'` turns
|
|
81
|
-
* them off for its descendants too — a long list kills every row's worklets with one
|
|
82
|
-
* prop instead of threading it down. An object switches them off one at a time.
|
|
83
|
-
*/
|
|
84
|
-
type AnimationProp = boolean | 'disabled' | 'disable-all' | AnimationConfig;
|
|
85
|
-
/** `animation` once normalised — what the components actually read. */
|
|
86
|
-
type ResolvedAnimation = {
|
|
87
|
-
scale: boolean;
|
|
88
|
-
highlight: boolean;
|
|
89
|
-
ripple: boolean;
|
|
90
|
-
/** True when every sub-animation is off: the branch that mounts no worklet at all. */
|
|
91
|
-
none: boolean;
|
|
92
|
-
/** Propagated to descendants through context. */
|
|
93
|
-
disableAll: boolean;
|
|
94
|
-
};
|
|
95
|
-
/**
|
|
96
|
-
* R14 — it renders a `Pressable`, so it takes that node's style keys as props. The
|
|
97
|
-
* primitive every pressable component in the library is built on cannot be the one place
|
|
98
|
-
* where `padding={16}` has to become an object again.
|
|
99
|
-
*/
|
|
100
|
-
type PressableFeedbackProps = Omit<PressableProps, 'style' | 'children' | 'disabled'> & ViewStyleProps & {
|
|
101
|
-
/** Controlled: the root owns the state, because its recipe resolves on it (R5). */
|
|
102
|
-
isPressed?: boolean;
|
|
103
|
-
/** R8: `disabled` is not part of the public vocabulary, `isX` is. */
|
|
104
|
-
isDisabled?: boolean;
|
|
105
|
-
/**
|
|
106
|
-
* Merge into the single child instead of rendering a pressable (R12) — **keeping the
|
|
107
|
-
* feedback**. Swapping this component out for a bare `Slot` would silently drop the
|
|
108
|
-
* touch feedback of every `asChild` control.
|
|
109
|
-
*/
|
|
110
|
-
asChild?: boolean;
|
|
111
|
-
animation?: AnimationProp;
|
|
112
|
-
style?: StyleProp<ViewStyle>;
|
|
113
|
-
/**
|
|
114
|
-
* The overlays are children, not a prop — `<PressableFeedback.Highlight />` or
|
|
115
|
-
* `<PressableFeedback.Ripple />`, in any order: the root paints them under everything
|
|
116
|
-
* else wherever they sit. The scale is the root's own and needs nothing rendered.
|
|
117
|
-
*
|
|
118
|
-
* `Pressable`'s function form is dropped on purpose. It exists to hand the press state
|
|
119
|
-
* to children; here the root above already owns that state and this publishes it
|
|
120
|
-
* through context, so the function form would be a second, quieter source of truth.
|
|
121
|
-
*/
|
|
122
|
-
children?: ReactNode;
|
|
123
|
-
};
|
|
124
|
-
/**
|
|
125
|
-
* A slot's own animation, overriding the blanket one on the root. `false` switches that
|
|
126
|
-
* slot off; the object tunes it. Deliberately two knobs rather than a full timing
|
|
127
|
-
* surface — anything past this is a different animation, and that is a component's job,
|
|
128
|
-
* not a prop's.
|
|
129
|
-
*/
|
|
130
|
-
type SlotAnimation = boolean | {
|
|
131
|
-
/** Milliseconds. Falls back to the shared press timing. */
|
|
132
|
-
duration?: number;
|
|
133
|
-
/** How far the overlay goes at full press, 0 to 1. */
|
|
134
|
-
opacity?: number;
|
|
135
|
-
};
|
|
136
|
-
/** One ripple wave. Two of them, so a rapid double tap does not cut the one in flight. */
|
|
137
|
-
type RippleWave = {
|
|
138
|
-
/** `0 → 1` as the circle opens. */
|
|
139
|
-
expand: SharedValue<number>;
|
|
140
|
-
/** `0 → 1` as the ink arrives, on its own curve. */
|
|
141
|
-
alpha: SharedValue<number>;
|
|
142
|
-
/** Where the finger landed, in the root's coordinates. */
|
|
143
|
-
origin: SharedValue<{
|
|
144
|
-
x: number;
|
|
145
|
-
y: number;
|
|
146
|
-
}>;
|
|
147
|
-
};
|
|
148
|
-
/**
|
|
149
|
-
* The corner keys an overlay copies off the root. The `Left`/`Right` forms are absent
|
|
150
|
-
* rather than forgotten: R13 bans them, because RN mirrors only the logical ones under RTL.
|
|
151
|
-
*/
|
|
152
|
-
type RadiusStyle = Pick<ViewStyle, 'borderRadius' | 'borderStartStartRadius' | 'borderStartEndRadius' | 'borderEndStartRadius' | 'borderEndEndRadius'>;
|
|
153
|
-
type FeedbackContext = {
|
|
154
|
-
/**
|
|
155
|
-
* The overlay's ink, resolved by the root from its own background.
|
|
156
|
-
*
|
|
157
|
-
* A wash or a wave has to contrast with what it sits on, and only the root knows that —
|
|
158
|
-
* it flattens its own `style` and reads `backgroundColor`, then takes the contrasting
|
|
159
|
-
* side the same way a tint does. Black ink at 10% on a saturated fill is close to
|
|
160
|
-
* invisible, which is the one thing a press indicator cannot be.
|
|
161
|
-
*/
|
|
162
|
-
ink: string;
|
|
163
|
-
/**
|
|
164
|
-
* The root's own corners, so an overlay rounds itself to match. `corners` and not
|
|
165
|
-
* `radius`: the ripple already has a radius, and it is a length in points rather than a
|
|
166
|
-
* shape.
|
|
167
|
-
*
|
|
168
|
-
* An absolute fill has square corners and every control here is rounded, so without this
|
|
169
|
-
* both the wash and the wave paint outside the surface at each corner. The overlay
|
|
170
|
-
* carries the clip rather than the root: clipping the root would also cut a child that
|
|
171
|
-
* legitimately overflows — a badge on a button's corner — and that child has nothing to
|
|
172
|
-
* do with the press.
|
|
173
|
-
*/
|
|
174
|
-
corners: RadiusStyle;
|
|
175
|
-
isPressed: boolean;
|
|
176
|
-
animation: ResolvedAnimation;
|
|
177
|
-
/** Absent on the static branch, where nothing animates and no worklet is mounted. */
|
|
178
|
-
progress?: SharedValue<number>;
|
|
179
|
-
/** How big the root is — what the scale coefficient is computed from. */
|
|
180
|
-
size?: SharedValue<{
|
|
181
|
-
width: number;
|
|
182
|
-
height: number;
|
|
183
|
-
}>;
|
|
184
|
-
/**
|
|
185
|
-
* The two ripple waves, driven by the **root**.
|
|
186
|
-
*
|
|
187
|
-
* They belong to the root because the root is the touch surface. An overlay carrying its
|
|
188
|
-
* own handlers only hears touches that land on *it* — and it is a sibling of the label,
|
|
189
|
-
* not its parent, so pressing the text of a button would do nothing. Touches bubble to
|
|
190
|
-
* the `Pressable`, which is why the handlers live there and the waves are published down.
|
|
191
|
-
*/
|
|
192
|
-
waves?: readonly [RippleWave, RippleWave];
|
|
193
|
-
};
|
|
194
|
-
|
|
195
|
-
/**
|
|
196
|
-
* A slot is a view or a text node, and a recipe writes one object per slot, so the two
|
|
197
|
-
* RN style shapes are merged rather than discriminated per slot.
|
|
198
|
-
*/
|
|
199
|
-
type SlotStyle = ViewStyle & TextStyle;
|
|
200
|
-
type SlotStyles<Slot extends string> = Partial<Record<Slot, SlotStyle>>;
|
|
201
|
-
/** The roles a variant consumes. The variant names tokens; `paint` says where they land. */
|
|
202
|
-
type VariantRole = 'bg' | 'bgPressed' | 'fg' | 'border';
|
|
203
|
-
/** Token names per role — no colour value ever appears in a recipe. */
|
|
204
|
-
type VariantTokens = Partial<Record<VariantRole, keyof XAUIColors>>;
|
|
205
|
-
/** The same roles resolved: theme colours, or the slices of a raw `color`. */
|
|
206
|
-
type VariantColors = Partial<Record<VariantRole, string>>;
|
|
207
|
-
/**
|
|
208
|
-
* `disabled` is applied last of the three: a control that is both pressed and disabled
|
|
209
|
-
* has to read disabled.
|
|
210
|
-
*/
|
|
211
|
-
type StateName = 'focused' | 'pressed' | 'disabled';
|
|
212
|
-
type States = Partial<Record<StateName, boolean>>;
|
|
213
|
-
/** Reads the theme and the variant's resolved colours; returns one style per slot. */
|
|
214
|
-
type StyleFn<Slot extends string> = (theme: XAUITheme, colors: VariantColors) => SlotStyles<Slot>;
|
|
215
|
-
/** Named axes of finite token values — `{ size: { sm: fn, md: fn } }`. */
|
|
216
|
-
type Axes<Slot extends string> = Record<string, Record<string, StyleFn<Slot>>>;
|
|
217
|
-
/** One value per axis, plus the variant. Missing keys fall back to `defaultVariants`. */
|
|
218
|
-
type Selection<Variant extends string, A extends Axes<string>> = {
|
|
219
|
-
variant?: Variant;
|
|
220
|
-
} & {
|
|
221
|
-
[Axis in keyof A]?: Extract<keyof A[Axis], string>;
|
|
222
|
-
};
|
|
223
|
-
type CompoundVariant<Slot extends string, Variant extends string, A extends Axes<Slot>> = {
|
|
224
|
-
when: Selection<Variant, A>;
|
|
225
|
-
style: StyleFn<Slot>;
|
|
226
|
-
};
|
|
227
|
-
type RecipeConfig<Slot extends string, Variant extends string, A extends Axes<Slot>> = {
|
|
228
|
-
/** Every slot the component publishes. Slots a recipe never styles resolve to `{}`. */
|
|
229
|
-
slots: readonly Slot[];
|
|
230
|
-
base?: StyleFn<Slot>;
|
|
231
|
-
variantTokens?: Record<Variant, VariantTokens>;
|
|
232
|
-
/** Where the variant's colours land — written once, and it holds for every variant. */
|
|
233
|
-
paint?: StyleFn<Slot>;
|
|
234
|
-
variants?: A;
|
|
235
|
-
compoundVariants?: ReadonlyArray<CompoundVariant<Slot, Variant, A>>;
|
|
236
|
-
states?: Partial<Record<StateName, StyleFn<Slot>>>;
|
|
237
|
-
/**
|
|
238
|
-
* `NoInfer`, because this is the one place a single variant name appears on its own:
|
|
239
|
-
* without it, inference reads `Variant` off `{ variant: 'primary' }` and narrows the
|
|
240
|
-
* whole recipe to that one value, so every other variant becomes a type error at the
|
|
241
|
-
* call site. `variantTokens` is the declaration; this only picks a default from it.
|
|
242
|
-
*/
|
|
243
|
-
defaultVariants?: Selection<NoInfer<Variant>, A>;
|
|
244
|
-
};
|
|
245
|
-
/** Stable references: the same object for the same tokens, for the app's lifetime. */
|
|
246
|
-
type ResolvedStyles<Slot extends string> = Readonly<Record<Slot, SlotStyle>>;
|
|
247
|
-
/** A selection with `defaultVariants` already folded in, keyed by axis name. */
|
|
248
|
-
type ResolvedSelection = Readonly<Record<string, string | undefined>>;
|
|
249
|
-
|
|
250
|
-
type ResolveArgs<Variant extends string, A extends Axes<string>> = {
|
|
251
|
-
theme: XAUITheme;
|
|
252
|
-
selection?: Selection<Variant, A>;
|
|
253
|
-
states?: States;
|
|
254
|
-
};
|
|
255
|
-
type TintArgs<Variant extends string, A extends Axes<string>> = ResolveArgs<Variant, A> & {
|
|
256
|
-
color: string;
|
|
257
|
-
};
|
|
258
|
-
type Recipe<Slot extends string, Variant extends string, A extends Axes<Slot>> = {
|
|
259
|
-
readonly slots: readonly Slot[];
|
|
260
|
-
/** The cached pass: stable `StyleSheet` references, keyed by tokens alone. */
|
|
261
|
-
resolve(args: ResolveArgs<Variant, A>): ResolvedStyles<Slot>;
|
|
262
|
-
/**
|
|
263
|
-
* The tint pass: the same functions run again with `color`'s slices in place of the
|
|
264
|
-
* theme's tokens. Uncached and allocating, and only ever called when `color` is set.
|
|
265
|
-
*/
|
|
266
|
-
tint(args: TintArgs<Variant, A>): SlotStyles<Slot>;
|
|
267
|
-
};
|
|
268
|
-
/**
|
|
269
|
-
* A component's style, declared once. Resolution splits in two because the two halves
|
|
270
|
-
* have different lifetimes: everything keyed by a finite token is cached forever, and
|
|
271
|
-
* an arbitrary `color` is recomputed per render — which is what keeps the cache bounded
|
|
272
|
-
* by the number of token combinations rather than by the palette users invent.
|
|
273
|
-
*
|
|
274
|
-
* const styles = buttonRecipe.resolve({ theme, selection: { variant, size }, states })
|
|
275
|
-
* const tint = color ? buttonRecipe.tint({ theme, color, selection, states }) : undefined
|
|
276
|
-
* <View style={[styles.root, tint?.root, style]} />
|
|
277
|
-
*/
|
|
278
|
-
declare function createRecipe<Slot extends string, Variant extends string, const A extends Axes<Slot>>(config: RecipeConfig<Slot, Variant, A>): Recipe<Slot, Variant, A>;
|
|
279
|
-
|
|
280
|
-
export { type AnimationConfig as A, type CompoundVariant as C, type DirectionalStyleKey as D, type FeedbackContext as F, type IconComponentProps as I, type PressableFeedbackProps as P, type RadiusStyle as R, type SlotAnimation as S, type TintArgs as T, type VariantColors as V, type IconContextValue as a, type IconProps as b, type AnimationProp as c, type ResolvedAnimation as d, type RippleWave as e, createRecipe as f, type Recipe as g, type ResolveArgs as h, type Axes as i, type RecipeConfig as j, type ResolvedSelection as k, type ResolvedStyles as l, type Selection as m, type SlotStyle as n, type SlotStyles as o, type StateName as p, type States as q, type StyleFn as r, type VariantRole as s, type VariantTokens as t, type ImageStyleProps as u, type StyleProps as v, type TextStyleProps as w, type ViewStyleProps as x };
|
|
@@ -1,280 +0,0 @@
|
|
|
1
|
-
import { ComponentType, ReactNode } from 'react';
|
|
2
|
-
import { ImageStyle, TextStyle, ViewStyle, ImageSourcePropType, StyleProp, PressableProps } from 'react-native';
|
|
3
|
-
import { SharedValue } from 'react-native-reanimated';
|
|
4
|
-
import { g as XAUITheme, X as XAUIColors } from './theme.type-C9bFJKFm.js';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* R13 — React Native mirrors a layout under RTL through the Start/End properties and only
|
|
8
|
-
* those. A props API is exactly where someone writes `paddingLeft` without thinking, so
|
|
9
|
-
* the type removes the temptation instead of leaving it to a review.
|
|
10
|
-
*/
|
|
11
|
-
type DirectionalStyleKey = 'left' | 'right' | 'paddingLeft' | 'paddingRight' | 'marginLeft' | 'marginRight' | 'borderLeftWidth' | 'borderRightWidth' | 'borderLeftColor' | 'borderRightColor' | 'borderTopLeftRadius' | 'borderTopRightRadius' | 'borderBottomLeftRadius' | 'borderBottomRightRadius';
|
|
12
|
-
/**
|
|
13
|
-
* `pointerEvents` is a style key *and* a `View` prop. R14 says the component's own prop
|
|
14
|
-
* wins, so it stays the prop it has always been and is not exposed twice — the one name
|
|
15
|
-
* where the two vocabularies collide.
|
|
16
|
-
*/
|
|
17
|
-
type ComponentOwnedStyleKey = 'pointerEvents';
|
|
18
|
-
/**
|
|
19
|
-
* The style keys of a node, exposed as props (R14). Not a maintained list: it derives
|
|
20
|
-
* from the React Native type, minus what R13 forbids.
|
|
21
|
-
*
|
|
22
|
-
* ```ts
|
|
23
|
-
* type CardProps = ViewStyleProps & { variant?: CardVariant }
|
|
24
|
-
* ```
|
|
25
|
-
*/
|
|
26
|
-
type StyleProps<Style> = Omit<Style, DirectionalStyleKey | ComponentOwnedStyleKey>;
|
|
27
|
-
/** A root, or any slot that renders a view. */
|
|
28
|
-
type ViewStyleProps = StyleProps<ViewStyle>;
|
|
29
|
-
/** A text slot — `color`, `fontSize`, `letterSpacing`… */
|
|
30
|
-
type TextStyleProps = StyleProps<TextStyle>;
|
|
31
|
-
/** An image slot — `resizeMode`, `tintColor`… */
|
|
32
|
-
type ImageStyleProps = StyleProps<ImageStyle>;
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* The props Lucide, Ionicons and `react-native-vector-icons` all accept — the shape
|
|
36
|
-
* `as` is handed. It is a convention rather than an interface anyone published, which is
|
|
37
|
-
* exactly why `Icon` exists: without it every call site computes the two values by hand.
|
|
38
|
-
*/
|
|
39
|
-
type IconComponentProps = {
|
|
40
|
-
size?: number;
|
|
41
|
-
color?: string;
|
|
42
|
-
};
|
|
43
|
-
/**
|
|
44
|
-
* R14 reaches the **`source` form only**, exactly like `style` below and for the same
|
|
45
|
-
* reason: it is the one of the three forms where we render the node. On the other two,
|
|
46
|
-
* `size` and `color` are what shapes the icon.
|
|
47
|
-
*/
|
|
48
|
-
type IconProps = ImageStyleProps & {
|
|
49
|
-
/** An icon component. `size` and `color` are injected into it. */
|
|
50
|
-
as?: ComponentType<IconComponentProps>;
|
|
51
|
-
/** A raw `react-native-svg` element, cloned with the resolved size and colour. */
|
|
52
|
-
children?: ReactNode;
|
|
53
|
-
/** An image, tinted with the resolved colour. */
|
|
54
|
-
source?: ImageSourcePropType;
|
|
55
|
-
/** Overrides what the surrounding slot asked for. */
|
|
56
|
-
size?: number;
|
|
57
|
-
/** A raw value (R7), never a token. Overrides the slot's. */
|
|
58
|
-
color?: string;
|
|
59
|
-
/**
|
|
60
|
-
* The **`source` form only** — it is the one of the three where we render the view.
|
|
61
|
-
* `as` hands its props to a third-party component and the children form clones an
|
|
62
|
-
* element the caller made; neither is a view this can style, and wrapping them would
|
|
63
|
-
* add a level of depth to every icon in the library. `size` and `color` are the
|
|
64
|
-
* escape hatch there.
|
|
65
|
-
*/
|
|
66
|
-
style?: StyleProp<ImageStyle>;
|
|
67
|
-
};
|
|
68
|
-
/** What a component root publishes so the icons inside it need no props at all. */
|
|
69
|
-
type IconContextValue = {
|
|
70
|
-
size?: number;
|
|
71
|
-
color?: string;
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
type AnimationConfig = {
|
|
75
|
-
scale?: boolean;
|
|
76
|
-
highlight?: boolean;
|
|
77
|
-
ripple?: boolean;
|
|
78
|
-
};
|
|
79
|
-
/**
|
|
80
|
-
* `false` and `'disabled'` turn this component's animations off. `'disable-all'` turns
|
|
81
|
-
* them off for its descendants too — a long list kills every row's worklets with one
|
|
82
|
-
* prop instead of threading it down. An object switches them off one at a time.
|
|
83
|
-
*/
|
|
84
|
-
type AnimationProp = boolean | 'disabled' | 'disable-all' | AnimationConfig;
|
|
85
|
-
/** `animation` once normalised — what the components actually read. */
|
|
86
|
-
type ResolvedAnimation = {
|
|
87
|
-
scale: boolean;
|
|
88
|
-
highlight: boolean;
|
|
89
|
-
ripple: boolean;
|
|
90
|
-
/** True when every sub-animation is off: the branch that mounts no worklet at all. */
|
|
91
|
-
none: boolean;
|
|
92
|
-
/** Propagated to descendants through context. */
|
|
93
|
-
disableAll: boolean;
|
|
94
|
-
};
|
|
95
|
-
/**
|
|
96
|
-
* R14 — it renders a `Pressable`, so it takes that node's style keys as props. The
|
|
97
|
-
* primitive every pressable component in the library is built on cannot be the one place
|
|
98
|
-
* where `padding={16}` has to become an object again.
|
|
99
|
-
*/
|
|
100
|
-
type PressableFeedbackProps = Omit<PressableProps, 'style' | 'children' | 'disabled'> & ViewStyleProps & {
|
|
101
|
-
/** Controlled: the root owns the state, because its recipe resolves on it (R5). */
|
|
102
|
-
isPressed?: boolean;
|
|
103
|
-
/** R8: `disabled` is not part of the public vocabulary, `isX` is. */
|
|
104
|
-
isDisabled?: boolean;
|
|
105
|
-
/**
|
|
106
|
-
* Merge into the single child instead of rendering a pressable (R12) — **keeping the
|
|
107
|
-
* feedback**. Swapping this component out for a bare `Slot` would silently drop the
|
|
108
|
-
* touch feedback of every `asChild` control.
|
|
109
|
-
*/
|
|
110
|
-
asChild?: boolean;
|
|
111
|
-
animation?: AnimationProp;
|
|
112
|
-
style?: StyleProp<ViewStyle>;
|
|
113
|
-
/**
|
|
114
|
-
* The overlays are children, not a prop — `<PressableFeedback.Highlight />` or
|
|
115
|
-
* `<PressableFeedback.Ripple />`, in any order: the root paints them under everything
|
|
116
|
-
* else wherever they sit. The scale is the root's own and needs nothing rendered.
|
|
117
|
-
*
|
|
118
|
-
* `Pressable`'s function form is dropped on purpose. It exists to hand the press state
|
|
119
|
-
* to children; here the root above already owns that state and this publishes it
|
|
120
|
-
* through context, so the function form would be a second, quieter source of truth.
|
|
121
|
-
*/
|
|
122
|
-
children?: ReactNode;
|
|
123
|
-
};
|
|
124
|
-
/**
|
|
125
|
-
* A slot's own animation, overriding the blanket one on the root. `false` switches that
|
|
126
|
-
* slot off; the object tunes it. Deliberately two knobs rather than a full timing
|
|
127
|
-
* surface — anything past this is a different animation, and that is a component's job,
|
|
128
|
-
* not a prop's.
|
|
129
|
-
*/
|
|
130
|
-
type SlotAnimation = boolean | {
|
|
131
|
-
/** Milliseconds. Falls back to the shared press timing. */
|
|
132
|
-
duration?: number;
|
|
133
|
-
/** How far the overlay goes at full press, 0 to 1. */
|
|
134
|
-
opacity?: number;
|
|
135
|
-
};
|
|
136
|
-
/** One ripple wave. Two of them, so a rapid double tap does not cut the one in flight. */
|
|
137
|
-
type RippleWave = {
|
|
138
|
-
/** `0 → 1` as the circle opens. */
|
|
139
|
-
expand: SharedValue<number>;
|
|
140
|
-
/** `0 → 1` as the ink arrives, on its own curve. */
|
|
141
|
-
alpha: SharedValue<number>;
|
|
142
|
-
/** Where the finger landed, in the root's coordinates. */
|
|
143
|
-
origin: SharedValue<{
|
|
144
|
-
x: number;
|
|
145
|
-
y: number;
|
|
146
|
-
}>;
|
|
147
|
-
};
|
|
148
|
-
/**
|
|
149
|
-
* The corner keys an overlay copies off the root. The `Left`/`Right` forms are absent
|
|
150
|
-
* rather than forgotten: R13 bans them, because RN mirrors only the logical ones under RTL.
|
|
151
|
-
*/
|
|
152
|
-
type RadiusStyle = Pick<ViewStyle, 'borderRadius' | 'borderStartStartRadius' | 'borderStartEndRadius' | 'borderEndStartRadius' | 'borderEndEndRadius'>;
|
|
153
|
-
type FeedbackContext = {
|
|
154
|
-
/**
|
|
155
|
-
* The overlay's ink, resolved by the root from its own background.
|
|
156
|
-
*
|
|
157
|
-
* A wash or a wave has to contrast with what it sits on, and only the root knows that —
|
|
158
|
-
* it flattens its own `style` and reads `backgroundColor`, then takes the contrasting
|
|
159
|
-
* side the same way a tint does. Black ink at 10% on a saturated fill is close to
|
|
160
|
-
* invisible, which is the one thing a press indicator cannot be.
|
|
161
|
-
*/
|
|
162
|
-
ink: string;
|
|
163
|
-
/**
|
|
164
|
-
* The root's own corners, so an overlay rounds itself to match. `corners` and not
|
|
165
|
-
* `radius`: the ripple already has a radius, and it is a length in points rather than a
|
|
166
|
-
* shape.
|
|
167
|
-
*
|
|
168
|
-
* An absolute fill has square corners and every control here is rounded, so without this
|
|
169
|
-
* both the wash and the wave paint outside the surface at each corner. The overlay
|
|
170
|
-
* carries the clip rather than the root: clipping the root would also cut a child that
|
|
171
|
-
* legitimately overflows — a badge on a button's corner — and that child has nothing to
|
|
172
|
-
* do with the press.
|
|
173
|
-
*/
|
|
174
|
-
corners: RadiusStyle;
|
|
175
|
-
isPressed: boolean;
|
|
176
|
-
animation: ResolvedAnimation;
|
|
177
|
-
/** Absent on the static branch, where nothing animates and no worklet is mounted. */
|
|
178
|
-
progress?: SharedValue<number>;
|
|
179
|
-
/** How big the root is — what the scale coefficient is computed from. */
|
|
180
|
-
size?: SharedValue<{
|
|
181
|
-
width: number;
|
|
182
|
-
height: number;
|
|
183
|
-
}>;
|
|
184
|
-
/**
|
|
185
|
-
* The two ripple waves, driven by the **root**.
|
|
186
|
-
*
|
|
187
|
-
* They belong to the root because the root is the touch surface. An overlay carrying its
|
|
188
|
-
* own handlers only hears touches that land on *it* — and it is a sibling of the label,
|
|
189
|
-
* not its parent, so pressing the text of a button would do nothing. Touches bubble to
|
|
190
|
-
* the `Pressable`, which is why the handlers live there and the waves are published down.
|
|
191
|
-
*/
|
|
192
|
-
waves?: readonly [RippleWave, RippleWave];
|
|
193
|
-
};
|
|
194
|
-
|
|
195
|
-
/**
|
|
196
|
-
* A slot is a view or a text node, and a recipe writes one object per slot, so the two
|
|
197
|
-
* RN style shapes are merged rather than discriminated per slot.
|
|
198
|
-
*/
|
|
199
|
-
type SlotStyle = ViewStyle & TextStyle;
|
|
200
|
-
type SlotStyles<Slot extends string> = Partial<Record<Slot, SlotStyle>>;
|
|
201
|
-
/** The roles a variant consumes. The variant names tokens; `paint` says where they land. */
|
|
202
|
-
type VariantRole = 'bg' | 'bgPressed' | 'fg' | 'border';
|
|
203
|
-
/** Token names per role — no colour value ever appears in a recipe. */
|
|
204
|
-
type VariantTokens = Partial<Record<VariantRole, keyof XAUIColors>>;
|
|
205
|
-
/** The same roles resolved: theme colours, or the slices of a raw `color`. */
|
|
206
|
-
type VariantColors = Partial<Record<VariantRole, string>>;
|
|
207
|
-
/**
|
|
208
|
-
* `disabled` is applied last of the three: a control that is both pressed and disabled
|
|
209
|
-
* has to read disabled.
|
|
210
|
-
*/
|
|
211
|
-
type StateName = 'focused' | 'pressed' | 'disabled';
|
|
212
|
-
type States = Partial<Record<StateName, boolean>>;
|
|
213
|
-
/** Reads the theme and the variant's resolved colours; returns one style per slot. */
|
|
214
|
-
type StyleFn<Slot extends string> = (theme: XAUITheme, colors: VariantColors) => SlotStyles<Slot>;
|
|
215
|
-
/** Named axes of finite token values — `{ size: { sm: fn, md: fn } }`. */
|
|
216
|
-
type Axes<Slot extends string> = Record<string, Record<string, StyleFn<Slot>>>;
|
|
217
|
-
/** One value per axis, plus the variant. Missing keys fall back to `defaultVariants`. */
|
|
218
|
-
type Selection<Variant extends string, A extends Axes<string>> = {
|
|
219
|
-
variant?: Variant;
|
|
220
|
-
} & {
|
|
221
|
-
[Axis in keyof A]?: Extract<keyof A[Axis], string>;
|
|
222
|
-
};
|
|
223
|
-
type CompoundVariant<Slot extends string, Variant extends string, A extends Axes<Slot>> = {
|
|
224
|
-
when: Selection<Variant, A>;
|
|
225
|
-
style: StyleFn<Slot>;
|
|
226
|
-
};
|
|
227
|
-
type RecipeConfig<Slot extends string, Variant extends string, A extends Axes<Slot>> = {
|
|
228
|
-
/** Every slot the component publishes. Slots a recipe never styles resolve to `{}`. */
|
|
229
|
-
slots: readonly Slot[];
|
|
230
|
-
base?: StyleFn<Slot>;
|
|
231
|
-
variantTokens?: Record<Variant, VariantTokens>;
|
|
232
|
-
/** Where the variant's colours land — written once, and it holds for every variant. */
|
|
233
|
-
paint?: StyleFn<Slot>;
|
|
234
|
-
variants?: A;
|
|
235
|
-
compoundVariants?: ReadonlyArray<CompoundVariant<Slot, Variant, A>>;
|
|
236
|
-
states?: Partial<Record<StateName, StyleFn<Slot>>>;
|
|
237
|
-
/**
|
|
238
|
-
* `NoInfer`, because this is the one place a single variant name appears on its own:
|
|
239
|
-
* without it, inference reads `Variant` off `{ variant: 'primary' }` and narrows the
|
|
240
|
-
* whole recipe to that one value, so every other variant becomes a type error at the
|
|
241
|
-
* call site. `variantTokens` is the declaration; this only picks a default from it.
|
|
242
|
-
*/
|
|
243
|
-
defaultVariants?: Selection<NoInfer<Variant>, A>;
|
|
244
|
-
};
|
|
245
|
-
/** Stable references: the same object for the same tokens, for the app's lifetime. */
|
|
246
|
-
type ResolvedStyles<Slot extends string> = Readonly<Record<Slot, SlotStyle>>;
|
|
247
|
-
/** A selection with `defaultVariants` already folded in, keyed by axis name. */
|
|
248
|
-
type ResolvedSelection = Readonly<Record<string, string | undefined>>;
|
|
249
|
-
|
|
250
|
-
type ResolveArgs<Variant extends string, A extends Axes<string>> = {
|
|
251
|
-
theme: XAUITheme;
|
|
252
|
-
selection?: Selection<Variant, A>;
|
|
253
|
-
states?: States;
|
|
254
|
-
};
|
|
255
|
-
type TintArgs<Variant extends string, A extends Axes<string>> = ResolveArgs<Variant, A> & {
|
|
256
|
-
color: string;
|
|
257
|
-
};
|
|
258
|
-
type Recipe<Slot extends string, Variant extends string, A extends Axes<Slot>> = {
|
|
259
|
-
readonly slots: readonly Slot[];
|
|
260
|
-
/** The cached pass: stable `StyleSheet` references, keyed by tokens alone. */
|
|
261
|
-
resolve(args: ResolveArgs<Variant, A>): ResolvedStyles<Slot>;
|
|
262
|
-
/**
|
|
263
|
-
* The tint pass: the same functions run again with `color`'s slices in place of the
|
|
264
|
-
* theme's tokens. Uncached and allocating, and only ever called when `color` is set.
|
|
265
|
-
*/
|
|
266
|
-
tint(args: TintArgs<Variant, A>): SlotStyles<Slot>;
|
|
267
|
-
};
|
|
268
|
-
/**
|
|
269
|
-
* A component's style, declared once. Resolution splits in two because the two halves
|
|
270
|
-
* have different lifetimes: everything keyed by a finite token is cached forever, and
|
|
271
|
-
* an arbitrary `color` is recomputed per render — which is what keeps the cache bounded
|
|
272
|
-
* by the number of token combinations rather than by the palette users invent.
|
|
273
|
-
*
|
|
274
|
-
* const styles = buttonRecipe.resolve({ theme, selection: { variant, size }, states })
|
|
275
|
-
* const tint = color ? buttonRecipe.tint({ theme, color, selection, states }) : undefined
|
|
276
|
-
* <View style={[styles.root, tint?.root, style]} />
|
|
277
|
-
*/
|
|
278
|
-
declare function createRecipe<Slot extends string, Variant extends string, const A extends Axes<Slot>>(config: RecipeConfig<Slot, Variant, A>): Recipe<Slot, Variant, A>;
|
|
279
|
-
|
|
280
|
-
export { type AnimationConfig as A, type CompoundVariant as C, type DirectionalStyleKey as D, type FeedbackContext as F, type IconComponentProps as I, type PressableFeedbackProps as P, type RadiusStyle as R, type SlotAnimation as S, type TintArgs as T, type VariantColors as V, type IconContextValue as a, type IconProps as b, type AnimationProp as c, type ResolvedAnimation as d, type RippleWave as e, createRecipe as f, type Recipe as g, type ResolveArgs as h, type Axes as i, type RecipeConfig as j, type ResolvedSelection as k, type ResolvedStyles as l, type Selection as m, type SlotStyle as n, type SlotStyles as o, type StateName as p, type States as q, type StyleFn as r, type VariantRole as s, type VariantTokens as t, type ImageStyleProps as u, type StyleProps as v, type TextStyleProps as w, type ViewStyleProps as x };
|