@xaui/native 0.0.9 → 0.0.11

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.
@@ -0,0 +1,358 @@
1
+ import {
2
+ CloseIcon
3
+ } from "./chunk-SIXET7TJ.js";
4
+ import {
5
+ useBorderRadiusStyles,
6
+ useXUITheme
7
+ } from "./chunk-NBRASCX4.js";
8
+
9
+ // src/components/alert/alert.tsx
10
+ import React2, {
11
+ cloneElement,
12
+ isValidElement,
13
+ useCallback,
14
+ useEffect,
15
+ useMemo as useMemo2,
16
+ useState
17
+ } from "react";
18
+ import { Pressable, Text, View } from "react-native";
19
+ import Animated, {
20
+ useSharedValue,
21
+ useAnimatedStyle,
22
+ withTiming,
23
+ runOnJS
24
+ } from "react-native-reanimated";
25
+
26
+ // src/components/alert/alert.style.ts
27
+ import { StyleSheet } from "react-native";
28
+ var styles = StyleSheet.create({
29
+ container: {
30
+ flexDirection: "row",
31
+ alignItems: "center",
32
+ width: "100%",
33
+ gap: 12
34
+ },
35
+ mainWrapper: {
36
+ flex: 1,
37
+ justifyContent: "center",
38
+ gap: 2
39
+ },
40
+ title: {
41
+ fontWeight: "600"
42
+ },
43
+ description: {
44
+ fontWeight: "400"
45
+ },
46
+ iconWrapper: {
47
+ width: 36,
48
+ height: 36,
49
+ borderRadius: 18,
50
+ alignItems: "center",
51
+ justifyContent: "center"
52
+ },
53
+ iconText: {
54
+ fontWeight: "600"
55
+ },
56
+ closeButton: {
57
+ alignSelf: "flex-start",
58
+ padding: 4
59
+ },
60
+ extraContent: {
61
+ marginTop: 4
62
+ }
63
+ });
64
+
65
+ // src/components/alert/alert.hook.ts
66
+ import { useMemo } from "react";
67
+ import { getSafeThemeColor, withOpacity } from "@xaui/core";
68
+ var useAlertColorScheme = (themeColor) => {
69
+ const theme = useXUITheme();
70
+ const safeThemeColor = getSafeThemeColor(themeColor);
71
+ return {
72
+ theme,
73
+ colorScheme: theme.colors[safeThemeColor],
74
+ isDefault: safeThemeColor === "default"
75
+ };
76
+ };
77
+ var useAlertContainerStyles = (themeColor, variant) => {
78
+ const { theme, colorScheme, isDefault } = useAlertColorScheme(themeColor);
79
+ const containerStyles = useMemo(() => {
80
+ const backgroundColor = variant === "solid" ? colorScheme.main : variant === "flat" ? colorScheme.background : variant === "faded" ? withOpacity(colorScheme.background, 0.75) : "transparent";
81
+ const borderWidth = variant === "bordered" || variant === "faded" ? theme.borderWidth.md : 0;
82
+ const borderColor = variant === "bordered" ? withOpacity(colorScheme.main, 0.75) : variant === "faded" ? withOpacity(isDefault ? theme.colors.foreground : colorScheme.main, 0.25) : "transparent";
83
+ return {
84
+ backgroundColor,
85
+ borderColor,
86
+ borderWidth,
87
+ paddingVertical: theme.spacing.sm,
88
+ paddingHorizontal: theme.spacing.md
89
+ };
90
+ }, [colorScheme, isDefault, theme, variant]);
91
+ return containerStyles;
92
+ };
93
+ var useAlertIconWrapperStyles = (themeColor, variant) => {
94
+ const { theme, colorScheme, isDefault } = useAlertColorScheme(themeColor);
95
+ const iconWrapperStyles = useMemo(() => {
96
+ const backgroundColor = variant === "solid" ? withOpacity(colorScheme.foreground, 0.16) : withOpacity(isDefault ? theme.colors.foreground : colorScheme.main, 0.12);
97
+ const borderWidth = variant === "bordered" || variant === "faded" ? theme.borderWidth.xs : 0;
98
+ const borderColor = withOpacity(
99
+ isDefault ? theme.colors.foreground : colorScheme.main,
100
+ 0.2
101
+ );
102
+ return {
103
+ backgroundColor,
104
+ borderColor,
105
+ borderWidth
106
+ };
107
+ }, [colorScheme, isDefault, theme, variant]);
108
+ return iconWrapperStyles;
109
+ };
110
+ var useAlertTextStyles = (themeColor, variant) => {
111
+ const { theme, colorScheme, isDefault } = useAlertColorScheme(themeColor);
112
+ const textStyles = useMemo(() => {
113
+ const baseTextColor = variant === "solid" ? colorScheme.foreground : isDefault ? theme.colors.foreground : colorScheme.main;
114
+ return {
115
+ titleStyles: {
116
+ color: baseTextColor,
117
+ fontSize: theme.fontSizes.sm,
118
+ fontWeight: theme.fontWeights.semibold
119
+ },
120
+ descriptionStyles: {
121
+ color: withOpacity(baseTextColor, 0.75),
122
+ fontSize: theme.fontSizes.xs,
123
+ fontWeight: theme.fontWeights.normal
124
+ },
125
+ iconColor: baseTextColor,
126
+ closeButtonColor: baseTextColor
127
+ };
128
+ }, [colorScheme, isDefault, theme, variant]);
129
+ return textStyles;
130
+ };
131
+
132
+ // src/components/alert/alert-icons.tsx
133
+ import React from "react";
134
+ import Svg, { Circle, Line, Path } from "react-native-svg";
135
+ function InfoIcon({ color, size }) {
136
+ return /* @__PURE__ */ React.createElement(Svg, { width: size, height: size, viewBox: "0 0 24 24", fill: "none" }, /* @__PURE__ */ React.createElement(Circle, { cx: 12, cy: 12, r: 10, stroke: color, strokeWidth: 2 }), /* @__PURE__ */ React.createElement(
137
+ Line,
138
+ {
139
+ x1: 12,
140
+ y1: 10,
141
+ x2: 12,
142
+ y2: 16,
143
+ stroke: color,
144
+ strokeWidth: 2,
145
+ strokeLinecap: "round"
146
+ }
147
+ ), /* @__PURE__ */ React.createElement(Circle, { cx: 12, cy: 7, r: 1, fill: color }));
148
+ }
149
+ function SuccessIcon({ color, size }) {
150
+ return /* @__PURE__ */ React.createElement(Svg, { width: size, height: size, viewBox: "0 0 24 24", fill: "none" }, /* @__PURE__ */ React.createElement(Circle, { cx: 12, cy: 12, r: 10, stroke: color, strokeWidth: 2 }), /* @__PURE__ */ React.createElement(
151
+ Path,
152
+ {
153
+ d: "M7 12.5L10.2 15.5L17 9",
154
+ stroke: color,
155
+ strokeWidth: 2,
156
+ strokeLinecap: "round",
157
+ strokeLinejoin: "round"
158
+ }
159
+ ));
160
+ }
161
+ function WarningIcon({ color, size }) {
162
+ return /* @__PURE__ */ React.createElement(Svg, { width: size, height: size, viewBox: "0 0 24 24", fill: "none" }, /* @__PURE__ */ React.createElement(
163
+ Path,
164
+ {
165
+ d: "M12 3L22 20H2L12 3Z",
166
+ stroke: color,
167
+ strokeWidth: 2,
168
+ strokeLinejoin: "round"
169
+ }
170
+ ), /* @__PURE__ */ React.createElement(
171
+ Line,
172
+ {
173
+ x1: 12,
174
+ y1: 9,
175
+ x2: 12,
176
+ y2: 14,
177
+ stroke: color,
178
+ strokeWidth: 2,
179
+ strokeLinecap: "round"
180
+ }
181
+ ), /* @__PURE__ */ React.createElement(Circle, { cx: 12, cy: 17, r: 1, fill: color }));
182
+ }
183
+ function DangerIcon({ color, size }) {
184
+ return /* @__PURE__ */ React.createElement(Svg, { width: size, height: size, viewBox: "0 0 24 24", fill: "none" }, /* @__PURE__ */ React.createElement(Circle, { cx: 12, cy: 12, r: 10, stroke: color, strokeWidth: 2 }), /* @__PURE__ */ React.createElement(
185
+ Line,
186
+ {
187
+ x1: 9,
188
+ y1: 9,
189
+ x2: 15,
190
+ y2: 15,
191
+ stroke: color,
192
+ strokeWidth: 2,
193
+ strokeLinecap: "round"
194
+ }
195
+ ), /* @__PURE__ */ React.createElement(
196
+ Line,
197
+ {
198
+ x1: 15,
199
+ y1: 9,
200
+ x2: 9,
201
+ y2: 15,
202
+ stroke: color,
203
+ strokeWidth: 2,
204
+ strokeLinecap: "round"
205
+ }
206
+ ));
207
+ }
208
+
209
+ // src/components/alert/alert.tsx
210
+ var iconMap = {
211
+ default: InfoIcon,
212
+ primary: InfoIcon,
213
+ secondary: InfoIcon,
214
+ tertiary: InfoIcon,
215
+ success: SuccessIcon,
216
+ warning: WarningIcon,
217
+ danger: DangerIcon
218
+ };
219
+ var Alert = ({
220
+ title,
221
+ description,
222
+ icon,
223
+ themeColor = "default",
224
+ variant = "flat",
225
+ radius = "md",
226
+ isClosable = false,
227
+ hideIcon = false,
228
+ closeButton,
229
+ isVisible,
230
+ customAppearance,
231
+ children,
232
+ onClose,
233
+ onVisibleChange
234
+ }) => {
235
+ const [internalVisible, setInternalVisible] = useState(isVisible ?? true);
236
+ const [shouldRender, setShouldRender] = useState(isVisible ?? true);
237
+ const isControlled = typeof isVisible === "boolean";
238
+ const visible = isControlled ? isVisible : internalVisible;
239
+ const opacity = useSharedValue(1);
240
+ const scale = useSharedValue(1);
241
+ const radiusStyles = useBorderRadiusStyles(radius);
242
+ const containerStyles = useAlertContainerStyles(themeColor, variant);
243
+ const iconWrapperStyles = useAlertIconWrapperStyles(themeColor, variant);
244
+ const { titleStyles, descriptionStyles, iconColor, closeButtonColor } = useAlertTextStyles(themeColor, variant);
245
+ const finishClosing = useCallback(() => {
246
+ setShouldRender(false);
247
+ if (!isControlled) {
248
+ setInternalVisible(false);
249
+ }
250
+ onVisibleChange?.(false);
251
+ onClose?.();
252
+ }, [isControlled, onClose, onVisibleChange]);
253
+ const handleClose = useCallback(() => {
254
+ if (!visible) return;
255
+ opacity.value = withTiming(0, { duration: 250 });
256
+ scale.value = withTiming(0.95, { duration: 250 }, (finished) => {
257
+ if (finished) {
258
+ runOnJS(finishClosing)();
259
+ }
260
+ });
261
+ }, [finishClosing, opacity, scale, visible]);
262
+ useEffect(() => {
263
+ if (visible && !shouldRender) {
264
+ setShouldRender(true);
265
+ opacity.value = 0;
266
+ scale.value = 0.95;
267
+ opacity.value = withTiming(1, { duration: 250 });
268
+ scale.value = withTiming(1, { duration: 250 });
269
+ return;
270
+ }
271
+ if (!visible && shouldRender) {
272
+ handleClose();
273
+ }
274
+ }, [visible, shouldRender, opacity, scale, handleClose]);
275
+ const animatedStyle = useAnimatedStyle(() => ({
276
+ opacity: opacity.value,
277
+ transform: [{ scale: scale.value }]
278
+ }));
279
+ const IconComponent = iconMap[themeColor] ?? InfoIcon;
280
+ const shouldShowClose = Boolean(closeButton || isClosable || onClose);
281
+ const renderIcon = () => {
282
+ if (hideIcon) return null;
283
+ if (icon && isValidElement(icon)) {
284
+ return cloneElement(icon, { color: iconColor, size: 22 });
285
+ }
286
+ if (icon) {
287
+ return /* @__PURE__ */ React2.createElement(Text, { style: [styles.iconText, { color: iconColor }] }, icon);
288
+ }
289
+ return /* @__PURE__ */ React2.createElement(IconComponent, { color: iconColor, size: 22 });
290
+ };
291
+ const renderContentText = (content) => {
292
+ if (content === null || content === void 0) return null;
293
+ if (typeof content === "string" || typeof content === "number") {
294
+ return /* @__PURE__ */ React2.createElement(
295
+ Text,
296
+ {
297
+ style: [
298
+ styles.description,
299
+ descriptionStyles,
300
+ customAppearance?.description
301
+ ]
302
+ },
303
+ content
304
+ );
305
+ }
306
+ return content;
307
+ };
308
+ const titleNode = useMemo2(() => {
309
+ if (title === null || title === void 0) return null;
310
+ if (typeof title === "string" || typeof title === "number") {
311
+ return /* @__PURE__ */ React2.createElement(Text, { style: [styles.title, titleStyles, customAppearance?.title] }, title);
312
+ }
313
+ return title;
314
+ }, [title, customAppearance?.title, titleStyles]);
315
+ const descriptionNode = renderContentText(description);
316
+ const childrenNode = renderContentText(children);
317
+ const closeButtonNode = useMemo2(() => {
318
+ if (!closeButton) return null;
319
+ if (!isValidElement(closeButton)) return closeButton;
320
+ const existingOnPress = closeButton.props.onPress;
321
+ return cloneElement(closeButton, {
322
+ onPress: (event) => {
323
+ existingOnPress?.(event);
324
+ handleClose();
325
+ }
326
+ });
327
+ }, [closeButton, handleClose]);
328
+ if (!shouldRender) return null;
329
+ return /* @__PURE__ */ React2.createElement(
330
+ Animated.View,
331
+ {
332
+ accessibilityRole: "alert",
333
+ style: [
334
+ styles.container,
335
+ containerStyles,
336
+ radiusStyles,
337
+ customAppearance?.container,
338
+ animatedStyle
339
+ ]
340
+ },
341
+ !hideIcon && /* @__PURE__ */ React2.createElement(View, { style: [styles.iconWrapper, iconWrapperStyles] }, renderIcon()),
342
+ /* @__PURE__ */ React2.createElement(View, { style: styles.mainWrapper }, titleNode, descriptionNode, childrenNode && /* @__PURE__ */ React2.createElement(View, { style: styles.extraContent }, childrenNode)),
343
+ shouldShowClose && /* @__PURE__ */ React2.createElement(View, null, closeButtonNode ?? /* @__PURE__ */ React2.createElement(
344
+ Pressable,
345
+ {
346
+ accessibilityRole: "button",
347
+ accessibilityLabel: "Close",
348
+ onPress: handleClose,
349
+ style: styles.closeButton
350
+ },
351
+ /* @__PURE__ */ React2.createElement(CloseIcon, { size: 20, color: closeButtonColor })
352
+ ))
353
+ );
354
+ };
355
+
356
+ export {
357
+ Alert
358
+ };
@@ -1,3 +1,6 @@
1
+ import {
2
+ isThemeColor
3
+ } from "./chunk-SIXET7TJ.js";
1
4
  import {
2
5
  useXUITheme
3
6
  } from "./chunk-NBRASCX4.js";
