zkit-ui 1.0.6 → 2.0.1

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.
Files changed (52) hide show
  1. package/README.md +25 -11
  2. package/dist/ZKitCoreProvider.d.ts +13 -0
  3. package/dist/ZKitCoreProvider.d.ts.map +1 -0
  4. package/dist/ZKitCoreProvider.js +10 -0
  5. package/dist/ZKitProvider.d.ts +2 -10
  6. package/dist/ZKitProvider.d.ts.map +1 -1
  7. package/dist/ZKitProvider.js +4 -5
  8. package/dist/all.d.ts +59 -0
  9. package/dist/all.d.ts.map +1 -0
  10. package/dist/all.js +92 -0
  11. package/dist/index.d.ts +2 -46
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +3 -73
  14. package/dist/services/PermissionPurposeDialogService/index.d.ts +1 -1
  15. package/dist/services/PermissionPurposeDialogService/index.js +1 -1
  16. package/dist/services/PickerService/index.d.ts +1 -1
  17. package/dist/services/PickerService/index.js +1 -1
  18. package/dist/ui/DatePicker/index.d.ts.map +1 -1
  19. package/dist/ui/DatePicker/index.js +7 -4
  20. package/dist/ui/DatePicker/utils.d.ts +5 -1
  21. package/dist/ui/DatePicker/utils.d.ts.map +1 -1
  22. package/dist/ui/DatePicker/utils.js +62 -12
  23. package/package.json +164 -2
  24. package/src/ZKitCoreProvider.tsx +34 -0
  25. package/src/ZKitProvider.tsx +25 -33
  26. package/src/all.ts +397 -0
  27. package/src/index.ts +5 -374
  28. package/src/services/ActionDialogService/README.md +3 -2
  29. package/src/services/CardToastService/README.md +2 -2
  30. package/src/services/ImagePreviewService/README.md +2 -2
  31. package/src/services/LoadingService/README.md +1 -1
  32. package/src/services/PermissionPurposeDialogService/README.md +2 -2
  33. package/src/services/PermissionPurposeDialogService/index.tsx +1 -1
  34. package/src/services/PickerService/README.md +2 -2
  35. package/src/services/PickerService/index.tsx +1 -1
  36. package/src/ui/Accordion/README.md +2 -2
  37. package/src/ui/AddressCascader/README.md +4 -2
  38. package/src/ui/BetweenTime/README.md +12 -12
  39. package/src/ui/Button/README.md +7 -7
  40. package/src/ui/Checkbox/README.md +2 -2
  41. package/src/ui/DatePicker/README.md +2 -1
  42. package/src/ui/DatePicker/index.tsx +23 -4
  43. package/src/ui/DatePicker/utils.ts +93 -14
  44. package/src/ui/LinkedScroll/README.md +2 -1
  45. package/src/ui/Picker/README.md +2 -1
  46. package/src/ui/Radio/README.md +2 -1
  47. package/src/ui/Sheet/README.md +3 -1
  48. package/src/ui/SliderCaptcha/README.md +1 -1
  49. package/src/ui/Switch/README.md +1 -1
  50. package/src/ui/Text/README.md +2 -2
  51. package/src/ui/TextInput/README.md +6 -6
  52. package/src/ui/WheelColumn/README.md +1 -1
@@ -5,7 +5,7 @@
5
5
  ## 基础用法
6
6
 
7
7
  ```tsx
8
- import { Button } from 'zkit-ui';
8
+ import { Button } from 'zkit-ui/button';
9
9
 
10
10
  export function Demo() {
11
11
  return <Button onPress={() => {}}>确定</Button>;
@@ -15,7 +15,7 @@ export function Demo() {
15
15
  ## 外观语义
16
16
 
17
17
  ```tsx
18
- import { Button } from 'zkit-ui';
18
+ import { Button } from 'zkit-ui/button';
19
19
 
