@xaui/native 0.0.21 → 0.0.24

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 (113) hide show
  1. package/README.md +195 -2
  2. package/dist/alert/index.js +1 -2
  3. package/dist/app-bar/index.cjs +217 -0
  4. package/dist/app-bar/index.d.cts +52 -0
  5. package/dist/app-bar/index.d.ts +52 -0
  6. package/dist/app-bar/index.js +142 -0
  7. package/dist/autocomplete/index.js +48 -36
  8. package/dist/avatar/index.js +1 -2
  9. package/dist/badge/index.js +1 -2
  10. package/dist/bottom-sheet/index.js +1 -2
  11. package/dist/bottom-tab-bar/index.cjs +571 -0
  12. package/dist/bottom-tab-bar/index.d.cts +211 -0
  13. package/dist/bottom-tab-bar/index.d.ts +211 -0
  14. package/dist/bottom-tab-bar/index.js +497 -0
  15. package/dist/button/index.d.cts +102 -5
  16. package/dist/button/index.d.ts +102 -5
  17. package/dist/button/index.js +2 -3
  18. package/dist/button.type-j1ZdkkSl.d.cts +4 -0
  19. package/dist/button.type-j1ZdkkSl.d.ts +4 -0
  20. package/dist/card/index.cjs +2 -0
  21. package/dist/card/index.d.cts +6 -1
  22. package/dist/card/index.d.ts +6 -1
  23. package/dist/card/index.js +4 -2
  24. package/dist/carousel/index.js +1 -1
  25. package/dist/chart/index.cjs +1067 -0
  26. package/dist/chart/index.d.cts +218 -0
  27. package/dist/chart/index.d.ts +218 -0
  28. package/dist/chart/index.js +1026 -0
  29. package/dist/checkbox/index.js +1 -2
  30. package/dist/chip/index.js +1 -2
  31. package/dist/chunk-3XSXTM3G.js +661 -0
  32. package/dist/chunk-4KSZLONZ.js +79 -0
  33. package/dist/{chunk-DXXNBF5P.js → chunk-CZFDZPAS.js} +0 -5
  34. package/dist/{chunk-LTKYHG5V.js → chunk-GHCVNQET.js} +12 -5
  35. package/dist/chunk-I4V5Y5GD.js +76 -0
  36. package/dist/{chunk-F7WH4DMG.js → chunk-UI5L26KD.js} +1 -1
  37. package/dist/{chunk-LUBWRVI2.js → chunk-ULJSCNPE.js} +1 -1
  38. package/dist/chunk-URBEEDFX.js +79 -0
  39. package/dist/core/index.js +3 -5
  40. package/dist/datepicker/index.js +1 -2
  41. package/dist/divider/index.js +2 -3
  42. package/dist/drawer/index.cjs +310 -0
  43. package/dist/drawer/index.d.cts +58 -0
  44. package/dist/drawer/index.d.ts +58 -0
  45. package/dist/drawer/index.js +236 -0
  46. package/dist/{accordion → expansion-panel}/index.cjs +45 -45
  47. package/dist/{accordion → expansion-panel}/index.d.cts +30 -30
  48. package/dist/{accordion → expansion-panel}/index.d.ts +30 -30
  49. package/dist/{accordion → expansion-panel}/index.js +40 -41
  50. package/dist/fab/index.d.cts +3 -3
  51. package/dist/fab/index.d.ts +3 -3
  52. package/dist/fab/index.js +3 -4
  53. package/dist/fab-menu/index.d.cts +2 -2
  54. package/dist/fab-menu/index.d.ts +2 -2
  55. package/dist/fab-menu/index.js +3 -4
  56. package/dist/{fab.type-Ba0QMprb.d.ts → fab.type-CgIYqQlT.d.ts} +1 -1
  57. package/dist/{fab.type-U09H8B7D.d.cts → fab.type-l2vjG8-p.d.cts} +1 -1
  58. package/dist/feature-discovery/index.cjs +531 -0
  59. package/dist/feature-discovery/index.d.cts +82 -0
  60. package/dist/feature-discovery/index.d.ts +82 -0
  61. package/dist/feature-discovery/index.js +464 -0
  62. package/dist/indicator/index.js +2 -3
  63. package/dist/input/index.cjs +258 -164
  64. package/dist/input/index.d.cts +15 -1
  65. package/dist/input/index.d.ts +15 -1
  66. package/dist/input/index.js +219 -126
  67. package/dist/list/index.js +1 -2
  68. package/dist/menu/index.js +2 -2
  69. package/dist/menubox/index.cjs +369 -0
  70. package/dist/menubox/index.d.cts +98 -0
  71. package/dist/menubox/index.d.ts +98 -0
  72. package/dist/menubox/index.js +296 -0
  73. package/dist/pager/index.cjs +243 -0
  74. package/dist/pager/index.d.cts +93 -0
  75. package/dist/pager/index.d.ts +93 -0
  76. package/dist/pager/index.js +205 -0
  77. package/dist/progress/index.js +1 -2
  78. package/dist/radio/index.cjs +537 -0
  79. package/dist/radio/index.d.cts +145 -0
  80. package/dist/radio/index.d.ts +145 -0
  81. package/dist/radio/index.js +464 -0
  82. package/dist/segment-button/index.js +2 -2
  83. package/dist/select/index.js +22 -10
  84. package/dist/skeleton/index.js +2 -2
  85. package/dist/slider/index.cjs +655 -0
  86. package/dist/slider/index.d.cts +171 -0
  87. package/dist/slider/index.d.ts +171 -0
  88. package/dist/slider/index.js +575 -0
  89. package/dist/stepper/index.cjs +624 -0
  90. package/dist/stepper/index.d.cts +137 -0
  91. package/dist/stepper/index.d.ts +137 -0
  92. package/dist/stepper/index.js +549 -0
  93. package/dist/switch/index.js +1 -2
  94. package/dist/tabs/index.cjs +523 -0
  95. package/dist/tabs/index.d.cts +176 -0
  96. package/dist/tabs/index.d.ts +176 -0
  97. package/dist/tabs/index.js +438 -0
  98. package/dist/timepicker/index.cjs +1280 -0
  99. package/dist/timepicker/index.d.cts +215 -0
  100. package/dist/timepicker/index.d.ts +215 -0
  101. package/dist/timepicker/index.js +1181 -0
  102. package/dist/toolbar/index.cjs +395 -0
  103. package/dist/toolbar/index.d.cts +100 -0
  104. package/dist/toolbar/index.d.ts +100 -0
  105. package/dist/toolbar/index.js +325 -0
  106. package/dist/typography/index.js +1 -2
  107. package/dist/view/index.cjs +16 -2
  108. package/dist/view/index.js +16 -2
  109. package/package.json +73 -8
  110. package/dist/button.type-D8tzEBo7.d.ts +0 -104
  111. package/dist/button.type-ikaWzhIg.d.cts +0 -104
  112. package/dist/chunk-GBHQCAKW.js +0 -19
  113. package/dist/chunk-JEGEPGVU.js +0 -287
