@tarojs/components-react 4.1.12-beta.60 → 4.1.12-beta.62

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 (25) hide show
  1. package/dist/components/picker/index.js +10 -0
  2. package/dist/components/picker/index.js.map +1 -1
  3. package/dist/components/picker/picker-group-legacy.js +936 -0
  4. package/dist/components/picker/picker-group-legacy.js.map +1 -0
  5. package/dist/components/picker/picker-group-slider.js +1046 -0
  6. package/dist/components/picker/picker-group-slider.js.map +1 -0
  7. package/dist/components/picker/picker-group.js +37 -926
  8. package/dist/components/picker/picker-group.js.map +1 -1
  9. package/dist/original/components/picker/index.js +10 -0
  10. package/dist/original/components/picker/index.js.map +1 -1
  11. package/dist/original/components/picker/picker-group-legacy.js +936 -0
  12. package/dist/original/components/picker/picker-group-legacy.js.map +1 -0
  13. package/dist/original/components/picker/picker-group-slider.js +1046 -0
  14. package/dist/original/components/picker/picker-group-slider.js.map +1 -0
  15. package/dist/original/components/picker/picker-group.js +37 -926
  16. package/dist/original/components/picker/picker-group.js.map +1 -1
  17. package/dist/solid/components/picker/index.js +10 -0
  18. package/dist/solid/components/picker/index.js.map +1 -1
  19. package/dist/solid/components/picker/picker-group-legacy.js +952 -0
  20. package/dist/solid/components/picker/picker-group-legacy.js.map +1 -0
  21. package/dist/solid/components/picker/picker-group-slider.js +1071 -0
  22. package/dist/solid/components/picker/picker-group-slider.js.map +1 -0
  23. package/dist/solid/components/picker/picker-group.js +33 -942
  24. package/dist/solid/components/picker/picker-group.js.map +1 -1
  25. package/package.json +6 -6
