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