@@ -0,0 +1,1181 @@
1
+ import {
2
+ Portal,
3
+ useXUITheme
4
+ } from "../chunk-4KSZLONZ.js";
5
+
6
+ // src/components/timepicker/timepicker.tsx
7
+ import React, { useEffect, useMemo as useMemo2, useState as useState2 } from "react";
8
+ import { View, Text, Pressable, TextInput } from "react-native";
9
+ import Animated, {
10
+ Easing,
11
+ useAnimatedStyle,
12
+ useSharedValue,
13
+ withTiming
14
+ } from "react-native-reanimated";
15
+
16
+ // src/components/timepicker/timepicker.hook.ts
17
+ import { useMemo, useState } from "react";
18
+ import { getSafeThemeColor, withOpacity } from "@xaui/core";
19
+
20
+ // src/components/timepicker/timepicker.utils.ts
21
+ var to12HourFormat = (hours) => {
22
+ if (hours === 0) {
23
+ return { hours: 12, period: "AM" };
24
+ }
25
+ if (hours < 12) {
26
+ return { hours, period: "AM" };
27
+ }
28
+ if (hours === 12) {
29
+ return { hours: 12, period: "PM" };
30
+ }
31
+ return { hours: hours - 12, period: "PM" };
32
+ };
33
+ var to24HourFormat = (hours, period) => {
34
+ if (period === "AM") {
35
+ return hours === 12 ? 0 : hours;
36
+ }
37
+ return hours === 12 ? 12 : hours + 12;
38
+ };
39
+ var formatTimeValue = (time, is24Hour) => {
40
+ const { hours, minutes } = time;
41
+ if (is24Hour) {
42
+ return `${hours.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")}`;
43
+ }
44
+ const { hours: displayHours, period } = to12HourFormat(hours);
45
+ return `${displayHours.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")} ${period}`;
46
+ };
47
+ var getHourAngle = (hour, is24Hour) => {
48
+ const displayHour = is24Hour ? hour % 12 : hour;
49
+ return displayHour * 30 % 360;
50
+ };
51
+ var getMinuteAngle = (minute) => {
52
+ return minute * 6 % 360;
53
+ };
54
+ var angleToHour = (angle, _is24Hour) => {
55
+ const normalizedAngle = (angle % 360 + 360) % 360;
56
+ const hour = Math.round(normalizedAngle / 30) % 12;
57
+ return hour === 0 ? 12 : hour;
58
+ };
59
+ var angleToMinute = (angle) => {
60
+ const normalizedAngle = (angle % 360 + 360) % 360;
61
+ return Math.round(normalizedAngle / 6) % 60;
62
+ };
63
+ var calculateAngleFromPosition = (centerX, centerY, touchX, touchY) => {
64
+ const deltaX = touchX - centerX;
65
+ const deltaY = touchY - centerY;
66
+ const radians = Math.atan2(deltaY, deltaX);
67
+ const degrees = radians * 180 / Math.PI;
68
+ return (degrees + 90 + 360) % 360;
69
+ };
70
+ var isTimeInRange = (time, minTime, maxTime) => {
71
+ if (!minTime && !maxTime) return true;
72
+ const timeInMinutes = time.hours * 60 + time.minutes;
73
+ if (minTime) {
74
+ const minInMinutes = minTime.hours * 60 + minTime.minutes;
75
+ if (timeInMinutes < minInMinutes) return false;
76
+ }
77
+ if (maxTime) {
78
+ const maxInMinutes = maxTime.hours * 60 + maxTime.minutes;
79
+ if (timeInMinutes > maxInMinutes) return false;
80
+ }
81
+ return true;
82
+ };
83
+ var getCurrentTime = () => {
84
+ const now = /* @__PURE__ */ new Date();
85
+ return {
86
+ hours: now.getHours(),
87
+ minutes: now.getMinutes()
88
+ };
89
+ };
90
+ var clampHour = (hour, is24Hour) => {
91
+ if (is24Hour) {
92
+ return Math.max(0, Math.min(23, hour));
93
+ }
94
+ return Math.max(1, Math.min(12, hour));
95
+ };
96
+ var clampMinute = (minute) => {
97
+ return Math.max(0, Math.min(59, minute));
98
+ };
99
+
100
+ // src/components/timepicker/timepicker.hook.ts
101
+ var useTimePickerState = (initialValue, is24Hour = false, onChange) => {
102
+ const [time, setTime] = useState(initialValue || getCurrentTime());
103
+ const [mode, setMode] = useState("hour");
104
+ const { hours: displayHours, period } = useMemo(
105
+ () => is24Hour ? { hours: time.hours, period: "AM" } : to12HourFormat(time.hours),
106
+ [time.hours, is24Hour]
107
+ );
108
+ const handleHourChange = (hour) => {
109
+ const newTime = {
110
+ ...time,
111
+ hours: hour
112
+ };
113
+ setTime(newTime);
114
+ onChange?.(newTime);
115
+ setMode("minute");
116
+ };
117
+ const handleMinuteChange = (minute) => {
118
+ const newTime = {
119
+ ...time,
120
+ minutes: minute
121
+ };
122
+ setTime(newTime);
123
+ onChange?.(newTime);
124
+ };
125
+ const handlePeriodToggle = (newPeriod) => {
126
+ if (is24Hour) return;
127
+ const newHours = to24HourFormat(displayHours, newPeriod);
128
+ const newTime = {
129
+ ...time,
130
+ hours: newHours
131
+ };
132
+ setTime(newTime);
133
+ onChange?.(newTime);
134
+ };
135
+ const handleManualInput = (hours, minutes) => {
136
+ const newTime = { hours, minutes };
137
+ setTime(newTime);
138
+ onChange?.(newTime);
139
+ };
140
+ const toggleMode = () => {
141
+ setMode((prev) => prev === "hour" ? "minute" : "hour");
142
+ };
143
+ return {
144
+ time,
145
+ displayHours,
146
+ period,
147
+ mode,
148
+ handleHourChange,
149
+ handleMinuteChange,
150
+ handlePeriodToggle,
151
+ handleManualInput,
152
+ toggleMode,
153
+ setMode
154
+ };
155
+ };
156
+ var useTimePickerColors = (themeColor) => {
157
+ const theme = useXUITheme();
158
+ const colorScheme = theme.colors[getSafeThemeColor(themeColor)];
159
+ return useMemo(() => {
160
+ return {
161
+ background: theme.colors.background,
162
+ surface: withOpacity(colorScheme.main, 0.12),
163
+ primary: colorScheme.main,
164
+ onPrimary: colorScheme.foreground,
165
+ text: theme.colors.foreground,
166
+ textSecondary: withOpacity(theme.colors.foreground, 0.6),
167
+ border: withOpacity(theme.colors.foreground, 0.12),
168
+ clockFace: withOpacity(colorScheme.main, 0.08),
169
+ selectedDigit: withOpacity(colorScheme.main, 0.12)
170
+ };
171
+ }, [
172
+ colorScheme.main,
173
+ colorScheme.foreground,
174
+ theme.colors.background,
175
+ theme.colors.foreground
176
+ ]);
177
+ };
178
+
179
+ // src/components/timepicker/timepicker.style.ts
180
+ import { StyleSheet } from "react-native";
181
+ var styles = StyleSheet.create({
182
+ container: {
183
+ padding: 24,
184
+ alignItems: "center"
185
+ },
186
+ header: {
187
+ alignSelf: "stretch",
188
+ marginBottom: 24
189
+ },
190
+ headerTitle: {
191
+ fontSize: 14,
192
+ fontWeight: "400",
193
+ marginBottom: 16
194
+ },
195
+ timeDisplay: {
196
+ flexDirection: "row",
197
+ alignItems: "center",
198
+ justifyContent: "center",
199
+ gap: 8
200
+ },
201
+ timeDisplayWithPeriod: {
202
+ justifyContent: "space-between"
203
+ },
204
+ timeSection: {
205
+ flexDirection: "row",
206
+ alignItems: "center",
207
+ gap: 4
208
+ },
209
+ timeDigit: {
210
+ fontSize: 57,
211
+ fontWeight: "400",
212
+ lineHeight: 64,
213
+ paddingHorizontal: 12,
214
+ paddingVertical: 8,
215
+ borderRadius: 8,
216
+ minWidth: 96,
217
+ textAlign: "center"
218
+ },
219
+ timeSeparator: {
220
+ fontSize: 57,
221
+ fontWeight: "400",
222
+ lineHeight: 64
223
+ },
224
+ periodSelector: {
225
+ gap: 4
226
+ },
227
+ periodButton: {
228
+ paddingVertical: 8,
229
+ paddingHorizontal: 12,
230
+ borderRadius: 8,
231
+ borderWidth: 1,
232
+ minWidth: 52,
233
+ alignItems: "center"
234
+ },
235
+ periodText: {
236
+ fontSize: 16,
237
+ fontWeight: "500"
238
+ },
239
+ clockContainer: {
240
+ width: 256,
241
+ height: 256,
242
+ justifyContent: "center",
243
+ alignItems: "center",
244
+ marginBottom: 24
245
+ },
246
+ clockFace: {
247
+ width: 256,
248
+ height: 256,
249
+ borderRadius: 128,
250
+ justifyContent: "center",
251
+ alignItems: "center",
252
+ position: "relative"
253
+ },
254
+ clockCenter: {
255
+ width: 6,
256
+ height: 6,
257
+ borderRadius: 3,
258
+ position: "absolute"
259
+ },
260
+ clockHand: {
261
+ position: "absolute",
262
+ width: 2,
263
+ backgroundColor: "transparent",
264
+ transformOrigin: "top center"
265
+ },
266
+ clockHandLine: {
267
+ width: 2,
268
+ backgroundColor: "transparent"
269
+ },
270
+ clockHandDot: {
271
+ width: 16,
272
+ height: 16,
273
+ borderRadius: 8,
274
+ position: "absolute",
275
+ top: -8,
276
+ left: -7,
277
+ justifyContent: "center",
278
+ alignItems: "center"
279
+ },
280
+ clockNumber: {
281
+ position: "absolute",
282
+ width: 48,
283
+ height: 48,
284
+ borderRadius: 24,
285
+ justifyContent: "center",
286
+ alignItems: "center"
287
+ },
288
+ clockNumberText: {
289
+ fontSize: 16,
290
+ fontWeight: "400"
291
+ },
292
+ actions: {
293
+ flexDirection: "row",
294
+ justifyContent: "flex-end",
295
+ gap: 8,
296
+ alignSelf: "stretch"
297
+ },
298
+ actionButton: {
299
+ paddingVertical: 10,
300
+ paddingHorizontal: 24,
301
+ borderRadius: 20
302
+ },
303
+ actionButtonText: {
304
+ fontSize: 14,
305
+ fontWeight: "500"
306
+ },
307
+ keyboardButton: {
308
+ width: 48,
309
+ height: 48,
310
+ borderRadius: 24,
311
+ justifyContent: "center",
312
+ alignItems: "center"
313
+ },
314
+ inputContainer: {
315
+ width: 256,
316
+ height: 256,
317
+ justifyContent: "center",
318
+ alignItems: "center",
319
+ gap: 16
320
+ },
321
+ inputRow: {
322
+ flexDirection: "row",
323
+ alignItems: "center",
324
+ gap: 8
325
+ },
326
+ input: {
327
+ width: 96,
328
+ height: 80,
329
+ borderRadius: 8,
330
+ borderWidth: 1,
331
+ fontSize: 57,
332
+ fontWeight: "400",
333
+ textAlign: "center",
334
+ padding: 8
335
+ },
336
+ inputSeparator: {
337
+ fontSize: 36,
338
+ fontWeight: "400"
339
+ },
340
+ trigger: {
341
+ minHeight: 52,
342
+ borderWidth: 1,
343
+ borderRadius: 12,
344
+ paddingHorizontal: 16,
345
+ paddingVertical: 12,
346
+ flexDirection: "row",
347
+ alignItems: "center",
348
+ justifyContent: "space-between",
349
+ gap: 12
350
+ },
351
+ triggerContent: {
352
+ flex: 1,
353
+ minWidth: 0
354
+ },
355
+ triggerText: {
356
+ fontSize: 16,
357
+ fontWeight: "500"
358
+ },
359
+ clearButton: {
360
+ alignItems: "center",
361
+ justifyContent: "center"
362
+ },
363
+ disabled: {
364
+ opacity: 0.5
365
+ }
366
+ });
367
+
368
+ // src/components/timepicker/timepicker.tsx
369
+ var TimePicker = ({
370
+ value,
371
+ onChange,
372
+ is24Hour = false,
373
+ themeColor = "primary",
374
+ style
375
+ }) => {
376
+ const {
377
+ time,
378
+ displayHours,
379
+ period,
380
+ mode,
381
+ handleHourChange,
382
+ handleMinuteChange,
383
+ handlePeriodToggle,
384
+ handleManualInput,
385
+ setMode
386
+ } = useTimePickerState(value, is24Hour, onChange);
387
+ const colors = useTimePickerColors(themeColor);
388
+ const hourAngle = useMemo2(
389
+ () => getHourAngle(displayHours, is24Hour),
390
+ [displayHours, is24Hour]
391
+ );
392
+ const minuteAngle = useMemo2(() => getMinuteAngle(time.minutes), [time.minutes]);
393
+ const currentAngle = mode === "hour" ? hourAngle : minuteAngle;
394
+ const handRotation = useSharedValue(currentAngle);
395
+ const [hourInput, setHourInput] = useState2(
396
+ displayHours.toString().padStart(2, "0")
397
+ );
398
+ const [minuteInput, setMinuteInput] = useState2(
399
+ time.minutes.toString().padStart(2, "0")
400
+ );
401
+ useEffect(() => {
402
+ handRotation.value = withTiming(currentAngle - 180, {
403
+ duration: 120,
404
+ easing: Easing.out(Easing.cubic)
405
+ });
406
+ }, [currentAngle, handRotation]);
407
+ useEffect(() => {
408
+ setHourInput(displayHours.toString().padStart(2, "0"));
409
+ }, [displayHours]);
410
+ useEffect(() => {
411
+ setMinuteInput(time.minutes.toString().padStart(2, "0"));
412
+ }, [time.minutes]);
413
+ const handStyle = useAnimatedStyle(() => ({
414
+ transform: [{ rotate: `${handRotation.value}deg` }]
415
+ }));
416
+ const commitHourInput = () => {
417
+ if (hourInput.trim() === "") {
418
+ setHourInput(displayHours.toString().padStart(2, "0"));
419
+ return;
420
+ }
421
+ const hours = parseInt(hourInput, 10);
422
+ if (isNaN(hours)) {
423
+ setHourInput(displayHours.toString().padStart(2, "0"));
424
+ return;
425
+ }
426
+ const clampedHours = clampHour(hours, is24Hour);
427
+ const finalHours = is24Hour ? clampedHours : period === "PM" && clampedHours !== 12 ? clampedHours + 12 : clampedHours === 12 && period === "AM" ? 0 : clampedHours;
428
+ handleManualInput(finalHours, time.minutes);
429
+ };
430
+ const commitMinuteInput = () => {
431
+ if (minuteInput.trim() === "") {
432
+ setMinuteInput(time.minutes.toString().padStart(2, "0"));
433
+ return;
434
+ }
435
+ const minutes = parseInt(minuteInput, 10);
436
+ if (isNaN(minutes)) {
437
+ setMinuteInput(time.minutes.toString().padStart(2, "0"));
438
+ return;
439
+ }
440
+ handleManualInput(time.hours, clampMinute(minutes));
441
+ };
442
+ const renderClockNumbers = () => {
443
+ if (mode === "hour" && is24Hour) {
444
+ const outerRadius = 104;
445
+ const innerRadius = 70;
446
+ return Array.from({ length: 12 }, (_, slot) => {
447
+ const angle = slot * 30;
448
+ const radian = (angle - 90) * Math.PI / 180;
449
+ const outerValue = slot === 0 ? 12 : slot;
450
+ const innerValue = slot === 0 ? 0 : slot + 12;
451
+ const outerX = outerRadius * Math.cos(radian);
452
+ const outerY = outerRadius * Math.sin(radian);
453
+ const innerX = innerRadius * Math.cos(radian);
454
+ const innerY = innerRadius * Math.sin(radian);
455
+ const outerSelected = outerValue === displayHours;
456
+ const innerSelected = innerValue === displayHours;
457
+ return /* @__PURE__ */ React.createElement(React.Fragment, { key: `hour-24-slot-${slot}` }, /* @__PURE__ */ React.createElement(
458
+ Pressable,
459
+ {
460
+ onPress: () => handleHourChange(outerValue),
461
+ style: [
462
+ styles.clockNumber,
463
+ {
464
+ transform: [{ translateX: outerX }, { translateY: outerY }],
465
+ backgroundColor: outerSelected ? colors.primary : "transparent"
466
+ }
467
+ ]
468
+ },
469
+ /* @__PURE__ */ React.createElement(
470
+ Text,
471
+ {
472
+ style: [
473
+ styles.clockNumberText,
474
+ { color: outerSelected ? colors.onPrimary : colors.text }
475
+ ]
476
+ },
477
+ outerValue
478
+ )
479
+ ), /* @__PURE__ */ React.createElement(
480
+ Pressable,
481
+ {
482
+ onPress: () => handleHourChange(innerValue),
483
+ style: [
484
+ styles.clockNumber,
485
+ {
486
+ transform: [{ translateX: innerX }, { translateY: innerY }],
487
+ backgroundColor: innerSelected ? colors.primary : "transparent"
488
+ }
489
+ ]
490
+ },
491
+ /* @__PURE__ */ React.createElement(
492
+ Text,
493
+ {
494
+ style: [
495
+ styles.clockNumberText,
496
+ { color: innerSelected ? colors.onPrimary : colors.text }
497
+ ]
498
+ },
499
+ innerValue === 0 ? 24 : innerValue
500
+ )
501
+ ));
502
+ });
503
+ }
504
+ const numbers = mode === "hour" ? 12 : 60;
505
+ const step = mode === "hour" ? 1 : 5;
506
+ const radius = 100;
507
+ return Array.from({ length: numbers / step }, (_, i) => {
508
+ const value2 = mode === "hour" ? i === 0 ? 12 : i * step : i * step;
509
+ const angle = value2 / (mode === "hour" ? 12 : 60) * 360;
510
+ const radian = (angle - 90) * Math.PI / 180;
511
+ const x = radius * Math.cos(radian);
512
+ const y = radius * Math.sin(radian);
513
+ const isSelected = mode === "hour" ? value2 === displayHours : value2 === time.minutes;
514
+ return /* @__PURE__ */ React.createElement(
515
+ Pressable,
516
+ {
517
+ key: `${mode}-${value2}`,
518
+ onPress: () => {
519
+ if (mode === "hour") {
520
+ handleHourChange(value2 === 12 && period === "PM" ? 12 : value2);
521
+ } else {
522
+ handleMinuteChange(value2);
523
+ }
524
+ },
525
+ style: [
526
+ styles.clockNumber,
527
+ {
528
+ transform: [{ translateX: x }, { translateY: y }],
529
+ backgroundColor: isSelected ? colors.primary : "transparent"
530
+ }
531
+ ]
532
+ },
533
+ /* @__PURE__ */ React.createElement(
534
+ Text,
535
+ {
536
+ style: [
537
+ styles.clockNumberText,
538
+ { color: isSelected ? colors.onPrimary : colors.text }
539
+ ]
540
+ },
541
+ mode === "minute" && value2 < 10 ? `0${value2}` : value2
542
+ )
543
+ );
544
+ });
545
+ };
546
+ return /* @__PURE__ */ React.createElement(View, { style: [styles.container, style] }, /* @__PURE__ */ React.createElement(View, { style: styles.header }, /* @__PURE__ */ React.createElement(Text, { style: [styles.headerTitle, { color: colors.textSecondary }] }, "Select time"), /* @__PURE__ */ React.createElement(
547
+ View,
548
+ {
549
+ style: [styles.timeDisplay, !is24Hour && styles.timeDisplayWithPeriod]
550
+ },
551
+ /* @__PURE__ */ React.createElement(View, { style: styles.timeSection }, /* @__PURE__ */ React.createElement(
552
+ TextInput,
553
+ {
554
+ style: [
555
+ styles.timeDigit,
556
+ {
557
+ color: mode === "hour" ? colors.primary : colors.text,
558
+ backgroundColor: mode === "hour" ? colors.selectedDigit : "transparent"
559
+ }
560
+ ],
561
+ value: hourInput,
562
+ onChangeText: (text) => {
563
+ const numeric = text.replace(/[^0-9]/g, "");
564
+ if (numeric.length > 2) return;
565
+ setHourInput(numeric);
566
+ if (numeric === "") return;
567
+ const hours = parseInt(numeric, 10);
568
+ if (isNaN(hours)) return;
569
+ const clampedHours = clampHour(hours, is24Hour);
570
+ const finalHours = is24Hour ? clampedHours : period === "PM" && clampedHours !== 12 ? clampedHours + 12 : clampedHours === 12 && period === "AM" ? 0 : clampedHours;
571
+ handleManualInput(finalHours, time.minutes);
572
+ },
573
+ onFocus: () => setMode("hour"),
574
+ onBlur: commitHourInput,
575
+ onSubmitEditing: commitHourInput,
576
+ keyboardType: "number-pad",
577
+ maxLength: 2,
578
+ selectTextOnFocus: true
579
+ }
580
+ ), /* @__PURE__ */ React.createElement(Text, { style: [styles.timeSeparator, { color: colors.text }] }, ":"), /* @__PURE__ */ React.createElement(
581
+ TextInput,
582
+ {
583
+ style: [
584
+ styles.timeDigit,
585
+ {
586
+ color: mode === "minute" ? colors.primary : colors.text,
587
+ backgroundColor: mode === "minute" ? colors.selectedDigit : "transparent"
588
+ }
589
+ ],
590
+ value: minuteInput,
591
+ onChangeText: (text) => {
592
+ const numeric = text.replace(/[^0-9]/g, "");
593
+ if (numeric.length > 2) return;
594
+ setMinuteInput(numeric);
595
+ if (numeric === "") return;
596
+ const minutes = parseInt(numeric, 10);
597
+ if (isNaN(minutes)) return;
598
+ handleManualInput(time.hours, clampMinute(minutes));
599
+ },
600
+ onFocus: () => setMode("minute"),
601
+ onBlur: commitMinuteInput,
602
+ onSubmitEditing: commitMinuteInput,
603
+ keyboardType: "number-pad",
604
+ maxLength: 2,
605
+ selectTextOnFocus: true
606
+ }
607
+ )),
608
+ !is24Hour && /* @__PURE__ */ React.createElement(View, { style: styles.periodSelector }, /* @__PURE__ */ React.createElement(
609
+ Pressable,
610
+ {
611
+ onPress: () => handlePeriodToggle("AM"),
612
+ style: [
613
+ styles.periodButton,
614
+ {
615
+ backgroundColor: period === "AM" ? colors.surface : "transparent",
616
+ borderColor: period === "AM" ? colors.primary : colors.border
617
+ }
618
+ ]
619
+ },
620
+ /* @__PURE__ */ React.createElement(
621
+ Text,
622
+ {
623
+ style: [
624
+ styles.periodText,
625
+ { color: period === "AM" ? colors.primary : colors.text }
626
+ ]
627
+ },
628
+ "AM"
629
+ )
630
+ ), /* @__PURE__ */ React.createElement(
631
+ Pressable,
632
+ {
633
+ onPress: () => handlePeriodToggle("PM"),
634
+ style: [
635
+ styles.periodButton,
636
+ {
637
+ backgroundColor: period === "PM" ? colors.surface : "transparent",
638
+ borderColor: period === "PM" ? colors.primary : colors.border
639
+ }
640
+ ]
641
+ },
642
+ /* @__PURE__ */ React.createElement(
643
+ Text,
644
+ {
645
+ style: [
646
+ styles.periodText,
647
+ { color: period === "PM" ? colors.primary : colors.text }
648
+ ]
649
+ },
650
+ "PM"
651
+ )
652
+ ))
653
+ )), /* @__PURE__ */ React.createElement(View, { style: styles.clockContainer }, /* @__PURE__ */ React.createElement(View, { style: [styles.clockFace, { backgroundColor: colors.clockFace }] }, renderClockNumbers(), /* @__PURE__ */ React.createElement(View, { style: [styles.clockCenter, { backgroundColor: colors.primary }] }), /* @__PURE__ */ React.createElement(
654
+ Animated.View,
655
+ {
656
+ style: [
657
+ styles.clockHand,
658
+ {
659
+ height: 84,
660
+ top: "50%",
661
+ left: "50%",
662
+ marginLeft: -1
663
+ },
664
+ handStyle
665
+ ]
666
+ },
667
+ /* @__PURE__ */ React.createElement(
668
+ View,
669
+ {
670
+ style: [
671
+ styles.clockHandLine,
672
+ { height: "100%", backgroundColor: colors.primary }
673
+ ]
674
+ }
675
+ ),
676
+ /* @__PURE__ */ React.createElement(
677
+ View,
678
+ {
679
+ style: [styles.clockHandDot, { backgroundColor: colors.primary }]
680
+ }
681
+ )
682
+ ))));
683
+ };
684
+
685
+ // src/components/timepicker/timepicker-dialog.tsx
686
+ import React3, { useState as useState4 } from "react";
687
+ import { View as View3, Text as Text2, Pressable as Pressable3 } from "react-native";
688
+
689
+ // src/components/bottom-sheet/bottom-sheet.tsx
690
+ import React2 from "react";
691
+ import { Animated as Animated4, Pressable as Pressable2, View as View2 } from "react-native";
692
+
693
+ // src/components/bottom-sheet/bottom-sheet.hook.ts
694
+ import { useCallback, useEffect as useEffect2, useMemo as useMemo3, useRef, useState as useState3 } from "react";
695
+ import { Animated as Animated3, Dimensions, PanResponder } from "react-native";
696
+ import { getSafeThemeColor as getSafeThemeColor2 } from "@xaui/core";
697
+
698
+ // src/components/bottom-sheet/bottom-sheet.animation.ts
699
+ import { Animated as Animated2, Easing as Easing2 } from "react-native";
700
+ var SPRING_CONFIG = {
701
+ useNativeDriver: true,
702
+ speed: 14,
703
+ bounciness: 4
704
+ };
705
+ var TIMING_CONFIG = {
706
+ duration: 280,
707
+ easing: Easing2.bezier(0.2, 0, 0, 1),
708
+ useNativeDriver: true
709
+ };
710
+ var runOpenAnimation = (translateY, backdropOpacity, targetTranslateY) => {
711
+ const animation = Animated2.parallel([
712
+ Animated2.spring(translateY, {
713
+ ...SPRING_CONFIG,
714
+ toValue: targetTranslateY
715
+ }),
716
+ Animated2.timing(backdropOpacity, {
717
+ ...TIMING_CONFIG,
718
+ toValue: 1
719
+ })
720
+ ]);
721
+ animation.start();
722
+ return animation;
723
+ };
724
+ var runCloseAnimation = (translateY, backdropOpacity, screenHeight, onComplete) => {
725
+ const animation = Animated2.parallel([
726
+ Animated2.timing(translateY, {
727
+ ...TIMING_CONFIG,
728
+ toValue: screenHeight
729
+ }),
730
+ Animated2.timing(backdropOpacity, {
731
+ ...TIMING_CONFIG,
732
+ toValue: 0
733
+ })
734
+ ]);
735
+ animation.start(({ finished }) => {
736
+ if (finished && onComplete) {
737
+ onComplete();
738
+ }
739
+ });
740
+ return animation;
741
+ };
742
+ var runSnapAnimation = (translateY, targetTranslateY) => {
743
+ const animation = Animated2.spring(translateY, {
744
+ ...SPRING_CONFIG,
745
+ toValue: targetTranslateY
746
+ });
747
+ animation.start();
748
+ return animation;
749
+ };
750
+
751
+ // src/components/bottom-sheet/bottom-sheet.hook.ts
752
+ var DISMISS_VELOCITY_THRESHOLD = 0.5;
753
+ var DISMISS_DISTANCE_FRACTION = 0.3;
754
+ var SCREEN_HEIGHT = Dimensions.get("window").height;
755
+ var getTranslateYForSnap = (snapFraction) => SCREEN_HEIGHT * (1 - snapFraction);
756
+ var useBottomSheetAnimation = ({
757
+ isOpen,
758
+ snapPoints,
759
+ initialSnapIndex,
760
+ enableSwipeToDismiss,
761
+ disableAnimation,
762
+ onClose,
763
+ onSnapChange
764
+ }) => {
765
+ const [shouldRender, setShouldRender] = useState3(false);
766
+ const currentSnapIndex = useRef(initialSnapIndex);
767
+ const animationRef = useRef(null);
768
+ const translateY = useRef(new Animated3.Value(SCREEN_HEIGHT)).current;
769
+ const backdropOpacity = useRef(new Animated3.Value(0)).current;
770
+ const sortedSnapPoints = useMemo3(
771
+ () => [...snapPoints].sort((a, b) => a - b),
772
+ [snapPoints]
773
+ );
774
+ const snapTranslateValues = useMemo3(
775
+ () => sortedSnapPoints.map(getTranslateYForSnap),
776
+ [sortedSnapPoints]
777
+ );
778
+ const open = useCallback(() => {
779
+ setShouldRender(true);
780
+ const targetIndex = Math.min(initialSnapIndex, sortedSnapPoints.length - 1);
781
+ currentSnapIndex.current = targetIndex;
782
+ if (disableAnimation) {
783
+ translateY.setValue(snapTranslateValues[targetIndex]);
784
+ backdropOpacity.setValue(1);
785
+ return;
786
+ }
787
+ translateY.setValue(SCREEN_HEIGHT);
788
+ backdropOpacity.setValue(0);
789
+ animationRef.current?.stop();
790
+ animationRef.current = runOpenAnimation(
791
+ translateY,
792
+ backdropOpacity,
793
+ snapTranslateValues[targetIndex]
794
+ );
795
+ }, [
796
+ initialSnapIndex,
797
+ sortedSnapPoints,
798
+ snapTranslateValues,
799
+ disableAnimation,
800
+ translateY,
801
+ backdropOpacity
802
+ ]);
803
+ const close = useCallback(() => {
804
+ if (disableAnimation) {
805
+ translateY.setValue(SCREEN_HEIGHT);
806
+ backdropOpacity.setValue(0);
807
+ setShouldRender(false);
808
+ onClose?.();
809
+ return;
810
+ }
811
+ animationRef.current?.stop();
812
+ animationRef.current = runCloseAnimation(
813
+ translateY,
814
+ backdropOpacity,
815
+ SCREEN_HEIGHT,
816
+ () => {
817
+ setShouldRender(false);
818
+ onClose?.();
819
+ }
820
+ );
821
+ }, [disableAnimation, translateY, backdropOpacity, onClose]);
822
+ const snapTo = useCallback(
823
+ (index) => {
824
+ const clampedIndex = Math.max(0, Math.min(index, sortedSnapPoints.length - 1));
825
+ currentSnapIndex.current = clampedIndex;
826
+ onSnapChange?.(clampedIndex);
827
+ if (disableAnimation) {
828
+ translateY.setValue(snapTranslateValues[clampedIndex]);
829
+ return;
830
+ }
831
+ animationRef.current?.stop();
832
+ animationRef.current = runSnapAnimation(
833
+ translateY,
834
+ snapTranslateValues[clampedIndex]
835
+ );
836
+ },
837
+ [
838
+ sortedSnapPoints,
839
+ snapTranslateValues,
840
+ disableAnimation,
841
+ translateY,
842
+ onSnapChange
843
+ ]
844
+ );
845
+ useEffect2(() => {
846
+ if (isOpen) {
847
+ open();
848
+ } else if (shouldRender) {
849
+ close();
850
+ }
851
+ }, [isOpen]);
852
+ const panResponder = useMemo3(
853
+ () => PanResponder.create({
854
+ onStartShouldSetPanResponder: () => true,
855
+ onMoveShouldSetPanResponder: (_, gestureState) => Math.abs(gestureState.dy) > 5,
856
+ onPanResponderMove: (_, gestureState) => {
857
+ const currentTranslate = snapTranslateValues[currentSnapIndex.current];
858
+ const newTranslateY = currentTranslate + gestureState.dy;
859
+ const maxExpanded = snapTranslateValues[snapTranslateValues.length - 1];
860
+ const clamped = Math.max(maxExpanded, newTranslateY);
861
+ translateY.setValue(clamped);
862
+ },
863
+ onPanResponderRelease: (_, gestureState) => {
864
+ const currentTranslate = snapTranslateValues[currentSnapIndex.current];
865
+ const finalPosition = currentTranslate + gestureState.dy;
866
+ if (enableSwipeToDismiss && (gestureState.vy > DISMISS_VELOCITY_THRESHOLD || finalPosition > SCREEN_HEIGHT * (1 - sortedSnapPoints[0] * DISMISS_DISTANCE_FRACTION))) {
867
+ close();
868
+ return;
869
+ }
870
+ if (gestureState.vy < -DISMISS_VELOCITY_THRESHOLD) {
871
+ const nextIndex = Math.min(
872
+ currentSnapIndex.current + 1,
873
+ sortedSnapPoints.length - 1
874
+ );
875
+ snapTo(nextIndex);
876
+ return;
877
+ }
878
+ if (gestureState.vy > DISMISS_VELOCITY_THRESHOLD) {
879
+ const prevIndex = Math.max(currentSnapIndex.current - 1, 0);
880
+ if (prevIndex === currentSnapIndex.current && enableSwipeToDismiss) {
881
+ close();
882
+ return;
883
+ }
884
+ snapTo(prevIndex);
885
+ return;
886
+ }
887
+ let closestIndex = 0;
888
+ let minDistance = Infinity;
889
+ snapTranslateValues.forEach((snapVal, index) => {
890
+ const distance = Math.abs(finalPosition - snapVal);
891
+ if (distance < minDistance) {
892
+ minDistance = distance;
893
+ closestIndex = index;
894
+ }
895
+ });
896
+ snapTo(closestIndex);
897
+ }
898
+ }),
899
+ [
900
+ snapTranslateValues,
901
+ sortedSnapPoints,
902
+ enableSwipeToDismiss,
903
+ translateY,
904
+ close,
905
+ snapTo
906
+ ]
907
+ );
908
+ return {
909
+ shouldRender,
910
+ translateY,
911
+ backdropOpacity,
912
+ panResponder,
913
+ close,
914
+ snapTo,
915
+ screenHeight: SCREEN_HEIGHT
916
+ };
917
+ };
918
+ var useBottomSheetStyles = (themeColor, radius) => {
919
+ const theme = useXUITheme();
920
+ const safeThemeColor = getSafeThemeColor2(themeColor);
921
+ const colorScheme = theme.colors[safeThemeColor];
922
+ const sheetStyles = useMemo3(
923
+ () => ({
924
+ backgroundColor: colorScheme.background ?? theme.colors.background ?? "#ffffff",
925
+ borderTopLeftRadius: theme.borderRadius[radius],
926
+ borderTopRightRadius: theme.borderRadius[radius]
927
+ }),
928
+ [theme, colorScheme, radius]
929
+ );
930
+ const handleIndicatorColor = useMemo3(
931
+ () => theme.mode === "dark" ? `${colorScheme.main}60` : `${colorScheme.main}40`,
932
+ [theme, colorScheme]
933
+ );
934
+ return { sheetStyles, handleIndicatorColor };
935
+ };
936
+
937
+ // src/components/bottom-sheet/bottom-sheet.style.ts
938
+ import { StyleSheet as StyleSheet2 } from "react-native";
939
+ var styles2 = StyleSheet2.create({
940
+ backdrop: {
941
+ position: "absolute",
942
+ top: 0,
943
+ left: 0,
944
+ right: 0,
945
+ bottom: 0,
946
+ backgroundColor: "rgba(0, 0, 0, 0.5)"
947
+ },
948
+ container: {
949
+ position: "absolute",
950
+ left: 0,
951
+ right: 0,
952
+ bottom: 0
953
+ },
954
+ sheet: {
955
+ overflow: "hidden"
956
+ },
957
+ handle: {
958
+ alignItems: "center",
959
+ justifyContent: "center",
960
+ paddingVertical: 10
961
+ },
962
+ handleIndicator: {
963
+ width: 36,
964
+ height: 4,
965
+ borderRadius: 2
966
+ },
967
+ content: {
968
+ flex: 1
969
+ }
970
+ });
971
+
972
+ // src/components/bottom-sheet/bottom-sheet.tsx
973
+ var BottomSheet = ({
974
+ children,
975
+ isOpen,
976
+ snapPoints = [0.4, 0.9],
977
+ initialSnapIndex = 0,
978
+ themeColor = "default",
979
+ radius = "lg",
980
+ showBackdrop = true,
981
+ closeOnBackdropPress = true,
982
+ enableSwipeToDismiss = true,
983
+ showHandle = true,
984
+ disableAnimation = false,
985
+ style,
986
+ handleContent,
987
+ onClose,
988
+ onSnapChange
989
+ }) => {
990
+ const {
991
+ shouldRender,
992
+ translateY,
993
+ backdropOpacity,
994
+ panResponder,
995
+ close,
996
+ screenHeight
997
+ } = useBottomSheetAnimation({
998
+ isOpen,
999
+ snapPoints,
1000
+ initialSnapIndex,
1001
+ enableSwipeToDismiss,
1002
+ disableAnimation,
1003
+ onClose,
1004
+ onSnapChange
1005
+ });
1006
+ const { sheetStyles, handleIndicatorColor } = useBottomSheetStyles(
1007
+ themeColor,
1008
+ radius
1009
+ );
1010
+ if (!shouldRender) {
1011
+ return null;
1012
+ }
1013
+ const handleBackdropPress = () => {
1014
+ if (closeOnBackdropPress) {
1015
+ close();
1016
+ }
1017
+ };
1018
+ return /* @__PURE__ */ React2.createElement(Portal, null, showBackdrop && /* @__PURE__ */ React2.createElement(Animated4.View, { style: [styles2.backdrop, { opacity: backdropOpacity }] }, /* @__PURE__ */ React2.createElement(Pressable2, { style: styles2.backdrop, onPress: handleBackdropPress })), /* @__PURE__ */ React2.createElement(
1019
+ Animated4.View,
1020
+ {
1021
+ style: [
1022
+ styles2.container,
1023
+ {
1024
+ height: screenHeight,
1025
+ transform: [{ translateY }]
1026
+ }
1027
+ ]
1028
+ },
1029
+ /* @__PURE__ */ React2.createElement(
1030
+ View2,
1031
+ {
1032
+ style: [styles2.sheet, { height: screenHeight }, sheetStyles, style],
1033
+ ...panResponder.panHandlers
1034
+ },
1035
+ showHandle && /* @__PURE__ */ React2.createElement(View2, { style: styles2.handle }, handleContent ?? /* @__PURE__ */ React2.createElement(
1036
+ View2,
1037
+ {
1038
+ style: [
1039
+ styles2.handleIndicator,
1040
+ { backgroundColor: handleIndicatorColor }
1041
+ ]
1042
+ }
1043
+ )),
1044
+ /* @__PURE__ */ React2.createElement(View2, { style: styles2.content }, children)
1045
+ )
1046
+ ));
1047
+ };
1048
+
1049
+ // src/components/timepicker/timepicker-dialog.tsx
1050
+ var TimePickerDialog = ({
1051
+ isOpen,
1052
+ onClose,
1053
+ value,
1054
+ onChange,
1055
+ is24Hour = false,
1056
+ themeColor = "primary",
1057
+ confirmText = "OK",
1058
+ cancelText = "Cancel",
1059
+ onConfirm,
1060
+ onCancel
1061
+ }) => {
1062
+ const [tempValue, setTempValue] = useState4(value);
1063
+ const colors = useTimePickerColors(themeColor);
1064
+ const handleChange = (time) => {
1065
+ setTempValue(time);
1066
+ onChange?.(time);
1067
+ };
1068
+ const handleConfirm = () => {
1069
+ if (tempValue) {
1070
+ onConfirm?.(tempValue);
1071
+ }
1072
+ onClose();
1073
+ };
1074
+ const handleCancel = () => {
1075
+ onCancel?.();
1076
+ onClose();
1077
+ };
1078
+ return /* @__PURE__ */ React3.createElement(BottomSheet, { isOpen, onClose, snapPoints: [0.7] }, /* @__PURE__ */ React3.createElement(View3, null, /* @__PURE__ */ React3.createElement(
1079
+ TimePicker,
1080
+ {
1081
+ value: tempValue,
1082
+ onChange: handleChange,
1083
+ is24Hour,
1084
+ themeColor
1085
+ }
1086
+ ), /* @__PURE__ */ React3.createElement(View3, { style: styles.actions }, /* @__PURE__ */ React3.createElement(
1087
+ Pressable3,
1088
+ {
1089
+ onPress: handleCancel,
1090
+ style: [styles.actionButton, { backgroundColor: "transparent" }]
1091
+ },
1092
+ /* @__PURE__ */ React3.createElement(Text2, { style: [styles.actionButtonText, { color: colors.primary }] }, cancelText)
1093
+ ), /* @__PURE__ */ React3.createElement(
1094
+ Pressable3,
1095
+ {
1096
+ onPress: handleConfirm,
1097
+ style: [styles.actionButton, { backgroundColor: "transparent" }]
1098
+ },
1099
+ /* @__PURE__ */ React3.createElement(Text2, { style: [styles.actionButtonText, { color: colors.primary }] }, confirmText)
1100
+ ))));
1101
+ };
1102
+
1103
+ // src/components/timepicker/timepicker-trigger.tsx
1104
+ import React4, { useMemo as useMemo4 } from "react";
1105
+ import { Pressable as Pressable4, Text as Text3, TouchableOpacity, View as View4 } from "react-native";
1106
+ import { CloseIcon, TimeIcon } from "@xaui/icons";
1107
+ var TimePickerTrigger = ({
1108
+ value,
1109
+ placeholder = "Select time",
1110
+ is24Hour = false,
1111
+ themeColor = "primary",
1112
+ isDisabled = false,
1113
+ isReadOnly = false,
1114
+ isClearable = true,
1115
+ icon,
1116
+ style,
1117
+ textStyle,
1118
+ onPress,
1119
+ onClear
1120
+ }) => {
1121
+ const theme = useXUITheme();
1122
+ const colors = useTimePickerColors(themeColor);
1123
+ const hasValue = Boolean(value);
1124
+ const displayValue = useMemo4(() => {
1125
+ if (!value) return placeholder;
1126
+ return formatTimeValue(value, is24Hour);
1127
+ }, [value, placeholder, is24Hour]);
1128
+ const triggerStyle = {
1129
+ borderColor: colors.border,
1130
+ backgroundColor: colors.background
1131
+ };
1132
+ const triggerTextStyle = {
1133
+ color: hasValue ? theme.colors.foreground : colors.textSecondary
1134
+ };
1135
+ const isBlocked = isDisabled || isReadOnly;
1136
+ return /* @__PURE__ */ React4.createElement(
1137
+ Pressable4,
1138
+ {
1139
+ onPress: isBlocked ? void 0 : onPress,
1140
+ disabled: isBlocked,
1141
+ style: [styles.trigger, triggerStyle, isBlocked && styles.disabled, style],
1142
+ accessibilityRole: "button",
1143
+ accessibilityState: { disabled: isBlocked }
1144
+ },
1145
+ /* @__PURE__ */ React4.createElement(View4, { style: styles.triggerContent }, /* @__PURE__ */ React4.createElement(
1146
+ Text3,
1147
+ {
1148
+ style: [styles.triggerText, triggerTextStyle, textStyle],
1149
+ numberOfLines: 1,
1150
+ ellipsizeMode: "tail"
1151
+ },
1152
+ displayValue
1153
+ )),
1154
+ isClearable && hasValue && !isBlocked ? /* @__PURE__ */ React4.createElement(
1155
+ TouchableOpacity,
1156
+ {
1157
+ onPress: onClear,
1158
+ style: styles.clearButton,
1159
+ hitSlop: { top: 8, right: 8, bottom: 8, left: 8 }
1160
+ },
1161
+ /* @__PURE__ */ React4.createElement(CloseIcon, { color: theme.colors.foreground, size: 20 })
1162
+ ) : icon ?? /* @__PURE__ */ React4.createElement(TimeIcon, { color: theme.colors.foreground, size: 20 })
1163
+ );
1164
+ };
1165
+ export {
1166
+ TimePicker,
1167
+ TimePickerDialog,
1168
+ TimePickerTrigger,
1169
+ angleToHour,
1170
+ angleToMinute,
1171
+ calculateAngleFromPosition,
1172
+ clampHour,
1173
+ clampMinute,
1174
+ formatTimeValue,
1175
+ getCurrentTime,
1176
+ getHourAngle,
1177
+ getMinuteAngle,
1178
+ isTimeInRange,
1179
+ to12HourFormat,
1180
+ to24HourFormat
1181
+ };