@xaui/native 0.0.17 → 0.0.18

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 (47) hide show
  1. package/dist/accordion/index.js +2 -2
  2. package/dist/alert/index.js +352 -4
  3. package/dist/autocomplete/index.js +1121 -5
  4. package/dist/avatar/index.js +276 -5
  5. package/dist/badge/index.js +193 -4
  6. package/dist/bottom-sheet/index.js +364 -4
  7. package/dist/button/index.js +2 -2
  8. package/dist/card/index.cjs +429 -0
  9. package/dist/card/index.d.cts +186 -0
  10. package/dist/card/index.d.ts +186 -0
  11. package/dist/card/index.js +336 -0
  12. package/dist/carousel/index.js +377 -3
  13. package/dist/checkbox/index.js +1 -1
  14. package/dist/chip/index.js +497 -6
  15. package/dist/{chunk-VUVE6PK7.js → chunk-F7WH4DMG.js} +1 -1
  16. package/dist/{chunk-TJ2FPLLZ.js → chunk-JEGEPGVU.js} +2 -2
  17. package/dist/{chunk-MZL77KV5.js → chunk-LTKYHG5V.js} +1 -1
  18. package/dist/{chunk-RIVFFZRO.js → chunk-LUBWRVI2.js} +1 -1
  19. package/dist/core/index.cjs +1 -1
  20. package/dist/core/index.js +1 -1
  21. package/dist/datepicker/index.js +1623 -4
  22. package/dist/divider/index.js +2 -2
  23. package/dist/fab/index.js +3 -3
  24. package/dist/fab-menu/index.js +324 -6
  25. package/dist/index.cjs +0 -6446
  26. package/dist/index.d.cts +2 -19
  27. package/dist/index.d.ts +2 -19
  28. package/dist/index.js +0 -73
  29. package/dist/indicator/index.js +2 -2
  30. package/dist/menu/index.js +1 -1
  31. package/dist/progress/index.js +1 -1
  32. package/dist/segment-button/index.js +400 -5
  33. package/dist/select/index.js +1 -1
  34. package/dist/switch/index.js +1 -1
  35. package/dist/typography/index.js +146 -4
  36. package/package.json +6 -1
  37. package/dist/chunk-6PXMB5CH.js +0 -503
  38. package/dist/chunk-DBKVHMSA.js +0 -329
  39. package/dist/chunk-EW5YLICE.js +0 -382
  40. package/dist/chunk-JJOVGRNI.js +0 -1627
  41. package/dist/chunk-K2HSVISE.js +0 -281
  42. package/dist/chunk-OXVIVNIJ.js +0 -356
  43. package/dist/chunk-PWCUULAL.js +0 -150
  44. package/dist/chunk-S3MGBM3G.js +0 -368
  45. package/dist/chunk-STUNTRKJ.js +0 -405
  46. package/dist/chunk-UGDGCMGC.js +0 -197
  47. package/dist/chunk-XUYIAA3A.js +0 -1127