@@ -0,0 +1,1071 @@
1
+ import { createComponent, mergeProps } from 'solid-js/web';
2
+ import { View, ScrollView } from '@tarojs/components';
3
+ import Taro from '@tarojs/taro';
4
+ import * as React from 'react';
5
+
6
+ /** 部分端同 id 连续 scrollIntoView 不生效:先清空再在下一宏任务设回目标 id */
7
+ function usePickerItemScrollIntoView() {
8
+ const [scrollIntoView, setScrollIntoView] = React.useState('');
9
+ const pulseRef = React.useRef(0);
10
+ const scrollToItemId = React.useCallback(itemId => {
11
+ pulseRef.current += 1;
12
+ const token = pulseRef.current;
13
+ setScrollIntoView('');
14
+ setTimeout(() => {
15
+ if (pulseRef.current !== token) return;
16
+ setScrollIntoView(itemId);
17
+ }, 0);
18
+ }, []);
19
+ return [scrollIntoView, scrollToItemId];
20
+ }
21
+ // 定义常量
22
+ const PICKER_LINE_HEIGHT = 34; // px
23
+ const PICKER_VISIBLE_ITEMS = 7; // 可见行数
24
+ const PICKER_BLANK_ITEMS = 3; // 空白行数
25
+ const getIndicatorStyle = lineColor => {
26
+ return {
27
+ borderTopColor: lineColor,
28
+ borderBottomColor: lineColor
29
+ };
30
+ };
31
+ // 大屏方案版本要求
32
+ const MIN_DESIGN_APP_VERSION = 16;
33
+ // 判断是否启用测量值缩放适配(true=启用, false=使用系统侧缩放)
34
+ const resolveUseMeasuredScale = res => {
35
+ // H5/weapp 不参与大屏系数
36
+ if (process.env.TARO_ENV === 'h5' || process.env.TARO_ENV === 'weapp') {
37
+ return false;
38
+ }
39
+ const designAppVersionRaw = res.designAppVersion;
40
+ const designAppVersionMajor = designAppVersionRaw != null ? parseInt(String(designAppVersionRaw).trim(), 10) : Number.NaN;
41
+ if (!Number.isFinite(designAppVersionMajor) || designAppVersionMajor < MIN_DESIGN_APP_VERSION) {
42
+ return false;
43
+ }
44
+ const platform = String(res.platform || '').toLowerCase();
45
+ if (platform === 'harmony' || platform === 'android' || platform === 'ios') {
46
+ return true;
47
+ }
48
+ return false;
49
+ };
50
+ // 辅助函数:计算 lengthScaleRatio
51
+ const calculateLengthScaleRatio = res => {
52
+ let lengthScaleRatio = res === null || res === void 0 ? void 0 : res.lengthScaleRatio;
53
+ if (lengthScaleRatio == null || lengthScaleRatio === 0) {
54
+ console.warn('Taro.getSystemInfo: lengthScaleRatio 不存在,使用计算值');
55
+ lengthScaleRatio = 1;
56
+ if (res.windowWidth < 320) {
57
+ lengthScaleRatio = res.windowWidth / 320;
58
+ } else if (res.windowWidth >= 400 && res.windowWidth < 600) {
59
+ lengthScaleRatio = res.windowWidth / 400;
60
+ }
61
+ const shortSide = res.windowWidth < res.windowHeight ? res.windowWidth : res.windowHeight;
62
+ const isBigScreen = shortSide >= 600;
63
+ if (isBigScreen) {
64
+ lengthScaleRatio = shortSide / 720;
65
+ }
66
+ }
67
+ return lengthScaleRatio;
68
+ };
69
+ // 辅助函数:获取系统信息的 lengthScaleRatio 并设置 targetScrollTop
70
+ const setTargetScrollTopWithScale = function (setTargetScrollTop, baseValue, randomOffset) {
71
+ let lengthScaleRatio = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 1;
72
+ // H5 和 weapp 不参与放大计算,直接使用 baseValue
73
+ if (process.env.TARO_ENV === 'h5' || process.env.TARO_ENV === 'weapp') {
74
+ const finalValue = randomOffset !== undefined ? baseValue + randomOffset : baseValue;
75
+ setTargetScrollTop(finalValue);
76
+ return;
77
+ }
78
+ if (process.env.TARO_PLATFORM === 'harmony') {
79
+ const scaledValue = baseValue;
80
+ const finalValue = randomOffset !== undefined ? scaledValue + randomOffset : scaledValue;
81
+ setTargetScrollTop(finalValue);
82
+ } else {
83
+ const scaledValue = baseValue * lengthScaleRatio;
84
+ const finalValue = randomOffset !== undefined ? scaledValue + randomOffset : scaledValue;
85
+ setTargetScrollTop(finalValue);
86
+ }
87
+ };
88
+ // 根据 scrollTop 计算选中索引
89
+ // 系统侧缩放模式:scrollHeight 已被系统缩放,直接相除即可
90
+ // 自行缩放模式:需要除以 ratio 换算(harmony 特殊处理,ratio 已内嵌在 itemHeight 中)
91
+ const getSelectedIndex = function (scrollTop, itemHeight) {
92
+ let lengthScaleRatio = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
93
+ let useMeasuredScale = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
94
+ if (!useMeasuredScale || process.env.TARO_PLATFORM === 'harmony') {
95
+ return Math.round(scrollTop / itemHeight);
96
+ }
97
+ return Math.round(scrollTop / lengthScaleRatio / itemHeight);
98
+ };
99
+ // 计算单项高度(返回设计稿值)
100
+ const calculateItemHeight = function (scrollView, lengthScaleRatio) {
101
+ let useMeasuredScale = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
102
+ if (process.env.TARO_PLATFORM === 'harmony') {
103
+ return useMeasuredScale ? PICKER_LINE_HEIGHT * lengthScaleRatio : PICKER_LINE_HEIGHT;
104
+ }
105
+ if (scrollView && (scrollView === null || scrollView === void 0 ? void 0 : scrollView.scrollHeight)) {
106
+ return useMeasuredScale ? scrollView.scrollHeight / lengthScaleRatio / scrollView.childNodes.length : scrollView.scrollHeight / scrollView.childNodes.length;
107
+ }
108
+ console.warn('Height measurement anomaly');
109
+ return PICKER_LINE_HEIGHT;
110
+ };
111
+ function PickerGroupBasic(props) {
112
+ const {
113
+ range = [],
114
+ rangeKey,
115
+ columnId,
116
+ updateIndex,
117
+ onColumnChange,
118
+ selectedIndex = 0,
119
+ // 使用selectedIndex参数,默认为0
120
+ colors = {},
121
+ enableClickItemScroll = true
122
+ } = props;
123
+ const indicatorStyle = colors.lineColor ? getIndicatorStyle(colors.lineColor) : null;
124
+ const [targetScrollTop, setTargetScrollTop] = React.useState(0);
125
+ const [scrollIntoView, scrollToItemId] = usePickerItemScrollIntoView();
126
+ const scrollViewRef = React.useRef(null);
127
+ // 使用selectedIndex初始化当前索引
128
+ const [currentIndex, setCurrentIndex] = React.useState(selectedIndex);
129
+ // 触摸状态用于优化用户体验
130
+ const isTouchingRef = React.useRef(false);
131
+ const lengthScaleRatioRef = React.useRef(1);
132
+ const useMeasuredScaleRef = React.useRef(false);
133
+ const itemHeightRef = React.useRef(PICKER_LINE_HEIGHT);
134
+ // 初始化时计算 lengthScaleRatio 并判定缩放模式
135
+ React.useEffect(() => {
136
+ Taro.getSystemInfo({
137
+ success: res => {
138
+ lengthScaleRatioRef.current = calculateLengthScaleRatio(res);
139
+ useMeasuredScaleRef.current = resolveUseMeasuredScale(res);
140
+ itemHeightRef.current = calculateItemHeight(scrollViewRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
141
+ },
142
+ fail: () => {
143
+ lengthScaleRatioRef.current = 1;
144
+ useMeasuredScaleRef.current = false;
145
+ }
146
+ });
147
+ }, []);
148
+ React.useEffect(() => {
149
+ itemHeightRef.current = calculateItemHeight(scrollViewRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
150
+ }, [range.length]); // 只在range长度变化时重新计算
151
+ // 滚动到指定索引(供程序化对齐与无障碍步进复用)
152
+ const scrollToIndex = React.useCallback(function (index) {
153
+ let withRandomOffset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
154
+ const baseValue = index * itemHeightRef.current;
155
+ const randomOffset = withRandomOffset ? Math.random() * 0.001 : undefined;
156
+ setTargetScrollTopWithScale(setTargetScrollTop, baseValue, randomOffset, lengthScaleRatioRef.current);
157
+ }, []);
158
+ // props 的 selectedIndex 变化:滚至对应项
159
+ React.useEffect(() => {
160
+ if (scrollViewRef.current && range.length > 0 && !isTouchingRef.current) {
161
+ scrollToIndex(selectedIndex);
162
+ setCurrentIndex(selectedIndex);
163
+ }
164
+ }, [selectedIndex, range, scrollToIndex]);
165
+ // 是否处于归中状态
166
+ const isCenterTimerId = React.useRef(null);
167
+ // 滚动静止后归中并同步选中
168
+ const handleScrollEnd = () => {
169
+ if (!scrollViewRef.current) return;
170
+ if (isCenterTimerId.current) {
171
+ clearTimeout(isCenterTimerId.current);
172
+ isCenterTimerId.current = null;
173
+ }
174
+ // 100ms 内无新滚动则归中并提交索引
175
+ isCenterTimerId.current = setTimeout(() => {
176
+ if (!scrollViewRef.current) return;
177
+ const scrollTop = scrollViewRef.current.scrollTop;
178
+ const newIndex = getSelectedIndex(scrollTop, itemHeightRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
179
+ isTouchingRef.current = false;
180
+ scrollToIndex(newIndex, true);
181
+ updateIndex(newIndex, columnId);
182
+ onColumnChange === null || onColumnChange === void 0 ? void 0 : onColumnChange({
183
+ columnId,
184
+ index: newIndex
185
+ });
186
+ isCenterTimerId.current = null;
187
+ }, 100);
188
+ };
189
+ // 滚动中:按 scrollTop 更新高亮索引
190
+ const handleScroll = () => {
191
+ if (!scrollViewRef.current) return;
192
+ if (isCenterTimerId.current) {
193
+ clearTimeout(isCenterTimerId.current);
194
+ isCenterTimerId.current = null;
195
+ }
196
+ const scrollTop = scrollViewRef.current.scrollTop;
197
+ const ih = itemHeightRef.current;
198
+ const newIndex = getSelectedIndex(scrollTop, ih, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
199
+ if (newIndex !== currentIndex) {
200
+ setCurrentIndex(newIndex);
201
+ }
202
+ };
203
+ // 无障碍:整列作单 slider,转子 increment/decrement 切相邻项
204
+ const clampIndex = index => Math.max(0, Math.min(index, range.length - 1));
205
+ // 切换后主动播报当前项:焦点停在 slider 容器上,aria 属性更新读屏不会自动重读,需主动触发
206
+ const announceIndex = index => {
207
+ const item = range[index];
208
+ const content = rangeKey && item && typeof item === 'object' ? item[rangeKey] : item;
209
+ const text = content != null ? String(content) : '';
210
+ if (!text) return;
211
+ const fn = Taro.accessibilityAnnounce;
212
+ if (typeof fn !== 'function') return;
213
+ fn({
214
+ announce: text,
215
+ delay: 300
216
+ });
217
+ };
218
+ const commitIndexByA11y = nextIndex => {
219
+ const clamped = clampIndex(nextIndex);
220
+ if (clamped === currentIndex) return;
221
+ isTouchingRef.current = false;
222
+ setCurrentIndex(clamped);
223
+ scrollToIndex(clamped, true);
224
+ updateIndex(clamped, columnId);
225
+ onColumnChange === null || onColumnChange === void 0 ? void 0 : onColumnChange({
226
+ columnId,
227
+ index: clamped
228
+ });
229
+ announceIndex(clamped);
230
+ };
231
+ const handleAriaAction = e => {
232
+ var _a;
233
+ const actionName = (_a = e === null || e === void 0 ? void 0 : e.detail) === null || _a === void 0 ? void 0 : _a.actionName;
234
+ if (actionName === 'increment') {
235
+ commitIndexByA11y(currentIndex + 1);
236
+ } else if (actionName === 'decrement') {
237
+ commitIndexByA11y(currentIndex - 1);
238
+ }
239
+ };
240
+ // 无障碍 label:当前项值(用 rangeKey 取显示值),仅 string 或 number(转 string)挂载,对象等其它类型不挂载
241
+ const currentItem = range[currentIndex];
242
+ const currentValue = rangeKey && currentItem && typeof currentItem === 'object' ? currentItem[rangeKey] : currentItem;
243
+ const ariaLabel = typeof currentValue === 'string' ? currentValue : typeof currentValue === 'number' ? String(currentValue) : undefined;
244
+ // 渲染选项
245
+ const pickerItem = range.map((item, index) => {
246
+ const content = rangeKey && item && typeof item === 'object' ? item[rangeKey] : item;
247
+ return createComponent(View, mergeProps({
248
+ id: `picker-item-${columnId}-${index}`,
249
+ key: index,
250
+ ariaHidden: true,
251
+ className: `taro-picker__item${index === currentIndex ? ' taro-picker__item--selected' : ''}`
252
+ }, enableClickItemScroll ? {
253
+ onClick: () => scrollToItemId(`picker-item-${columnId}-${index}`)
254
+ } : {}, {
255
+ get style() {
256
+ return {
257
+ height: PICKER_LINE_HEIGHT,
258
+ color: index === currentIndex ? colors.itemSelectedColor || undefined : colors.itemDefaultColor || undefined
259
+ };
260
+ },
261
+ children: content
262
+ }));
263
+ });
264
+ const realPickerItems = [...new Array(PICKER_BLANK_ITEMS).fill(null).map((_, idx) => createComponent(View, {
265
+ key: `blank-top-${idx}`,
266
+ ariaHidden: true,
267
+ className: "taro-picker__item taro-picker__item--blank",
268
+ style: {
269
+ height: PICKER_LINE_HEIGHT
270
+ }
271
+ })), ...pickerItem, ...new Array(PICKER_BLANK_ITEMS).fill(null).map((_, idx) => createComponent(View, {
272
+ key: `blank-bottom-${idx}`,
273
+ ariaHidden: true,
274
+ className: "taro-picker__item taro-picker__item--blank",
275
+ style: {
276
+ height: PICKER_LINE_HEIGHT
277
+ }
278
+ }))];
279
+ const clickScrollViewProps = enableClickItemScroll ? {
280
+ scrollIntoView,
281
+ scrollIntoViewAlignment: 'center'
282
+ } : {};
283
+ return createComponent(View, {
284
+ className: "taro-picker__group",
285
+ style: {
286
+ position: 'relative'
287
+ },
288
+ get children() {
289
+ return [createComponent(View, {
290
+ className: "taro-picker__mask",
291
+ ariaHidden: true
292
+ }), createComponent(View, mergeProps({
293
+ className: "taro-picker__indicator",
294
+ ariaHidden: true
295
+ }, indicatorStyle ? {
296
+ style: indicatorStyle
297
+ } : {})), createComponent(ScrollView, mergeProps({
298
+ ref: scrollViewRef,
299
+ scrollY: true,
300
+ showScrollbar: false,
301
+ className: "taro-picker__content",
302
+ ariaHidden: true
303
+ }, {
304
+ accessibilityElementsHidden: true,
305
+ importantForAccessibility: 'no-hide-descendants'
306
+ }, {
307
+ style: {
308
+ height: PICKER_LINE_HEIGHT * PICKER_VISIBLE_ITEMS
309
+ },
310
+ scrollTop: targetScrollTop
311
+ }, clickScrollViewProps, {
312
+ onScroll: handleScroll,
313
+ onTouchStart: () => {
314
+ isTouchingRef.current = true;
315
+ },
316
+ onScrollEnd: handleScrollEnd,
317
+ scrollWithAnimation: true,
318
+ children: realPickerItems
319
+ })), createComponent(View, mergeProps({
320
+ className: "taro-picker__a11y-overlay",
321
+ style: {
322
+ position: 'absolute',
323
+ top: 0,
324
+ left: 0,
325
+ right: 0,
326
+ bottom: 0,
327
+ pointerEvents: 'none'
328
+ },
329
+ ariaRole: "slider"
330
+ }, ariaLabel !== undefined ? {
331
+ ariaLabel
332
+ } : {}, {
333
+ ariaAction: [{
334
+ name: 'increment',
335
+ label: 'increment'
336
+ }, {
337
+ name: 'decrement',
338
+ label: 'decrement'
339
+ }],
340
+ onAriaAction: handleAriaAction
341
+ }))];
342
+ }
343
+ });
344
+ }
345
+ // 时间选择器实现
346
+ function PickerGroupTime(props) {
347
+ const {
348
+ range = [],
349
+ rangeKey,
350
+ columnId,
351
+ updateIndex,
352
+ selectedIndex = 0,
353
+ colors = {},
354
+ timeA11yLimitFocus,
355
+ timeA11yLimitEventNonce,
356
+ enableClickItemScroll = true
357
+ } = props;
358
+ const indicatorStyle = colors.lineColor ? getIndicatorStyle(colors.lineColor) : null;
359
+ const [targetScrollTop, setTargetScrollTop] = React.useState(0);
360
+ const [scrollIntoView, scrollToItemId] = usePickerItemScrollIntoView();
361
+ const scrollViewRef = React.useRef(null);
362
+ const [currentIndex, setCurrentIndex] = React.useState(selectedIndex);
363
+ const isTouchingRef = React.useRef(false);
364
+ const lengthScaleRatioRef = React.useRef(1);
365
+ const useMeasuredScaleRef = React.useRef(false);
366
+ const itemHeightRef = React.useRef(PICKER_LINE_HEIGHT);
367
+ // 初始化时计算 lengthScaleRatio 并判定缩放模式
368
+ React.useEffect(() => {
369
+ Taro.getSystemInfo({
370
+ success: res => {
371
+ lengthScaleRatioRef.current = calculateLengthScaleRatio(res);
372
+ useMeasuredScaleRef.current = resolveUseMeasuredScale(res);
373
+ itemHeightRef.current = calculateItemHeight(scrollViewRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
374
+ },
375
+ fail: () => {
376
+ lengthScaleRatioRef.current = 1;
377
+ useMeasuredScaleRef.current = false;
378
+ }
379
+ });
380
+ }, []);
381
+ React.useEffect(() => {
382
+ itemHeightRef.current = calculateItemHeight(scrollViewRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
383
+ }, [range.length]); // 只在range长度变化时重新计算
384
+ // 滚动到指定索引(供程序化对齐与无障碍步进复用)
385
+ const scrollToIndex = React.useCallback(function (index) {
386
+ let withRandomOffset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
387
+ const baseValue = index * itemHeightRef.current;
388
+ const randomOffset = withRandomOffset ? Math.random() * 0.001 : undefined;
389
+ setTargetScrollTopWithScale(setTargetScrollTop, baseValue, randomOffset, lengthScaleRatioRef.current);
390
+ }, []);
391
+ // props 的 selectedIndex 变化:滚至对应项
392
+ React.useEffect(() => {
393
+ if (scrollViewRef.current && range.length > 0 && !isTouchingRef.current) {
394
+ scrollToIndex(selectedIndex);
395
+ setCurrentIndex(selectedIndex);
396
+ }
397
+ }, [selectedIndex, range, scrollToIndex]);
398
+ // 限位回弹强制对齐:限位后即使 selectedIndex 值不变(回弹到同一边界),nonce 变化也强制重新对齐 scrollTop
399
+ React.useEffect(() => {
400
+ if (!timeA11yLimitEventNonce) return;
401
+ if (!scrollViewRef.current || range.length === 0 || isTouchingRef.current) return;
402
+ scrollToIndex(selectedIndex, true);
403
+ setCurrentIndex(selectedIndex);
404
+ // 仅被限位触发的列在回弹稳定后补播报一次修正值(nonce 两列共享,需按 columnId 过滤)
405
+ if (timeA11yLimitFocus && timeA11yLimitFocus.columnId === columnId) {
406
+ const item = range[selectedIndex];
407
+ const content = rangeKey && item && typeof item === 'object' ? item[rangeKey] : item;
408
+ const text = content != null ? String(content) : '';
409
+ const fn = Taro.accessibilityAnnounce;
410
+ if (text && typeof fn === 'function') {
411
+ fn({
412
+ announce: text,
413
+ delay: 300
414
+ });
415
+ }
416
+ }
417
+ }, [timeA11yLimitEventNonce]); // 仅依赖 nonce,其余用 ref
418
+ // 是否处于归中状态
419
+ const isCenterTimerId = React.useRef(null);
420
+ // 滚动静止后归中并同步选中(保留 time 限位业务:超 start/end 由父级修正后经 selectedIndex 回弹)
421
+ const handleScrollEnd = () => {
422
+ if (!scrollViewRef.current) return;
423
+ if (isCenterTimerId.current) {
424
+ clearTimeout(isCenterTimerId.current);
425
+ isCenterTimerId.current = null;
426
+ }
427
+ // 100ms 内无新滚动则归中并提交索引
428
+ isCenterTimerId.current = setTimeout(() => {
429
+ if (!scrollViewRef.current) return;
430
+ const scrollTop = scrollViewRef.current.scrollTop;
431
+ const newIndex = getSelectedIndex(scrollTop, itemHeightRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
432
+ isTouchingRef.current = false;
433
+ const isLimited = Boolean(updateIndex(newIndex, columnId, true));
434
+ // 限位时不归中:父级会通过 selectedIndex / nonce 下发修正值触发重新对齐
435
+ if (!isLimited) {
436
+ scrollToIndex(newIndex, true);
437
+ }
438
+ isCenterTimerId.current = null;
439
+ }, 100);
440
+ };
441
+ // 滚动中:按 scrollTop 更新高亮索引
442
+ const handleScroll = () => {
443
+ if (!scrollViewRef.current) return;
444
+ if (isCenterTimerId.current) {
445
+ clearTimeout(isCenterTimerId.current);
446
+ isCenterTimerId.current = null;
447
+ }
448
+ const scrollTop = scrollViewRef.current.scrollTop;
449
+ const ih = itemHeightRef.current;
450
+ const newIndex = getSelectedIndex(scrollTop, ih, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
451
+ if (newIndex !== currentIndex) {
452
+ setCurrentIndex(newIndex);
453
+ }
454
+ };
455
+ // 无障碍:整列作单 slider,转子 increment/decrement 切相邻项(保留 time 限位)
456
+ const clampIndex = index => Math.max(0, Math.min(index, range.length - 1));
457
+ // 切换后主动播报当前项:焦点停在 slider 覆盖层上,aria 属性更新读屏不会自动重读,需主动触发
458
+ const announceIndex = index => {
459
+ const item = range[index];
460
+ const content = rangeKey && item && typeof item === 'object' ? item[rangeKey] : item;
461
+ const text = content != null ? String(content) : '';
462
+ if (!text) return;
463
+ const fn = Taro.accessibilityAnnounce;
464
+ if (typeof fn !== 'function') return;
465
+ fn({
466
+ announce: text,
467
+ delay: 300
468
+ });
469
+ };
470
+ const commitIndexByA11y = nextIndex => {
471
+ const clamped = clampIndex(nextIndex);
472
+ if (clamped === currentIndex) return;
473
+ isTouchingRef.current = false;
474
+ setCurrentIndex(clamped);
475
+ scrollToIndex(clamped, true);
476
+ // 保留 time 限位:超 start/end 时父级修正并经 selectedIndex / nonce 回弹对齐
477
+ updateIndex(clamped, columnId, true);
478
+ announceIndex(clamped);
479
+ };
480
+ const handleAriaAction = e => {
481
+ var _a;
482
+ const actionName = (_a = e === null || e === void 0 ? void 0 : e.detail) === null || _a === void 0 ? void 0 : _a.actionName;
483
+ if (actionName === 'increment') {
484
+ commitIndexByA11y(currentIndex + 1);
485
+ } else if (actionName === 'decrement') {
486
+ commitIndexByA11y(currentIndex - 1);
487
+ }
488
+ };
489
+ // 无障碍 label:当前项值,仅 string 或 number(转 string)挂载,对象等其它类型不挂载
490
+ const currentItem = range[currentIndex];
491
+ const currentValue = rangeKey && currentItem && typeof currentItem === 'object' ? currentItem[rangeKey] : currentItem;
492
+ const ariaLabel = typeof currentValue === 'string' ? currentValue : typeof currentValue === 'number' ? String(currentValue) : undefined;
493
+ // 渲染选项
494
+ const pickerItem = range.map((item, index) => {
495
+ const content = rangeKey && item && typeof item === 'object' ? item[rangeKey] : item;
496
+ return createComponent(View, mergeProps({
497
+ id: `picker-item-${columnId}-${index}`,
498
+ key: index,
499
+ ariaHidden: true,
500
+ className: `taro-picker__item${index === currentIndex ? ' taro-picker__item--selected' : ''}`
501
+ }, enableClickItemScroll ? {
502
+ onClick: () => scrollToItemId(`picker-item-${columnId}-${index}`)
503
+ } : {}, {
504
+ get style() {
505
+ return {
506
+ height: PICKER_LINE_HEIGHT,
507
+ color: index === currentIndex ? colors.itemSelectedColor || undefined : colors.itemDefaultColor || undefined
508
+ };
509
+ },
510
+ children: content
511
+ }));
512
+ });
513
+ const realPickerItems = [...new Array(PICKER_BLANK_ITEMS).fill(null).map((_, idx) => createComponent(View, {
514
+ key: `blank-top-${idx}`,
515
+ ariaHidden: true,
516
+ className: "taro-picker__item taro-picker__item--blank",
517
+ style: {
518
+ height: PICKER_LINE_HEIGHT
519
+ }
520
+ })), ...pickerItem, ...new Array(PICKER_BLANK_ITEMS).fill(null).map((_, idx) => createComponent(View, {
521
+ key: `blank-bottom-${idx}`,
522
+ ariaHidden: true,
523
+ className: "taro-picker__item taro-picker__item--blank",
524
+ style: {
525
+ height: PICKER_LINE_HEIGHT
526
+ }
527
+ }))];
528
+ const clickScrollViewProps = enableClickItemScroll ? {
529
+ scrollIntoView,
530
+ scrollIntoViewAlignment: 'center'
531
+ } : {};
532
+ return createComponent(View, {
533
+ className: "taro-picker__group",
534
+ style: {
535
+ position: 'relative'
536
+ },
537
+ get children() {
538
+ return [createComponent(View, {
539
+ className: "taro-picker__mask",
540
+ ariaHidden: true
541
+ }), createComponent(View, mergeProps({
542
+ className: "taro-picker__indicator",
543
+ ariaHidden: true
544
+ }, indicatorStyle ? {
545
+ style: indicatorStyle
546
+ } : {})), createComponent(ScrollView, mergeProps({
547
+ ref: scrollViewRef,
548
+ scrollY: true,
549
+ showScrollbar: false,
550
+ className: "taro-picker__content",
551
+ ariaHidden: true
552
+ }, {
553
+ accessibilityElementsHidden: true,
554
+ importantForAccessibility: 'no-hide-descendants'
555
+ }, {
556
+ style: {
557
+ height: PICKER_LINE_HEIGHT * PICKER_VISIBLE_ITEMS
558
+ },
559
+ scrollTop: targetScrollTop
560
+ }, clickScrollViewProps, {
561
+ onScroll: handleScroll,
562
+ onTouchStart: () => {
563
+ isTouchingRef.current = true;
564
+ },
565
+ onScrollEnd: handleScrollEnd,
566
+ scrollWithAnimation: true,
567
+ children: realPickerItems
568
+ })), createComponent(View, mergeProps({
569
+ className: "taro-picker__a11y-overlay",
570
+ style: {
571
+ position: 'absolute',
572
+ top: 0,
573
+ left: 0,
574
+ right: 0,
575
+ bottom: 0,
576
+ pointerEvents: 'none'
577
+ },
578
+ ariaRole: "slider"
579
+ }, ariaLabel !== undefined ? {
580
+ ariaLabel
581
+ } : {}, {
582
+ ariaAction: [{
583
+ name: 'increment',
584
+ label: 'increment'
585
+ }, {
586
+ name: 'decrement',
587
+ label: 'decrement'
588
+ }],
589
+ onAriaAction: handleAriaAction
590
+ }))];
591
+ }
592
+ });
593
+ }
594
+ // 日期选择器实现
595
+ function PickerGroupDate(props) {
596
+ const {
597
+ range = [],
598
+ columnId,
599
+ updateDay,
600
+ selectedIndex = 0,
601
+ colors = {},
602
+ enableClickItemScroll = true
603
+ } = props;
604
+ const indicatorStyle = colors.lineColor ? getIndicatorStyle(colors.lineColor) : null;
605
+ const [targetScrollTop, setTargetScrollTop] = React.useState(0);
606
+ const [scrollIntoView, scrollToItemId] = usePickerItemScrollIntoView();
607
+ const scrollViewRef = React.useRef(null);
608
+ const [currentIndex, setCurrentIndex] = React.useState(selectedIndex);
609
+ const isTouchingRef = React.useRef(false);
610
+ const lengthScaleRatioRef = React.useRef(1);
611
+ const useMeasuredScaleRef = React.useRef(false);
612
+ const itemHeightRef = React.useRef(PICKER_LINE_HEIGHT);
613
+ // 初始化时计算 lengthScaleRatio 并判定缩放模式
614
+ React.useEffect(() => {
615
+ Taro.getSystemInfo({
616
+ success: res => {
617
+ lengthScaleRatioRef.current = calculateLengthScaleRatio(res);
618
+ useMeasuredScaleRef.current = resolveUseMeasuredScale(res);
619
+ itemHeightRef.current = calculateItemHeight(scrollViewRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
620
+ },
621
+ fail: () => {
622
+ lengthScaleRatioRef.current = 1;
623
+ useMeasuredScaleRef.current = false;
624
+ }
625
+ });
626
+ }, []);
627
+ React.useEffect(() => {
628
+ itemHeightRef.current = calculateItemHeight(scrollViewRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
629
+ }, [range.length]); // 只在range长度变化时重新计算
630
+ // 滚动到指定索引(供程序化对齐与无障碍步进复用)
631
+ const scrollToIndex = React.useCallback(function (index) {
632
+ let withRandomOffset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
633
+ const baseValue = index * itemHeightRef.current;
634
+ const randomOffset = withRandomOffset ? Math.random() * 0.001 : undefined;
635
+ setTargetScrollTopWithScale(setTargetScrollTop, baseValue, randomOffset, lengthScaleRatioRef.current);
636
+ }, []);
637
+ // props 的 selectedIndex 变化:滚至对应项
638
+ React.useEffect(() => {
639
+ if (scrollViewRef.current && range.length > 0 && !isTouchingRef.current) {
640
+ scrollToIndex(selectedIndex);
641
+ setCurrentIndex(selectedIndex);
642
+ }
643
+ }, [selectedIndex, range, scrollToIndex]);
644
+ // 提交日期值:解析文本中的数字(移除年、月、日等后缀)后回调 updateDay
645
+ const commitDay = index => {
646
+ if (!updateDay) return;
647
+ const valueText = range[index] || '';
648
+ const numericValue = parseInt(valueText.replace(/[^0-9]/g, ''));
649
+ updateDay(isNaN(numericValue) ? 0 : numericValue, parseInt(columnId));
650
+ };
651
+ // 是否处于归中状态
652
+ const isCenterTimerId = React.useRef(null);
653
+ // 滚动静止后归中并同步选中
654
+ const handleScrollEnd = () => {
655
+ if (!scrollViewRef.current) return;
656
+ if (isCenterTimerId.current) {
657
+ clearTimeout(isCenterTimerId.current);
658
+ isCenterTimerId.current = null;
659
+ }
660
+ // 100ms 内无新滚动则归中并提交索引
661
+ isCenterTimerId.current = setTimeout(() => {
662
+ if (!scrollViewRef.current) return;
663
+ const scrollTop = scrollViewRef.current.scrollTop;
664
+ const newIndex = getSelectedIndex(scrollTop, itemHeightRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
665
+ isTouchingRef.current = false;
666
+ scrollToIndex(newIndex, true);
667
+ commitDay(newIndex);
668
+ isCenterTimerId.current = null;
669
+ }, 100);
670
+ };
671
+ // 滚动中:按 scrollTop 更新高亮索引
672
+ const handleScroll = () => {
673
+ if (!scrollViewRef.current) return;
674
+ if (isCenterTimerId.current) {
675
+ clearTimeout(isCenterTimerId.current);
676
+ isCenterTimerId.current = null;
677
+ }
678
+ const scrollTop = scrollViewRef.current.scrollTop;
679
+ const ih = itemHeightRef.current;
680
+ const newIndex = getSelectedIndex(scrollTop, ih, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
681
+ if (newIndex !== currentIndex) {
682
+ setCurrentIndex(newIndex);
683
+ }
684
+ };
685
+ // 无障碍:整列作单 slider,转子 increment/decrement 切相邻项
686
+ const clampIndex = index => Math.max(0, Math.min(index, range.length - 1));
687
+ // 切换后主动播报当前项:焦点停在 slider 覆盖层上,aria 属性更新读屏不会自动重读,需主动触发
688
+ const announceIndex = index => {
689
+ const text = range[index] != null ? String(range[index]) : '';
690
+ if (!text) return;
691
+ const fn = Taro.accessibilityAnnounce;
692
+ if (typeof fn !== 'function') return;
693
+ fn({
694
+ announce: text,
695
+ delay: 300
696
+ });
697
+ };
698
+ const commitIndexByA11y = nextIndex => {
699
+ const clamped = clampIndex(nextIndex);
700
+ if (clamped === currentIndex) return;
701
+ isTouchingRef.current = false;
702
+ setCurrentIndex(clamped);
703
+ scrollToIndex(clamped, true);
704
+ commitDay(clamped);
705
+ announceIndex(clamped);
706
+ };
707
+ const handleAriaAction = e => {
708
+ var _a;
709
+ const actionName = (_a = e === null || e === void 0 ? void 0 : e.detail) === null || _a === void 0 ? void 0 : _a.actionName;
710
+ if (actionName === 'increment') {
711
+ commitIndexByA11y(currentIndex + 1);
712
+ } else if (actionName === 'decrement') {
713
+ commitIndexByA11y(currentIndex - 1);
714
+ }
715
+ };
716
+ // 无障碍 label:当前项值,仅 string 或 number(转 string)挂载,对象等其它类型不挂载
717
+ const currentValue = range[currentIndex];
718
+ const ariaLabel = typeof currentValue === 'string' ? currentValue : typeof currentValue === 'number' ? String(currentValue) : undefined;
719
+ // 渲染选项
720
+ const pickerItem = range.map((item, index) => {
721
+ return createComponent(View, mergeProps({
722
+ id: `picker-item-${columnId}-${index}`,
723
+ key: index,
724
+ ariaHidden: true,
725
+ className: `taro-picker__item${index === currentIndex ? ' taro-picker__item--selected' : ''}`
726
+ }, enableClickItemScroll ? {
727
+ onClick: () => scrollToItemId(`picker-item-${columnId}-${index}`)
728
+ } : {}, {
729
+ get style() {
730
+ return {
731
+ height: PICKER_LINE_HEIGHT,
732
+ color: index === currentIndex ? colors.itemSelectedColor || undefined : colors.itemDefaultColor || undefined
733
+ };
734
+ },
735
+ children: item
736
+ }));
737
+ });
738
+ const realPickerItems = [...new Array(PICKER_BLANK_ITEMS).fill(null).map((_, idx) => createComponent(View, {
739
+ key: `blank-top-${idx}`,
740
+ ariaHidden: true,
741
+ className: "taro-picker__item taro-picker__item--blank",
742
+ style: {
743
+ height: PICKER_LINE_HEIGHT
744
+ }
745
+ })), ...pickerItem, ...new Array(PICKER_BLANK_ITEMS).fill(null).map((_, idx) => createComponent(View, {
746
+ key: `blank-bottom-${idx}`,
747
+ ariaHidden: true,
748
+ className: "taro-picker__item taro-picker__item--blank",
749
+ style: {
750
+ height: PICKER_LINE_HEIGHT
751
+ }
752
+ }))];
753
+ const clickScrollViewProps = enableClickItemScroll ? {
754
+ scrollIntoView,
755
+ scrollIntoViewAlignment: 'center'
756
+ } : {};
757
+ return createComponent(View, {
758
+ className: "taro-picker__group",
759
+ style: {
760
+ position: 'relative'
761
+ },
762
+ get children() {
763
+ return [createComponent(View, {
764
+ className: "taro-picker__mask",
765
+ ariaHidden: true
766
+ }), createComponent(View, mergeProps({
767
+ className: "taro-picker__indicator",
768
+ ariaHidden: true
769
+ }, indicatorStyle ? {
770
+ style: indicatorStyle
771
+ } : {})), createComponent(ScrollView, mergeProps({
772
+ ref: scrollViewRef,
773
+ scrollY: true,
774
+ showScrollbar: false,
775
+ className: "taro-picker__content",
776
+ ariaHidden: true
777
+ }, {
778
+ accessibilityElementsHidden: true,
779
+ importantForAccessibility: 'no-hide-descendants'
780
+ }, {
781
+ style: {
782
+ height: PICKER_LINE_HEIGHT * PICKER_VISIBLE_ITEMS
783
+ },
784
+ scrollTop: targetScrollTop
785
+ }, clickScrollViewProps, {
786
+ onScroll: handleScroll,
787
+ onTouchStart: () => {
788
+ isTouchingRef.current = true;
789
+ },
790
+ onScrollEnd: handleScrollEnd,
791
+ scrollWithAnimation: true,
792
+ children: realPickerItems
793
+ })), createComponent(View, mergeProps({
794
+ className: "taro-picker__a11y-overlay",
795
+ style: {
796
+ position: 'absolute',
797
+ top: 0,
798
+ left: 0,
799
+ right: 0,
800
+ bottom: 0,
801
+ pointerEvents: 'none'
802
+ },
803
+ ariaRole: "slider"
804
+ }, ariaLabel !== undefined ? {
805
+ ariaLabel
806
+ } : {}, {
807
+ ariaAction: [{
808
+ name: 'increment',
809
+ label: 'increment'
810
+ }, {
811
+ name: 'decrement',
812
+ label: 'decrement'
813
+ }],
814
+ onAriaAction: handleAriaAction
815
+ }))];
816
+ }
817
+ });
818
+ }
819
+ // 地区选择器实现
820
+ function PickerGroupRegion(props) {
821
+ const {
822
+ range = [],
823
+ rangeKey,
824
+ columnId,
825
+ updateIndex,
826
+ selectedIndex = 0,
827
+ // 使用selectedIndex参数,默认为0
828
+ colors = {},
829
+ enableClickItemScroll = true
830
+ } = props;
831
+ const indicatorStyle = colors.lineColor ? getIndicatorStyle(colors.lineColor) : null;
832
+ const scrollViewRef = React.useRef(null);
833
+ const [targetScrollTop, setTargetScrollTop] = React.useState(0);
834
+ const [scrollIntoView, scrollToItemId] = usePickerItemScrollIntoView();
835
+ const [currentIndex, setCurrentIndex] = React.useState(selectedIndex);
836
+ const isTouchingRef = React.useRef(false);
837
+ // 程序化滚动标记:开屏/受控同步预设值时置 true,避免被 region 级联门误判为用户滚动而重置后续列
838
+ const syncScrollFromPropsRef = React.useRef(false);
839
+ const lengthScaleRatioRef = React.useRef(1);
840
+ const useMeasuredScaleRef = React.useRef(false);
841
+ const itemHeightRef = React.useRef(PICKER_LINE_HEIGHT);
842
+ // 初始化时计算 lengthScaleRatio 并判定缩放模式
843
+ React.useEffect(() => {
844
+ Taro.getSystemInfo({
845
+ success: res => {
846
+ lengthScaleRatioRef.current = calculateLengthScaleRatio(res);
847
+ useMeasuredScaleRef.current = resolveUseMeasuredScale(res);
848
+ itemHeightRef.current = calculateItemHeight(scrollViewRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
849
+ },
850
+ fail: () => {
851
+ lengthScaleRatioRef.current = 1;
852
+ useMeasuredScaleRef.current = false;
853
+ }
854
+ });
855
+ }, []);
856
+ React.useEffect(() => {
857
+ itemHeightRef.current = calculateItemHeight(scrollViewRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
858
+ }, [range.length]); // 只在range长度变化时重新计算
859
+ // 滚动到指定索引(供程序化对齐与无障碍步进复用)
860
+ const scrollToIndex = React.useCallback(function (index) {
861
+ let withRandomOffset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
862
+ const baseValue = index * itemHeightRef.current;
863
+ const randomOffset = withRandomOffset ? Math.random() * 0.001 : undefined;
864
+ setTargetScrollTopWithScale(setTargetScrollTop, baseValue, randomOffset, lengthScaleRatioRef.current);
865
+ }, []);
866
+ // props 的 selectedIndex 变化:滚至对应项,并短时标记程序化滚动(避免级联门误判)
867
+ React.useEffect(() => {
868
+ if (scrollViewRef.current && range.length > 0 && !isTouchingRef.current) {
869
+ syncScrollFromPropsRef.current = true;
870
+ scrollToIndex(selectedIndex);
871
+ setCurrentIndex(selectedIndex);
872
+ const tid = setTimeout(() => {
873
+ syncScrollFromPropsRef.current = false;
874
+ }, 400);
875
+ return () => clearTimeout(tid);
876
+ }
877
+ }, [selectedIndex, range, scrollToIndex]);
878
+ // 滚动静止后归中(debounce)
879
+ const isCenterTimerId = React.useRef(null);
880
+ const handleScrollEnd = () => {
881
+ if (!scrollViewRef.current) return;
882
+ if (isCenterTimerId.current) {
883
+ clearTimeout(isCenterTimerId.current);
884
+ isCenterTimerId.current = null;
885
+ }
886
+ // 100ms 内无新滚动则归中并提交索引
887
+ isCenterTimerId.current = setTimeout(() => {
888
+ if (!scrollViewRef.current) return;
889
+ const scrollTop = scrollViewRef.current.scrollTop;
890
+ const newIndex = getSelectedIndex(scrollTop, itemHeightRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
891
+ // 程序化滚动(受控同步预设值)不触发级联初始化,仅用户滚动才翻转初始化标志并重置后续列
892
+ const isUserScroll = !syncScrollFromPropsRef.current;
893
+ isTouchingRef.current = false;
894
+ scrollToIndex(newIndex, true);
895
+ updateIndex(newIndex, columnId, false, isUserScroll);
896
+ syncScrollFromPropsRef.current = false;
897
+ isCenterTimerId.current = null;
898
+ }, 100);
899
+ };
900
+ // 滚动中:按 scrollTop 更新高亮索引
901
+ const handleScroll = () => {
902
+ if (!scrollViewRef.current) return;
903
+ if (isCenterTimerId.current) {
904
+ clearTimeout(isCenterTimerId.current);
905
+ isCenterTimerId.current = null;
906
+ }
907
+ // 用户触摸滚动立即清程序化标志,使其 scrollEnd 被正确判为用户滚动(触发 region 级联)
908
+ if (isTouchingRef.current) {
909
+ syncScrollFromPropsRef.current = false;
910
+ }
911
+ const scrollTop = scrollViewRef.current.scrollTop;
912
+ const ih = itemHeightRef.current;
913
+ const newIndex = getSelectedIndex(scrollTop, ih, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
914
+ if (newIndex !== currentIndex) {
915
+ setCurrentIndex(newIndex);
916
+ }
917
+ };
918
+ // 无障碍:整列作单 slider,转子 increment/decrement 切相邻项
919
+ const clampIndex = index => Math.max(0, Math.min(index, range.length - 1));
920
+ // 切换后主动播报当前项:焦点停在 slider 覆盖层上,aria 属性更新读屏不会自动重读,需主动触发
921
+ const announceIndex = index => {
922
+ const item = range[index];
923
+ const content = rangeKey && item && typeof item === 'object' ? item[rangeKey] : item;
924
+ const text = content != null ? String(content) : '';
925
+ if (!text) return;
926
+ const fn = Taro.accessibilityAnnounce;
927
+ if (typeof fn !== 'function') return;
928
+ fn({
929
+ announce: text,
930
+ delay: 300
931
+ });
932
+ };
933
+ const commitIndexByA11y = nextIndex => {
934
+ const clamped = clampIndex(nextIndex);
935
+ if (clamped === currentIndex) return;
936
+ isTouchingRef.current = false;
937
+ setCurrentIndex(clamped);
938
+ scrollToIndex(clamped, true);
939
+ updateIndex(clamped, columnId, false, true);
940
+ announceIndex(clamped);
941
+ };
942
+ const handleAriaAction = e => {
943
+ var _a;
944
+ const actionName = (_a = e === null || e === void 0 ? void 0 : e.detail) === null || _a === void 0 ? void 0 : _a.actionName;
945
+ if (actionName === 'increment') {
946
+ commitIndexByA11y(currentIndex + 1);
947
+ } else if (actionName === 'decrement') {
948
+ commitIndexByA11y(currentIndex - 1);
949
+ }
950
+ };
951
+ // 无障碍 label:当前项值(region 用 rangeKey 取显示值),仅 string 或 number 挂载
952
+ const currentItem = range[currentIndex];
953
+ const currentValue = rangeKey && currentItem && typeof currentItem === 'object' ? currentItem[rangeKey] : currentItem;
954
+ const ariaLabel = typeof currentValue === 'string' ? currentValue : typeof currentValue === 'number' ? String(currentValue) : undefined;
955
+ // 渲染选项
956
+ const pickerItem = range.map((item, index) => {
957
+ const content = rangeKey && item && typeof item === 'object' ? item[rangeKey] : item;
958
+ return createComponent(View, mergeProps({
959
+ id: `picker-item-${columnId}-${index}`,
960
+ key: index,
961
+ ariaHidden: true,
962
+ className: `taro-picker__item${index === currentIndex ? ' taro-picker__item--selected' : ''}`
963
+ }, enableClickItemScroll ? {
964
+ onClick: () => scrollToItemId(`picker-item-${columnId}-${index}`)
965
+ } : {}, {
966
+ get style() {
967
+ return {
968
+ height: PICKER_LINE_HEIGHT,
969
+ color: index === currentIndex ? colors.itemSelectedColor || undefined : colors.itemDefaultColor || undefined
970
+ };
971
+ },
972
+ children: content
973
+ }));
974
+ });
975
+ const realPickerItems = [...new Array(PICKER_BLANK_ITEMS).fill(null).map((_, idx) => createComponent(View, {
976
+ key: `blank-top-${idx}`,
977
+ ariaHidden: true,
978
+ className: "taro-picker__item taro-picker__item--blank",
979
+ style: {
980
+ height: PICKER_LINE_HEIGHT
981
+ }
982
+ })), ...pickerItem, ...new Array(PICKER_BLANK_ITEMS).fill(null).map((_, idx) => createComponent(View, {
983
+ key: `blank-bottom-${idx}`,
984
+ ariaHidden: true,
985
+ className: "taro-picker__item taro-picker__item--blank",
986
+ style: {
987
+ height: PICKER_LINE_HEIGHT
988
+ }
989
+ }))];
990
+ const clickScrollViewProps = enableClickItemScroll ? {
991
+ scrollIntoView,
992
+ scrollIntoViewAlignment: 'center'
993
+ } : {};
994
+ return createComponent(View, {
995
+ className: "taro-picker__group",
996
+ style: {
997
+ position: 'relative'
998
+ },
999
+ get children() {
1000
+ return [createComponent(View, {
1001
+ className: "taro-picker__mask",
1002
+ ariaHidden: true
1003
+ }), createComponent(View, mergeProps({
1004
+ className: "taro-picker__indicator",
1005
+ ariaHidden: true
1006
+ }, indicatorStyle ? {
1007
+ style: indicatorStyle
1008
+ } : {})), createComponent(ScrollView, mergeProps({
1009
+ ref: scrollViewRef,
1010
+ scrollY: true,
1011
+ showScrollbar: false,
1012
+ className: "taro-picker__content",
1013
+ ariaHidden: true
1014
+ }, {
1015
+ accessibilityElementsHidden: true,
1016
+ importantForAccessibility: 'no-hide-descendants'
1017
+ }, {
1018
+ style: {
1019
+ height: PICKER_LINE_HEIGHT * PICKER_VISIBLE_ITEMS
1020
+ },
1021
+ scrollTop: targetScrollTop
1022
+ }, clickScrollViewProps, {
1023
+ onScroll: handleScroll,
1024
+ onTouchStart: () => {
1025
+ isTouchingRef.current = true;
1026
+ },
1027
+ onScrollEnd: handleScrollEnd,
1028
+ scrollWithAnimation: true,
1029
+ children: realPickerItems
1030
+ })), createComponent(View, mergeProps({
1031
+ className: "taro-picker__a11y-overlay",
1032
+ style: {
1033
+ position: 'absolute',
1034
+ top: 0,
1035
+ left: 0,
1036
+ right: 0,
1037
+ bottom: 0,
1038
+ pointerEvents: 'none'
1039
+ },
1040
+ ariaRole: "slider"
1041
+ }, ariaLabel !== undefined ? {
1042
+ ariaLabel
1043
+ } : {}, {
1044
+ ariaAction: [{
1045
+ name: 'increment',
1046
+ label: 'increment'
1047
+ }, {
1048
+ name: 'decrement',
1049
+ label: 'decrement'
1050
+ }],
1051
+ onAriaAction: handleAriaAction
1052
+ }))];
1053
+ }
1054
+ });
1055
+ }
1056
+ // 新版无障碍(slider 遮挡方案),根据 mode 自动分发
1057
+ function PickerGroupSlider(props) {
1058
+ switch (props.mode) {
1059
+ case 'time':
1060
+ return createComponent(PickerGroupTime, props);
1061
+ case 'date':
1062
+ return createComponent(PickerGroupDate, props);
1063
+ case 'region':
1064
+ return createComponent(PickerGroupRegion, props);
1065
+ default:
1066
+ return createComponent(PickerGroupBasic, props);
1067
+ }
1068
+ }
1069
+
1070
+ export { PickerGroupBasic, PickerGroupDate, PickerGroupRegion, PickerGroupSlider, PickerGroupTime };
1071
+ //# sourceMappingURL=picker-group-slider.js.map