@unif/react-native-design 0.18.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.
@@ -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: [leading != null ? /*#__PURE__*/_jsx(View, {
33
- children: leading
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: disabled,
67
+ disabled: inactive,
49
68
  accessibilityRole: "button",
50
69
  accessibilityState: {
51
70
  selected: !!selected,
52
- disabled: !!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,SAASC,KAAK,EAAEC,cAAc,EAAEC,CAAC,EAAEC,EAAE,EAAEC,eAAe,QAAQ,yBAAgB;AAC9E,SAASC,UAAU,QAAQ,aAAU;AAAC,SAAAC,GAAA,IAAAC,IAAA,EAAAC,IAAA,IAAAC,KAAA;AAGtC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,IAAIA,CAAC;EACnBC,KAAK;EACLC,QAAQ;EACRC,OAAO;EACPC,QAAQ;EACRC,OAAO;EACPC,QAAQ;EACRC,KAAK;EACLC;AACS,CAAC,EAAqB;EAC/B,MAAMC,MAAM,GAAGf,eAAe,CAACC,UAAU,CAAC;EAC1C,MAAMe,KAAK,gBACTX,KAAA,CAACX,IAAI;IACHmB,KAAK,EAAE,CAACE,MAAM,CAACE,IAAI,EAAET,QAAQ,IAAIO,MAAM,CAACG,MAAM,EAAEL,KAAK,CAAE;IACvDC,MAAM,EAAEL,OAAO,GAAGU,SAAS,GAAGL,MAAO;IAAAM,QAAA,GAEpCT,OAAO,IAAI,IAAI,gBAAGR,IAAA,CAACT,IAAI;MAAA0B,QAAA,EAAET;IAAO,CAAO,CAAC,GAAG,IAAI,eAChDR,IAAA,CAACV,IAAI;MAACoB,KAAK,EAAE,CAACE,MAAM,CAACM,IAAI,EAAEb,QAAQ,IAAIO,MAAM,CAACO,MAAM,CAAE;MAACC,aAAa,EAAE,CAAE;MAAAH,QAAA,EACrEb;IAAK,CACF,CAAC,EACNK,QAAQ,IAAI,IAAI,gBAAGT,IAAA,CAACT,IAAI;MAAA0B,QAAA,EAAER;IAAQ,CAAO,CAAC,GAAG,IAAI;EAAA,CAC9C,CACP;EAED,IAAIH,OAAO,EAAE;IACX;IACA;IACA,MAAMe,YAAY,GAAGC,IAAI,CAACC,GAAG,CAC3B,CAAC,EACDD,IAAI,CAACE,KAAK,CAAC,CAAC/B,KAAK,CAACgC,SAAS,IAAI,CAAC,GAAG9B,CAAC,CAAC,CAAC,CAAC,GAAGC,EAAE,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,CAC9D,CAAC;IACD,oBACEI,IAAA,CAACR,SAAS;MACRc,OAAO,EAAEA,OAAQ;MACjBC,QAAQ,EAAEA,QAAS;MACnBmB,iBAAiB,EAAC,QAAQ;MAC1BC,kBAAkB,EAAE;QAAEtB,QAAQ,EAAE,CAAC,CAACA,QAAQ;QAAEE,QAAQ,EAAE,CAAC,CAACA;MAAS,CAAE;MACnEqB,kBAAkB,EAAExB,KAAM;MAC1BO,MAAM,EAAEA,MAAO;MACfkB,OAAO,EAAE;QAAEC,GAAG,EAAET,YAAY;QAAEU,MAAM,EAAEV,YAAY;QAAEW,IAAI,EAAE,CAAC;QAAEC,KAAK,EAAE;MAAE,CAAE;MACxEvB,KAAK,EAAEA,CAAC;QAAEwB;MAAQ,CAAC,KAAK,CACtB;QACEC,SAAS,EAAE,YAAY;QACvBC,OAAO,EAAE7B,QAAQ,GAAG,GAAG,GAAG2B,OAAO,GAAGxC,cAAc,GAAG;MACvD,CAAC,CACD;MAAAuB,QAAA,EAEDJ;IAAK,CACG,CAAC;EAEhB;EACA,OAAOA,KAAK;AACd","ignoreList":[]}
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":"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","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;AAK1B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEzC;;;;;;;;GAQG;AACH,wBAAgB,IAAI,CAAC,EACnB,KAAK,EACL,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,KAAK,EACL,MAAM,GACP,EAAE,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CA2C/B"}
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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unif/react-native-design",
3
- "version": "0.18.0",
3
+ "version": "0.19.0",
4
4
  "description": "Unif 设计系统:theme + icons + utils + components",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",
@@ -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 { fixed, pressedOpacity, r, rf, useThemedStyles } from '../../../theme';
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
- {leading != null ? <View>{leading}</View> : null}
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={disabled}
81
+ disabled={inactive}
52
82
  accessibilityRole="button"
53
- accessibilityState={{ selected: !!selected, disabled: !!disabled }}
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 ? 0.5 : pressed ? pressedOpacity : 1,
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
  /** 可选的后置插槽 —— 如一个小的 × 关闭按钮 */