@@ -1,1127 +0,0 @@
1
- import {
2
- CheckmarkIcon
3
- } from "./chunk-GBHQCAKW.js";
4
- import {
5
- Portal,
6
- useXUITheme
7
- } from "./chunk-MZL77KV5.js";
8
-
9
- // src/components/autocomplete/autocomplete.tsx
10
- import React4, { useCallback as useCallback3, useMemo as useMemo3, useRef as useRef3, useState as useState3 } from "react";
11
- import { Keyboard as Keyboard2, Text as Text3, View as View4 } from "react-native";
12
-
13
- // src/components/autocomplete/autocomplete-context.ts
14
- import { createContext } from "react";
15
- var AutocompleteContext = createContext({
16
- size: "md",
17
- themeColor: "default",
18
- isDisabled: false
19
- });
20
-
21
- // src/components/autocomplete/autocomplete.hook.ts
22
- import { useMemo } from "react";
23
- import { getSafeThemeColor } from "@xaui/core";
24
- import { colors } from "@xaui/core/palette";
25
- var useAutocompleteColorScheme = (themeColor) => {
26
- const theme = useXUITheme();
27
- const safeThemeColor = getSafeThemeColor(themeColor);
28
- const colorScheme = theme.colors[safeThemeColor];
29
- return { theme, colorScheme };
30
- };
31
- var useAutocompleteSizeStyles = (size) => {
32
- const theme = useXUITheme();
33
- return useMemo(() => {
34
- const sizes = {
35
- xs: {
36
- minHeight: 34,
37
- paddingHorizontal: theme.spacing.sm,
38
- paddingVertical: theme.spacing.xs,
39
- fontSize: theme.fontSizes.xs,
40
- labelSize: theme.fontSizes.xs
41
- },
42
- sm: {
43
- minHeight: 38,
44
- paddingHorizontal: theme.spacing.md,
45
- paddingVertical: theme.spacing.xs,
46
- fontSize: theme.fontSizes.sm,
47
- labelSize: theme.fontSizes.xs
48
- },
49
- md: {
50
- minHeight: 42,
51
- paddingHorizontal: theme.spacing.md,
52
- paddingVertical: theme.spacing.sm,
53
- fontSize: theme.fontSizes.md,
54
- labelSize: theme.fontSizes.sm
55
- },
56
- lg: {
57
- minHeight: 50,
58
- paddingHorizontal: theme.spacing.lg,
59
- paddingVertical: theme.spacing.md,
60
- fontSize: theme.fontSizes.lg,
61
- labelSize: theme.fontSizes.md
62
- }
63
- };
64
- return sizes[size];
65
- }, [size, theme]);
66
- };
67
- var useAutocompleteRadiusStyles = (radius) => {
68
- const theme = useXUITheme();
69
- const radiusStyles = useMemo(() => {
70
- const radii = {
71
- none: theme.borderRadius.none,
72
- sm: theme.borderRadius.sm,
73
- md: theme.borderRadius.md,
74
- lg: theme.borderRadius.lg,
75
- full: theme.borderRadius.full
76
- };
77
- return { borderRadius: radii[radius] };
78
- }, [radius, theme]);
79
- const listboxRadius = useMemo(() => {
80
- const radii = {
81
- none: theme.borderRadius.none,
82
- sm: theme.borderRadius.sm,
83
- md: theme.borderRadius.md,
84
- lg: theme.borderRadius.lg,
85
- full: theme.borderRadius.full
86
- };
87
- return Math.min(radii[radius], theme.borderRadius.lg);
88
- }, [radius, theme]);
89
- return { radiusStyles, listboxRadius };
90
- };
91
- var useAutocompleteVariantStyles = (themeColor, variant, isInvalid) => {
92
- const { theme, colorScheme } = useAutocompleteColorScheme(themeColor);
93
- return useMemo(() => {
94
- let borderColor = isInvalid ? theme.colors.danger.main : colorScheme.main;
95
- if ((variant === "outlined" || variant === "faded") && themeColor === "default") {
96
- borderColor = colors.gray[300];
97
- }
98
- const styles4 = {
99
- outlined: {
100
- backgroundColor: "transparent",
101
- borderWidth: theme.borderWidth.md,
102
- borderColor
103
- },
104
- flat: {
105
- backgroundColor: colorScheme.background,
106
- borderWidth: 0
107
- },
108
- light: {
109
- backgroundColor: "transparent",
110
- borderWidth: 0
111
- },
112
- faded: {
113
- backgroundColor: `${colorScheme.background}90`,
114
- borderWidth: theme.borderWidth.md,
115
- borderColor
116
- },
117
- underlined: {
118
- backgroundColor: "transparent",
119
- borderBottomWidth: theme.borderWidth.md,
120
- borderColor
121
- }
122
- };
123
- return styles4[variant];
124
- }, [variant, theme, colorScheme, isInvalid, themeColor]);
125
- };
126
- var useAutocompleteLabelStyle = (themeColor, isInvalid, labelSize) => {
127
- const { theme, colorScheme } = useAutocompleteColorScheme(themeColor);
128
- return useMemo(() => {
129
- let baseColor = theme.colors.foreground;
130
- if (isInvalid) {
131
- baseColor = theme.colors.danger.main;
132
- } else if (themeColor !== "default") {
133
- baseColor = colorScheme.main;
134
- }
135
- return {
136
- fontSize: labelSize,
137
- color: baseColor
138
- };
139
- }, [isInvalid, labelSize, theme, themeColor, colorScheme]);
140
- };
141
- var useAutocompleteHelperColor = (isInvalid) => {
142
- const theme = useXUITheme();
143
- return useMemo(() => {
144
- if (isInvalid) {
145
- return theme.colors.danger.main;
146
- }
147
- return colors.gray[600];
148
- }, [isInvalid, theme]);
149
- };
150
-
151
- // src/components/autocomplete/autocomplete.style.ts
152
- import { StyleSheet } from "react-native";
153
- var styles = StyleSheet.create({
154
- container: {
155
- gap: 6,
156
- position: "relative"
157
- },
158
- fullWidth: {
159
- flexShrink: 1,
160
- flexBasis: "auto",
161
- width: "100%"
162
- },
163
- minWidth: {
164
- minWidth: 170
165
- },
166
- label: {
167
- fontWeight: "500"
168
- },
169
- trigger: {
170
- flexDirection: "row",
171
- alignItems: "center",
172
- justifyContent: "space-between",
173
- gap: 8
174
- },
175
- triggerText: {
176
- flex: 1
177
- },
178
- triggerWrapper: {
179
- position: "relative"
180
- },
181
- triggerContent: {
182
- flexDirection: "row",
183
- alignItems: "center",
184
- flex: 1,
185
- gap: 8
186
- },
187
- triggerContentColumn: {
188
- flexDirection: "column",
189
- alignItems: "flex-start"
190
- },
191
- inputWrapper: {
192
- flex: 1,
193
- gap: 2
194
- },
195
- input: {
196
- flexShrink: 1,
197
- padding: 0
198
- },
199
- endSlot: {
200
- flexDirection: "row",
201
- alignItems: "center",
202
- gap: 8
203
- },
204
- clearButton: {
205
- padding: 2,
206
- paddingLeft: 4,
207
- marginRight: -4
208
- },
209
- helperText: {
210
- fontSize: 12
211
- },
212
- disabled: {
213
- opacity: 0.5
214
- },
215
- listbox: {
216
- overflow: "hidden",
217
- marginTop: 0,
218
- position: "absolute",
219
- left: 0,
220
- right: 0,
221
- zIndex: 50,
222
- elevation: 4
223
- },
224
- listboxContent: {
225
- flexShrink: 1
226
- },
227
- emptyMessage: {
228
- paddingHorizontal: 16,
229
- paddingVertical: 12,
230
- textAlign: "center"
231
- },
232
- outsideLeftRow: {
233
- flexDirection: "row",
234
- alignItems: "center",
235
- gap: 12
236
- }
237
- });
238
-
239
- // src/components/autocomplete/autocomplete.state.hook.ts
240
- import { useCallback, useEffect, useRef, useState } from "react";
241
- var useAutocompleteOpenState = ({
242
- isOpened,
243
- isDisabled,
244
- onOpenChange,
245
- onClose
246
- }) => {
247
- const [internalIsOpen, setInternalIsOpen] = useState(false);
248
- const isOpen = isOpened !== void 0 ? isOpened : internalIsOpen;
249
- const setOpen = useCallback(
250
- (open) => {
251
- if (isDisabled) {
252
- return;
253
- }
254
- if (isOpened === void 0) {
255
- setInternalIsOpen(open);
256
- }
257
- onOpenChange?.(open);
258
- if (!open) {
259
- onClose?.();
260
- }
261
- },
262
- [isDisabled, isOpened, onOpenChange, onClose]
263
- );
264
- return { isOpen, setOpen };
265
- };
266
- var useAutocompleteInputState = ({
267
- inputValue,
268
- defaultInputValue,
269
- selectedKey,
270
- onInputChange
271
- }) => {
272
- const [internalInputValue, setInternalInputValue] = useState(
273
- defaultInputValue ?? ""
274
- );
275
- const currentInputValue = inputValue !== void 0 ? inputValue : internalInputValue;
276
- const updateInputValue = useCallback(
277
- (value) => {
278
- if (inputValue === void 0) {
279
- setInternalInputValue(value);
280
- }
281
- onInputChange?.(value);
282
- },
283
- [inputValue, onInputChange]
284
- );
285
- useEffect(() => {
286
- if (selectedKey === null && inputValue === void 0) {
287
- setInternalInputValue("");
288
- }
289
- }, [selectedKey, inputValue]);
290
- return { currentInputValue, updateInputValue };
291
- };
292
- var useAutocompleteSelection = ({
293
- onSelectionChange
294
- }) => {
295
- const [currentSelectedKey, setCurrentSelectedKey] = useState(null);
296
- const updateSelection = useCallback(
297
- (key) => {
298
- setCurrentSelectedKey(key);
299
- onSelectionChange?.(key);
300
- },
301
- [onSelectionChange]
302
- );
303
- return { currentSelectedKey, updateSelection };
304
- };
305
-
306
- // src/components/autocomplete/autocomplete.utils.ts
307
- var getTextValue = (node) => {
308
- if (typeof node === "string" || typeof node === "number") {
309
- return String(node);
310
- }
311
- return null;
312
- };
313
- var defaultFilterFunction = (textValue, inputValue) => {
314
- const normalizedText = textValue.toLowerCase().trim();
315
- const normalizedInput = inputValue.toLowerCase().trim();
316
- return normalizedText.includes(normalizedInput);
317
- };
318
-
319
- // src/components/dialogs/autocomplete-dialog/autocomplete-dialog.tsx
320
- import React2, { useCallback as useCallback2, useEffect as useEffect3, useMemo as useMemo2, useRef as useRef2, useState as useState2 } from "react";
321
- import {
322
- Animated as Animated3,
323
- BackHandler,
324
- FlatList,
325
- InteractionManager,
326
- Keyboard,
327
- Platform,
328
- Pressable as Pressable2,
329
- View as View2,
330
- useWindowDimensions
331
- } from "react-native";
332
-
333
- // src/components/dialogs/autocomplete-dialog/autocomplete-dialog-header.tsx
334
- import React from "react";
335
- import {
336
- Animated,
337
- Pressable,
338
- Text,
339
- TextInput,
340
- View
341
- } from "react-native";
342
- import { ArrowBackIcon, CloseIcon } from "@xaui/icons";
343
-
344
- // src/components/dialogs/autocomplete-dialog/autocomplete-dialog.style.ts
345
- import { StyleSheet as StyleSheet2 } from "react-native";
346
- var styles2 = StyleSheet2.create({
347
- backdrop: {
348
- ...StyleSheet2.absoluteFillObject,
349
- backgroundColor: "rgba(0, 0, 0, 0.5)"
350
- },
351
- dialogContainer: {
352
- flex: 1,
353
- zIndex: 1
354
- },
355
- container: {
356
- flex: 1,
357
- paddingTop: 55,
358
- paddingHorizontal: 16
359
- },
360
- header: {
361
- marginBottom: 12
362
- },
363
- titleRow: {
364
- flexDirection: "row",
365
- alignItems: "center",
366
- gap: 8,
367
- marginBottom: 16
368
- },
369
- backButton: {
370
- padding: 4
371
- },
372
- title: {
373
- fontSize: 20,
374
- fontWeight: "600"
375
- },
376
- inputContainer: {
377
- flexDirection: "row",
378
- alignItems: "center",
379
- gap: 8
380
- },
381
- inputWrapper: {
382
- flex: 1,
383
- flexDirection: "row",
384
- alignItems: "center",
385
- position: "relative"
386
- },
387
- input: {
388
- flex: 1,
389
- paddingVertical: 12,
390
- paddingHorizontal: 16,
391
- paddingRight: 40,
392
- borderRadius: 8,
393
- fontSize: 16
394
- },
395
- clearInputButton: {
396
- position: "absolute",
397
- right: 8,
398
- padding: 4
399
- },
400
- listContainer: {
401
- flex: 1
402
- },
403
- listContentContainer: {
404
- paddingBottom: 80
405
- },
406
- checkmarkButtonContainer: {
407
- position: "absolute",
408
- bottom: 24,
409
- right: 24
410
- },
411
- checkmarkButton: {
412
- width: 54,
413
- height: 54,
414
- borderRadius: 27,
415
- justifyContent: "center",
416
- alignItems: "center",
417
- elevation: 8
418
- }
419
- });
420
-
421
- // src/components/dialogs/autocomplete-dialog/autocomplete-dialog-header.tsx
422
- import { withOpacity } from "@xaui/core";
423
- var AutocompleteDialogHeader = ({
424
- title,
425
- inputValue,
426
- placeholder = "Search...",
427
- inputRef,
428
- inputAnimatedStyle,
429
- inputTextStyle,
430
- onInputChange,
431
- onClose,
432
- onCheckmarkPress,
433
- onFocus,
434
- onBlur
435
- }) => {
436
- const theme = useXUITheme();
437
- return /* @__PURE__ */ React.createElement(View, { style: styles2.header }, title ? /* @__PURE__ */ React.createElement(View, { style: styles2.titleRow }, /* @__PURE__ */ React.createElement(
438
- Pressable,
439
- {
440
- style: styles2.backButton,
441
- onPress: onClose,
442
- accessibilityLabel: "Back",
443
- accessibilityRole: "button"
444
- },
445
- /* @__PURE__ */ React.createElement(ArrowBackIcon, { size: 20, color: theme.colors.foreground })
446
- ), /* @__PURE__ */ React.createElement(Text, { style: [styles2.title, { color: theme.colors.foreground }] }, title)) : null, /* @__PURE__ */ React.createElement(View, { style: styles2.inputContainer }, /* @__PURE__ */ React.createElement(Animated.View, { style: [styles2.inputWrapper, inputAnimatedStyle] }, /* @__PURE__ */ React.createElement(
447
- TextInput,
448
- {
449
- ref: inputRef,
450
- value: inputValue,
451
- onChangeText: onInputChange,
452
- placeholder,
453
- placeholderTextColor: withOpacity(theme.colors.foreground, 0.5),
454
- style: [
455
- styles2.input,
456
- {
457
- backgroundColor: theme.colors.default.background,
458
- color: theme.colors.foreground
459
- },
460
- inputTextStyle
461
- ],
462
- autoFocus: true,
463
- returnKeyType: "done",
464
- onSubmitEditing: onCheckmarkPress,
465
- onFocus,
466
- onBlur
467
- }
468
- ), inputValue ? /* @__PURE__ */ React.createElement(
469
- Pressable,
470
- {
471
- style: styles2.clearInputButton,
472
- onPress: () => onInputChange?.(""),
473
- accessibilityLabel: "Clear input",
474
- accessibilityRole: "button"
475
- },
476
- /* @__PURE__ */ React.createElement(CloseIcon, { color: theme.colors.foreground })
477
- ) : null)));
478
- };
479
-
480
- // src/components/dialogs/autocomplete-dialog/autocomplete-dialog.animation.ts
481
- import { useEffect as useEffect2 } from "react";
482
- import { Animated as Animated2 } from "react-native";
483
- var useAutocompleteDialogAnimation = ({
484
- visible,
485
- fadeAnim,
486
- slideAnim,
487
- scaleAnim
488
- }) => {
489
- useEffect2(() => {
490
- if (visible) {
491
- Animated2.parallel([
492
- Animated2.timing(fadeAnim, {
493
- toValue: 1,
494
- duration: 250,
495
- useNativeDriver: true
496
- }),
497
- Animated2.spring(slideAnim, {
498
- toValue: 1,
499
- useNativeDriver: true,
500
- tension: 65,
501
- friction: 10
502
- }),
503
- Animated2.spring(scaleAnim, {
504
- toValue: 1,
505
- useNativeDriver: true,
506
- tension: 50,
507
- friction: 8
508
- })
509
- ]).start();
510
- } else {
511
- fadeAnim.setValue(0);
512
- slideAnim.setValue(0);
513
- scaleAnim.setValue(0);
514
- }
515
- }, [visible, fadeAnim, slideAnim, scaleAnim]);
516
- };
517
-
518
- // src/components/dialogs/autocomplete-dialog/autocomplete-dialog.tsx
519
- var AutocompleteDialog = ({
520
- visible,
521
- inputValue,
522
- placeholder = "Search...",
523
- title,
524
- themeColor = "primary",
525
- children,
526
- showCheckmark = true,
527
- checkmarkIcon,
528
- inputTextStyle,
529
- style,
530
- onInputChange,
531
- onClose,
532
- onCheckmark,
533
- onFocus,
534
- onBlur
535
- }) => {
536
- const theme = useXUITheme();
537
- const { width: screenWidth, height: screenHeight } = useWindowDimensions();
538
- const fadeAnim = useRef2(new Animated3.Value(0)).current;
539
- const slideAnim = useRef2(new Animated3.Value(0)).current;
540
- const scaleAnim = useRef2(new Animated3.Value(0)).current;
541
- const inputRef = useRef2(null);
542
- const [keyboardHeight, setKeyboardHeight] = useState2(0);
543
- useEffect3(() => {
544
- const showEvent = Platform.OS === "ios" ? "keyboardWillShow" : "keyboardDidShow";
545
- const hideEvent = Platform.OS === "ios" ? "keyboardWillHide" : "keyboardDidHide";
546
- const showSub = Keyboard.addListener(showEvent, (e) => {
547
- setKeyboardHeight(e.endCoordinates.height);
548
- });
549
- const hideSub = Keyboard.addListener(hideEvent, () => {
550
- setKeyboardHeight(0);
551
- });
552
- return () => {
553
- showSub.remove();
554
- hideSub.remove();
555
- };
556
- }, []);
557
- const items = useMemo2(
558
- () => React2.Children.toArray(children).filter(
559
- React2.isValidElement
560
- ),
561
- [children]
562
- );
563
- const checkmarkColor = theme.colors[themeColor].main;
564
- const checkmarkBackgroundColor = theme.colors[themeColor].background;
565
- useAutocompleteDialogAnimation({ visible, fadeAnim, slideAnim, scaleAnim });
566
- useEffect3(() => {
567
- if (!visible) return;
568
- const sub = BackHandler.addEventListener("hardwareBackPress", () => {
569
- onClose?.();
570
- return true;
571
- });
572
- return () => sub.remove();
573
- }, [visible, onClose]);
574
- const focusInput = useCallback2(() => {
575
- const delay = Platform.OS === "android" ? 300 : 100;
576
- InteractionManager.runAfterInteractions(() => {
577
- setTimeout(() => {
578
- inputRef.current?.focus();
579
- }, delay);
580
- });
581
- }, []);
582
- const handleCheckmarkPress = () => {
583
- onCheckmark?.();
584
- Keyboard.dismiss();
585
- };
586
- useEffect3(() => {
587
- if (!visible) {
588
- Keyboard.dismiss();
589
- return;
590
- }
591
- focusInput();
592
- }, [focusInput, visible]);
593
- const listBottomPadding = useMemo2(() => {
594
- const basePadding = showCheckmark ? 96 : 64;
595
- return (keyboardHeight > 0 ? keyboardHeight : 0) + basePadding;
596
- }, [keyboardHeight, showCheckmark]);
597
- if (!visible) return null;
598
- const overlayStyle = {
599
- position: "absolute",
600
- top: 0,
601
- left: 0,
602
- width: screenWidth,
603
- height: screenHeight
604
- };
605
- const containerAnimatedStyle = {
606
- transform: [
607
- {
608
- translateY: slideAnim.interpolate({
609
- inputRange: [0, 1],
610
- outputRange: [screenHeight, 0]
611
- })
612
- }
613
- ]
614
- };
615
- const inputAnimatedStyle = {
616
- transform: [{ scaleX: scaleAnim }]
617
- };
618
- const listHeader = /* @__PURE__ */ React2.createElement(
619
- AutocompleteDialogHeader,
620
- {
621
- title,
622
- inputValue,
623
- placeholder,
624
- inputRef,
625
- inputAnimatedStyle,
626
- inputTextStyle,
627
- onInputChange,
628
- onClose,
629
- onCheckmarkPress: handleCheckmarkPress,
630
- onFocus,
631
- onBlur
632
- }
633
- );
634
- return /* @__PURE__ */ React2.createElement(Portal, null, /* @__PURE__ */ React2.createElement(View2, { style: [overlayStyle, style] }, /* @__PURE__ */ React2.createElement(Animated3.View, { style: [styles2.backdrop, { opacity: fadeAnim }] }), /* @__PURE__ */ React2.createElement(Animated3.View, { style: [styles2.dialogContainer, containerAnimatedStyle] }, /* @__PURE__ */ React2.createElement(
635
- View2,
636
- {
637
- style: [styles2.container, { backgroundColor: theme.colors.background }]
638
- },
639
- listHeader,
640
- /* @__PURE__ */ React2.createElement(
641
- FlatList,
642
- {
643
- data: items,
644
- renderItem: ({ item }) => item,
645
- keyExtractor: (_, index) => String(index),
646
- style: styles2.listContainer,
647
- contentContainerStyle: {
648
- paddingBottom: listBottomPadding
649
- },
650
- keyboardShouldPersistTaps: "always",
651
- keyboardDismissMode: "none",
652
- showsVerticalScrollIndicator: false
653
- }
654
- ),
655
- showCheckmark ? /* @__PURE__ */ React2.createElement(View2, { style: styles2.checkmarkButtonContainer }, /* @__PURE__ */ React2.createElement(
656
- Pressable2,
657
- {
658
- style: [
659
- styles2.checkmarkButton,
660
- { backgroundColor: checkmarkBackgroundColor }
661
- ],
662
- onPress: handleCheckmarkPress,
663
- accessibilityLabel: "Confirm",
664
- accessibilityRole: "button"
665
- },
666
- checkmarkIcon ?? /* @__PURE__ */ React2.createElement(CheckmarkIcon, { color: checkmarkColor, size: 20 })
667
- )) : null
668
- ))));
669
- };
670
-
671
- // src/components/autocomplete/autocomplete-trigger.tsx
672
- import React3 from "react";
673
- import { Pressable as Pressable3, Text as Text2, TouchableOpacity, View as View3 } from "react-native";
674
- import { CloseIcon as CloseIcon2 } from "@xaui/icons";
675
- var AutocompleteTrigger = ({
676
- triggerRef,
677
- isDisabled,
678
- currentSelectedKey,
679
- currentInputValue,
680
- displayValue,
681
- sizeStyles,
682
- radiusStyles,
683
- variantStyles,
684
- theme,
685
- isClearable,
686
- label,
687
- labelText,
688
- isLabelInside,
689
- clearIcon,
690
- style,
691
- textStyle,
692
- onPress: handleTriggerPress,
693
- onClear: handleClear,
694
- onLayout: handleTriggerLayout
695
- }) => {
696
- const renderLabel = isLabelInside && label;
697
- return /* @__PURE__ */ React3.createElement(
698
- Pressable3,
699
- {
700
- ref: triggerRef,
701
- onPress: handleTriggerPress,
702
- onLayout: handleTriggerLayout,
703
- disabled: isDisabled,
704
- style: [
705
- styles.trigger,
706
- {
707
- minHeight: sizeStyles.minHeight,
708
- paddingHorizontal: sizeStyles.paddingHorizontal,
709
- paddingVertical: sizeStyles.paddingVertical
710
- },
711
- radiusStyles,
712
- variantStyles,
713
- isDisabled && styles.disabled,
714
- style
715
- ],
716
- accessibilityLabel: labelText ?? (typeof label === "string" ? label : void 0),
717
- accessibilityRole: "button",
718
- accessibilityState: { disabled: isDisabled }
719
- },
720
- /* @__PURE__ */ React3.createElement(View3, { style: styles.triggerContent }, isLabelInside && renderLabel, /* @__PURE__ */ React3.createElement(
721
- Text2,
722
- {
723
- style: [
724
- styles.triggerText,
725
- { fontSize: sizeStyles.fontSize, color: theme.colors.foreground },
726
- !currentSelectedKey && !currentInputValue && { opacity: 0.5 },
727
- textStyle
728
- ],
729
- numberOfLines: 1,
730
- ellipsizeMode: "tail"
731
- },
732
- displayValue
733
- )),
734
- isClearable && (currentSelectedKey || currentInputValue) ? /* @__PURE__ */ React3.createElement(
735
- TouchableOpacity,
736
- {
737
- onPress: handleClear,
738
- style: styles.clearButton,
739
- hitSlop: { top: 8, right: 8, bottom: 8, left: 8 }
740
- },
741
- clearIcon ?? /* @__PURE__ */ React3.createElement(CloseIcon2, { color: theme.colors.foreground, size: 20 })
742
- ) : null
743
- );
744
- };
745
-
746
- // src/components/autocomplete/autocomplete.tsx
747
- var defaultPlaceholder = "Search...";
748
- var Autocomplete = ({
749
- children,
750
- variant = "flat",
751
- themeColor = "default",
752
- size = "md",
753
- radius = "md",
754
- placeholder = defaultPlaceholder,
755
- labelPlacement = "outside",
756
- label,
757
- description,
758
- errorMessage,
759
- clearIcon,
760
- fullWidth = false,
761
- isDisabled = false,
762
- isInvalid = false,
763
- isClearable = true,
764
- allowsCustomValue = false,
765
- forceSelection = false,
766
- allowsEmptyCollection = true,
767
- disableLocalFilter = false,
768
- inputValue,
769
- defaultInputValue,
770
- customAppearance,
771
- onClose,
772
- onOpenChange,
773
- onSelectionChange,
774
- onInputChange,
775
- onClear
776
- }) => {
777
- const { currentSelectedKey, updateSelection } = useAutocompleteSelection({
778
- onSelectionChange
779
- });
780
- const { currentInputValue, updateInputValue } = useAutocompleteInputState({
781
- inputValue,
782
- defaultInputValue,
783
- selectedKey: currentSelectedKey,
784
- onInputChange
785
- });
786
- const { isOpen, setOpen } = useAutocompleteOpenState({
787
- isOpened: void 0,
788
- isDisabled,
789
- onOpenChange,
790
- onClose
791
- });
792
- const triggerRef = useRef3(null);
793
- const [triggerLayout, setTriggerLayout] = useState3();
794
- const handleTriggerLayout = useCallback3(() => {
795
- triggerRef.current?.measureInWindow((x, y, width, height) => {
796
- setTriggerLayout({ x, y, width, height });
797
- });
798
- }, []);
799
- const items = useMemo3(() => {
800
- const elements = React4.Children.toArray(children).filter(Boolean);
801
- return elements.map((child, index) => {
802
- if (!React4.isValidElement(child)) {
803
- return null;
804
- }
805
- const key = child.props.value ?? String(index);
806
- const labelText = getTextValue(child.props.label) ?? key;
807
- return {
808
- key,
809
- element: child,
810
- labelText
811
- };
812
- }).filter((item) => item !== null);
813
- }, [children]);
814
- const filteredItems = useMemo3(() => {
815
- if (disableLocalFilter || !currentInputValue.trim()) {
816
- return items;
817
- }
818
- return items.filter(
819
- (item) => defaultFilterFunction(item.labelText, currentInputValue)
820
- );
821
- }, [disableLocalFilter, items, currentInputValue]);
822
- const theme = useXUITheme();
823
- const sizeStyles = useAutocompleteSizeStyles(size);
824
- const { radiusStyles } = useAutocompleteRadiusStyles(radius);
825
- const variantStyles = useAutocompleteVariantStyles(themeColor, variant, isInvalid);
826
- const labelStyle = useAutocompleteLabelStyle(
827
- themeColor,
828
- isInvalid,
829
- sizeStyles.labelSize
830
- );
831
- const helperColor = useAutocompleteHelperColor(isInvalid);
832
- const selectedItem = items.find((item) => item.key === currentSelectedKey);
833
- const displayValue = forceSelection ? selectedItem?.labelText || placeholder : currentInputValue || placeholder;
834
- const handleInputChange = useCallback3(
835
- (text) => {
836
- updateInputValue(text);
837
- const selectedLabel = selectedItem?.labelText ?? "";
838
- const shouldClearSelection = !text.trim() && !allowsCustomValue || currentSelectedKey !== null && text !== selectedLabel;
839
- if (shouldClearSelection) {
840
- updateSelection(null);
841
- }
842
- },
843
- [
844
- updateInputValue,
845
- allowsCustomValue,
846
- updateSelection,
847
- selectedItem,
848
- currentSelectedKey
849
- ]
850
- );
851
- const handleItemSelection = useCallback3(
852
- (key, itemLabel) => {
853
- if (isDisabled) {
854
- return;
855
- }
856
- updateSelection(key);
857
- updateInputValue(itemLabel);
858
- setTimeout(() => {
859
- Keyboard2.dismiss();
860
- setOpen(false);
861
- }, 50);
862
- },
863
- [isDisabled, updateSelection, updateInputValue, setOpen]
864
- );
865
- const handleCheckmark = useCallback3(() => {
866
- setOpen(false);
867
- }, [setOpen]);
868
- const handleClear = useCallback3(() => {
869
- if (isDisabled) {
870
- return;
871
- }
872
- updateSelection(null);
873
- updateInputValue("");
874
- onClear?.();
875
- }, [isDisabled, updateSelection, updateInputValue, onClear]);
876
- const handleTriggerPress = useCallback3(() => {
877
- if (!isDisabled) {
878
- if (selectedItem && !currentInputValue) {
879
- updateInputValue(selectedItem.labelText);
880
- }
881
- setOpen(true);
882
- }
883
- }, [isDisabled, setOpen, selectedItem, currentInputValue, updateInputValue]);
884
- const listItems = filteredItems.map((item) => {
885
- const itemProps = item.element.props;
886
- const itemDisabled = isDisabled || itemProps.isDisabled;
887
- const itemSelected = itemProps.isSelected ?? currentSelectedKey === item.key;
888
- const handleItemSelected = () => {
889
- if (itemDisabled || itemProps.isReadOnly) {
890
- return;
891
- }
892
- handleItemSelection(item.key, item.labelText);
893
- itemProps.onSelected?.();
894
- };
895
- return React4.cloneElement(item.element, {
896
- key: item.key,
897
- isDisabled: itemDisabled,
898
- isSelected: itemSelected,
899
- onSelected: handleItemSelected
900
- });
901
- });
902
- const showEmptyMessage = !allowsEmptyCollection && listItems.length === 0;
903
- const isLabelInside = labelPlacement === "inside";
904
- const isLabelOutsideLeft = labelPlacement === "outside-left";
905
- const isLabelOutside = labelPlacement === "outside" || labelPlacement === "outside-top";
906
- const renderLabel = label ? typeof label === "string" || typeof label === "number" ? /* @__PURE__ */ React4.createElement(Text3, { style: [styles.label, labelStyle] }, label) : /* @__PURE__ */ React4.createElement(View4, null, label) : null;
907
- const shouldShowHelper = Boolean(description || errorMessage);
908
- const helperContent = isInvalid && errorMessage ? errorMessage : description;
909
- const triggerContent = /* @__PURE__ */ React4.createElement(
910
- AutocompleteTrigger,
911
- {
912
- triggerRef,
913
- isDisabled,
914
- currentSelectedKey,
915
- currentInputValue,
916
- displayValue,
917
- sizeStyles,
918
- radiusStyles,
919
- variantStyles,
920
- theme,
921
- isClearable,
922
- label: renderLabel,
923
- labelText: typeof label === "string" ? label : void 0,
924
- isLabelInside,
925
- clearIcon,
926
- style: customAppearance?.container,
927
- textStyle: customAppearance?.text,
928
- onPress: handleTriggerPress,
929
- onClear: handleClear,
930
- onLayout: handleTriggerLayout
931
- }
932
- );
933
- const labelBlock = isLabelOutside || isLabelInside ? renderLabel : null;
934
- return /* @__PURE__ */ React4.createElement(View4, { style: [styles.container, fullWidth ? styles.fullWidth : styles.minWidth] }, isLabelOutside && labelBlock, isLabelOutsideLeft ? /* @__PURE__ */ React4.createElement(View4, { style: styles.outsideLeftRow }, renderLabel, triggerContent) : triggerContent, shouldShowHelper && helperContent ? typeof helperContent === "string" || typeof helperContent === "number" ? /* @__PURE__ */ React4.createElement(Text3, { style: [styles.helperText, { color: helperColor }] }, helperContent) : /* @__PURE__ */ React4.createElement(View4, null, helperContent) : null, /* @__PURE__ */ React4.createElement(
935
- AutocompleteDialog,
936
- {
937
- visible: isOpen,
938
- inputValue: currentInputValue,
939
- placeholder,
940
- title: typeof label === "string" ? label : void 0,
941
- themeColor,
942
- _triggerLayout: triggerLayout,
943
- showCheckmark: false,
944
- onInputChange: handleInputChange,
945
- onClose: () => setOpen(false),
946
- onCheckmark: handleCheckmark
947
- },
948
- /* @__PURE__ */ React4.createElement(AutocompleteContext.Provider, { value: { size, themeColor, isDisabled } }, showEmptyMessage ? /* @__PURE__ */ React4.createElement(Text3, { style: [styles.emptyMessage, { color: theme.colors.foreground }] }, "No results found") : listItems)
949
- ));
950
- };
951
-
952
- // src/components/autocomplete/autocomplete-item.tsx
953
- import React5, { useContext as useContext2 } from "react";
954
- import { Pressable as Pressable4, Text as Text4, View as View5 } from "react-native";
955
-
956
- // src/components/autocomplete/autocomplete-item.style.ts
957
- import { StyleSheet as StyleSheet3 } from "react-native";
958
- var styles3 = StyleSheet3.create({
959
- item: {
960
- flexDirection: "row",
961
- alignItems: "center",
962
- gap: 8
963
- },
964
- content: {
965
- flex: 1,
966
- gap: 2
967
- },
968
- title: {
969
- fontWeight: "500"
970
- },
971
- description: {
972
- opacity: 0.7
973
- },
974
- disabled: {
975
- opacity: 0.5
976
- }
977
- });
978
-
979
- // src/components/autocomplete/autocomplete-item.hook.ts
980
- import { useContext, useMemo as useMemo4 } from "react";
981
- import { getSafeThemeColor as getSafeThemeColor2 } from "@xaui/core";
982
- var useAutocompleteItemSizeStyles = (size) => {
983
- const theme = useXUITheme();
984
- return useMemo4(() => {
985
- const sizes = {
986
- xs: {
987
- paddingVertical: theme.spacing.sm,
988
- paddingHorizontal: theme.spacing.sm,
989
- titleSize: theme.fontSizes.xs,
990
- descriptionSize: theme.fontSizes.xs
991
- },
992
- sm: {
993
- paddingVertical: theme.spacing.sm,
994
- paddingHorizontal: theme.spacing.sm,
995
- titleSize: theme.fontSizes.sm,
996
- descriptionSize: theme.fontSizes.xs
997
- },
998
- md: {
999
- paddingVertical: theme.spacing.sm,
1000
- paddingHorizontal: theme.spacing.sm,
1001
- titleSize: theme.fontSizes.md,
1002
- descriptionSize: theme.fontSizes.xs
1003
- },
1004
- lg: {
1005
- paddingVertical: theme.spacing.sm,
1006
- paddingHorizontal: theme.spacing.sm,
1007
- titleSize: theme.fontSizes.lg,
1008
- descriptionSize: theme.fontSizes.md
1009
- }
1010
- };
1011
- return sizes[size];
1012
- }, [size, theme]);
1013
- };
1014
- var useAutocompleteItemBackgroundColor = (themeColor, isSelected) => {
1015
- const theme = useXUITheme();
1016
- const safeThemeColor = getSafeThemeColor2(themeColor);
1017
- const colorScheme = theme.colors[safeThemeColor];
1018
- return useMemo4(() => {
1019
- return "transparent";
1020
- }, [isSelected, colorScheme]);
1021
- };
1022
- var useAutocompleteItemTextColors = () => {
1023
- const theme = useXUITheme();
1024
- return useMemo4(() => {
1025
- return {
1026
- textColor: theme.colors.foreground,
1027
- descriptionColor: theme.colors.foreground
1028
- };
1029
- }, [theme]);
1030
- };
1031
- var useAutocompleteItemCheckmarkColor = (themeColor) => {
1032
- const theme = useXUITheme();
1033
- const safeThemeColor = getSafeThemeColor2(themeColor);
1034
- const colorScheme = theme.colors[safeThemeColor];
1035
- return useMemo4(() => {
1036
- if (themeColor === "default") {
1037
- return theme.colors.primary.main;
1038
- }
1039
- return colorScheme.main;
1040
- }, [themeColor, colorScheme, theme]);
1041
- };
1042
- var useAutocompleteItemStyles = (isSelected, _isDisabled) => {
1043
- const context = useContext(AutocompleteContext);
1044
- const backgroundColor = useAutocompleteItemBackgroundColor(
1045
- context.themeColor,
1046
- isSelected
1047
- );
1048
- const { textColor, descriptionColor } = useAutocompleteItemTextColors();
1049
- const checkmarkColor = useAutocompleteItemCheckmarkColor(context.themeColor);
1050
- return {
1051
- backgroundColor,
1052
- labelColor: textColor,
1053
- descriptionColor,
1054
- checkmarkColor
1055
- };
1056
- };
1057
-
1058
- // src/components/autocomplete/autocomplete-item.tsx
1059
- var defaultSize = "md";
1060
- var AutocompleteItem = ({
1061
- label,
1062
- description,
1063
- startContent,
1064
- endContent,
1065
- selectedIcon: _selectedIcon,
1066
- isDisabled = false,
1067
- isSelected = false,
1068
- isReadOnly = false,
1069
- customAppearance,
1070
- onSelected
1071
- }) => {
1072
- const context = useContext2(AutocompleteContext);
1073
- const size = context?.size ?? defaultSize;
1074
- const isItemDisabled = context?.isDisabled ? true : isDisabled;
1075
- const sizeStyles = useAutocompleteItemSizeStyles(size);
1076
- const { backgroundColor, labelColor, descriptionColor } = useAutocompleteItemStyles(isSelected, isItemDisabled);
1077
- const handlePress = () => {
1078
- if (isItemDisabled || isReadOnly) {
1079
- return;
1080
- }
1081
- onSelected?.();
1082
- };
1083
- return /* @__PURE__ */ React5.createElement(
1084
- Pressable4,
1085
- {
1086
- onPress: handlePress,
1087
- disabled: isItemDisabled,
1088
- style: [
1089
- styles3.item,
1090
- {
1091
- paddingVertical: sizeStyles.paddingVertical,
1092
- paddingHorizontal: sizeStyles.paddingHorizontal,
1093
- backgroundColor
1094
- },
1095
- isItemDisabled && styles3.disabled,
1096
- customAppearance?.container
1097
- ]
1098
- },
1099
- startContent,
1100
- /* @__PURE__ */ React5.createElement(View5, { style: styles3.content }, /* @__PURE__ */ React5.createElement(
1101
- Text4,
1102
- {
1103
- style: [
1104
- styles3.title,
1105
- { fontSize: sizeStyles.titleSize, color: labelColor },
1106
- customAppearance?.text
1107
- ]
1108
- },
1109
- label
1110
- ), description && /* @__PURE__ */ React5.createElement(
1111
- Text4,
1112
- {
1113
- style: [
1114
- styles3.description,
1115
- { fontSize: sizeStyles.descriptionSize, color: descriptionColor }
1116
- ]
1117
- },
1118
- description
1119
- )),
1120
- endContent
1121
- );
1122
- };
1123
-
1124
- export {
1125
- Autocomplete,
1126
- AutocompleteItem
1127
- };