@xaui/native 0.9.1-alpha.15 → 0.9.1-alpha.17
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-PUER6Y4M.cjs → chunk-2UICXD3Q.cjs} +75 -381
- 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-E3756MJC.js → chunk-ASXK7XU4.js} +16 -15
- package/dist/{chunk-DDYMIWLW.cjs → chunk-BHAHJHAI.cjs} +9 -5
- package/dist/{chunk-64L44HEI.js → chunk-F432IDIW.js} +89 -389
- package/dist/{chunk-NLFE3CRM.cjs → chunk-IZYRU7S2.cjs} +24 -23
- package/dist/{chunk-UOJBK5Z4.js → chunk-L3AQNVRN.js} +1 -1
- package/dist/{chunk-BAACHVM4.cjs → chunk-M2VYRHVS.cjs} +2 -2
- package/dist/{chunk-4O3PXFQ7.js → chunk-XQE5PXOD.js} +9 -5
- package/dist/components/button/index.cjs +4 -3
- package/dist/components/button/index.d.cts +3 -2
- package/dist/components/button/index.d.ts +3 -2
- 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/{create-recipe-DD9W6m9b.d.ts → pressable-feedback.type-C9kjAuVQ.d.cts} +3 -116
- package/dist/{create-recipe-BcUu9b2I.d.cts → pressable-feedback.type-KcPvFf6f.d.ts} +3 -116
- package/dist/system/index.cjs +5 -3
- package/dist/system/index.d.cts +5 -3
- package/dist/system/index.d.ts +5 -3
- package/dist/system/index.js +11 -9
- package/dist/theme/index.cjs +2 -2
- package/dist/theme/index.d.cts +6 -6
- package/dist/theme/index.d.ts +6 -6
- 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
|
@@ -36,11 +36,12 @@ function _optionalChain(ops) {
|
|
|
36
36
|
}
|
|
37
37
|
return value;
|
|
38
38
|
}
|
|
39
|
-
var
|
|
39
|
+
var _chunk2UICXD3Qcjs = require('./chunk-2UICXD3Q.cjs');
|
|
40
|
+
var _chunk5SU7FXWHcjs = require('./chunk-5SU7FXWH.cjs');
|
|
40
41
|
var _chunk6N5JXRUZcjs = require('./chunk-6N5JXRUZ.cjs');
|
|
41
42
|
|
|
42
43
|
// src/components/button/button.context.ts
|
|
43
|
-
var [ButtonProvider, useButton] =
|
|
44
|
+
var [ButtonProvider, useButton] = _chunk5SU7FXWHcjs.createSlotContext.call(void 0, "Button");
|
|
44
45
|
|
|
45
46
|
// src/components/button/button-icon.tsx
|
|
46
47
|
var _jsxruntime = require('react/jsx-runtime');
|
|
@@ -52,7 +53,7 @@ function ButtonIcon({
|
|
|
52
53
|
const {
|
|
53
54
|
icon
|
|
54
55
|
} = useButton();
|
|
55
|
-
return /* @__PURE__ */_jsxruntime.jsx.call(void 0,
|
|
56
|
+
return /* @__PURE__ */_jsxruntime.jsx.call(void 0, _chunk2UICXD3Qcjs.Icon, {
|
|
56
57
|
size: _nullishCoalesce(size, () => icon.size),
|
|
57
58
|
color: _nullishCoalesce(color, () => icon.color),
|
|
58
59
|
...rest
|
|
@@ -72,7 +73,7 @@ var ButtonLabel = _react.forwardRef.call(void 0, function ButtonLabel2({
|
|
|
72
73
|
const {
|
|
73
74
|
labelStyle
|
|
74
75
|
} = useButton();
|
|
75
|
-
const [styleProps, rest] =
|
|
76
|
+
const [styleProps, rest] = _chunk5SU7FXWHcjs.useStyleProps.call(void 0, props);
|
|
76
77
|
return /* @__PURE__ */_jsxruntime.jsx.call(void 0, _reactnative.Text, {
|
|
77
78
|
ref,
|
|
78
79
|
numberOfLines,
|
|
@@ -96,7 +97,7 @@ function ButtonSpinner({
|
|
|
96
97
|
const {
|
|
97
98
|
spinnerStyle
|
|
98
99
|
} = useButton();
|
|
99
|
-
const [styleProps] =
|
|
100
|
+
const [styleProps] = _chunk5SU7FXWHcjs.useStyleProps.call(void 0, props);
|
|
100
101
|
const ringStyle = [spinnerStyle, styleProps, style];
|
|
101
102
|
if (!animation) return /* @__PURE__ */_jsxruntime.jsx.call(void 0, _reactnative.View, {
|
|
102
103
|
style: ringStyle
|
|
@@ -106,10 +107,10 @@ function ButtonSpinner({
|
|
|
106
107
|
});
|
|
107
108
|
}
|
|
108
109
|
ButtonSpinner.displayName = "XAUI.Button.Spinner";
|
|
109
|
-
const
|
|
110
|
-
code: "function
|
|
111
|
-
location: "/home/runner/work/xaui/xaui/packages/native/dist/chunk-
|
|
112
|
-
sourceMap: "{\"version\":3,\"names\":[\"
|
|
110
|
+
const _worklet_11467162648159_init_data = {
|
|
111
|
+
code: "function chunkIZYRU7S2Cjs1(){const{angle}=this.__closure;return{transform:[{rotate:angle.value+\"deg\"}]};}",
|
|
112
|
+
location: "/home/runner/work/xaui/xaui/packages/native/dist/chunk-IZYRU7S2.cjs",
|
|
113
|
+
sourceMap: "{\"version\":3,\"names\":[\"chunkIZYRU7S2Cjs1\",\"angle\",\"__closure\",\"transform\",\"rotate\",\"value\"],\"sources\":[\"/home/runner/work/xaui/xaui/packages/native/dist/chunk-IZYRU7S2.cjs\"],\"mappings\":\"AA4E6E,SAAAA,iBAAMA,CAAA,QAAAC,KAAA,OAAAC,SAAA,CAE/E,MAAO,CAAEC,SAAS,CAAE,CAAC,CAAEC,MAAM,CAAKH,KAAK,CAACI,KAAK,MAAM,CAAC,CAAE,CAAC,CACzD\",\"ignoreList\":[]}"
|
|
113
114
|
};
|
|
114
115
|
function SpinningRing({
|
|
115
116
|
style
|
|
@@ -122,28 +123,28 @@ function SpinningRing({
|
|
|
122
123
|
}), -1, false);
|
|
123
124
|
return () => _reactnativereanimated.cancelAnimation.call(void 0, angle);
|
|
124
125
|
}, [angle]);
|
|
125
|
-
const animatedStyle = _reactnativereanimated.useAnimatedStyle.call(void 0, function
|
|
126
|
-
|
|
126
|
+
const animatedStyle = _reactnativereanimated.useAnimatedStyle.call(void 0, function chunkIZYRU7S2Cjs1Factory({
|
|
127
|
+
_worklet_11467162648159_init_data,
|
|
127
128
|
angle
|
|
128
129
|
}) {
|
|
129
130
|
const _e = [new global.Error(), -2, -27];
|
|
130
|
-
const
|
|
131
|
+
const chunkIZYRU7S2Cjs1 = function () {
|
|
131
132
|
return {
|
|
132
133
|
transform: [{
|
|
133
134
|
rotate: `${angle.value}deg`
|
|
134
135
|
}]
|
|
135
136
|
};
|
|
136
137
|
};
|
|
137
|
-
|
|
138
|
+
chunkIZYRU7S2Cjs1.__closure = {
|
|
138
139
|
angle
|
|
139
140
|
};
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
return
|
|
141
|
+
chunkIZYRU7S2Cjs1.__workletHash = 11467162648159;
|
|
142
|
+
chunkIZYRU7S2Cjs1.__pluginVersion = "0.7.4";
|
|
143
|
+
chunkIZYRU7S2Cjs1.__initData = _worklet_11467162648159_init_data;
|
|
144
|
+
chunkIZYRU7S2Cjs1.__stackDetails = _e;
|
|
145
|
+
return chunkIZYRU7S2Cjs1;
|
|
145
146
|
}({
|
|
146
|
-
|
|
147
|
+
_worklet_11467162648159_init_data,
|
|
147
148
|
angle
|
|
148
149
|
}), [angle]);
|
|
149
150
|
return /* @__PURE__ */_jsxruntime.jsx.call(void 0, _reactnativereanimated2.default.View, {
|
|
@@ -254,7 +255,7 @@ function sizeAxis(step) {
|
|
|
254
255
|
spinner: ring(theme, theme.fontSizes[glyph])
|
|
255
256
|
});
|
|
256
257
|
}
|
|
257
|
-
var buttonRecipe =
|
|
258
|
+
var buttonRecipe = _chunk5SU7FXWHcjs.createRecipe.call(void 0, {
|
|
258
259
|
slots: SLOTS,
|
|
259
260
|
base: theme => ({
|
|
260
261
|
root: {
|
|
@@ -443,7 +444,7 @@ var ButtonRoot = _react.forwardRef.call(void 0, function Button({
|
|
|
443
444
|
...props
|
|
444
445
|
}, ref) {
|
|
445
446
|
const theme = _chunk6N5JXRUZcjs.useXAUITheme.call(void 0);
|
|
446
|
-
const [styleProps, rest] =
|
|
447
|
+
const [styleProps, rest] = _chunk5SU7FXWHcjs.useStyleProps.call(void 0, props);
|
|
447
448
|
const [isPressed, press] = usePressState({
|
|
448
449
|
onPressIn,
|
|
449
450
|
onPressOut
|
|
@@ -487,14 +488,14 @@ var ButtonRoot = _react.forwardRef.call(void 0, function Button({
|
|
|
487
488
|
const rootStyle = [styles.root, _optionalChain([tint, 'optionalAccess', _8 => _8.root]), styleProps, typeof style === "function" ? style({
|
|
488
489
|
pressed: isPressed
|
|
489
490
|
}) : style];
|
|
490
|
-
const text =
|
|
491
|
+
const text = _chunk5SU7FXWHcjs.childrenToString.call(void 0, children);
|
|
491
492
|
const showSpinner = isLoading && !containsElementOfType(children, ButtonSpinner);
|
|
492
493
|
if (isIconOnly && !rest.accessibilityLabel && !rest["aria-label"]) {
|
|
493
494
|
warnDev("Button: an icon-only button needs an `accessibilityLabel` \u2014 there is no text for a screen reader to read, so it announces as an unlabelled button.");
|
|
494
495
|
}
|
|
495
496
|
return /* @__PURE__ */_jsxruntime.jsx.call(void 0, ButtonProvider, {
|
|
496
497
|
value: context,
|
|
497
|
-
children: /* @__PURE__ */_jsxruntime.jsx.call(void 0,
|
|
498
|
+
children: /* @__PURE__ */_jsxruntime.jsx.call(void 0, _chunk2UICXD3Qcjs.PressableFeedback, {
|
|
498
499
|
ref,
|
|
499
500
|
isPressed,
|
|
500
501
|
isDisabled: isDisabled || isLoading,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var _chunk5SU7FXWHcjs = require('./chunk-5SU7FXWH.cjs');
|
|
4
4
|
|
|
5
5
|
// src/system/portal/portal.tsx
|
|
6
6
|
var _react = require('react');
|
|
@@ -31,7 +31,7 @@ var styles = _reactnative.StyleSheet.create({
|
|
|
31
31
|
container: { flex: 1 }
|
|
32
32
|
});
|
|
33
33
|
function PortalHost({ children, ...props }) {
|
|
34
|
-
const [styleProps] =
|
|
34
|
+
const [styleProps] = _chunk5SU7FXWHcjs.useStyleProps.call(void 0, props);
|
|
35
35
|
const [portals, setPortals] = _react.useState.call(void 0, /* @__PURE__ */ new Map());
|
|
36
36
|
const addPortal = _react.useCallback.call(void 0, (key, element) => {
|
|
37
37
|
setPortals((current) => new Map(current).set(key, element));
|
|
@@ -47,6 +47,7 @@ function deriveColors(s) {
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
// src/theme/scales.ts
|
|
50
|
+
import { Platform } from "react-native";
|
|
50
51
|
var SPACING_UNIT = 4;
|
|
51
52
|
var RADIUS_BASE = 12;
|
|
52
53
|
function buildRadius(base) {
|
|
@@ -98,7 +99,10 @@ var fontWeights = {
|
|
|
98
99
|
var fontFamilies = {
|
|
99
100
|
body: "System",
|
|
100
101
|
heading: "System",
|
|
101
|
-
|
|
102
|
+
// `'monospace'` is an Android family name, not a generic one: iOS does not resolve it and
|
|
103
|
+
// silently falls back to the system face, so code set with it is not monospaced there.
|
|
104
|
+
// Menlo is the face iOS ships, and it is what HeroUI Native selects for the same reason.
|
|
105
|
+
mono: Platform.OS === "ios" ? "Menlo" : "monospace"
|
|
102
106
|
};
|
|
103
107
|
var borderWidth = { default: 1, field: 1 };
|
|
104
108
|
var opacity = { disabled: 0.5 };
|
|
@@ -163,7 +167,7 @@ var tokens = {
|
|
|
163
167
|
overlayForeground: "#18181b",
|
|
164
168
|
backdrop: "rgba(0, 0, 0, 0.2)",
|
|
165
169
|
muted: "#71717a",
|
|
166
|
-
default: "#
|
|
170
|
+
default: "#e4e4e7",
|
|
167
171
|
defaultForeground: "#18181b",
|
|
168
172
|
accent: "#9333ea",
|
|
169
173
|
accentForeground: "#faf5ff",
|
|
@@ -187,11 +191,11 @@ var tokens = {
|
|
|
187
191
|
successPressed: "#1b753a",
|
|
188
192
|
warningPressed: "#a34d13",
|
|
189
193
|
dangerPressed: "#c72927",
|
|
190
|
-
defaultPressed: "#
|
|
194
|
+
defaultPressed: "#dbdbde",
|
|
191
195
|
surfacePressed: "#eaeaea",
|
|
192
|
-
defaultSoft: "rgba(
|
|
196
|
+
defaultSoft: "rgba(228, 228, 231, 0.5)",
|
|
193
197
|
defaultSoftForeground: "#18181b",
|
|
194
|
-
defaultSoftPressed: "rgba(
|
|
198
|
+
defaultSoftPressed: "rgba(228, 228, 231, 0.6)",
|
|
195
199
|
accentSoft: "rgba(147, 51, 234, 0.15)",
|
|
196
200
|
accentSoftForeground: "#7833bc",
|
|
197
201
|
accentSoftPressed: "rgba(147, 51, 234, 0.2)",
|
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
var
|
|
6
|
-
require('../../chunk-
|
|
5
|
+
var _chunkIZYRU7S2cjs = require('../../chunk-IZYRU7S2.cjs');
|
|
6
|
+
require('../../chunk-2UICXD3Q.cjs');
|
|
7
|
+
require('../../chunk-5SU7FXWH.cjs');
|
|
7
8
|
require('../../chunk-6N5JXRUZ.cjs');
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
|
|
12
|
-
exports.Button =
|
|
13
|
+
exports.Button = _chunkIZYRU7S2cjs.Button; exports.buttonRecipe = _chunkIZYRU7S2cjs.buttonRecipe; exports.useButton = _chunkIZYRU7S2cjs.useButton;
|
|
@@ -2,8 +2,9 @@ import * as react from 'react';
|
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
3
|
import * as react_native from 'react-native';
|
|
4
4
|
import { StyleProp, TextStyle, ViewStyle, TextProps, PressableStateCallbackType } from 'react-native';
|
|
5
|
-
import {
|
|
6
|
-
import { S as Size, R as RadiusKey,
|
|
5
|
+
import { o as TextStyleProps, V as ViewStyleProps, R as Recipe, g as SlotStyles } from '../../create-recipe-3_ElpCYt.cjs';
|
|
6
|
+
import { S as Size, R as RadiusKey, X as XAUITheme } from '../../theme.type-C2gNHpEx.cjs';
|
|
7
|
+
import { a as IconContextValue, b as IconProps, P as PressableFeedbackProps, c as AnimationProp } from '../../pressable-feedback.type-C9kjAuVQ.cjs';
|
|
7
8
|
import 'react-native-reanimated';
|
|
8
9
|
|
|
9
10
|
type ButtonSlot = 'root' | 'label' | 'icon' | 'spinner';
|
|
@@ -2,8 +2,9 @@ import * as react from 'react';
|
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
3
|
import * as react_native from 'react-native';
|
|
4
4
|
import { StyleProp, TextStyle, ViewStyle, TextProps, PressableStateCallbackType } from 'react-native';
|
|
5
|
-
import {
|
|
6
|
-
import { S as Size, R as RadiusKey,
|
|
5
|
+
import { o as TextStyleProps, V as ViewStyleProps, R as Recipe, g as SlotStyles } from '../../create-recipe-DImq1AZA.js';
|
|
6
|
+
import { S as Size, R as RadiusKey, X as XAUITheme } from '../../theme.type-C2gNHpEx.js';
|
|
7
|
+
import { a as IconContextValue, b as IconProps, P as PressableFeedbackProps, c as AnimationProp } from '../../pressable-feedback.type-KcPvFf6f.js';
|
|
7
8
|
import 'react-native-reanimated';
|
|
8
9
|
|
|
9
10
|
type ButtonSlot = 'root' | 'label' | 'icon' | 'spinner';
|
|
@@ -2,8 +2,9 @@ import {
|
|
|
2
2
|
Button,
|
|
3
3
|
buttonRecipe,
|
|
4
4
|
useButton
|
|
5
|
-
} from "../../chunk-
|
|
6
|
-
import "../../chunk-
|
|
5
|
+
} from "../../chunk-ASXK7XU4.js";
|
|
6
|
+
import "../../chunk-F432IDIW.js";
|
|
7
|
+
import "../../chunk-4K3LZS7M.js";
|
|
7
8
|
import "../../chunk-XJARE6SC.js";
|
|
8
9
|
export {
|
|
9
10
|
Button,
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
var _chunk6VTBGBPPcjs = require('../../chunk-6VTBGBPP.cjs');
|
|
6
|
+
require('../../chunk-5SU7FXWH.cjs');
|
|
7
|
+
require('../../chunk-6N5JXRUZ.cjs');
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
exports.TextSpan = _chunk6VTBGBPPcjs.TextSpan; exports.Typography = _chunk6VTBGBPPcjs.Typography; exports.typographyRecipe = _chunk6VTBGBPPcjs.typographyRecipe;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import * as react_native from 'react-native';
|
|
4
|
+
import { TextProps, StyleProp, TextStyle, Text } from 'react-native';
|
|
5
|
+
import { o as TextStyleProps, R as Recipe } from '../../create-recipe-3_ElpCYt.cjs';
|
|
6
|
+
import { X as XAUITheme } from '../../theme.type-C2gNHpEx.cjs';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The ten roles, aligned with HeroUI Native's `text` — six headings, three body steps and
|
|
10
|
+
* inline code. Each one fixes **size, line height, weight and family together**, which is
|
|
11
|
+
* what removes the separate `size` and `weight` props the legacy component carried, and
|
|
12
|
+
* with them the illegal combinations they allowed: a heading in `weight="light"`, a
|
|
13
|
+
* caption in `lg`.
|
|
14
|
+
*
|
|
15
|
+
* `h1`–`h6` name a level, not an HTML tag — React Native has no document outline, so the
|
|
16
|
+
* number is the step on the scale and nothing more. Announcing a heading to a screen
|
|
17
|
+
* reader stays explicit: `accessibilityRole="header"`.
|
|
18
|
+
*/
|
|
19
|
+
type TypographyVariant = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'body' | 'body-sm' | 'body-xs' | 'code';
|
|
20
|
+
type TypographySlot = 'root';
|
|
21
|
+
type TypographyOwnProps = {
|
|
22
|
+
/** The role. It fixes size, line height, weight and family at once. */
|
|
23
|
+
variant?: TypographyVariant;
|
|
24
|
+
/**
|
|
25
|
+
* A raw tint (`'#7c3aed'`), never a token (R7). In a text component there is only one
|
|
26
|
+
* thing to tint, so it lands on the text itself.
|
|
27
|
+
*/
|
|
28
|
+
color?: string;
|
|
29
|
+
/** R12 — the child element becomes the text node, keeping this variant's style. */
|
|
30
|
+
asChild?: boolean;
|
|
31
|
+
style?: StyleProp<TextStyle>;
|
|
32
|
+
children?: ReactNode;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* R14 — the role's own vocabulary, then every `TextStyle` key it does not already claim.
|
|
36
|
+
* `color` is the component's, so it keeps its R7 meaning here rather than becoming the
|
|
37
|
+
* style key of the same name; `fontSize` and `fontWeight` stay available, which is how a
|
|
38
|
+
* one-off deviation is written without inventing a prop for it.
|
|
39
|
+
*/
|
|
40
|
+
type TypographyProps = Omit<TextProps, 'style'> & TypographyOwnProps & Omit<TextStyleProps, keyof TypographyOwnProps | keyof TextProps>;
|
|
41
|
+
type TextSpanOwnProps = {
|
|
42
|
+
/** R12 — the child element becomes the span. */
|
|
43
|
+
asChild?: boolean;
|
|
44
|
+
style?: StyleProp<TextStyle>;
|
|
45
|
+
children?: ReactNode;
|
|
46
|
+
};
|
|
47
|
+
type TextSpanProps = Omit<TextProps, 'style'> & TextSpanOwnProps & Omit<TextStyleProps, keyof TextSpanOwnProps | keyof TextProps>;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Text, by the role it plays.
|
|
51
|
+
*
|
|
52
|
+
* ```tsx
|
|
53
|
+
* <Typography variant="heading-lg">Projets</Typography>
|
|
54
|
+
* <Typography>Trois en cours, un archivé.</Typography>
|
|
55
|
+
* <Typography variant="caption">Mis à jour il y a deux minutes</Typography>
|
|
56
|
+
* ```
|
|
57
|
+
*
|
|
58
|
+
* **One node, and no slots.** A paragraph is a `Text`; there is nothing inside it for the
|
|
59
|
+
* component to publish. Styling a fragment of it is `TextSpan`'s job, not a slot of this
|
|
60
|
+
* one — React Native already makes a nested `Text` inherit from its parent, so a span
|
|
61
|
+
* needs no context, no resolved style and nothing from here. This component would only be
|
|
62
|
+
* duplicating a mechanism the platform ships.
|
|
63
|
+
*
|
|
64
|
+
* **The role fixes size, line height, weight and family together**, which is why there is
|
|
65
|
+
* no `size` and no `weight` prop: those axes are not free to combine. A one-off deviation
|
|
66
|
+
* is a style prop — `fontSize={17}` — said plainly rather than dressed as vocabulary.
|
|
67
|
+
*
|
|
68
|
+
* Alignment likewise has no prop of its own: `textAlign` is a `TextStyle` key, so R14
|
|
69
|
+
* already exposes it, and the caller writes the value React Native understands instead of
|
|
70
|
+
* a translation layer this component would have to keep honest.
|
|
71
|
+
*/
|
|
72
|
+
declare const Typography: react.ForwardRefExoticComponent<Omit<react_native.TextProps, "style"> & {
|
|
73
|
+
variant?: TypographyVariant;
|
|
74
|
+
color?: string;
|
|
75
|
+
asChild?: boolean;
|
|
76
|
+
style?: react_native.StyleProp<react_native.TextStyle>;
|
|
77
|
+
children?: react.ReactNode;
|
|
78
|
+
} & Omit<TextStyleProps, "color" | "pointerEvents" | "children" | "style" | "id" | "onLayout" | "testID" | "nativeID" | "accessible" | "accessibilityActions" | "accessibilityLabel" | "aria-label" | "accessibilityRole" | "accessibilityState" | "aria-busy" | "aria-checked" | "aria-disabled" | "aria-expanded" | "aria-selected" | "accessibilityHint" | "accessibilityValue" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "onAccessibilityAction" | "importantForAccessibility" | "aria-hidden" | "aria-modal" | "role" | "accessibilityLabelledBy" | "aria-labelledby" | "accessibilityLiveRegion" | "aria-live" | "screenReaderFocusable" | "accessibilityElementsHidden" | "accessibilityViewIsModal" | "onAccessibilityEscape" | "onAccessibilityTap" | "onMagicTap" | "accessibilityIgnoresInvertColors" | "accessibilityLanguage" | "accessibilityShowsLargeContentViewer" | "accessibilityLargeContentTitle" | "accessibilityRespondsToUserInteraction" | "disabled" | "onPress" | "onPressIn" | "onPressOut" | "onLongPress" | "pressRetentionOffset" | "asChild" | "variant" | "allowFontScaling" | "ellipsizeMode" | "lineBreakMode" | "numberOfLines" | "onTextLayout" | "maxFontSizeMultiplier" | "minimumFontScale" | "adjustsFontSizeToFit" | "dynamicTypeRamp" | "suppressHighlighting" | "lineBreakStrategyIOS" | "selectable" | "selectionColor" | "textBreakStrategy" | "dataDetectorType" | "android_hyphenationFrequency"> & react.RefAttributes<Text>>;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* A fragment of text, styled apart from the text around it.
|
|
82
|
+
*
|
|
83
|
+
* ```tsx
|
|
84
|
+
* <Typography>
|
|
85
|
+
* Supprimer <TextSpan fontWeight="600">trois projets</TextSpan> définitivement.
|
|
86
|
+
* </Typography>
|
|
87
|
+
* ```
|
|
88
|
+
*
|
|
89
|
+
* **It is a bare React Native `Text`, and that is the whole design.** Nesting a `Text`
|
|
90
|
+
* inside a `Text` already inherits the parent's font, size, weight and colour on both
|
|
91
|
+
* platforms — so a span needs no context to read, no role to resolve and no provider
|
|
92
|
+
* above it. The legacy component published a `TextSpanContext` to carry that inheritance
|
|
93
|
+
* by hand; it was reimplementing the platform, and it is gone.
|
|
94
|
+
*
|
|
95
|
+
* What is left is R14 and nothing else: every `TextStyle` key as a prop, and `style` after
|
|
96
|
+
* them. There is no `variant` here on purpose — a span that names a role would be a
|
|
97
|
+
* `Typography`, and nesting one of those is how you change role mid-sentence.
|
|
98
|
+
*/
|
|
99
|
+
declare const TextSpan: react.ForwardRefExoticComponent<Omit<react_native.TextProps, "style"> & {
|
|
100
|
+
asChild?: boolean;
|
|
101
|
+
style?: react_native.StyleProp<react_native.TextStyle>;
|
|
102
|
+
children?: react.ReactNode;
|
|
103
|
+
} & Omit<TextStyleProps, "pointerEvents" | "children" | "style" | "id" | "onLayout" | "testID" | "nativeID" | "accessible" | "accessibilityActions" | "accessibilityLabel" | "aria-label" | "accessibilityRole" | "accessibilityState" | "aria-busy" | "aria-checked" | "aria-disabled" | "aria-expanded" | "aria-selected" | "accessibilityHint" | "accessibilityValue" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "onAccessibilityAction" | "importantForAccessibility" | "aria-hidden" | "aria-modal" | "role" | "accessibilityLabelledBy" | "aria-labelledby" | "accessibilityLiveRegion" | "aria-live" | "screenReaderFocusable" | "accessibilityElementsHidden" | "accessibilityViewIsModal" | "onAccessibilityEscape" | "onAccessibilityTap" | "onMagicTap" | "accessibilityIgnoresInvertColors" | "accessibilityLanguage" | "accessibilityShowsLargeContentViewer" | "accessibilityLargeContentTitle" | "accessibilityRespondsToUserInteraction" | "disabled" | "onPress" | "onPressIn" | "onPressOut" | "onLongPress" | "pressRetentionOffset" | "asChild" | "allowFontScaling" | "ellipsizeMode" | "lineBreakMode" | "numberOfLines" | "onTextLayout" | "maxFontSizeMultiplier" | "minimumFontScale" | "adjustsFontSizeToFit" | "dynamicTypeRamp" | "suppressHighlighting" | "lineBreakStrategyIOS" | "selectable" | "selectionColor" | "textBreakStrategy" | "dataDetectorType" | "android_hyphenationFrequency"> & react.RefAttributes<Text>>;
|
|
104
|
+
|
|
105
|
+
/** Every role produces the same one slot, so the recipe's style functions share a shape. */
|
|
106
|
+
type StyleFn = (theme: XAUITheme) => Record<TypographySlot, TextStyle>;
|
|
107
|
+
/**
|
|
108
|
+
* There is no `base`. A text node's defaults are React Native's own, and restating them
|
|
109
|
+
* here would only give them a second place to drift from.
|
|
110
|
+
*/
|
|
111
|
+
declare const typographyRecipe: Recipe<"root", TypographyVariant, {
|
|
112
|
+
readonly variant: Record<TypographyVariant, StyleFn>;
|
|
113
|
+
}>;
|
|
114
|
+
|
|
115
|
+
export { TextSpan, type TextSpanProps, Typography, type TypographyProps, type TypographySlot, type TypographyVariant, typographyRecipe };
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import * as react_native from 'react-native';
|
|
4
|
+
import { TextProps, StyleProp, TextStyle, Text } from 'react-native';
|
|
5
|
+
import { o as TextStyleProps, R as Recipe } from '../../create-recipe-DImq1AZA.js';
|
|
6
|
+
import { X as XAUITheme } from '../../theme.type-C2gNHpEx.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The ten roles, aligned with HeroUI Native's `text` — six headings, three body steps and
|
|
10
|
+
* inline code. Each one fixes **size, line height, weight and family together**, which is
|
|
11
|
+
* what removes the separate `size` and `weight` props the legacy component carried, and
|
|
12
|
+
* with them the illegal combinations they allowed: a heading in `weight="light"`, a
|
|
13
|
+
* caption in `lg`.
|
|
14
|
+
*
|
|
15
|
+
* `h1`–`h6` name a level, not an HTML tag — React Native has no document outline, so the
|
|
16
|
+
* number is the step on the scale and nothing more. Announcing a heading to a screen
|
|
17
|
+
* reader stays explicit: `accessibilityRole="header"`.
|
|
18
|
+
*/
|
|
19
|
+
type TypographyVariant = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'body' | 'body-sm' | 'body-xs' | 'code';
|
|
20
|
+
type TypographySlot = 'root';
|
|
21
|
+
type TypographyOwnProps = {
|
|
22
|
+
/** The role. It fixes size, line height, weight and family at once. */
|
|
23
|
+
variant?: TypographyVariant;
|
|
24
|
+
/**
|
|
25
|
+
* A raw tint (`'#7c3aed'`), never a token (R7). In a text component there is only one
|
|
26
|
+
* thing to tint, so it lands on the text itself.
|
|
27
|
+
*/
|
|
28
|
+
color?: string;
|
|
29
|
+
/** R12 — the child element becomes the text node, keeping this variant's style. */
|
|
30
|
+
asChild?: boolean;
|
|
31
|
+
style?: StyleProp<TextStyle>;
|
|
32
|
+
children?: ReactNode;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* R14 — the role's own vocabulary, then every `TextStyle` key it does not already claim.
|
|
36
|
+
* `color` is the component's, so it keeps its R7 meaning here rather than becoming the
|
|
37
|
+
* style key of the same name; `fontSize` and `fontWeight` stay available, which is how a
|
|
38
|
+
* one-off deviation is written without inventing a prop for it.
|
|
39
|
+
*/
|
|
40
|
+
type TypographyProps = Omit<TextProps, 'style'> & TypographyOwnProps & Omit<TextStyleProps, keyof TypographyOwnProps | keyof TextProps>;
|
|
41
|
+
type TextSpanOwnProps = {
|
|
42
|
+
/** R12 — the child element becomes the span. */
|
|
43
|
+
asChild?: boolean;
|
|
44
|
+
style?: StyleProp<TextStyle>;
|
|
45
|
+
children?: ReactNode;
|
|
46
|
+
};
|
|
47
|
+
type TextSpanProps = Omit<TextProps, 'style'> & TextSpanOwnProps & Omit<TextStyleProps, keyof TextSpanOwnProps | keyof TextProps>;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Text, by the role it plays.
|
|
51
|
+
*
|
|
52
|
+
* ```tsx
|
|
53
|
+
* <Typography variant="heading-lg">Projets</Typography>
|
|
54
|
+
* <Typography>Trois en cours, un archivé.</Typography>
|
|
55
|
+
* <Typography variant="caption">Mis à jour il y a deux minutes</Typography>
|
|
56
|
+
* ```
|
|
57
|
+
*
|
|
58
|
+
* **One node, and no slots.** A paragraph is a `Text`; there is nothing inside it for the
|
|
59
|
+
* component to publish. Styling a fragment of it is `TextSpan`'s job, not a slot of this
|
|
60
|
+
* one — React Native already makes a nested `Text` inherit from its parent, so a span
|
|
61
|
+
* needs no context, no resolved style and nothing from here. This component would only be
|
|
62
|
+
* duplicating a mechanism the platform ships.
|
|
63
|
+
*
|
|
64
|
+
* **The role fixes size, line height, weight and family together**, which is why there is
|
|
65
|
+
* no `size` and no `weight` prop: those axes are not free to combine. A one-off deviation
|
|
66
|
+
* is a style prop — `fontSize={17}` — said plainly rather than dressed as vocabulary.
|
|
67
|
+
*
|
|
68
|
+
* Alignment likewise has no prop of its own: `textAlign` is a `TextStyle` key, so R14
|
|
69
|
+
* already exposes it, and the caller writes the value React Native understands instead of
|
|
70
|
+
* a translation layer this component would have to keep honest.
|
|
71
|
+
*/
|
|
72
|
+
declare const Typography: react.ForwardRefExoticComponent<Omit<react_native.TextProps, "style"> & {
|
|
73
|
+
variant?: TypographyVariant;
|
|
74
|
+
color?: string;
|
|
75
|
+
asChild?: boolean;
|
|
76
|
+
style?: react_native.StyleProp<react_native.TextStyle>;
|
|
77
|
+
children?: react.ReactNode;
|
|
78
|
+
} & Omit<TextStyleProps, "color" | "pointerEvents" | "children" | "style" | "id" | "onLayout" | "testID" | "nativeID" | "accessible" | "accessibilityActions" | "accessibilityLabel" | "aria-label" | "accessibilityRole" | "accessibilityState" | "aria-busy" | "aria-checked" | "aria-disabled" | "aria-expanded" | "aria-selected" | "accessibilityHint" | "accessibilityValue" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "onAccessibilityAction" | "importantForAccessibility" | "aria-hidden" | "aria-modal" | "role" | "accessibilityLabelledBy" | "aria-labelledby" | "accessibilityLiveRegion" | "aria-live" | "screenReaderFocusable" | "accessibilityElementsHidden" | "accessibilityViewIsModal" | "onAccessibilityEscape" | "onAccessibilityTap" | "onMagicTap" | "accessibilityIgnoresInvertColors" | "accessibilityLanguage" | "accessibilityShowsLargeContentViewer" | "accessibilityLargeContentTitle" | "accessibilityRespondsToUserInteraction" | "disabled" | "onPress" | "onPressIn" | "onPressOut" | "onLongPress" | "pressRetentionOffset" | "asChild" | "variant" | "allowFontScaling" | "ellipsizeMode" | "lineBreakMode" | "numberOfLines" | "onTextLayout" | "maxFontSizeMultiplier" | "minimumFontScale" | "adjustsFontSizeToFit" | "dynamicTypeRamp" | "suppressHighlighting" | "lineBreakStrategyIOS" | "selectable" | "selectionColor" | "textBreakStrategy" | "dataDetectorType" | "android_hyphenationFrequency"> & react.RefAttributes<Text>>;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* A fragment of text, styled apart from the text around it.
|
|
82
|
+
*
|
|
83
|
+
* ```tsx
|
|
84
|
+
* <Typography>
|
|
85
|
+
* Supprimer <TextSpan fontWeight="600">trois projets</TextSpan> définitivement.
|
|
86
|
+
* </Typography>
|
|
87
|
+
* ```
|
|
88
|
+
*
|
|
89
|
+
* **It is a bare React Native `Text`, and that is the whole design.** Nesting a `Text`
|
|
90
|
+
* inside a `Text` already inherits the parent's font, size, weight and colour on both
|
|
91
|
+
* platforms — so a span needs no context to read, no role to resolve and no provider
|
|
92
|
+
* above it. The legacy component published a `TextSpanContext` to carry that inheritance
|
|
93
|
+
* by hand; it was reimplementing the platform, and it is gone.
|
|
94
|
+
*
|
|
95
|
+
* What is left is R14 and nothing else: every `TextStyle` key as a prop, and `style` after
|
|
96
|
+
* them. There is no `variant` here on purpose — a span that names a role would be a
|
|
97
|
+
* `Typography`, and nesting one of those is how you change role mid-sentence.
|
|
98
|
+
*/
|
|
99
|
+
declare const TextSpan: react.ForwardRefExoticComponent<Omit<react_native.TextProps, "style"> & {
|
|
100
|
+
asChild?: boolean;
|
|
101
|
+
style?: react_native.StyleProp<react_native.TextStyle>;
|
|
102
|
+
children?: react.ReactNode;
|
|
103
|
+
} & Omit<TextStyleProps, "pointerEvents" | "children" | "style" | "id" | "onLayout" | "testID" | "nativeID" | "accessible" | "accessibilityActions" | "accessibilityLabel" | "aria-label" | "accessibilityRole" | "accessibilityState" | "aria-busy" | "aria-checked" | "aria-disabled" | "aria-expanded" | "aria-selected" | "accessibilityHint" | "accessibilityValue" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "onAccessibilityAction" | "importantForAccessibility" | "aria-hidden" | "aria-modal" | "role" | "accessibilityLabelledBy" | "aria-labelledby" | "accessibilityLiveRegion" | "aria-live" | "screenReaderFocusable" | "accessibilityElementsHidden" | "accessibilityViewIsModal" | "onAccessibilityEscape" | "onAccessibilityTap" | "onMagicTap" | "accessibilityIgnoresInvertColors" | "accessibilityLanguage" | "accessibilityShowsLargeContentViewer" | "accessibilityLargeContentTitle" | "accessibilityRespondsToUserInteraction" | "disabled" | "onPress" | "onPressIn" | "onPressOut" | "onLongPress" | "pressRetentionOffset" | "asChild" | "allowFontScaling" | "ellipsizeMode" | "lineBreakMode" | "numberOfLines" | "onTextLayout" | "maxFontSizeMultiplier" | "minimumFontScale" | "adjustsFontSizeToFit" | "dynamicTypeRamp" | "suppressHighlighting" | "lineBreakStrategyIOS" | "selectable" | "selectionColor" | "textBreakStrategy" | "dataDetectorType" | "android_hyphenationFrequency"> & react.RefAttributes<Text>>;
|
|
104
|
+
|
|
105
|
+
/** Every role produces the same one slot, so the recipe's style functions share a shape. */
|
|
106
|
+
type StyleFn = (theme: XAUITheme) => Record<TypographySlot, TextStyle>;
|
|
107
|
+
/**
|
|
108
|
+
* There is no `base`. A text node's defaults are React Native's own, and restating them
|
|
109
|
+
* here would only give them a second place to drift from.
|
|
110
|
+
*/
|
|
111
|
+
declare const typographyRecipe: Recipe<"root", TypographyVariant, {
|
|
112
|
+
readonly variant: Record<TypographyVariant, StyleFn>;
|
|
113
|
+
}>;
|
|
114
|
+
|
|
115
|
+
export { TextSpan, type TextSpanProps, Typography, type TypographyProps, type TypographySlot, type TypographyVariant, typographyRecipe };
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { ImageStyle, TextStyle, ViewStyle } from 'react-native';
|
|
2
|
+
import { X as XAUITheme, a as XAUIColors } from './theme.type-C2gNHpEx.cjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* R13 — React Native mirrors a layout under RTL through the Start/End properties and only
|
|
6
|
+
* those. A props API is exactly where someone writes `paddingLeft` without thinking, so
|
|
7
|
+
* the type removes the temptation instead of leaving it to a review.
|
|
8
|
+
*/
|
|
9
|
+
type DirectionalStyleKey = 'left' | 'right' | 'paddingLeft' | 'paddingRight' | 'marginLeft' | 'marginRight' | 'borderLeftWidth' | 'borderRightWidth' | 'borderLeftColor' | 'borderRightColor' | 'borderTopLeftRadius' | 'borderTopRightRadius' | 'borderBottomLeftRadius' | 'borderBottomRightRadius';
|
|
10
|
+
/**
|
|
11
|
+
* `pointerEvents` is a style key *and* a `View` prop. R14 says the component's own prop
|
|
12
|
+
* wins, so it stays the prop it has always been and is not exposed twice — the one name
|
|
13
|
+
* where the two vocabularies collide.
|
|
14
|
+
*/
|
|
15
|
+
type ComponentOwnedStyleKey = 'pointerEvents';
|
|
16
|
+
/**
|
|
17
|
+
* The style keys of a node, exposed as props (R14). Not a maintained list: it derives
|
|
18
|
+
* from the React Native type, minus what R13 forbids.
|
|
19
|
+
*
|
|
20
|
+
* ```ts
|
|
21
|
+
* type CardProps = ViewStyleProps & { variant?: CardVariant }
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
type StyleProps<Style> = Omit<Style, DirectionalStyleKey | ComponentOwnedStyleKey>;
|
|
25
|
+
/** A root, or any slot that renders a view. */
|
|
26
|
+
type ViewStyleProps = StyleProps<ViewStyle>;
|
|
27
|
+
/** A text slot — `color`, `fontSize`, `letterSpacing`… */
|
|
28
|
+
type TextStyleProps = StyleProps<TextStyle>;
|
|
29
|
+
/** An image slot — `resizeMode`, `tintColor`… */
|
|
30
|
+
type ImageStyleProps = StyleProps<ImageStyle>;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* A slot is a view or a text node, and a recipe writes one object per slot, so the two
|
|
34
|
+
* RN style shapes are merged rather than discriminated per slot.
|
|
35
|
+
*/
|
|
36
|
+
type SlotStyle = ViewStyle & TextStyle;
|
|
37
|
+
type SlotStyles<Slot extends string> = Partial<Record<Slot, SlotStyle>>;
|
|
38
|
+
/** The roles a variant consumes. The variant names tokens; `paint` says where they land. */
|
|
39
|
+
type VariantRole = 'bg' | 'bgPressed' | 'fg' | 'border';
|
|
40
|
+
/** Token names per role — no colour value ever appears in a recipe. */
|
|
41
|
+
type VariantTokens = Partial<Record<VariantRole, keyof XAUIColors>>;
|
|
42
|
+
/** The same roles resolved: theme colours, or the slices of a raw `color`. */
|
|
43
|
+
type VariantColors = Partial<Record<VariantRole, string>>;
|
|
44
|
+
/**
|
|
45
|
+
* `disabled` is applied last of the three: a control that is both pressed and disabled
|
|
46
|
+
* has to read disabled.
|
|
47
|
+
*/
|
|
48
|
+
type StateName = 'focused' | 'pressed' | 'disabled';
|
|
49
|
+
type States = Partial<Record<StateName, boolean>>;
|
|
50
|
+
/** Reads the theme and the variant's resolved colours; returns one style per slot. */
|
|
51
|
+
type StyleFn<Slot extends string> = (theme: XAUITheme, colors: VariantColors) => SlotStyles<Slot>;
|
|
52
|
+
/** Named axes of finite token values — `{ size: { sm: fn, md: fn } }`. */
|
|
53
|
+
type Axes<Slot extends string> = Record<string, Record<string, StyleFn<Slot>>>;
|
|
54
|
+
/** One value per axis, plus the variant. Missing keys fall back to `defaultVariants`. */
|
|
55
|
+
type Selection<Variant extends string, A extends Axes<string>> = {
|
|
56
|
+
variant?: Variant;
|
|
57
|
+
} & {
|
|
58
|
+
[Axis in keyof A]?: Extract<keyof A[Axis], string>;
|
|
59
|
+
};
|
|
60
|
+
type CompoundVariant<Slot extends string, Variant extends string, A extends Axes<Slot>> = {
|
|
61
|
+
when: Selection<Variant, A>;
|
|
62
|
+
style: StyleFn<Slot>;
|
|
63
|
+
};
|
|
64
|
+
type RecipeConfig<Slot extends string, Variant extends string, A extends Axes<Slot>> = {
|
|
65
|
+
/** Every slot the component publishes. Slots a recipe never styles resolve to `{}`. */
|
|
66
|
+
slots: readonly Slot[];
|
|
67
|
+
base?: StyleFn<Slot>;
|
|
68
|
+
variantTokens?: Record<Variant, VariantTokens>;
|
|
69
|
+
/** Where the variant's colours land — written once, and it holds for every variant. */
|
|
70
|
+
paint?: StyleFn<Slot>;
|
|
71
|
+
variants?: A;
|
|
72
|
+
compoundVariants?: ReadonlyArray<CompoundVariant<Slot, Variant, A>>;
|
|
73
|
+
states?: Partial<Record<StateName, StyleFn<Slot>>>;
|
|
74
|
+
/**
|
|
75
|
+
* `NoInfer`, because this is the one place a single variant name appears on its own:
|
|
76
|
+
* without it, inference reads `Variant` off `{ variant: 'primary' }` and narrows the
|
|
77
|
+
* whole recipe to that one value, so every other variant becomes a type error at the
|
|
78
|
+
* call site. `variantTokens` is the declaration; this only picks a default from it.
|
|
79
|
+
*/
|
|
80
|
+
defaultVariants?: Selection<NoInfer<Variant>, A>;
|
|
81
|
+
};
|
|
82
|
+
/** Stable references: the same object for the same tokens, for the app's lifetime. */
|
|
83
|
+
type ResolvedStyles<Slot extends string> = Readonly<Record<Slot, SlotStyle>>;
|
|
84
|
+
/** A selection with `defaultVariants` already folded in, keyed by axis name. */
|
|
85
|
+
type ResolvedSelection = Readonly<Record<string, string | undefined>>;
|
|
86
|
+
|
|
87
|
+
type ResolveArgs<Variant extends string, A extends Axes<string>> = {
|
|
88
|
+
theme: XAUITheme;
|
|
89
|
+
selection?: Selection<Variant, A>;
|
|
90
|
+
states?: States;
|
|
91
|
+
};
|
|
92
|
+
type TintArgs<Variant extends string, A extends Axes<string>> = ResolveArgs<Variant, A> & {
|
|
93
|
+
color: string;
|
|
94
|
+
};
|
|
95
|
+
type Recipe<Slot extends string, Variant extends string, A extends Axes<Slot>> = {
|
|
96
|
+
readonly slots: readonly Slot[];
|
|
97
|
+
/** The cached pass: stable `StyleSheet` references, keyed by tokens alone. */
|
|
98
|
+
resolve(args: ResolveArgs<Variant, A>): ResolvedStyles<Slot>;
|
|
99
|
+
/**
|
|
100
|
+
* The tint pass: the same functions run again with `color`'s slices in place of the
|
|
101
|
+
* theme's tokens. Uncached and allocating, and only ever called when `color` is set.
|
|
102
|
+
*/
|
|
103
|
+
tint(args: TintArgs<Variant, A>): SlotStyles<Slot>;
|
|
104
|
+
};
|
|
105
|
+
/**
|
|
106
|
+
* A component's style, declared once. Resolution splits in two because the two halves
|
|
107
|
+
* have different lifetimes: everything keyed by a finite token is cached forever, and
|
|
108
|
+
* an arbitrary `color` is recomputed per render — which is what keeps the cache bounded
|
|
109
|
+
* by the number of token combinations rather than by the palette users invent.
|
|
110
|
+
*
|
|
111
|
+
* const styles = buttonRecipe.resolve({ theme, selection: { variant, size }, states })
|
|
112
|
+
* const tint = color ? buttonRecipe.tint({ theme, color, selection, states }) : undefined
|
|
113
|
+
* <View style={[styles.root, tint?.root, style]} />
|
|
114
|
+
*/
|
|
115
|
+
declare function createRecipe<Slot extends string, Variant extends string, const A extends Axes<Slot>>(config: RecipeConfig<Slot, Variant, A>): Recipe<Slot, Variant, A>;
|
|
116
|
+
|
|
117
|
+
export { type Axes as A, type CompoundVariant as C, type DirectionalStyleKey as D, type ImageStyleProps as I, type Recipe as R, type Selection as S, type TintArgs as T, type ViewStyleProps as V, type ResolveArgs as a, type RecipeConfig as b, createRecipe as c, type ResolvedSelection as d, type ResolvedStyles as e, type SlotStyle as f, type SlotStyles as g, type StateName as h, type States as i, type StyleFn as j, type VariantColors as k, type VariantRole as l, type VariantTokens as m, type StyleProps as n, type TextStyleProps as o };
|