@unif/react-native-design 0.17.0 → 0.19.0
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/lib/module/components/ui/Chip/Chip.js +26 -6
- package/lib/module/components/ui/Chip/Chip.js.map +1 -1
- package/lib/module/theme/ThemeProvider.js +5 -3
- package/lib/module/theme/ThemeProvider.js.map +1 -1
- package/lib/module/theme/useTheme.js +2 -1
- package/lib/module/theme/useTheme.js.map +1 -1
- package/lib/module/theme/useThemedStyles.js +48 -6
- package/lib/module/theme/useThemedStyles.js.map +1 -1
- package/lib/typescript/src/components/ui/Chip/Chip.d.ts +2 -1
- package/lib/typescript/src/components/ui/Chip/Chip.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Chip/types.d.ts +4 -0
- package/lib/typescript/src/components/ui/Chip/types.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Input/Input.d.ts +3 -3
- package/lib/typescript/src/components/ui/Search/Search.d.ts +3 -3
- package/lib/typescript/src/components/ui/TextField/TextFieldBase.d.ts +3 -3
- package/lib/typescript/src/components/ui/Textarea/Textarea.d.ts +3 -3
- package/lib/typescript/src/theme/ThemeProvider.d.ts +7 -1
- package/lib/typescript/src/theme/ThemeProvider.d.ts.map +1 -1
- package/lib/typescript/src/theme/useTheme.d.ts.map +1 -1
- package/lib/typescript/src/theme/useThemedStyles.d.ts +10 -4
- package/lib/typescript/src/theme/useThemedStyles.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/ui/Chip/Chip.tsx +45 -5
- package/src/components/ui/Chip/types.ts +4 -0
- package/src/theme/ThemeProvider.tsx +13 -2
- package/src/theme/useTheme.ts +1 -0
- package/src/theme/useThemedStyles.ts +56 -6
|
@@ -3,15 +3,23 @@
|
|
|
3
3
|
import React from 'react';
|
|
4
4
|
import { Text, View } from 'react-native';
|
|
5
5
|
import { Pressable } from 'react-native-gesture-handler';
|
|
6
|
-
import { fixed, pressedOpacity, r, rf, useThemedStyles } from "../../../theme/index.js";
|
|
6
|
+
import { fixed, pressedOpacity, r, rf, useColors, useThemedStyles } from "../../../theme/index.js";
|
|
7
|
+
import { Spinner } from "../Spinner/index.js";
|
|
7
8
|
import { makeStyles } from "./styles.js";
|
|
8
9
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
10
|
+
/** 处理中 chip 的透明度 —— 比 disabled(0.5)亮、比按下(pressedOpacity)暗:
|
|
11
|
+
* 「正在办」既要压下去,又不能和「不能点」长一样(那两者只靠 spinner 区分就太弱了)。 */
|
|
12
|
+
const busyOpacity = 0.6;
|
|
13
|
+
/** busy spinner 直径 —— 与调用方常用的 leading icon(12)等大,顶替时不改 chip 宽度。 */
|
|
14
|
+
const busySpinner = r(12);
|
|
15
|
+
|
|
9
16
|
/**
|
|
10
17
|
* 胶囊形可点击 chip。
|
|
11
18
|
* - 默认:surface 底 + outline 细线边框,foreground 文本
|
|
12
19
|
* - 选中:主色边框 + 主色文本
|
|
13
20
|
* - 按下:透明度 pressedOpacity(与 ButtonBase 同源)
|
|
14
21
|
* - 禁用:透明度 0.5 + 不响应 onPress
|
|
22
|
+
* - 处理中(`busy`):leading 换 spinner + 透明度 0.6 + 不响应二次点击
|
|
15
23
|
*
|
|
16
24
|
* 常用于建议 chip、筛选 pill、多选标签等。
|
|
17
25
|
*/
|
|
@@ -20,17 +28,26 @@ export function Chip({
|
|
|
20
28
|
selected,
|
|
21
29
|
onPress,
|
|
22
30
|
disabled,
|
|
31
|
+
busy,
|
|
23
32
|
leading,
|
|
24
33
|
trailing,
|
|
25
34
|
style,
|
|
26
35
|
testID
|
|
27
36
|
}) {
|
|
37
|
+
const c = useColors();
|
|
28
38
|
const styles = useThemedStyles(makeStyles);
|
|
39
|
+
// 处理中把 spinner 放进 leading 位(有 leading 就顶掉它):label 必须留着 —— 换掉它 chip
|
|
40
|
+
// 会塌成一个圆点,同排 chip 集体重排。spinner 跟随文本色,不在未选中的 chip 上凭空冒主色。
|
|
41
|
+
const lead = busy ? /*#__PURE__*/_jsx(Spinner, {
|
|
42
|
+
size: busySpinner,
|
|
43
|
+
thickness: r(1.5),
|
|
44
|
+
color: selected ? c.primary : c.foreground
|
|
45
|
+
}) : leading;
|
|
29
46
|
const inner = /*#__PURE__*/_jsxs(View, {
|
|
30
47
|
style: [styles.chip, selected && styles.chipOn, style],
|
|
31
48
|
testID: onPress ? undefined : testID,
|
|
32
|
-
children: [
|
|
33
|
-
children:
|
|
49
|
+
children: [lead != null ? /*#__PURE__*/_jsx(View, {
|
|
50
|
+
children: lead
|
|
34
51
|
}) : null, /*#__PURE__*/_jsx(Text, {
|
|
35
52
|
style: [styles.text, selected && styles.textOn],
|
|
36
53
|
numberOfLines: 1,
|
|
@@ -43,13 +60,16 @@ export function Chip({
|
|
|
43
60
|
// [M-7] chip 内容高 ≈ 2×space[3] + xs 行高 ≈ 34pt < 44pt
|
|
44
61
|
// Pressable 是外壳,hitSlop 向外补足到 fixed.hitTarget
|
|
45
62
|
const chipHitSlopV = Math.max(0, Math.round((fixed.hitTarget - (2 * r(8) + rf(13) * 1.4)) / 2));
|
|
63
|
+
// 处理中同样不响应:chip 的高频用法是「点一下发起一次请求」,放行二次点击就是重复提交。
|
|
64
|
+
const inactive = !!disabled || !!busy;
|
|
46
65
|
return /*#__PURE__*/_jsx(Pressable, {
|
|
47
66
|
onPress: onPress,
|
|
48
|
-
disabled:
|
|
67
|
+
disabled: inactive,
|
|
49
68
|
accessibilityRole: "button",
|
|
50
69
|
accessibilityState: {
|
|
51
70
|
selected: !!selected,
|
|
52
|
-
disabled:
|
|
71
|
+
disabled: inactive,
|
|
72
|
+
busy: !!busy
|
|
53
73
|
},
|
|
54
74
|
accessibilityLabel: label,
|
|
55
75
|
testID: testID,
|
|
@@ -63,7 +83,7 @@ export function Chip({
|
|
|
63
83
|
pressed
|
|
64
84
|
}) => [{
|
|
65
85
|
alignSelf: 'flex-start',
|
|
66
|
-
opacity: disabled ? 0.5 : pressed ? pressedOpacity : 1
|
|
86
|
+
opacity: disabled ? 0.5 : busy ? busyOpacity : pressed ? pressedOpacity : 1
|
|
67
87
|
}],
|
|
68
88
|
children: inner
|
|
69
89
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","Text","View","Pressable","fixed","pressedOpacity","r","rf","useThemedStyles","makeStyles","jsx","_jsx","jsxs","_jsxs","Chip","label","selected","onPress","disabled","leading","trailing","style","testID","styles","inner","chip","chipOn","undefined","children","text","textOn","numberOfLines","chipHitSlopV","Math","max","round","hitTarget","accessibilityRole","accessibilityState","accessibilityLabel","hitSlop","top","bottom","left","right","pressed","alignSelf","opacity"],"sourceRoot":"../../../../../src","sources":["components/ui/Chip/Chip.tsx"],"mappings":";;AAAA,OAAOA,KAAK,MAAM,OAAO;AACzB,SAASC,IAAI,EAAEC,IAAI,QAAQ,cAAc;AACzC,SAASC,SAAS,QAAQ,8BAA8B;AACxD,
|
|
1
|
+
{"version":3,"names":["React","Text","View","Pressable","fixed","pressedOpacity","r","rf","useColors","useThemedStyles","Spinner","makeStyles","jsx","_jsx","jsxs","_jsxs","busyOpacity","busySpinner","Chip","label","selected","onPress","disabled","busy","leading","trailing","style","testID","c","styles","lead","size","thickness","color","primary","foreground","inner","chip","chipOn","undefined","children","text","textOn","numberOfLines","chipHitSlopV","Math","max","round","hitTarget","inactive","accessibilityRole","accessibilityState","accessibilityLabel","hitSlop","top","bottom","left","right","pressed","alignSelf","opacity"],"sourceRoot":"../../../../../src","sources":["components/ui/Chip/Chip.tsx"],"mappings":";;AAAA,OAAOA,KAAK,MAAM,OAAO;AACzB,SAASC,IAAI,EAAEC,IAAI,QAAQ,cAAc;AACzC,SAASC,SAAS,QAAQ,8BAA8B;AACxD,SACEC,KAAK,EACLC,cAAc,EACdC,CAAC,EACDC,EAAE,EACFC,SAAS,EACTC,eAAe,QACV,yBAAgB;AACvB,SAASC,OAAO,QAAQ,qBAAY;AACpC,SAASC,UAAU,QAAQ,aAAU;AAAC,SAAAC,GAAA,IAAAC,IAAA,EAAAC,IAAA,IAAAC,KAAA;AAGtC;AACA;AACA,MAAMC,WAAW,GAAG,GAAG;AACvB;AACA,MAAMC,WAAW,GAAGX,CAAC,CAAC,EAAE,CAAC;;AAEzB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASY,IAAIA,CAAC;EACnBC,KAAK;EACLC,QAAQ;EACRC,OAAO;EACPC,QAAQ;EACRC,IAAI;EACJC,OAAO;EACPC,QAAQ;EACRC,KAAK;EACLC;AACS,CAAC,EAAqB;EAC/B,MAAMC,CAAC,GAAGpB,SAAS,CAAC,CAAC;EACrB,MAAMqB,MAAM,GAAGpB,eAAe,CAACE,UAAU,CAAC;EAC1C;EACA;EACA,MAAMmB,IAAI,GAAGP,IAAI,gBACfV,IAAA,CAACH,OAAO;IACNqB,IAAI,EAAEd,WAAY;IAClBe,SAAS,EAAE1B,CAAC,CAAC,GAAG,CAAE;IAClB2B,KAAK,EAAEb,QAAQ,GAAGQ,CAAC,CAACM,OAAO,GAAGN,CAAC,CAACO;EAAW,CAC5C,CAAC,GAEFX,OACD;EACD,MAAMY,KAAK,gBACTrB,KAAA,CAACb,IAAI;IACHwB,KAAK,EAAE,CAACG,MAAM,CAACQ,IAAI,EAAEjB,QAAQ,IAAIS,MAAM,CAACS,MAAM,EAAEZ,KAAK,CAAE;IACvDC,MAAM,EAAEN,OAAO,GAAGkB,SAAS,GAAGZ,MAAO;IAAAa,QAAA,GAEpCV,IAAI,IAAI,IAAI,gBAAGjB,IAAA,CAACX,IAAI;MAAAsC,QAAA,EAAEV;IAAI,CAAO,CAAC,GAAG,IAAI,eAC1CjB,IAAA,CAACZ,IAAI;MAACyB,KAAK,EAAE,CAACG,MAAM,CAACY,IAAI,EAAErB,QAAQ,IAAIS,MAAM,CAACa,MAAM,CAAE;MAACC,aAAa,EAAE,CAAE;MAAAH,QAAA,EACrErB;IAAK,CACF,CAAC,EACNM,QAAQ,IAAI,IAAI,gBAAGZ,IAAA,CAACX,IAAI;MAAAsC,QAAA,EAAEf;IAAQ,CAAO,CAAC,GAAG,IAAI;EAAA,CAC9C,CACP;EAED,IAAIJ,OAAO,EAAE;IACX;IACA;IACA,MAAMuB,YAAY,GAAGC,IAAI,CAACC,GAAG,CAC3B,CAAC,EACDD,IAAI,CAACE,KAAK,CAAC,CAAC3C,KAAK,CAAC4C,SAAS,IAAI,CAAC,GAAG1C,CAAC,CAAC,CAAC,CAAC,GAAGC,EAAE,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,CAC9D,CAAC;IACD;IACA,MAAM0C,QAAQ,GAAG,CAAC,CAAC3B,QAAQ,IAAI,CAAC,CAACC,IAAI;IACrC,oBACEV,IAAA,CAACV,SAAS;MACRkB,OAAO,EAAEA,OAAQ;MACjBC,QAAQ,EAAE2B,QAAS;MACnBC,iBAAiB,EAAC,QAAQ;MAC1BC,kBAAkB,EAAE;QAClB/B,QAAQ,EAAE,CAAC,CAACA,QAAQ;QACpBE,QAAQ,EAAE2B,QAAQ;QAClB1B,IAAI,EAAE,CAAC,CAACA;MACV,CAAE;MACF6B,kBAAkB,EAAEjC,KAAM;MAC1BQ,MAAM,EAAEA,MAAO;MACf0B,OAAO,EAAE;QAAEC,GAAG,EAAEV,YAAY;QAAEW,MAAM,EAAEX,YAAY;QAAEY,IAAI,EAAE,CAAC;QAAEC,KAAK,EAAE;MAAE,CAAE;MACxE/B,KAAK,EAAEA,CAAC;QAAEgC;MAAQ,CAAC,KAAK,CACtB;QACEC,SAAS,EAAE,YAAY;QACvBC,OAAO,EAAEtC,QAAQ,GACb,GAAG,GACHC,IAAI,GACFP,WAAW,GACX0C,OAAO,GACLrD,cAAc,GACd;MACV,CAAC,CACD;MAAAmC,QAAA,EAEDJ;IAAK,CACG,CAAC;EAEhB;EACA,OAAOA,KAAK;AACd","ignoreList":[]}
|
|
@@ -8,7 +8,8 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
8
8
|
export const ThemeContext = /*#__PURE__*/createContext(null);
|
|
9
9
|
export function ThemeProvider({
|
|
10
10
|
children,
|
|
11
|
-
forceScheme
|
|
11
|
+
forceScheme,
|
|
12
|
+
fontScale = 1
|
|
12
13
|
}) {
|
|
13
14
|
const sysScheme = useColorScheme();
|
|
14
15
|
const scheme = forceScheme ?? (sysScheme === 'dark' ? 'dark' : 'light');
|
|
@@ -18,8 +19,9 @@ export function ThemeProvider({
|
|
|
18
19
|
const value = useMemo(() => ({
|
|
19
20
|
scheme,
|
|
20
21
|
colors: scheme === 'dark' ? darkColors : lightColors,
|
|
21
|
-
shadow: scheme === 'dark' ? darkShadow : lightShadow
|
|
22
|
-
|
|
22
|
+
shadow: scheme === 'dark' ? darkShadow : lightShadow,
|
|
23
|
+
fontScale
|
|
24
|
+
}), [scheme, fontScale]);
|
|
23
25
|
return /*#__PURE__*/_jsx(ThemeContext.Provider, {
|
|
24
26
|
value: value,
|
|
25
27
|
children: children
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","createContext","useMemo","useColorScheme","lightColors","darkColors","lightShadow","darkShadow","jsx","_jsx","ThemeContext","ThemeProvider","children","forceScheme","sysScheme","scheme","value","colors","shadow","Provider"],"sourceRoot":"../../../src","sources":["theme/ThemeProvider.tsx"],"mappings":";;AAAA,OAAOA,KAAK,IAAIC,aAAa,EAAEC,OAAO,QAAQ,OAAO;AACrD,SAASC,cAAc,QAAQ,cAAc;AAC7C,SAASC,WAAW,EAAEC,UAAU,QAA0B,aAAU;AACpE,SAASC,WAAW,EAAEC,UAAU,QAA2B,aAAU;AAAC,SAAAC,GAAA,IAAAC,IAAA;
|
|
1
|
+
{"version":3,"names":["React","createContext","useMemo","useColorScheme","lightColors","darkColors","lightShadow","darkShadow","jsx","_jsx","ThemeContext","ThemeProvider","children","forceScheme","fontScale","sysScheme","scheme","value","colors","shadow","Provider"],"sourceRoot":"../../../src","sources":["theme/ThemeProvider.tsx"],"mappings":";;AAAA,OAAOA,KAAK,IAAIC,aAAa,EAAEC,OAAO,QAAQ,OAAO;AACrD,SAASC,cAAc,QAAQ,cAAc;AAC7C,SAASC,WAAW,EAAEC,UAAU,QAA0B,aAAU;AACpE,SAASC,WAAW,EAAEC,UAAU,QAA2B,aAAU;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAatE,OAAO,MAAMC,YAAY,gBAAGT,aAAa,CAA2B,IAAI,CAAC;AAWzE,OAAO,SAASU,aAAaA,CAAC;EAC5BC,QAAQ;EACRC,WAAW;EACXC,SAAS,GAAG;AACM,CAAC,EAAE;EACrB,MAAMC,SAAS,GAAGZ,cAAc,CAAC,CAAC;EAClC,MAAMa,MAAmB,GACvBH,WAAW,KAAKE,SAAS,KAAK,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;;EAE1D;EACA;EACA,MAAME,KAAK,GAAGf,OAAO,CACnB,OAAO;IACLc,MAAM;IACNE,MAAM,EAAEF,MAAM,KAAK,MAAM,GAAGX,UAAU,GAAGD,WAAW;IACpDe,MAAM,EAAEH,MAAM,KAAK,MAAM,GAAGT,UAAU,GAAGD,WAAW;IACpDQ;EACF,CAAC,CAAC,EACF,CAACE,MAAM,EAAEF,SAAS,CACpB,CAAC;EAED,oBACEL,IAAA,CAACC,YAAY,CAACU,QAAQ;IAACH,KAAK,EAAEA,KAAM;IAAAL,QAAA,EAAEA;EAAQ,CAAwB,CAAC;AAE3E","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["useContext","ThemeContext","lightColors","lightShadow","FALLBACK","scheme","colors","shadow","_warnedMissingProvider","useTheme","ctx","undefined","__DEV__","console","warn","useColors","useShadow"],"sourceRoot":"../../../src","sources":["theme/useTheme.ts"],"mappings":";;AAAA,SAASA,UAAU,QAAQ,OAAO;AAClC,SAASC,YAAY,QAAgC,oBAAiB;AACtE,SAASC,WAAW,QAAQ,aAAU;AACtC,SAASC,WAAW,QAAQ,aAAU;AAEtC,MAAMC,QAA2B,GAAG;EAClCC,MAAM,EAAE,OAAO;EACfC,MAAM,EAAEJ,WAAW;EACnBK,MAAM,EAAEJ;
|
|
1
|
+
{"version":3,"names":["useContext","ThemeContext","lightColors","lightShadow","FALLBACK","scheme","colors","shadow","fontScale","_warnedMissingProvider","useTheme","ctx","undefined","__DEV__","console","warn","useColors","useShadow"],"sourceRoot":"../../../src","sources":["theme/useTheme.ts"],"mappings":";;AAAA,SAASA,UAAU,QAAQ,OAAO;AAClC,SAASC,YAAY,QAAgC,oBAAiB;AACtE,SAASC,WAAW,QAAQ,aAAU;AACtC,SAASC,WAAW,QAAQ,aAAU;AAEtC,MAAMC,QAA2B,GAAG;EAClCC,MAAM,EAAE,OAAO;EACfC,MAAM,EAAEJ,WAAW;EACnBK,MAAM,EAAEJ,WAAW;EACnBK,SAAS,EAAE;AACb,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA,IAAIC,sBAAsB,GAAG,KAAK;AAElC,OAAO,SAASC,QAAQA,CAAA,EAAsB;EAC5C,MAAMC,GAAG,GAAGX,UAAU,CAACC,YAAY,CAAC;EACpC,IAAIU,GAAG,KAAKC,SAAS,IAAI,CAACH,sBAAsB,EAAE;IAChDA,sBAAsB,GAAG,IAAI;IAC7B,IAAI,OAAOI,OAAO,KAAK,WAAW,IAAIA,OAAO,EAAE;MAC7CC,OAAO,CAACC,IAAI,CACV,mFACF,CAAC;IACH;EACF;EACA,OAAOJ,GAAG,IAAIP,QAAQ;AACxB;AAEA,OAAO,SAASY,SAASA,CAAA,EAAG;EAC1B,OAAON,QAAQ,CAAC,CAAC,CAACJ,MAAM;AAC1B;AAEA,OAAO,SAASW,SAASA,CAAA,EAAG;EAC1B,OAAOP,QAAQ,CAAC,CAAC,CAACH,MAAM;AAC1B","ignoreList":[]}
|
|
@@ -6,18 +6,60 @@ import { useTheme } from "./useTheme.js";
|
|
|
6
6
|
/** RN 0.85 strict-api 不再导出 `StyleSheet.NamedStyles`,这里本地保留同名约束:
|
|
7
7
|
* `{ [k]: ViewStyle | TextStyle | ImageStyle }` —— 给 maker 返回值兜底。 */
|
|
8
8
|
|
|
9
|
+
/** 应用级字号缩放只作用于文字三属性 —— 与 RN allowFontScaling 的原生缩放
|
|
10
|
+
* 范围一致(只缩文字,不缩 padding / 高度等布局尺寸)。无字号系属性的
|
|
11
|
+
* style 返回原引用。strict-api 下 TextStyle 只读,用条件展开构造新对象。 */
|
|
12
|
+
function scaleTextStyle(style, factor) {
|
|
13
|
+
const {
|
|
14
|
+
fontSize,
|
|
15
|
+
lineHeight,
|
|
16
|
+
letterSpacing
|
|
17
|
+
} = style;
|
|
18
|
+
if (typeof fontSize !== 'number' && typeof lineHeight !== 'number' && typeof letterSpacing !== 'number') {
|
|
19
|
+
return style;
|
|
20
|
+
}
|
|
21
|
+
return {
|
|
22
|
+
...style,
|
|
23
|
+
...(typeof fontSize === 'number' ? {
|
|
24
|
+
fontSize: fontSize * factor
|
|
25
|
+
} : null),
|
|
26
|
+
...(typeof lineHeight === 'number' ? {
|
|
27
|
+
lineHeight: lineHeight * factor
|
|
28
|
+
} : null),
|
|
29
|
+
...(typeof letterSpacing === 'number' ? {
|
|
30
|
+
letterSpacing: letterSpacing * factor
|
|
31
|
+
} : null)
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** maker 产物按 fontScale 缩放字号系属性。factor = 1 时恒等返回**原引用**——
|
|
36
|
+
* 未接入 fontScale 的消费方(web 文档站等)行为与引用完全不变。
|
|
37
|
+
* 导出仅供单测,不进 barrel。 */
|
|
38
|
+
export function scaleNamedStyles(styles, factor) {
|
|
39
|
+
if (factor === 1) return styles;
|
|
40
|
+
const out = {};
|
|
41
|
+
for (const [key, style] of Object.entries(styles)) {
|
|
42
|
+
// ViewStyle / ImageStyle 无字号三属性,按 TextStyle 探测后恒等返回原引用。
|
|
43
|
+
out[key] = style && typeof style === 'object' ? scaleTextStyle(style, factor) : style;
|
|
44
|
+
}
|
|
45
|
+
return out;
|
|
46
|
+
}
|
|
47
|
+
|
|
9
48
|
/**
|
|
10
|
-
* 接收 (colors, shadow) => StyleSheet 工厂,返回当前主题对应的 themed StyleSheet
|
|
49
|
+
* 接收 (colors, shadow) => StyleSheet 工厂,返回当前主题对应的 themed StyleSheet,
|
|
50
|
+
* 并按 ThemeProvider 的 fontScale 缩放字号系属性(fontSize / lineHeight /
|
|
51
|
+
* letterSpacing;fontScale = 1 时恒等)。
|
|
11
52
|
*
|
|
12
|
-
* 缓存依赖 [colors, shadow, maker]。`maker` 必须定义在模块顶层
|
|
13
|
-
*
|
|
14
|
-
* colors / shadow 引用稳定。
|
|
53
|
+
* 缓存依赖 [colors, shadow, fontScale, maker]。`maker` 必须定义在模块顶层
|
|
54
|
+
* (不要写在组件内联),否则引用每次变,缓存失效。ThemeProvider 通过
|
|
55
|
+
* useMemo([scheme, fontScale]) 保证主题不变时 colors / shadow 引用稳定。
|
|
15
56
|
*/
|
|
16
57
|
export function useThemedStyles(maker) {
|
|
17
58
|
const {
|
|
18
59
|
colors,
|
|
19
|
-
shadow
|
|
60
|
+
shadow,
|
|
61
|
+
fontScale
|
|
20
62
|
} = useTheme();
|
|
21
|
-
return useMemo(() => maker(colors, shadow), [colors, shadow, maker]);
|
|
63
|
+
return useMemo(() => scaleNamedStyles(maker(colors, shadow), fontScale), [colors, shadow, fontScale, maker]);
|
|
22
64
|
}
|
|
23
65
|
//# sourceMappingURL=useThemedStyles.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["useMemo","useTheme","useThemedStyles","maker","colors","shadow"],"sourceRoot":"../../../src","sources":["theme/useThemedStyles.ts"],"mappings":";;AAAA,SAASA,OAAO,QAAQ,OAAO;AAI/B,SAASC,QAAQ,QAAQ,eAAY;;AAErC;AACA;;AAQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,
|
|
1
|
+
{"version":3,"names":["useMemo","useTheme","scaleTextStyle","style","factor","fontSize","lineHeight","letterSpacing","scaleNamedStyles","styles","out","key","Object","entries","useThemedStyles","maker","colors","shadow","fontScale"],"sourceRoot":"../../../src","sources":["theme/useThemedStyles.ts"],"mappings":";;AAAA,SAASA,OAAO,QAAQ,OAAO;AAI/B,SAASC,QAAQ,QAAQ,eAAY;;AAErC;AACA;;AAQA;AACA;AACA;AACA,SAASC,cAAcA,CAACC,KAAgB,EAAEC,MAAc,EAAa;EACnE,MAAM;IAAEC,QAAQ;IAAEC,UAAU;IAAEC;EAAc,CAAC,GAAGJ,KAAK;EACrD,IACE,OAAOE,QAAQ,KAAK,QAAQ,IAC5B,OAAOC,UAAU,KAAK,QAAQ,IAC9B,OAAOC,aAAa,KAAK,QAAQ,EACjC;IACA,OAAOJ,KAAK;EACd;EACA,OAAO;IACL,GAAGA,KAAK;IACR,IAAI,OAAOE,QAAQ,KAAK,QAAQ,GAAG;MAAEA,QAAQ,EAAEA,QAAQ,GAAGD;IAAO,CAAC,GAAG,IAAI,CAAC;IAC1E,IAAI,OAAOE,UAAU,KAAK,QAAQ,GAC9B;MAAEA,UAAU,EAAEA,UAAU,GAAGF;IAAO,CAAC,GACnC,IAAI,CAAC;IACT,IAAI,OAAOG,aAAa,KAAK,QAAQ,GACjC;MAAEA,aAAa,EAAEA,aAAa,GAAGH;IAAO,CAAC,GACzC,IAAI;EACV,CAAC;AACH;;AAEA;AACA;AACA;AACA,OAAO,SAASI,gBAAgBA,CAC9BC,MAAS,EACTL,MAAc,EACX;EACH,IAAIA,MAAM,KAAK,CAAC,EAAE,OAAOK,MAAM;EAC/B,MAAMC,GAAuD,GAAG,CAAC,CAAC;EAClE,KAAK,MAAM,CAACC,GAAG,EAAER,KAAK,CAAC,IAAIS,MAAM,CAACC,OAAO,CACvCJ,MACF,CAAC,EAAE;IACD;IACAC,GAAG,CAACC,GAAG,CAAC,GACNR,KAAK,IAAI,OAAOA,KAAK,KAAK,QAAQ,GAC9BD,cAAc,CAACC,KAAK,EAAeC,MAAM,CAAC,GAC1CD,KAAK;EACb;EACA,OAAOO,GAAG;AACZ;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASI,eAAeA,CAC7BC,KAAqB,EAClB;EACH,MAAM;IAAEC,MAAM;IAAEC,MAAM;IAAEC;EAAU,CAAC,GAAGjB,QAAQ,CAAC,CAAC;EAChD,OAAOD,OAAO,CACZ,MAAMQ,gBAAgB,CAACO,KAAK,CAACC,MAAM,EAAEC,MAAM,CAAC,EAAEC,SAAS,CAAC,EACxD,CAACF,MAAM,EAAEC,MAAM,EAAEC,SAAS,EAAEH,KAAK,CACnC,CAAC;AACH","ignoreList":[]}
|
|
@@ -6,8 +6,9 @@ import type { ChipProps } from './types';
|
|
|
6
6
|
* - 选中:主色边框 + 主色文本
|
|
7
7
|
* - 按下:透明度 pressedOpacity(与 ButtonBase 同源)
|
|
8
8
|
* - 禁用:透明度 0.5 + 不响应 onPress
|
|
9
|
+
* - 处理中(`busy`):leading 换 spinner + 透明度 0.6 + 不响应二次点击
|
|
9
10
|
*
|
|
10
11
|
* 常用于建议 chip、筛选 pill、多选标签等。
|
|
11
12
|
*/
|
|
12
|
-
export declare function Chip({ label, selected, onPress, disabled, leading, trailing, style, testID, }: ChipProps): React.JSX.Element;
|
|
13
|
+
export declare function Chip({ label, selected, onPress, disabled, busy, leading, trailing, style, testID, }: ChipProps): React.JSX.Element;
|
|
13
14
|
//# sourceMappingURL=Chip.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Chip.d.ts","sourceRoot":"","sources":["../../../../../../src/components/ui/Chip/Chip.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"Chip.d.ts","sourceRoot":"","sources":["../../../../../../src/components/ui/Chip/Chip.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAa1B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAQzC;;;;;;;;;GASG;AACH,wBAAgB,IAAI,CAAC,EACnB,KAAK,EACL,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,IAAI,EACJ,OAAO,EACP,QAAQ,EACR,KAAK,EACL,MAAM,GACP,EAAE,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAmE/B"}
|
|
@@ -6,6 +6,10 @@ export type ChipProps = {
|
|
|
6
6
|
onPress?: () => void;
|
|
7
7
|
/** 整体禁用:opacity 0.5 + 不响应 onPress + accessibilityState.disabled */
|
|
8
8
|
disabled?: boolean;
|
|
9
|
+
/** 处理中(点了、请求在飞):leading 位换 spinner + opacity 0.6 + 不响应二次点击 +
|
|
10
|
+
* accessibilityState.busy。label 保留 —— 换掉它 chip 会塌成一个圆点、整行跟着重排。
|
|
11
|
+
* 与 `disabled` 的分工:disabled = 现在不能点(更暗、无 spinner),busy = 正在办。 */
|
|
12
|
+
busy?: boolean;
|
|
9
13
|
/** 可选的前置插槽 —— 如 <Icon name="spark" /> */
|
|
10
14
|
leading?: ReactNode;
|
|
11
15
|
/** 可选的后置插槽 —— 如一个小的 × 关闭按钮 */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../../src/components/ui/Chip/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzD,MAAM,MAAM,SAAS,GAAG;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,mEAAmE;IACnE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,yCAAyC;IACzC,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,8BAA8B;IAC9B,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,iBAAiB;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../../src/components/ui/Chip/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzD,MAAM,MAAM,SAAS,GAAG;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,mEAAmE;IACnE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;sEAEkE;IAClE,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,yCAAyC;IACzC,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,8BAA8B;IAC9B,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,iBAAiB;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC"}
|
|
@@ -136,7 +136,7 @@ export declare const Input: import("react").ForwardRefExoticComponent<Omit<Reado
|
|
|
136
136
|
pointerEvents?: ("auto" | "box-none" | "box-only" | "none") | undefined;
|
|
137
137
|
removeClippedSubviews?: boolean | undefined;
|
|
138
138
|
experimental_accessibilityOrder?: Array<string> | undefined;
|
|
139
|
-
}>, never>>, "style" | "experimental_accessibilityOrder">, "value" | "textAlign" | "
|
|
139
|
+
}>, never>>, "style" | "experimental_accessibilityOrder">, "value" | "textAlign" | "style" | "onChange" | "onBlur" | "onFocus" | "onPress" | "lineBreakStrategyIOS" | "selectionColor" | "textBreakStrategy" | "allowFontScaling" | "maxFontSizeMultiplier" | "numberOfLines" | "onPressIn" | "onPressOut" | "disableKeyboardShortcuts" | "clearButtonMode" | "clearTextOnFocus" | "dataDetectorTypes" | "enablesReturnKeyAutomatically" | "inputAccessoryViewID" | "inputAccessoryViewButtonLabel" | "keyboardAppearance" | "passwordRules" | "rejectResponderTermination" | "scrollEnabled" | "spellCheck" | "textContentType" | "lineBreakModeIOS" | "smartInsertDelete" | "cursorColor" | "selectionHandleColor" | "disableFullscreenUI" | "importantForAutofill" | "inlineImageLeft" | "inlineImagePadding" | "returnKeyLabel" | "rows" | "showSoftInputOnFocus" | "underlineColorAndroid" | "experimental_acceptDragAndDropTypes" | "autoCapitalize" | "autoComplete" | "autoCorrect" | "autoFocus" | "caretHidden" | "contextMenuHidden" | "defaultValue" | "editable" | "forwardedRef" | "enterKeyHint" | "inputMode" | "keyboardType" | "maxLength" | "multiline" | "onChangeText" | "onContentSizeChange" | "onEndEditing" | "onKeyPress" | "onSelectionChange" | "onSubmitEditing" | "onScroll" | "placeholder" | "placeholderTextColor" | "readOnly" | "returnKeyType" | "secureTextEntry" | "selection" | "selectTextOnFocus" | "blurOnSubmit" | "submitBehavior"> & Omit<Readonly<{
|
|
140
140
|
disableKeyboardShortcuts?: boolean | undefined;
|
|
141
141
|
clearButtonMode?: ("never" | "while-editing" | "unless-editing" | "always") | undefined;
|
|
142
142
|
clearTextOnFocus?: boolean | undefined;
|
|
@@ -153,7 +153,7 @@ export declare const Input: import("react").ForwardRefExoticComponent<Omit<Reado
|
|
|
153
153
|
lineBreakStrategyIOS?: ("none" | "standard" | "hangul-word" | "push-out") | undefined;
|
|
154
154
|
lineBreakModeIOS?: ("wordWrapping" | "char" | "clip" | "head" | "middle" | "tail") | undefined;
|
|
155
155
|
smartInsertDelete?: boolean | undefined;
|
|
156
|
-
}>, "value" | "textAlign" | "
|
|
156
|
+
}>, "value" | "textAlign" | "style" | "onChange" | "onBlur" | "onFocus" | "onPress" | "selectionColor" | "textBreakStrategy" | "allowFontScaling" | "maxFontSizeMultiplier" | "numberOfLines" | "onPressIn" | "onPressOut" | "cursorColor" | "selectionHandleColor" | "disableFullscreenUI" | "importantForAutofill" | "inlineImageLeft" | "inlineImagePadding" | "returnKeyLabel" | "rows" | "showSoftInputOnFocus" | "underlineColorAndroid" | "experimental_acceptDragAndDropTypes" | "autoCapitalize" | "autoComplete" | "autoCorrect" | "autoFocus" | "caretHidden" | "contextMenuHidden" | "defaultValue" | "editable" | "forwardedRef" | "enterKeyHint" | "inputMode" | "keyboardType" | "maxLength" | "multiline" | "onChangeText" | "onContentSizeChange" | "onEndEditing" | "onKeyPress" | "onSelectionChange" | "onSubmitEditing" | "onScroll" | "placeholder" | "placeholderTextColor" | "readOnly" | "returnKeyType" | "secureTextEntry" | "selection" | "selectTextOnFocus" | "blurOnSubmit" | "submitBehavior"> & Omit<Readonly<{
|
|
157
157
|
cursorColor?: import("react-native").ColorValue | undefined;
|
|
158
158
|
selectionHandleColor?: import("react-native").ColorValue | undefined;
|
|
159
159
|
disableFullscreenUI?: boolean | undefined;
|
|
@@ -166,7 +166,7 @@ export declare const Input: import("react").ForwardRefExoticComponent<Omit<Reado
|
|
|
166
166
|
showSoftInputOnFocus?: boolean | undefined;
|
|
167
167
|
textBreakStrategy?: ("simple" | "highQuality" | "balanced") | undefined;
|
|
168
168
|
underlineColorAndroid?: import("react-native").ColorValue | undefined;
|
|
169
|
-
}>, "value" | "textAlign" | "
|
|
169
|
+
}>, "value" | "textAlign" | "style" | "onChange" | "onBlur" | "onFocus" | "onPress" | "selectionColor" | "allowFontScaling" | "maxFontSizeMultiplier" | "onPressIn" | "onPressOut" | "experimental_acceptDragAndDropTypes" | "autoCapitalize" | "autoComplete" | "autoCorrect" | "autoFocus" | "caretHidden" | "contextMenuHidden" | "defaultValue" | "editable" | "forwardedRef" | "enterKeyHint" | "inputMode" | "keyboardType" | "maxLength" | "multiline" | "onChangeText" | "onContentSizeChange" | "onEndEditing" | "onKeyPress" | "onSelectionChange" | "onSubmitEditing" | "onScroll" | "placeholder" | "placeholderTextColor" | "readOnly" | "returnKeyType" | "secureTextEntry" | "selection" | "selectTextOnFocus" | "blurOnSubmit" | "submitBehavior"> & Omit<Readonly<{
|
|
170
170
|
experimental_acceptDragAndDropTypes?: ReadonlyArray<string> | undefined;
|
|
171
171
|
autoCapitalize?: import("react-native").AutoCapitalize | undefined;
|
|
172
172
|
autoComplete?: ("additional-name" | "address-line1" | "address-line2" | "birthdate-day" | "birthdate-full" | "birthdate-month" | "birthdate-year" | "cc-csc" | "cc-exp" | "cc-exp-day" | "cc-exp-month" | "cc-exp-year" | "cc-number" | "cc-name" | "cc-given-name" | "cc-middle-name" | "cc-family-name" | "cc-type" | "country" | "current-password" | "email" | "family-name" | "gender" | "given-name" | "honorific-prefix" | "honorific-suffix" | "name" | "name-family" | "name-given" | "name-middle" | "name-middle-initial" | "name-prefix" | "name-suffix" | "new-password" | "nickname" | "one-time-code" | "organization" | "organization-title" | "password" | "password-new" | "postal-address" | "postal-address-country" | "postal-address-extended" | "postal-address-extended-postal-code" | "postal-address-locality" | "postal-address-region" | "postal-code" | "street-address" | "sms-otp" | "tel" | "tel-country-code" | "tel-national" | "tel-device" | "url" | "username" | "username-new" | "off") | undefined;
|
|
@@ -133,7 +133,7 @@ export declare const Search: React.ForwardRefExoticComponent<Omit<Readonly<Omit<
|
|
|
133
133
|
pointerEvents?: ("auto" | "box-none" | "box-only" | "none") | undefined;
|
|
134
134
|
removeClippedSubviews?: boolean | undefined;
|
|
135
135
|
experimental_accessibilityOrder?: Array<string> | undefined;
|
|
136
|
-
}>, never>>, "style" | "experimental_accessibilityOrder">, "value" | "textAlign" | "
|
|
136
|
+
}>, never>>, "style" | "experimental_accessibilityOrder">, "value" | "textAlign" | "style" | "onChange" | "onBlur" | "onFocus" | "onPress" | "lineBreakStrategyIOS" | "selectionColor" | "textBreakStrategy" | "allowFontScaling" | "maxFontSizeMultiplier" | "numberOfLines" | "onPressIn" | "onPressOut" | "disableKeyboardShortcuts" | "clearButtonMode" | "clearTextOnFocus" | "dataDetectorTypes" | "enablesReturnKeyAutomatically" | "inputAccessoryViewID" | "inputAccessoryViewButtonLabel" | "keyboardAppearance" | "passwordRules" | "rejectResponderTermination" | "scrollEnabled" | "spellCheck" | "textContentType" | "lineBreakModeIOS" | "smartInsertDelete" | "cursorColor" | "selectionHandleColor" | "disableFullscreenUI" | "importantForAutofill" | "inlineImageLeft" | "inlineImagePadding" | "returnKeyLabel" | "rows" | "showSoftInputOnFocus" | "underlineColorAndroid" | "experimental_acceptDragAndDropTypes" | "autoCapitalize" | "autoComplete" | "autoCorrect" | "autoFocus" | "caretHidden" | "contextMenuHidden" | "defaultValue" | "editable" | "forwardedRef" | "enterKeyHint" | "inputMode" | "keyboardType" | "maxLength" | "multiline" | "onChangeText" | "onContentSizeChange" | "onEndEditing" | "onKeyPress" | "onSelectionChange" | "onSubmitEditing" | "onScroll" | "placeholder" | "placeholderTextColor" | "readOnly" | "returnKeyType" | "secureTextEntry" | "selection" | "selectTextOnFocus" | "blurOnSubmit" | "submitBehavior"> & Omit<Readonly<{
|
|
137
137
|
disableKeyboardShortcuts?: boolean | undefined;
|
|
138
138
|
clearButtonMode?: ("never" | "while-editing" | "unless-editing" | "always") | undefined;
|
|
139
139
|
clearTextOnFocus?: boolean | undefined;
|
|
@@ -150,7 +150,7 @@ export declare const Search: React.ForwardRefExoticComponent<Omit<Readonly<Omit<
|
|
|
150
150
|
lineBreakStrategyIOS?: ("none" | "standard" | "hangul-word" | "push-out") | undefined;
|
|
151
151
|
lineBreakModeIOS?: ("wordWrapping" | "char" | "clip" | "head" | "middle" | "tail") | undefined;
|
|
152
152
|
smartInsertDelete?: boolean | undefined;
|
|
153
|
-
}>, "value" | "textAlign" | "
|
|
153
|
+
}>, "value" | "textAlign" | "style" | "onChange" | "onBlur" | "onFocus" | "onPress" | "selectionColor" | "textBreakStrategy" | "allowFontScaling" | "maxFontSizeMultiplier" | "numberOfLines" | "onPressIn" | "onPressOut" | "cursorColor" | "selectionHandleColor" | "disableFullscreenUI" | "importantForAutofill" | "inlineImageLeft" | "inlineImagePadding" | "returnKeyLabel" | "rows" | "showSoftInputOnFocus" | "underlineColorAndroid" | "experimental_acceptDragAndDropTypes" | "autoCapitalize" | "autoComplete" | "autoCorrect" | "autoFocus" | "caretHidden" | "contextMenuHidden" | "defaultValue" | "editable" | "forwardedRef" | "enterKeyHint" | "inputMode" | "keyboardType" | "maxLength" | "multiline" | "onChangeText" | "onContentSizeChange" | "onEndEditing" | "onKeyPress" | "onSelectionChange" | "onSubmitEditing" | "onScroll" | "placeholder" | "placeholderTextColor" | "readOnly" | "returnKeyType" | "secureTextEntry" | "selection" | "selectTextOnFocus" | "blurOnSubmit" | "submitBehavior"> & Omit<Readonly<{
|
|
154
154
|
cursorColor?: import("react-native").ColorValue | undefined;
|
|
155
155
|
selectionHandleColor?: import("react-native").ColorValue | undefined;
|
|
156
156
|
disableFullscreenUI?: boolean | undefined;
|
|
@@ -163,7 +163,7 @@ export declare const Search: React.ForwardRefExoticComponent<Omit<Readonly<Omit<
|
|
|
163
163
|
showSoftInputOnFocus?: boolean | undefined;
|
|
164
164
|
textBreakStrategy?: ("simple" | "highQuality" | "balanced") | undefined;
|
|
165
165
|
underlineColorAndroid?: import("react-native").ColorValue | undefined;
|
|
166
|
-
}>, "value" | "textAlign" | "
|
|
166
|
+
}>, "value" | "textAlign" | "style" | "onChange" | "onBlur" | "onFocus" | "onPress" | "selectionColor" | "allowFontScaling" | "maxFontSizeMultiplier" | "onPressIn" | "onPressOut" | "experimental_acceptDragAndDropTypes" | "autoCapitalize" | "autoComplete" | "autoCorrect" | "autoFocus" | "caretHidden" | "contextMenuHidden" | "defaultValue" | "editable" | "forwardedRef" | "enterKeyHint" | "inputMode" | "keyboardType" | "maxLength" | "multiline" | "onChangeText" | "onContentSizeChange" | "onEndEditing" | "onKeyPress" | "onSelectionChange" | "onSubmitEditing" | "onScroll" | "placeholder" | "placeholderTextColor" | "readOnly" | "returnKeyType" | "secureTextEntry" | "selection" | "selectTextOnFocus" | "blurOnSubmit" | "submitBehavior"> & Omit<Readonly<{
|
|
167
167
|
experimental_acceptDragAndDropTypes?: ReadonlyArray<string> | undefined;
|
|
168
168
|
autoCapitalize?: import("react-native").AutoCapitalize | undefined;
|
|
169
169
|
autoComplete?: ("additional-name" | "address-line1" | "address-line2" | "birthdate-day" | "birthdate-full" | "birthdate-month" | "birthdate-year" | "cc-csc" | "cc-exp" | "cc-exp-day" | "cc-exp-month" | "cc-exp-year" | "cc-number" | "cc-name" | "cc-given-name" | "cc-middle-name" | "cc-family-name" | "cc-type" | "country" | "current-password" | "email" | "family-name" | "gender" | "given-name" | "honorific-prefix" | "honorific-suffix" | "name" | "name-family" | "name-given" | "name-middle" | "name-middle-initial" | "name-prefix" | "name-suffix" | "new-password" | "nickname" | "one-time-code" | "organization" | "organization-title" | "password" | "password-new" | "postal-address" | "postal-address-country" | "postal-address-extended" | "postal-address-extended-postal-code" | "postal-address-locality" | "postal-address-region" | "postal-code" | "street-address" | "sms-otp" | "tel" | "tel-country-code" | "tel-national" | "tel-device" | "url" | "username" | "username-new" | "off") | undefined;
|
|
@@ -144,7 +144,7 @@ export declare const TextFieldBase: React.ForwardRefExoticComponent<Readonly<Omi
|
|
|
144
144
|
pointerEvents?: ("auto" | "box-none" | "box-only" | "none") | undefined;
|
|
145
145
|
removeClippedSubviews?: boolean | undefined;
|
|
146
146
|
experimental_accessibilityOrder?: Array<string> | undefined;
|
|
147
|
-
}>, never>>, "style" | "experimental_accessibilityOrder">, "value" | "textAlign" | "
|
|
147
|
+
}>, never>>, "style" | "experimental_accessibilityOrder">, "value" | "textAlign" | "style" | "onChange" | "onBlur" | "onFocus" | "onPress" | "lineBreakStrategyIOS" | "selectionColor" | "textBreakStrategy" | "allowFontScaling" | "maxFontSizeMultiplier" | "numberOfLines" | "onPressIn" | "onPressOut" | "disableKeyboardShortcuts" | "clearButtonMode" | "clearTextOnFocus" | "dataDetectorTypes" | "enablesReturnKeyAutomatically" | "inputAccessoryViewID" | "inputAccessoryViewButtonLabel" | "keyboardAppearance" | "passwordRules" | "rejectResponderTermination" | "scrollEnabled" | "spellCheck" | "textContentType" | "lineBreakModeIOS" | "smartInsertDelete" | "cursorColor" | "selectionHandleColor" | "disableFullscreenUI" | "importantForAutofill" | "inlineImageLeft" | "inlineImagePadding" | "returnKeyLabel" | "rows" | "showSoftInputOnFocus" | "underlineColorAndroid" | "experimental_acceptDragAndDropTypes" | "autoCapitalize" | "autoComplete" | "autoCorrect" | "autoFocus" | "caretHidden" | "contextMenuHidden" | "defaultValue" | "editable" | "forwardedRef" | "enterKeyHint" | "inputMode" | "keyboardType" | "maxLength" | "multiline" | "onChangeText" | "onContentSizeChange" | "onEndEditing" | "onKeyPress" | "onSelectionChange" | "onSubmitEditing" | "onScroll" | "placeholder" | "placeholderTextColor" | "readOnly" | "returnKeyType" | "secureTextEntry" | "selection" | "selectTextOnFocus" | "blurOnSubmit" | "submitBehavior"> & Omit<Readonly<{
|
|
148
148
|
disableKeyboardShortcuts?: boolean | undefined;
|
|
149
149
|
clearButtonMode?: ("never" | "while-editing" | "unless-editing" | "always") | undefined;
|
|
150
150
|
clearTextOnFocus?: boolean | undefined;
|
|
@@ -161,7 +161,7 @@ export declare const TextFieldBase: React.ForwardRefExoticComponent<Readonly<Omi
|
|
|
161
161
|
lineBreakStrategyIOS?: ("none" | "standard" | "hangul-word" | "push-out") | undefined;
|
|
162
162
|
lineBreakModeIOS?: ("wordWrapping" | "char" | "clip" | "head" | "middle" | "tail") | undefined;
|
|
163
163
|
smartInsertDelete?: boolean | undefined;
|
|
164
|
-
}>, "value" | "textAlign" | "
|
|
164
|
+
}>, "value" | "textAlign" | "style" | "onChange" | "onBlur" | "onFocus" | "onPress" | "selectionColor" | "textBreakStrategy" | "allowFontScaling" | "maxFontSizeMultiplier" | "numberOfLines" | "onPressIn" | "onPressOut" | "cursorColor" | "selectionHandleColor" | "disableFullscreenUI" | "importantForAutofill" | "inlineImageLeft" | "inlineImagePadding" | "returnKeyLabel" | "rows" | "showSoftInputOnFocus" | "underlineColorAndroid" | "experimental_acceptDragAndDropTypes" | "autoCapitalize" | "autoComplete" | "autoCorrect" | "autoFocus" | "caretHidden" | "contextMenuHidden" | "defaultValue" | "editable" | "forwardedRef" | "enterKeyHint" | "inputMode" | "keyboardType" | "maxLength" | "multiline" | "onChangeText" | "onContentSizeChange" | "onEndEditing" | "onKeyPress" | "onSelectionChange" | "onSubmitEditing" | "onScroll" | "placeholder" | "placeholderTextColor" | "readOnly" | "returnKeyType" | "secureTextEntry" | "selection" | "selectTextOnFocus" | "blurOnSubmit" | "submitBehavior"> & Omit<Readonly<{
|
|
165
165
|
cursorColor?: import("react-native").ColorValue | undefined;
|
|
166
166
|
selectionHandleColor?: import("react-native").ColorValue | undefined;
|
|
167
167
|
disableFullscreenUI?: boolean | undefined;
|
|
@@ -174,7 +174,7 @@ export declare const TextFieldBase: React.ForwardRefExoticComponent<Readonly<Omi
|
|
|
174
174
|
showSoftInputOnFocus?: boolean | undefined;
|
|
175
175
|
textBreakStrategy?: ("simple" | "highQuality" | "balanced") | undefined;
|
|
176
176
|
underlineColorAndroid?: import("react-native").ColorValue | undefined;
|
|
177
|
-
}>, "value" | "textAlign" | "
|
|
177
|
+
}>, "value" | "textAlign" | "style" | "onChange" | "onBlur" | "onFocus" | "onPress" | "selectionColor" | "allowFontScaling" | "maxFontSizeMultiplier" | "onPressIn" | "onPressOut" | "experimental_acceptDragAndDropTypes" | "autoCapitalize" | "autoComplete" | "autoCorrect" | "autoFocus" | "caretHidden" | "contextMenuHidden" | "defaultValue" | "editable" | "forwardedRef" | "enterKeyHint" | "inputMode" | "keyboardType" | "maxLength" | "multiline" | "onChangeText" | "onContentSizeChange" | "onEndEditing" | "onKeyPress" | "onSelectionChange" | "onSubmitEditing" | "onScroll" | "placeholder" | "placeholderTextColor" | "readOnly" | "returnKeyType" | "secureTextEntry" | "selection" | "selectTextOnFocus" | "blurOnSubmit" | "submitBehavior"> & Omit<Readonly<{
|
|
178
178
|
experimental_acceptDragAndDropTypes?: ReadonlyArray<string> | undefined;
|
|
179
179
|
autoCapitalize?: import("react-native").AutoCapitalize | undefined;
|
|
180
180
|
autoComplete?: ("additional-name" | "address-line1" | "address-line2" | "birthdate-day" | "birthdate-full" | "birthdate-month" | "birthdate-year" | "cc-csc" | "cc-exp" | "cc-exp-day" | "cc-exp-month" | "cc-exp-year" | "cc-number" | "cc-name" | "cc-given-name" | "cc-middle-name" | "cc-family-name" | "cc-type" | "country" | "current-password" | "email" | "family-name" | "gender" | "given-name" | "honorific-prefix" | "honorific-suffix" | "name" | "name-family" | "name-given" | "name-middle" | "name-middle-initial" | "name-prefix" | "name-suffix" | "new-password" | "nickname" | "one-time-code" | "organization" | "organization-title" | "password" | "password-new" | "postal-address" | "postal-address-country" | "postal-address-extended" | "postal-address-extended-postal-code" | "postal-address-locality" | "postal-address-region" | "postal-code" | "street-address" | "sms-otp" | "tel" | "tel-country-code" | "tel-national" | "tel-device" | "url" | "username" | "username-new" | "off") | undefined;
|
|
@@ -138,7 +138,7 @@ export declare const Textarea: import("react").ForwardRefExoticComponent<Omit<Re
|
|
|
138
138
|
pointerEvents?: ("auto" | "box-none" | "box-only" | "none") | undefined;
|
|
139
139
|
removeClippedSubviews?: boolean | undefined;
|
|
140
140
|
experimental_accessibilityOrder?: Array<string> | undefined;
|
|
141
|
-
}>, never>>, "style" | "experimental_accessibilityOrder">, "value" | "textAlign" | "
|
|
141
|
+
}>, never>>, "style" | "experimental_accessibilityOrder">, "value" | "textAlign" | "style" | "onChange" | "onBlur" | "onFocus" | "onPress" | "lineBreakStrategyIOS" | "selectionColor" | "textBreakStrategy" | "allowFontScaling" | "maxFontSizeMultiplier" | "numberOfLines" | "onPressIn" | "onPressOut" | "disableKeyboardShortcuts" | "clearButtonMode" | "clearTextOnFocus" | "dataDetectorTypes" | "enablesReturnKeyAutomatically" | "inputAccessoryViewID" | "inputAccessoryViewButtonLabel" | "keyboardAppearance" | "passwordRules" | "rejectResponderTermination" | "scrollEnabled" | "spellCheck" | "textContentType" | "lineBreakModeIOS" | "smartInsertDelete" | "cursorColor" | "selectionHandleColor" | "disableFullscreenUI" | "importantForAutofill" | "inlineImageLeft" | "inlineImagePadding" | "returnKeyLabel" | "rows" | "showSoftInputOnFocus" | "underlineColorAndroid" | "experimental_acceptDragAndDropTypes" | "autoCapitalize" | "autoComplete" | "autoCorrect" | "autoFocus" | "caretHidden" | "contextMenuHidden" | "defaultValue" | "editable" | "forwardedRef" | "enterKeyHint" | "inputMode" | "keyboardType" | "maxLength" | "multiline" | "onChangeText" | "onContentSizeChange" | "onEndEditing" | "onKeyPress" | "onSelectionChange" | "onSubmitEditing" | "onScroll" | "placeholder" | "placeholderTextColor" | "readOnly" | "returnKeyType" | "secureTextEntry" | "selection" | "selectTextOnFocus" | "blurOnSubmit" | "submitBehavior"> & Omit<Readonly<{
|
|
142
142
|
disableKeyboardShortcuts?: boolean | undefined;
|
|
143
143
|
clearButtonMode?: ("never" | "while-editing" | "unless-editing" | "always") | undefined;
|
|
144
144
|
clearTextOnFocus?: boolean | undefined;
|
|
@@ -155,7 +155,7 @@ export declare const Textarea: import("react").ForwardRefExoticComponent<Omit<Re
|
|
|
155
155
|
lineBreakStrategyIOS?: ("none" | "standard" | "hangul-word" | "push-out") | undefined;
|
|
156
156
|
lineBreakModeIOS?: ("wordWrapping" | "char" | "clip" | "head" | "middle" | "tail") | undefined;
|
|
157
157
|
smartInsertDelete?: boolean | undefined;
|
|
158
|
-
}>, "value" | "textAlign" | "
|
|
158
|
+
}>, "value" | "textAlign" | "style" | "onChange" | "onBlur" | "onFocus" | "onPress" | "selectionColor" | "textBreakStrategy" | "allowFontScaling" | "maxFontSizeMultiplier" | "numberOfLines" | "onPressIn" | "onPressOut" | "cursorColor" | "selectionHandleColor" | "disableFullscreenUI" | "importantForAutofill" | "inlineImageLeft" | "inlineImagePadding" | "returnKeyLabel" | "rows" | "showSoftInputOnFocus" | "underlineColorAndroid" | "experimental_acceptDragAndDropTypes" | "autoCapitalize" | "autoComplete" | "autoCorrect" | "autoFocus" | "caretHidden" | "contextMenuHidden" | "defaultValue" | "editable" | "forwardedRef" | "enterKeyHint" | "inputMode" | "keyboardType" | "maxLength" | "multiline" | "onChangeText" | "onContentSizeChange" | "onEndEditing" | "onKeyPress" | "onSelectionChange" | "onSubmitEditing" | "onScroll" | "placeholder" | "placeholderTextColor" | "readOnly" | "returnKeyType" | "secureTextEntry" | "selection" | "selectTextOnFocus" | "blurOnSubmit" | "submitBehavior"> & Omit<Readonly<{
|
|
159
159
|
cursorColor?: import("react-native").ColorValue | undefined;
|
|
160
160
|
selectionHandleColor?: import("react-native").ColorValue | undefined;
|
|
161
161
|
disableFullscreenUI?: boolean | undefined;
|
|
@@ -168,7 +168,7 @@ export declare const Textarea: import("react").ForwardRefExoticComponent<Omit<Re
|
|
|
168
168
|
showSoftInputOnFocus?: boolean | undefined;
|
|
169
169
|
textBreakStrategy?: ("simple" | "highQuality" | "balanced") | undefined;
|
|
170
170
|
underlineColorAndroid?: import("react-native").ColorValue | undefined;
|
|
171
|
-
}>, "value" | "textAlign" | "
|
|
171
|
+
}>, "value" | "textAlign" | "style" | "onChange" | "onBlur" | "onFocus" | "onPress" | "selectionColor" | "allowFontScaling" | "maxFontSizeMultiplier" | "onPressIn" | "onPressOut" | "experimental_acceptDragAndDropTypes" | "autoCapitalize" | "autoComplete" | "autoCorrect" | "autoFocus" | "caretHidden" | "contextMenuHidden" | "defaultValue" | "editable" | "forwardedRef" | "enterKeyHint" | "inputMode" | "keyboardType" | "maxLength" | "multiline" | "onChangeText" | "onContentSizeChange" | "onEndEditing" | "onKeyPress" | "onSelectionChange" | "onSubmitEditing" | "onScroll" | "placeholder" | "placeholderTextColor" | "readOnly" | "returnKeyType" | "secureTextEntry" | "selection" | "selectTextOnFocus" | "blurOnSubmit" | "submitBehavior"> & Omit<Readonly<{
|
|
172
172
|
experimental_acceptDragAndDropTypes?: ReadonlyArray<string> | undefined;
|
|
173
173
|
autoCapitalize?: import("react-native").AutoCapitalize | undefined;
|
|
174
174
|
autoComplete?: ("additional-name" | "address-line1" | "address-line2" | "birthdate-day" | "birthdate-full" | "birthdate-month" | "birthdate-year" | "cc-csc" | "cc-exp" | "cc-exp-day" | "cc-exp-month" | "cc-exp-year" | "cc-number" | "cc-name" | "cc-given-name" | "cc-middle-name" | "cc-family-name" | "cc-type" | "country" | "current-password" | "email" | "family-name" | "gender" | "given-name" | "honorific-prefix" | "honorific-suffix" | "name" | "name-family" | "name-given" | "name-middle" | "name-middle-initial" | "name-prefix" | "name-suffix" | "new-password" | "nickname" | "one-time-code" | "organization" | "organization-title" | "password" | "password-new" | "postal-address" | "postal-address-country" | "postal-address-extended" | "postal-address-extended-postal-code" | "postal-address-locality" | "postal-address-region" | "postal-code" | "street-address" | "sms-otp" | "tel" | "tel-country-code" | "tel-national" | "tel-device" | "url" | "username" | "username-new" | "off") | undefined;
|
|
@@ -6,13 +6,19 @@ export type ThemeContextValue = {
|
|
|
6
6
|
scheme: ColorScheme;
|
|
7
7
|
colors: ColorTokens;
|
|
8
8
|
shadow: ShadowTokens;
|
|
9
|
+
/** 应用级字号缩放倍数(app 内字体大小档)。useThemedStyles 出口对
|
|
10
|
+
* fontSize / lineHeight / letterSpacing 生效;1 = 不缩放。 */
|
|
11
|
+
fontScale: number;
|
|
9
12
|
};
|
|
10
13
|
export declare const ThemeContext: React.Context<ThemeContextValue | null>;
|
|
11
14
|
type ThemeProviderProps = {
|
|
12
15
|
children: React.ReactNode;
|
|
13
16
|
/** 强制使用某个 scheme(覆盖 useColorScheme)。用于测试或 settingsStore 接入。 */
|
|
14
17
|
forceScheme?: ColorScheme;
|
|
18
|
+
/** 应用级字号缩放倍数,默认 1(不缩放)。接入方自持档位状态(persist
|
|
19
|
+
* store 等)并传入;变更即触发全树 themed 样式重算。 */
|
|
20
|
+
fontScale?: number;
|
|
15
21
|
};
|
|
16
|
-
export declare function ThemeProvider({ children, forceScheme }: ThemeProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
22
|
+
export declare function ThemeProvider({ children, forceScheme, fontScale, }: ThemeProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
17
23
|
export {};
|
|
18
24
|
//# sourceMappingURL=ThemeProvider.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ThemeProvider.d.ts","sourceRoot":"","sources":["../../../../src/theme/ThemeProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAiC,MAAM,OAAO,CAAC;AAEtD,OAAO,EAA2B,KAAK,WAAW,EAAE,MAAM,UAAU,CAAC;AACrE,OAAO,EAA2B,KAAK,YAAY,EAAE,MAAM,UAAU,CAAC;AAEtE,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,MAAM,CAAC;AAE3C,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,EAAE,WAAW,CAAC;IACpB,MAAM,EAAE,WAAW,CAAC;IACpB,MAAM,EAAE,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"ThemeProvider.d.ts","sourceRoot":"","sources":["../../../../src/theme/ThemeProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAiC,MAAM,OAAO,CAAC;AAEtD,OAAO,EAA2B,KAAK,WAAW,EAAE,MAAM,UAAU,CAAC;AACrE,OAAO,EAA2B,KAAK,YAAY,EAAE,MAAM,UAAU,CAAC;AAEtE,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,MAAM,CAAC;AAE3C,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,EAAE,WAAW,CAAC;IACpB,MAAM,EAAE,WAAW,CAAC;IACpB,MAAM,EAAE,YAAY,CAAC;IACrB;4DACwD;IACxD,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,eAAO,MAAM,YAAY,yCAAgD,CAAC;AAE1E,KAAK,kBAAkB,GAAG;IACxB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,+DAA+D;IAC/D,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B;2CACuC;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,WAAW,EACX,SAAa,GACd,EAAE,kBAAkB,2CAoBpB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useTheme.d.ts","sourceRoot":"","sources":["../../../../src/theme/useTheme.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"useTheme.d.ts","sourceRoot":"","sources":["../../../../src/theme/useTheme.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAkBvE,wBAAgB,QAAQ,IAAI,iBAAiB,CAW5C;AAED,wBAAgB,SAAS,mCAExB;AAED,wBAAgB,SAAS,oCAExB"}
|
|
@@ -7,12 +7,18 @@ type NamedStyles<T> = {
|
|
|
7
7
|
[P in keyof T]: ViewStyle | TextStyle | ImageStyle;
|
|
8
8
|
};
|
|
9
9
|
export type StylesMaker<S extends NamedStyles<S>> = (c: ColorTokens, s: ShadowTokens) => S;
|
|
10
|
+
/** maker 产物按 fontScale 缩放字号系属性。factor = 1 时恒等返回**原引用**——
|
|
11
|
+
* 未接入 fontScale 的消费方(web 文档站等)行为与引用完全不变。
|
|
12
|
+
* 导出仅供单测,不进 barrel。 */
|
|
13
|
+
export declare function scaleNamedStyles<S extends NamedStyles<S>>(styles: S, factor: number): S;
|
|
10
14
|
/**
|
|
11
|
-
* 接收 (colors, shadow) => StyleSheet 工厂,返回当前主题对应的 themed StyleSheet
|
|
15
|
+
* 接收 (colors, shadow) => StyleSheet 工厂,返回当前主题对应的 themed StyleSheet,
|
|
16
|
+
* 并按 ThemeProvider 的 fontScale 缩放字号系属性(fontSize / lineHeight /
|
|
17
|
+
* letterSpacing;fontScale = 1 时恒等)。
|
|
12
18
|
*
|
|
13
|
-
* 缓存依赖 [colors, shadow, maker]。`maker` 必须定义在模块顶层
|
|
14
|
-
*
|
|
15
|
-
* colors / shadow 引用稳定。
|
|
19
|
+
* 缓存依赖 [colors, shadow, fontScale, maker]。`maker` 必须定义在模块顶层
|
|
20
|
+
* (不要写在组件内联),否则引用每次变,缓存失效。ThemeProvider 通过
|
|
21
|
+
* useMemo([scheme, fontScale]) 保证主题不变时 colors / shadow 引用稳定。
|
|
16
22
|
*/
|
|
17
23
|
export declare function useThemedStyles<S extends NamedStyles<S>>(maker: StylesMaker<S>): S;
|
|
18
24
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useThemedStyles.d.ts","sourceRoot":"","sources":["../../../../src/theme/useThemedStyles.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACrE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAG7C;sEACsE;AACtE,KAAK,WAAW,CAAC,CAAC,IAAI;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,SAAS,GAAG,SAAS,GAAG,UAAU;CAAE,CAAC;AAE7E,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,WAAW,CAAC,CAAC,CAAC,IAAI,CAClD,CAAC,EAAE,WAAW,EACd,CAAC,EAAE,YAAY,KACZ,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"useThemedStyles.d.ts","sourceRoot":"","sources":["../../../../src/theme/useThemedStyles.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACrE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAG7C;sEACsE;AACtE,KAAK,WAAW,CAAC,CAAC,IAAI;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,SAAS,GAAG,SAAS,GAAG,UAAU;CAAE,CAAC;AAE7E,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,WAAW,CAAC,CAAC,CAAC,IAAI,CAClD,CAAC,EAAE,WAAW,EACd,CAAC,EAAE,YAAY,KACZ,CAAC,CAAC;AA0BP;;wBAEwB;AACxB,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,WAAW,CAAC,CAAC,CAAC,EACvD,MAAM,EAAE,CAAC,EACT,MAAM,EAAE,MAAM,GACb,CAAC,CAaH;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,WAAW,CAAC,CAAC,CAAC,EACtD,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,GACpB,CAAC,CAMH"}
|
package/package.json
CHANGED
|
@@ -1,16 +1,31 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { Text, View } from 'react-native';
|
|
3
3
|
import { Pressable } from 'react-native-gesture-handler';
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
fixed,
|
|
6
|
+
pressedOpacity,
|
|
7
|
+
r,
|
|
8
|
+
rf,
|
|
9
|
+
useColors,
|
|
10
|
+
useThemedStyles,
|
|
11
|
+
} from '../../../theme';
|
|
12
|
+
import { Spinner } from '../Spinner';
|
|
5
13
|
import { makeStyles } from './styles';
|
|
6
14
|
import type { ChipProps } from './types';
|
|
7
15
|
|
|
16
|
+
/** 处理中 chip 的透明度 —— 比 disabled(0.5)亮、比按下(pressedOpacity)暗:
|
|
17
|
+
* 「正在办」既要压下去,又不能和「不能点」长一样(那两者只靠 spinner 区分就太弱了)。 */
|
|
18
|
+
const busyOpacity = 0.6;
|
|
19
|
+
/** busy spinner 直径 —— 与调用方常用的 leading icon(12)等大,顶替时不改 chip 宽度。 */
|
|
20
|
+
const busySpinner = r(12);
|
|
21
|
+
|
|
8
22
|
/**
|
|
9
23
|
* 胶囊形可点击 chip。
|
|
10
24
|
* - 默认:surface 底 + outline 细线边框,foreground 文本
|
|
11
25
|
* - 选中:主色边框 + 主色文本
|
|
12
26
|
* - 按下:透明度 pressedOpacity(与 ButtonBase 同源)
|
|
13
27
|
* - 禁用:透明度 0.5 + 不响应 onPress
|
|
28
|
+
* - 处理中(`busy`):leading 换 spinner + 透明度 0.6 + 不响应二次点击
|
|
14
29
|
*
|
|
15
30
|
* 常用于建议 chip、筛选 pill、多选标签等。
|
|
16
31
|
*/
|
|
@@ -19,18 +34,31 @@ export function Chip({
|
|
|
19
34
|
selected,
|
|
20
35
|
onPress,
|
|
21
36
|
disabled,
|
|
37
|
+
busy,
|
|
22
38
|
leading,
|
|
23
39
|
trailing,
|
|
24
40
|
style,
|
|
25
41
|
testID,
|
|
26
42
|
}: ChipProps): React.JSX.Element {
|
|
43
|
+
const c = useColors();
|
|
27
44
|
const styles = useThemedStyles(makeStyles);
|
|
45
|
+
// 处理中把 spinner 放进 leading 位(有 leading 就顶掉它):label 必须留着 —— 换掉它 chip
|
|
46
|
+
// 会塌成一个圆点,同排 chip 集体重排。spinner 跟随文本色,不在未选中的 chip 上凭空冒主色。
|
|
47
|
+
const lead = busy ? (
|
|
48
|
+
<Spinner
|
|
49
|
+
size={busySpinner}
|
|
50
|
+
thickness={r(1.5)}
|
|
51
|
+
color={selected ? c.primary : c.foreground}
|
|
52
|
+
/>
|
|
53
|
+
) : (
|
|
54
|
+
leading
|
|
55
|
+
);
|
|
28
56
|
const inner = (
|
|
29
57
|
<View
|
|
30
58
|
style={[styles.chip, selected && styles.chipOn, style]}
|
|
31
59
|
testID={onPress ? undefined : testID}
|
|
32
60
|
>
|
|
33
|
-
{
|
|
61
|
+
{lead != null ? <View>{lead}</View> : null}
|
|
34
62
|
<Text style={[styles.text, selected && styles.textOn]} numberOfLines={1}>
|
|
35
63
|
{label}
|
|
36
64
|
</Text>
|
|
@@ -45,19 +73,31 @@ export function Chip({
|
|
|
45
73
|
0,
|
|
46
74
|
Math.round((fixed.hitTarget - (2 * r(8) + rf(13) * 1.4)) / 2)
|
|
47
75
|
);
|
|
76
|
+
// 处理中同样不响应:chip 的高频用法是「点一下发起一次请求」,放行二次点击就是重复提交。
|
|
77
|
+
const inactive = !!disabled || !!busy;
|
|
48
78
|
return (
|
|
49
79
|
<Pressable
|
|
50
80
|
onPress={onPress}
|
|
51
|
-
disabled={
|
|
81
|
+
disabled={inactive}
|
|
52
82
|
accessibilityRole="button"
|
|
53
|
-
accessibilityState={{
|
|
83
|
+
accessibilityState={{
|
|
84
|
+
selected: !!selected,
|
|
85
|
+
disabled: inactive,
|
|
86
|
+
busy: !!busy,
|
|
87
|
+
}}
|
|
54
88
|
accessibilityLabel={label}
|
|
55
89
|
testID={testID}
|
|
56
90
|
hitSlop={{ top: chipHitSlopV, bottom: chipHitSlopV, left: 0, right: 0 }}
|
|
57
91
|
style={({ pressed }) => [
|
|
58
92
|
{
|
|
59
93
|
alignSelf: 'flex-start',
|
|
60
|
-
opacity: disabled
|
|
94
|
+
opacity: disabled
|
|
95
|
+
? 0.5
|
|
96
|
+
: busy
|
|
97
|
+
? busyOpacity
|
|
98
|
+
: pressed
|
|
99
|
+
? pressedOpacity
|
|
100
|
+
: 1,
|
|
61
101
|
},
|
|
62
102
|
]}
|
|
63
103
|
>
|
|
@@ -7,6 +7,10 @@ export type ChipProps = {
|
|
|
7
7
|
onPress?: () => void;
|
|
8
8
|
/** 整体禁用:opacity 0.5 + 不响应 onPress + accessibilityState.disabled */
|
|
9
9
|
disabled?: boolean;
|
|
10
|
+
/** 处理中(点了、请求在飞):leading 位换 spinner + opacity 0.6 + 不响应二次点击 +
|
|
11
|
+
* accessibilityState.busy。label 保留 —— 换掉它 chip 会塌成一个圆点、整行跟着重排。
|
|
12
|
+
* 与 `disabled` 的分工:disabled = 现在不能点(更暗、无 spinner),busy = 正在办。 */
|
|
13
|
+
busy?: boolean;
|
|
10
14
|
/** 可选的前置插槽 —— 如 <Icon name="spark" /> */
|
|
11
15
|
leading?: ReactNode;
|
|
12
16
|
/** 可选的后置插槽 —— 如一个小的 × 关闭按钮 */
|
|
@@ -9,6 +9,9 @@ export type ThemeContextValue = {
|
|
|
9
9
|
scheme: ColorScheme;
|
|
10
10
|
colors: ColorTokens;
|
|
11
11
|
shadow: ShadowTokens;
|
|
12
|
+
/** 应用级字号缩放倍数(app 内字体大小档)。useThemedStyles 出口对
|
|
13
|
+
* fontSize / lineHeight / letterSpacing 生效;1 = 不缩放。 */
|
|
14
|
+
fontScale: number;
|
|
12
15
|
};
|
|
13
16
|
|
|
14
17
|
export const ThemeContext = createContext<ThemeContextValue | null>(null);
|
|
@@ -17,9 +20,16 @@ type ThemeProviderProps = {
|
|
|
17
20
|
children: React.ReactNode;
|
|
18
21
|
/** 强制使用某个 scheme(覆盖 useColorScheme)。用于测试或 settingsStore 接入。 */
|
|
19
22
|
forceScheme?: ColorScheme;
|
|
23
|
+
/** 应用级字号缩放倍数,默认 1(不缩放)。接入方自持档位状态(persist
|
|
24
|
+
* store 等)并传入;变更即触发全树 themed 样式重算。 */
|
|
25
|
+
fontScale?: number;
|
|
20
26
|
};
|
|
21
27
|
|
|
22
|
-
export function ThemeProvider({
|
|
28
|
+
export function ThemeProvider({
|
|
29
|
+
children,
|
|
30
|
+
forceScheme,
|
|
31
|
+
fontScale = 1,
|
|
32
|
+
}: ThemeProviderProps) {
|
|
23
33
|
const sysScheme = useColorScheme();
|
|
24
34
|
const scheme: ColorScheme =
|
|
25
35
|
forceScheme ?? (sysScheme === 'dark' ? 'dark' : 'light');
|
|
@@ -31,8 +41,9 @@ export function ThemeProvider({ children, forceScheme }: ThemeProviderProps) {
|
|
|
31
41
|
scheme,
|
|
32
42
|
colors: scheme === 'dark' ? darkColors : lightColors,
|
|
33
43
|
shadow: scheme === 'dark' ? darkShadow : lightShadow,
|
|
44
|
+
fontScale,
|
|
34
45
|
}),
|
|
35
|
-
[scheme]
|
|
46
|
+
[scheme, fontScale]
|
|
36
47
|
);
|
|
37
48
|
|
|
38
49
|
return (
|
package/src/theme/useTheme.ts
CHANGED
|
@@ -13,16 +13,66 @@ export type StylesMaker<S extends NamedStyles<S>> = (
|
|
|
13
13
|
s: ShadowTokens
|
|
14
14
|
) => S;
|
|
15
15
|
|
|
16
|
+
/** 应用级字号缩放只作用于文字三属性 —— 与 RN allowFontScaling 的原生缩放
|
|
17
|
+
* 范围一致(只缩文字,不缩 padding / 高度等布局尺寸)。无字号系属性的
|
|
18
|
+
* style 返回原引用。strict-api 下 TextStyle 只读,用条件展开构造新对象。 */
|
|
19
|
+
function scaleTextStyle(style: TextStyle, factor: number): TextStyle {
|
|
20
|
+
const { fontSize, lineHeight, letterSpacing } = style;
|
|
21
|
+
if (
|
|
22
|
+
typeof fontSize !== 'number' &&
|
|
23
|
+
typeof lineHeight !== 'number' &&
|
|
24
|
+
typeof letterSpacing !== 'number'
|
|
25
|
+
) {
|
|
26
|
+
return style;
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
...style,
|
|
30
|
+
...(typeof fontSize === 'number' ? { fontSize: fontSize * factor } : null),
|
|
31
|
+
...(typeof lineHeight === 'number'
|
|
32
|
+
? { lineHeight: lineHeight * factor }
|
|
33
|
+
: null),
|
|
34
|
+
...(typeof letterSpacing === 'number'
|
|
35
|
+
? { letterSpacing: letterSpacing * factor }
|
|
36
|
+
: null),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** maker 产物按 fontScale 缩放字号系属性。factor = 1 时恒等返回**原引用**——
|
|
41
|
+
* 未接入 fontScale 的消费方(web 文档站等)行为与引用完全不变。
|
|
42
|
+
* 导出仅供单测,不进 barrel。 */
|
|
43
|
+
export function scaleNamedStyles<S extends NamedStyles<S>>(
|
|
44
|
+
styles: S,
|
|
45
|
+
factor: number
|
|
46
|
+
): S {
|
|
47
|
+
if (factor === 1) return styles;
|
|
48
|
+
const out: Record<string, ViewStyle | TextStyle | ImageStyle> = {};
|
|
49
|
+
for (const [key, style] of Object.entries(
|
|
50
|
+
styles as Record<string, ViewStyle | TextStyle | ImageStyle>
|
|
51
|
+
)) {
|
|
52
|
+
// ViewStyle / ImageStyle 无字号三属性,按 TextStyle 探测后恒等返回原引用。
|
|
53
|
+
out[key] =
|
|
54
|
+
style && typeof style === 'object'
|
|
55
|
+
? scaleTextStyle(style as TextStyle, factor)
|
|
56
|
+
: style;
|
|
57
|
+
}
|
|
58
|
+
return out as S;
|
|
59
|
+
}
|
|
60
|
+
|
|
16
61
|
/**
|
|
17
|
-
* 接收 (colors, shadow) => StyleSheet 工厂,返回当前主题对应的 themed StyleSheet
|
|
62
|
+
* 接收 (colors, shadow) => StyleSheet 工厂,返回当前主题对应的 themed StyleSheet,
|
|
63
|
+
* 并按 ThemeProvider 的 fontScale 缩放字号系属性(fontSize / lineHeight /
|
|
64
|
+
* letterSpacing;fontScale = 1 时恒等)。
|
|
18
65
|
*
|
|
19
|
-
* 缓存依赖 [colors, shadow, maker]。`maker` 必须定义在模块顶层
|
|
20
|
-
*
|
|
21
|
-
* colors / shadow 引用稳定。
|
|
66
|
+
* 缓存依赖 [colors, shadow, fontScale, maker]。`maker` 必须定义在模块顶层
|
|
67
|
+
* (不要写在组件内联),否则引用每次变,缓存失效。ThemeProvider 通过
|
|
68
|
+
* useMemo([scheme, fontScale]) 保证主题不变时 colors / shadow 引用稳定。
|
|
22
69
|
*/
|
|
23
70
|
export function useThemedStyles<S extends NamedStyles<S>>(
|
|
24
71
|
maker: StylesMaker<S>
|
|
25
72
|
): S {
|
|
26
|
-
const { colors, shadow } = useTheme();
|
|
27
|
-
return useMemo(
|
|
73
|
+
const { colors, shadow, fontScale } = useTheme();
|
|
74
|
+
return useMemo(
|
|
75
|
+
() => scaleNamedStyles(maker(colors, shadow), fontScale),
|
|
76
|
+
[colors, shadow, fontScale, maker]
|
|
77
|
+
);
|
|
28
78
|
}
|