20
20
  export function Demo() {
21
21
  return (
@@ -37,7 +37,7 @@ export function Demo() {
37
37
  ## 尺寸与布局
38
38
 
39
39
  ```tsx
40
- import { Button } from 'zkit-ui';
40
+ import { Button } from 'zkit-ui/button';
41
41
  import { sp, wp } from 'zkit-tools';
42
42
 
43
43
  export function Demo() {
@@ -67,7 +67,7 @@ export function Demo() {
67
67
  ## 图标
68
68
 
69
69
  ```tsx
70
- import { Button } from 'zkit-ui';
70
+ import { Button } from 'zkit-ui/button';
71
71
  import { wp } from 'zkit-tools';
72
72
 
73
73
  export function Demo() {
@@ -94,7 +94,7 @@ export function Demo() {
94
94
  ## 加载状态
95
95
 
96
96
  ```tsx
97
- import { Button } from 'zkit-ui';
97
+ import { Button } from 'zkit-ui/button';
98
98
 
99
99
  export function Demo() {
100
100
  return (
@@ -114,7 +114,7 @@ export function Demo() {
114
114
  ## 精确覆盖
115
115
 
116
116
  ```tsx
117
- import { Button } from 'zkit-ui';
117
+ import { Button } from 'zkit-ui/button';
118
118
  import { wp } from 'zkit-tools';
119
119
 
120
120
  export function Demo() {
@@ -139,7 +139,7 @@ export function Demo() {
139
139
  ## 渐变、阴影与按压反馈
140
140
 
141
141
  ```tsx
142
- import { Button } from 'zkit-ui';
142
+ import { Button } from 'zkit-ui/button';
143
143
 
144
144
  export function Demo() {
145
145
  return (
@@ -16,7 +16,7 @@ Checkbox 是三端一致的复选框组件,适合协议勾选、多选列表
16
16
 
17
17
  ```tsx
18
18
  import * as React from 'react';
19
- import { Checkbox } from 'zkit-ui';
19
+ import { Checkbox } from 'zkit-ui/checkbox';
20
20
 
21
21
  export function Demo() {
22
22
  const [checked, setChecked] = React.useState(false);
@@ -51,7 +51,7 @@ const partiallyChecked = selected.length > 0 && !allChecked;
51
51
  ## CheckboxGroup
52
52
 
53
53
  ```tsx
54
- import { Checkbox, CheckboxGroup } from 'zkit-ui';
54
+ import { Checkbox, CheckboxGroup } from 'zkit-ui/checkbox';
55
55
  import { wp } from 'zkit-tools';
56
56
 
57
57
  const options = [
@@ -13,7 +13,8 @@ DatePicker 是日期语义组件,底层复用 Picker 的三端滚轮与 Sheet
13
13
 
14
14
  ```tsx
15
15
  import * as React from 'react';
16
- import { Button, DatePicker } from 'zkit-ui';
16
+ import { Button } from 'zkit-ui/button';
17
+ import { DatePicker } from 'zkit-ui/date-picker';
17
18
 
18
19
  export function Demo() {
19
20
  const [value, setValue] = React.useState<string | null>(null);
@@ -10,6 +10,8 @@ import {
10
10
  import { useI18n } from '../../i18n/useI18n';
11
11
  import {
12
12
  buildDatePickerOptions,
13
+ createDatePickerOptionChildrenResolver,
14
+ createDatePickerOptionDisabledResolver,
13
15
  createDatePickerSelection,
14
16
  createDatePickerSelectionFromDate,
15
17
  DATE_PICKER_COLUMNS,
@@ -138,10 +140,19 @@ export const DatePicker = React.forwardRef<DatePickerHandle, DatePickerProps>(fu
138
140
  const committedValue = isValueControlled ? valueProp : innerValue;
139
141
 
140
142
  const bounds = React.useMemo(() => resolveDatePickerBounds(min, max), [max, min]);
141
- const options = React.useMemo(
142
- () => buildDatePickerOptions({ bounds, precision, isDateDisabled }),
143
+ const optionConfig = React.useMemo(
144
+ () => ({ bounds, precision, isDateDisabled }),
143
145
  [bounds, isDateDisabled, precision]
144
146
  );
147
+ const options = React.useMemo(() => buildDatePickerOptions(optionConfig), [optionConfig]);
148
+ const getDateOptionChildren = React.useMemo(
149
+ () => createDatePickerOptionChildrenResolver(optionConfig),
150
+ [optionConfig]
151
+ );
152
+ const isDateOptionDisabled = React.useMemo(
153
+ () => createDatePickerOptionDisabledResolver(optionConfig, getDateOptionChildren),
154
+ [getDateOptionChildren, optionConfig]
155
+ );
145
156
  const committedDate = React.useMemo(
146
157
  () => resolveCommittedDate(committedValue, bounds, precision),
147
158
  [bounds, committedValue, precision]
@@ -154,9 +165,15 @@ export const DatePicker = React.forwardRef<DatePickerHandle, DatePickerProps>(fu
154
165
  const committedSelection = React.useMemo(
155
166
  () =>
156
167
  committedDate
157
- ? createDatePickerSelectionFromDate(committedDate, precision, options, labelFormat)
168
+ ? createDatePickerSelectionFromDate(
169
+ committedDate,
170
+ precision,
171
+ options,
172
+ labelFormat,
173
+ getDateOptionChildren
174
+ )
158
175
  : null,
159
- [committedDate, labelFormat, options, precision]
176
+ [committedDate, getDateOptionChildren, labelFormat, options, precision]
160
177
  );
161
178
 
162
179
  const resolveSelection = React.useCallback(
@@ -281,6 +298,8 @@ export const DatePicker = React.forwardRef<DatePickerHandle, DatePickerProps>(fu
281
298
  emptyText={emptyText}
282
299
  formatLabel={formatPickerLabel}
283
300
  renderColumnHeader={handleRenderColumnHeader}
301
+ getOptionChildren={getDateOptionChildren}
302
+ isOptionDisabled={isDateOptionDisabled}
284
303
  maxColumns={getColumnCount(precision)}
285
304
  lazyContent={lazyContent}
286
305
  sheetHeight={sheetHeight}
@@ -51,6 +51,18 @@ type BuildOptionsConfig = {
51
51
  isDateDisabled?: DatePickerProps['isDateDisabled'];
52
52
  };
53
53
 
54
+ export type DatePickerOptionChildrenResolver = (
55
+ option: DatePickerOption,
56
+ index: number,
57
+ path: DatePickerOption[]
58
+ ) => readonly DatePickerOption[] | undefined;
59
+
60
+ export type DatePickerOptionDisabledResolver = (
61
+ option: DatePickerOption,
62
+ index: number,
63
+ path: DatePickerOption[]
64
+ ) => boolean;
65
+
54
66
  function pad2(n: number) {
55
67
  return String(n).padStart(2, '0');
56
68
  }
@@ -261,11 +273,6 @@ function buildMonths(year: number, config: BuildOptionsConfig) {
261
273
  : false
262
274
  );
263
275
 
264
- if (precision === 'day') {
265
- option.children = buildDays(year, month, config);
266
- option.disabled = option.children.length > 0 && option.children.every((child) => child.disabled);
267
- }
268
-
269
276
  months.push(option);
270
277
  }
271
278
 
@@ -286,17 +293,81 @@ export function buildDatePickerOptions(config: BuildOptionsConfig) {
286
293
  : false
287
294
  );
288
295
 
289
- if (precision !== 'year') {
290
- option.children = buildMonths(year, config);
291
- option.disabled = option.children.length > 0 && option.children.every((child) => child.disabled);
292
- }
293
-
294
296
  years.push(option);
295
297
  }
296
298
 
297
299
  return years;
298
300
  }
299
301
 
302
+ export function createDatePickerOptionChildrenResolver(
303
+ config: BuildOptionsConfig
304
+ ): DatePickerOptionChildrenResolver {
305
+ const cache = new Map<string, DatePickerOption[]>();
306
+
307
+ return (option) => {
308
+ if (option.column === 'year' && config.precision !== 'year') {
309
+ const key = `months:${option.year}`;
310
+ const cached = cache.get(key);
311
+ if (cached) return cached;
312
+
313
+ const months = buildMonths(option.year, config);
314
+ cache.set(key, months);
315
+ return months;
316
+ }
317
+
318
+ if (option.column === 'month' && config.precision === 'day' && option.month != null) {
319
+ const key = `days:${option.year}-${option.month}`;
320
+ const cached = cache.get(key);
321
+ if (cached) return cached;
322
+
323
+ const days = buildDays(option.year, option.month, config);
324
+ cache.set(key, days);
325
+ return days;
326
+ }
327
+
328
+ return [];
329
+ };
330
+ }
331
+
332
+ function getOptionPathKey(option: DatePickerOption) {
333
+ return `${option.column}:${option.year}-${option.month ?? 0}-${option.day ?? 0}`;
334
+ }
335
+
336
+ export function createDatePickerOptionDisabledResolver(
337
+ config: BuildOptionsConfig,
338
+ getOptionChildren: DatePickerOptionChildrenResolver
339
+ ): DatePickerOptionDisabledResolver {
340
+ const cache = new Map<string, boolean>();
341
+
342
+ const resolveOption = (
343
+ option: DatePickerOption,
344
+ index: number,
345
+ path: DatePickerOption[]
346
+ ): boolean => {
347
+ const key = getOptionPathKey(option);
348
+ const cached = cache.get(key);
349
+ if (cached != null) return cached;
350
+
351
+ let disabled = false;
352
+
353
+ if (option.column === config.precision) {
354
+ disabled =
355
+ option.disabled ??
356
+ resolveDisabled(optionDate(option), option, option.column, config.precision, config.isDateDisabled);
357
+ } else if (config.isDateDisabled) {
358
+ const children = getOptionChildren(option, index, path) ?? [];
359
+ disabled =
360
+ children.length > 0 &&
361
+ children.every((child, childIndex) => resolveOption(child, childIndex, [...path, child]));
362
+ }
363
+
364
+ cache.set(key, disabled);
365
+ return disabled;
366
+ };
367
+
368
+ return resolveOption;
369
+ }
370
+
300
371
  function numberValues(values: PickerSelection<DatePickerOption>['values']) {
301
372
  return values.map((value) => Number(value)).filter((value) => Number.isFinite(value));
302
373
  }
@@ -348,11 +419,16 @@ export function createDatePickerSelection(
348
419
  };
349
420
  }
350
421
 
351
- function findOptionPath(options: DatePickerOption[], values: number[]) {
422
+ function findOptionPath(
423
+ options: DatePickerOption[],
424
+ values: number[],
425
+ getOptionChildren?: DatePickerOptionChildrenResolver
426
+ ) {
352
427
  const items: DatePickerOption[] = [];
353
428
  const columns: DatePickerOption[][] = [];
354
429
  const indices: number[] = [];
355
430
  let current = options;
431
+ let path: DatePickerOption[] = [];
356
432
 
357
433
  for (const value of values) {
358
434
  columns.push(current);
@@ -364,7 +440,9 @@ function findOptionPath(options: DatePickerOption[], values: number[]) {
364
440
 
365
441
  items.push(item);
366
442
  indices.push(index);
367
- current = Array.isArray(item.children) ? item.children : [];
443
+ const nextPath = [...path, item];
444
+ current = [...(getOptionChildren?.(item, index, nextPath) ?? item.children ?? [])];
445
+ path = nextPath;
368
446
  }
369
447
 
370
448
  return { items, columns, indices };
@@ -374,10 +452,11 @@ export function createDatePickerSelectionFromDate(
374
452
  date: Dayjs,
375
453
  precision: DatePickerPrecision,
376
454
  options: DatePickerOption[],
377
- labelFormat?: DatePickerLabelFormat
455
+ labelFormat?: DatePickerLabelFormat,
456
+ getOptionChildren?: DatePickerOptionChildrenResolver
378
457
  ): DatePickerSelection {
379
458
  const values = pathFromDate(date, precision);
380
- const { items, columns, indices } = findOptionPath(options, values);
459
+ const { items, columns, indices } = findOptionPath(options, values, getOptionChildren);
381
460
  const labels = values.map((value, index) => (index === 0 ? String(value) : pad2(value)));
382
461
  const base: DatePickerSelection = {
383
462
  value: formatDatePickerValue(date, precision),
@@ -8,7 +8,8 @@
8
8
 
9
9
  ```tsx
10
10
  import { View } from 'react-native';
11
- import { LinkedScroll, Text } from 'zkit-ui';
11
+ import { Text } from 'zkit-ui/text';
12
+ import { LinkedScroll } from 'zkit-ui/linked-scroll';
12
13
  import { wp } from 'zkit-tools';
13
14
 
14
15
  const items = [
@@ -11,7 +11,8 @@
11
11
 
12
12
  ```tsx
13
13
  import * as React from 'react';
14
- import { Picker, Text } from 'zkit-ui';
14
+ import { Text } from 'zkit-ui/text';
15
+ import { Picker } from 'zkit-ui/picker';
15
16
 
16
17
  const options = [
17
18
  { value: 'design', label: 'Design' },
@@ -17,7 +17,8 @@ Radio 是三端一致的单选组件,适合互斥选项、设置项模式选
17
17
 
18
18
  ```tsx
19
19
  import * as React from 'react';
20
- import { Radio, RadioGroup, Text } from 'zkit-ui';
20
+ import { Text } from 'zkit-ui/text';
21
+ import { Radio, RadioGroup } from 'zkit-ui/radio';
21
22
  import { wp } from 'zkit-tools';
22
23
 
23
24
  type Density = 'compact' | 'comfortable' | 'spacious';
@@ -6,7 +6,9 @@
6
6
 
7
7
  ```tsx
8
8
  import * as React from 'react';
9
- import { Button, Sheet, Text } from 'zkit-ui';
9
+ import { Text } from 'zkit-ui/text';
10
+ import { Button } from 'zkit-ui/button';
11
+ import { Sheet } from 'zkit-ui/sheet';
10
12
 
11
13
  export function Demo() {
12
14
  const [open, setOpen] = React.useState(false);
@@ -19,7 +19,7 @@
19
19
 
20
20
  ```tsx
21
21
  import * as React from 'react';
22
- import { SliderCaptcha, type SliderCaptchaChallenge } from 'zkit-ui';
22
+ import { SliderCaptcha, type SliderCaptchaChallenge } from 'zkit-ui/slider-captcha';
23
23
 
24
24
  type LoginCaptchaChallenge = SliderCaptchaChallenge & {
25
25
  nonceStr: string;
@@ -14,7 +14,7 @@ Switch 是布尔开关组件,适合“立即启用/停用某项设置”的场
14
14
 
15
15
  ```tsx
16
16
  import * as React from 'react';
17
- import { Switch } from 'zkit-ui';
17
+ import { Switch } from 'zkit-ui/switch';
18
18
 
19
19
  export function Demo() {
20
20
  const [checked, setChecked] = React.useState(false);
@@ -17,7 +17,7 @@
17
17
  ## 基础用法
18
18
 
19
19
  ```tsx
20
- import { Text } from 'zkit-ui';
20
+ import { Text } from 'zkit-ui/text';
21
21
 
22
22
  export function Demo() {
23
23
  return <Text>默认正文</Text>;
@@ -35,7 +35,7 @@ export function Demo() {
35
35
  ## 排版语义
36
36
 
37
37
  ```tsx
38
- import { Text } from 'zkit-ui';
38
+ import { Text } from 'zkit-ui/text';
39
39
 
40
40
  export function Demo() {
41
41
  return (
@@ -17,7 +17,7 @@
17
17
 
18
18
  ```tsx
19
19
  import * as React from 'react';
20
- import { TextInput } from 'zkit-ui';
20
+ import { TextInput } from 'zkit-ui/text-input';
21
21
 
22
22
  export function Demo() {
23
23
  const [value, setValue] = React.useState('');
@@ -36,7 +36,7 @@ export function Demo() {
36
36
  ## 原生薄封装
37
37
 
38
38
  ```tsx
39
- import { TextInputPrimitive } from 'zkit-ui';
39
+ import { TextInputPrimitive } from 'zkit-ui/text-input';
40
40
  import { wp } from 'zkit-tools';
41
41
 
42
42
  export function Demo() {
@@ -54,7 +54,7 @@ export function Demo() {
54
54
  ## 非受控
55
55
 
56
56
  ```tsx
57
- import { TextInput } from 'zkit-ui';
57
+ import { TextInput } from 'zkit-ui/text-input';
58
58
 
59
59
  export function Demo() {
60
60
  return (
@@ -72,7 +72,7 @@ export function Demo() {
72
72
  ## 描述、错误和计数
73
73
 
74
74
  ```tsx
75
- import { TextInput } from 'zkit-ui';
75
+ import { TextInput } from 'zkit-ui/text-input';
76
76
 
77
77
  export function Demo() {
78
78
  return (
@@ -95,7 +95,7 @@ export function Demo() {
95
95
  ## 前后缀与清除按钮
96
96
 
97
97
  ```tsx
98
- import { TextInput } from 'zkit-ui';
98
+ import { TextInput } from 'zkit-ui/text-input';
99
99
 
100
100
  export function Demo() {
101
101
  return (
@@ -116,7 +116,7 @@ export function Demo() {
116
116
  ## 外观
117
117
 
118
118
  ```tsx
119
- import { TextInput } from 'zkit-ui';
119
+ import { TextInput } from 'zkit-ui/text-input';
120
120
  import { wp } from 'zkit-tools';
121
121
 
122
122
  export function Demo() {
@@ -14,7 +14,7 @@
14
14
  ## 基础用法
15
15
 
16
16
  ```tsx
17
- import { WheelColumn, type WheelColumnOption } from 'zkit-ui';
17
+ import { WheelColumn, type WheelColumnOption } from 'zkit-ui/wheel-column';
18
18
  import { wp } from 'zkit-tools';
19
19
 
20
20
  const options: WheelColumnOption[] = [