@@ -6,22 +9,6 @@ import {
6
9
  import React, { useEffect, useMemo, useRef } from "react";
7
10
  import { Animated } from "react-native";
8
11
  import Svg, { Circle, Path, Rect } from "react-native-svg";
9
-
10
- // src/components/icon/icon.utils.ts
11
- var isThemeColor = (color) => {
12
- const themeColors = [
13
- "primary",
14
- "secondary",
15
- "tertiary",
16
- "danger",
17
- "warning",
18
- "success",
19
- "default"
20
- ];
21
- return themeColors.includes(color);
22
- };
23
-
24
- // src/components/icon/icons/arrow-back.tsx
25
12
  var AnimatedPath = Animated.createAnimatedComponent(Path);
26
13
  var ArrowBackIcon = ({
27
14
  variant = "baseline",
@@ -450,157 +437,8 @@ var ChevronDownIcon = ({
450
437
  return /* @__PURE__ */ React3.createElement(Svg3, { width: size, height: size, viewBox: "0 0 512 512" }, renderVariant());
451
438
  };
452
439
 
453
- // src/components/icon/icons/close.tsx
454
- import React4, { useEffect as useEffect4, useMemo as useMemo4, useRef as useRef4 } from "react";
455
- import { Animated as Animated4 } from "react-native";
456
- import Svg4, { Path as Path4, Rect as Rect4, Circle as Circle4 } from "react-native-svg";
457
- var AnimatedPath4 = Animated4.createAnimatedComponent(Path4);
458
- var CloseIcon = ({
459
- variant = "baseline",
460
- size = 24,
461
- color = "default",
462
- isAnimated = false
463
- }) => {
464
- const theme = useXUITheme();
465
- const scaleAnim = useRef4(new Animated4.Value(isAnimated ? 0 : 1)).current;
466
- const opacityAnim = useRef4(new Animated4.Value(isAnimated ? 0 : 1)).current;
467
- const resolvedColor = useMemo4(() => {
468
- if (typeof color === "string" && isThemeColor(color)) {
469
- return theme.colors[color].main;
470
- }
471
- return color;
472
- }, [color, theme]);
473
- useEffect4(() => {
474
- if (isAnimated) {
475
- Animated4.parallel([
476
- Animated4.spring(scaleAnim, {
477
- toValue: 1,
478
- useNativeDriver: true,
479
- tension: 50,
480
- friction: 7
481
- }),
482
- Animated4.timing(opacityAnim, {
483
- toValue: 1,
484
- duration: 200,
485
- useNativeDriver: true
486
- })
487
- ]).start();
488
- }
489
- }, [isAnimated, scaleAnim, opacityAnim]);
490
- const animatedProps = isAnimated ? {
491
- transform: [{ scale: scaleAnim }],
492
- opacity: opacityAnim
493
- } : void 0;
494
- const renderBaseline = () => /* @__PURE__ */ React4.createElement(
495
- AnimatedPath4,
496
- {
497
- fill: resolvedColor,
498
- d: "m289.94 256l95-95A24 24 0 0 0 351 127l-95 95l-95-95a24 24 0 0 0-34 34l95 95l-95 95a24 24 0 1 0 34 34l95-95l95 95a24 24 0 0 0 34-34Z",
499
- ...animatedProps
500
- }
501
- );
502
- const renderFilled = () => /* @__PURE__ */ React4.createElement(
503
- AnimatedPath4,
504
- {
505
- fill: resolvedColor,
506
- d: "M256 48C141.31 48 48 141.31 48 256s93.31 208 208 208 208-93.31 208-208S370.69 48 256 48zm75.31 260.69a16 16 0 1 1-22.62 22.62L256 278.63l-52.69 52.68a16 16 0 0 1-22.62-22.62L233.37 256l-52.68-52.69a16 16 0 0 1 22.62-22.62L256 233.37l52.69-52.68a16 16 0 0 1 22.62 22.62L278.63 256z",
507
- ...animatedProps
508
- }
509
- );
510
- const renderDuotone = () => /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement(
511
- Path4,
512
- {
513
- fill: resolvedColor,
514
- opacity: 0.3,
515
- d: "M256 48C141.31 48 48 141.31 48 256s93.31 208 208 208 208-93.31 208-208S370.69 48 256 48z"
516
- }
517
- ), /* @__PURE__ */ React4.createElement(
518
- AnimatedPath4,
519
- {
520
- fill: resolvedColor,
521
- d: "m289.94 256l95-95A24 24 0 0 0 351 127l-95 95l-95-95a24 24 0 0 0-34 34l95 95l-95 95a24 24 0 1 0 34 34l95-95l95 95a24 24 0 0 0 34-34Z",
522
- ...animatedProps
523
- }
524
- ));
525
- const renderRoundOutlined = () => /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement(
526
- Circle4,
527
- {
528
- cx: "256",
529
- cy: "256",
530
- r: "192",
531
- fill: "none",
532
- stroke: resolvedColor,
533
- strokeWidth: 32
534
- }
535
- ), /* @__PURE__ */ React4.createElement(
536
- AnimatedPath4,
537
- {
538
- fill: resolvedColor,
539
- d: "m289.94 256l95-95A24 24 0 0 0 351 127l-95 95l-95-95a24 24 0 0 0-34 34l95 95l-95 95a24 24 0 1 0 34 34l95-95l95 95a24 24 0 0 0 34-34Z",
540
- ...animatedProps
541
- }
542
- ));
543
- const renderSquareOutlined = () => /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement(
544
- Rect4,
545
- {
546
- x: "64",
547
- y: "64",
548
- width: "384",
549
- height: "384",
550
- rx: "48",
551
- fill: "none",
552
- stroke: resolvedColor,
553
- strokeWidth: 32
554
- }
555
- ), /* @__PURE__ */ React4.createElement(
556
- AnimatedPath4,
557
- {
558
- fill: resolvedColor,
559
- d: "m289.94 256l95-95A24 24 0 0 0 351 127l-95 95l-95-95a24 24 0 0 0-34 34l95 95l-95 95a24 24 0 1 0 34 34l95-95l95 95a24 24 0 0 0 34-34Z",
560
- ...animatedProps
561
- }
562
- ));
563
- const renderRoundFilled = () => /* @__PURE__ */ React4.createElement(
564
- AnimatedPath4,
565
- {
566
- fill: resolvedColor,
567
- d: "M256 48C141.31 48 48 141.31 48 256s93.31 208 208 208 208-93.31 208-208S370.69 48 256 48zm75.31 260.69a16 16 0 1 1-22.62 22.62L256 278.63l-52.69 52.68a16 16 0 0 1-22.62-22.62L233.37 256l-52.68-52.69a16 16 0 0 1 22.62-22.62L256 233.37l52.69-52.68a16 16 0 0 1 22.62 22.62L278.63 256z",
568
- ...animatedProps
569
- }
570
- );
571
- const renderSquareFilled = () => /* @__PURE__ */ React4.createElement(
572
- AnimatedPath4,
573
- {
574
- fill: resolvedColor,
575
- d: "M400 64H112a48 48 0 0 0-48 48v288a48 48 0 0 0 48 48h288a48 48 0 0 0 48-48V112a48 48 0 0 0-48-48zm-59.31 244.69a16 16 0 1 1-22.62 22.62L256 278.63l-62.07 52.68a16 16 0 0 1-22.62-22.62L223.37 256l-52.06-52.69a16 16 0 0 1 22.62-22.62L256 233.37l62.07-52.68a16 16 0 0 1 22.62 22.62L288.63 256z",
576
- ...animatedProps
577
- }
578
- );
579
- const renderVariant = () => {
580
- switch (variant) {
581
- case "filled":
582
- return renderFilled();
583
- case "duotone":
584
- return renderDuotone();
585
- case "round-outlined":
586
- return renderRoundOutlined();
587
- case "square-outlined":
588
- return renderSquareOutlined();
589
- case "round-filled":
590
- return renderRoundFilled();
591
- case "square-filled":
592
- return renderSquareFilled();
593
- case "baseline":
594
- default:
595
- return renderBaseline();
596
- }
597
- };
598
- return /* @__PURE__ */ React4.createElement(Svg4, { width: size, height: size, viewBox: "0 0 512 512" }, renderVariant());
599
- };
600
-
601
440
  export {
602
441
  ArrowBackIcon,
603
442
  CheckmarkIcon,
604
- ChevronDownIcon,
605
- CloseIcon
443
+ ChevronDownIcon
606
444
  };