@almadar/mobile 1.1.0 → 1.2.1

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 (103) hide show
  1. package/dist/{chunk-S2IT7WZT.js → chunk-5JVEVV74.js} +1 -1
  2. package/dist/{chunk-DY52O4T3.js → chunk-5U5Z65ZO.js} +46 -83
  3. package/dist/chunk-5U5Z65ZO.js.map +1 -0
  4. package/dist/chunk-A56SRZKI.js +59 -0
  5. package/dist/chunk-A56SRZKI.js.map +1 -0
  6. package/dist/{chunk-DMLYJFYQ.js → chunk-BFRVXKSP.js} +594 -88
  7. package/dist/chunk-BFRVXKSP.js.map +1 -0
  8. package/dist/{chunk-YMJZLYLV.js → chunk-ETD72PHO.js} +1991 -466
  9. package/dist/chunk-ETD72PHO.js.map +1 -0
  10. package/dist/{chunk-LFHVNHVA.js → chunk-GMR5FKKB.js} +3 -83
  11. package/dist/chunk-GMR5FKKB.js.map +1 -0
  12. package/dist/chunk-K2JGK2QD.js +17 -0
  13. package/dist/chunk-K2JGK2QD.js.map +1 -0
  14. package/dist/chunk-MLTSQPVN.js +337 -0
  15. package/dist/chunk-MLTSQPVN.js.map +1 -0
  16. package/dist/{chunk-T77JPOTP.js → chunk-PBO6ZN2M.js} +1206 -1269
  17. package/dist/chunk-PBO6ZN2M.js.map +1 -0
  18. package/dist/{chunk-7C5JCLLY.js → chunk-QUFLYKWA.js} +125 -45
  19. package/dist/chunk-QUFLYKWA.js.map +1 -0
  20. package/dist/chunk-TRYFJDL3.js +7 -0
  21. package/dist/chunk-TRYFJDL3.js.map +1 -0
  22. package/dist/components/atoms/AnimatedCounter.d.ts +15 -0
  23. package/dist/components/atoms/AnimatedCounter.d.ts.map +1 -0
  24. package/dist/components/atoms/DayCell.d.ts +18 -0
  25. package/dist/components/atoms/DayCell.d.ts.map +1 -0
  26. package/dist/components/atoms/InfiniteScrollSentinel.d.ts +14 -0
  27. package/dist/components/atoms/InfiniteScrollSentinel.d.ts.map +1 -0
  28. package/dist/components/atoms/RangeSlider.d.ts +20 -0
  29. package/dist/components/atoms/RangeSlider.d.ts.map +1 -0
  30. package/dist/components/atoms/StatusDot.d.ts +16 -0
  31. package/dist/components/atoms/StatusDot.d.ts.map +1 -0
  32. package/dist/components/atoms/TextHighlight.d.ts +17 -0
  33. package/dist/components/atoms/TextHighlight.d.ts.map +1 -0
  34. package/dist/components/atoms/ThemeToggle.d.ts +13 -0
  35. package/dist/components/atoms/ThemeToggle.d.ts.map +1 -0
  36. package/dist/components/atoms/TrendIndicator.d.ts +16 -0
  37. package/dist/components/atoms/TrendIndicator.d.ts.map +1 -0
  38. package/dist/components/atoms/TypewriterText.d.ts +16 -0
  39. package/dist/components/atoms/TypewriterText.d.ts.map +1 -0
  40. package/dist/components/atoms/index.d.ts +18 -0
  41. package/dist/components/atoms/index.d.ts.map +1 -1
  42. package/dist/components/atoms/index.js +30 -10
  43. package/dist/components/index.js +59 -18
  44. package/dist/components/molecules/Accordion.d.ts +20 -0
  45. package/dist/components/molecules/Accordion.d.ts.map +1 -0
  46. package/dist/components/molecules/CalendarGrid.d.ts +22 -0
  47. package/dist/components/molecules/CalendarGrid.d.ts.map +1 -0
  48. package/dist/components/molecules/Carousel.d.ts +17 -0
  49. package/dist/components/molecules/Carousel.d.ts.map +1 -0
  50. package/dist/components/molecules/DataGrid.d.ts +43 -0
  51. package/dist/components/molecules/DataGrid.d.ts.map +1 -0
  52. package/dist/components/molecules/DataList.d.ts +43 -0
  53. package/dist/components/molecules/DataList.d.ts.map +1 -0
  54. package/dist/components/molecules/FlipCard.d.ts +16 -0
  55. package/dist/components/molecules/FlipCard.d.ts.map +1 -0
  56. package/dist/components/molecules/Lightbox.d.ts +19 -0
  57. package/dist/components/molecules/Lightbox.d.ts.map +1 -0
  58. package/dist/components/molecules/NumberStepper.d.ts +19 -0
  59. package/dist/components/molecules/NumberStepper.d.ts.map +1 -0
  60. package/dist/components/molecules/PullToRefresh.d.ts +14 -0
  61. package/dist/components/molecules/PullToRefresh.d.ts.map +1 -0
  62. package/dist/components/molecules/SortableList.d.ts +17 -0
  63. package/dist/components/molecules/SortableList.d.ts.map +1 -0
  64. package/dist/components/molecules/StarRating.d.ts +19 -0
  65. package/dist/components/molecules/StarRating.d.ts.map +1 -0
  66. package/dist/components/molecules/SwipeableRow.d.ts +20 -0
  67. package/dist/components/molecules/SwipeableRow.d.ts.map +1 -0
  68. package/dist/components/molecules/index.d.ts +24 -0
  69. package/dist/components/molecules/index.d.ts.map +1 -1
  70. package/dist/components/molecules/index.js +30 -5
  71. package/dist/components/organisms/FormSection.d.ts +7 -0
  72. package/dist/components/organisms/FormSection.d.ts.map +1 -1
  73. package/dist/components/organisms/index.d.ts +0 -4
  74. package/dist/components/organisms/index.d.ts.map +1 -1
  75. package/dist/components/organisms/index.js +4 -8
  76. package/dist/index.js +72 -26
  77. package/dist/index.js.map +1 -1
  78. package/dist/lib/getNestedValue.d.ts +5 -0
  79. package/dist/lib/getNestedValue.d.ts.map +1 -0
  80. package/dist/lib/index.d.ts +1 -0
  81. package/dist/lib/index.d.ts.map +1 -1
  82. package/dist/lib/index.js +6 -2
  83. package/dist/providers/ThemeProvider.d.ts +7 -0
  84. package/dist/providers/ThemeProvider.d.ts.map +1 -1
  85. package/dist/providers/index.d.ts +2 -2
  86. package/dist/providers/index.d.ts.map +1 -1
  87. package/dist/providers/index.js +8 -4
  88. package/package.json +30 -29
  89. package/dist/chunk-6RVITGGH.js +0 -167
  90. package/dist/chunk-6RVITGGH.js.map +0 -1
  91. package/dist/chunk-7C5JCLLY.js.map +0 -1
  92. package/dist/chunk-DMLYJFYQ.js.map +0 -1
  93. package/dist/chunk-DY52O4T3.js.map +0 -1
  94. package/dist/chunk-LFHVNHVA.js.map +0 -1
  95. package/dist/chunk-T77JPOTP.js.map +0 -1
  96. package/dist/chunk-VLUJ7BXN.js +0 -36
  97. package/dist/chunk-VLUJ7BXN.js.map +0 -1
  98. package/dist/chunk-YMJZLYLV.js.map +0 -1
  99. package/dist/components/organisms/EntityCard.d.ts +0 -11
  100. package/dist/components/organisms/EntityCard.d.ts.map +0 -1
  101. package/dist/components/organisms/EntityList.d.ts +0 -17
  102. package/dist/components/organisms/EntityList.d.ts.map +0 -1
  103. /package/dist/{chunk-S2IT7WZT.js.map → chunk-5JVEVV74.js.map} +0 -0
@@ -1,7 +1,14 @@
1
+ import {
2
+ useThemeMode
3
+ } from "./chunk-A56SRZKI.js";
1
4
  import {
2
5
  ErrorState,
3
- LoadingState
4
- } from "./chunk-7C5JCLLY.js";
6
+ HStack,
7
+ Icon,
8
+ LoadingState,
9
+ Typography,
10
+ VStack
11
+ } from "./chunk-QUFLYKWA.js";
5
12
  import {
6
13
  useEventBus
7
14
  } from "./chunk-YTVYMEKU.js";
@@ -313,42 +320,12 @@ var styles4 = StyleSheet4.create({
313
320
  });
314
321
  Textarea.displayName = "Textarea";
315
322
 
316
- // src/components/atoms/Spinner.tsx
317
- import React5 from "react";
318
- import { ActivityIndicator, StyleSheet as StyleSheet5, View as View5 } from "react-native";
319
- var Spinner = ({
320
- size = "md",
321
- color,
322
- style
323
- }) => {
324
- const theme = useTheme();
325
- const sizeMap = {
326
- sm: 16,
327
- md: 24,
328
- lg: 32
329
- };
330
- return /* @__PURE__ */ React5.createElement(View5, { style: [styles5.container, style] }, /* @__PURE__ */ React5.createElement(
331
- ActivityIndicator,
332
- {
333
- size: sizeMap[size],
334
- color: color || theme.colors.primary
335
- }
336
- ));
337
- };
338
- var styles5 = StyleSheet5.create({
339
- container: {
340
- alignItems: "center",
341
- justifyContent: "center"
342
- }
343
- });
344
- Spinner.displayName = "Spinner";
345
-
346
323
  // src/components/atoms/Avatar.tsx
347
- import React6 from "react";
324
+ import React5 from "react";
348
325
  import {
349
- View as View6,
326
+ View as View5,
350
327
  Text as Text2,
351
- StyleSheet as StyleSheet6,
328
+ StyleSheet as StyleSheet5,
352
329
  Image
353
330
  } from "react-native";
354
331
  var Avatar = ({
@@ -361,18 +338,18 @@ var Avatar = ({
361
338
  error
362
339
  }) => {
363
340
  const theme = useTheme();
364
- const sizeMap = {
341
+ const sizeMap2 = {
365
342
  sm: { container: 32, fontSize: 12 },
366
343
  md: { container: 40, fontSize: 14 },
367
344
  lg: { container: 48, fontSize: 16 },
368
345
  xl: { container: 64, fontSize: 20 }
369
346
  };
370
- const { container, fontSize } = sizeMap[size];
347
+ const { container, fontSize } = sizeMap2[size];
371
348
  if (isLoading) {
372
- return /* @__PURE__ */ React6.createElement(View6, { style: [styles6.container, { width: container, height: container }, style] }, /* @__PURE__ */ React6.createElement(LoadingState, { message: "" }));
349
+ return /* @__PURE__ */ React5.createElement(View5, { style: [styles5.container, { width: container, height: container }, style] }, /* @__PURE__ */ React5.createElement(LoadingState, { message: "" }));
373
350
  }
374
351
  if (error) {
375
- return /* @__PURE__ */ React6.createElement(View6, { style: [styles6.container, { width: container, height: container }, style] }, /* @__PURE__ */ React6.createElement(ErrorState, { message: error.message }));
352
+ return /* @__PURE__ */ React5.createElement(View5, { style: [styles5.container, { width: container, height: container }, style] }, /* @__PURE__ */ React5.createElement(ErrorState, { message: error.message }));
376
353
  }
377
354
  const getInitials = () => {
378
355
  if (initials) return initials;
@@ -382,12 +359,12 @@ var Avatar = ({
382
359
  return "?";
383
360
  };
384
361
  if (src) {
385
- return /* @__PURE__ */ React6.createElement(
362
+ return /* @__PURE__ */ React5.createElement(
386
363
  Image,
387
364
  {
388
365
  source: src,
389
366
  style: [
390
- styles6.image,
367
+ styles5.image,
391
368
  {
392
369
  width: container,
393
370
  height: container,
@@ -399,11 +376,11 @@ var Avatar = ({
399
376
  }
400
377
  );
401
378
  }
402
- return /* @__PURE__ */ React6.createElement(
403
- View6,
379
+ return /* @__PURE__ */ React5.createElement(
380
+ View5,
404
381
  {
405
382
  style: [
406
- styles6.container,
383
+ styles5.container,
407
384
  {
408
385
  width: container,
409
386
  height: container,
@@ -413,11 +390,11 @@ var Avatar = ({
413
390
  style
414
391
  ]
415
392
  },
416
- /* @__PURE__ */ React6.createElement(
393
+ /* @__PURE__ */ React5.createElement(
417
394
  Text2,
418
395
  {
419
396
  style: [
420
- styles6.initials,
397
+ styles5.initials,
421
398
  {
422
399
  fontSize,
423
400
  color: theme.colors["primary-foreground"]
@@ -428,7 +405,7 @@ var Avatar = ({
428
405
  )
429
406
  );
430
407
  };
431
- var styles6 = StyleSheet6.create({
408
+ var styles5 = StyleSheet5.create({
432
409
  container: {
433
410
  alignItems: "center",
434
411
  justifyContent: "center"
@@ -443,11 +420,11 @@ var styles6 = StyleSheet6.create({
443
420
  Avatar.displayName = "Avatar";
444
421
 
445
422
  // src/components/atoms/Overlay.tsx
446
- import React7 from "react";
423
+ import React6 from "react";
447
424
  import {
448
425
  TouchableWithoutFeedback,
449
- View as View7,
450
- StyleSheet as StyleSheet7
426
+ View as View6,
427
+ StyleSheet as StyleSheet6
451
428
  } from "react-native";
452
429
  var Overlay = ({
453
430
  isVisible = true,
@@ -465,23 +442,23 @@ var Overlay = ({
465
442
  }
466
443
  onPress?.();
467
444
  };
468
- return /* @__PURE__ */ React7.createElement(TouchableWithoutFeedback, { onPress: handlePress }, /* @__PURE__ */ React7.createElement(
469
- View7,
445
+ return /* @__PURE__ */ React6.createElement(TouchableWithoutFeedback, { onPress: handlePress }, /* @__PURE__ */ React6.createElement(
446
+ View6,
470
447
  {
471
448
  style: [
472
- styles7.overlay,
449
+ styles6.overlay,
473
450
  {
474
451
  backgroundColor: theme.colors.background,
475
452
  opacity: 0.8
476
453
  },
477
- blur && styles7.blur,
454
+ blur && styles6.blur,
478
455
  ...style ? [style] : []
479
456
  ],
480
457
  pointerEvents: "auto"
481
458
  }
482
459
  ));
483
460
  };
484
- var styles7 = StyleSheet7.create({
461
+ var styles6 = StyleSheet6.create({
485
462
  overlay: {
486
463
  position: "absolute",
487
464
  top: 0,
@@ -498,8 +475,8 @@ var styles7 = StyleSheet7.create({
498
475
  Overlay.displayName = "Overlay";
499
476
 
500
477
  // src/components/atoms/Spacer.tsx
501
- import React8 from "react";
502
- import { View as View8 } from "react-native";
478
+ import React7 from "react";
479
+ import { View as View7 } from "react-native";
503
480
  var sizeValues = {
504
481
  xs: 4,
505
482
  sm: 8,
@@ -514,8 +491,8 @@ var Spacer = ({
514
491
  style
515
492
  }) => {
516
493
  if (size === "auto") {
517
- return /* @__PURE__ */ React8.createElement(
518
- View8,
494
+ return /* @__PURE__ */ React7.createElement(
495
+ View7,
519
496
  {
520
497
  style: [{ flex: 1 }, ...style ? [style] : []],
521
498
  accessibilityElementsHidden: true
@@ -524,8 +501,8 @@ var Spacer = ({
524
501
  }
525
502
  const sizeValue = sizeValues[size];
526
503
  const spacerStyle = axis === "horizontal" ? { width: sizeValue } : { height: sizeValue };
527
- return /* @__PURE__ */ React8.createElement(
528
- View8,
504
+ return /* @__PURE__ */ React7.createElement(
505
+ View7,
529
506
  {
530
507
  style: [
531
508
  spacerStyle,
@@ -538,7 +515,7 @@ var Spacer = ({
538
515
  Spacer.displayName = "Spacer";
539
516
 
540
517
  // src/components/atoms/ConditionalWrapper.tsx
541
- import React9 from "react";
518
+ import React8 from "react";
542
519
  import { Animated as Animated2 } from "react-native";
543
520
  function evaluateCondition(condition, context = { formValues: {}, globalVariables: {} }) {
544
521
  if (typeof condition === "boolean") {
@@ -590,9 +567,9 @@ var ConditionalWrapper = ({
590
567
  animate = false,
591
568
  style
592
569
  }) => {
593
- const [isVisible, setIsVisible] = React9.useState(!condition ? true : false);
594
- const fadeAnim = React9.useRef(new Animated2.Value(!condition ? 1 : 0)).current;
595
- React9.useEffect(() => {
570
+ const [isVisible, setIsVisible] = React8.useState(!condition ? true : false);
571
+ const fadeAnim = React8.useRef(new Animated2.Value(!condition ? 1 : 0)).current;
572
+ React8.useEffect(() => {
596
573
  if (!condition) {
597
574
  setIsVisible(true);
598
575
  return;
@@ -610,10 +587,10 @@ var ConditionalWrapper = ({
610
587
  }
611
588
  }, [condition, context, animate, fadeAnim]);
612
589
  if (!condition) {
613
- return /* @__PURE__ */ React9.createElement(React9.Fragment, null, children);
590
+ return /* @__PURE__ */ React8.createElement(React8.Fragment, null, children);
614
591
  }
615
592
  if (animate) {
616
- return /* @__PURE__ */ React9.createElement(
593
+ return /* @__PURE__ */ React8.createElement(
617
594
  Animated2.View,
618
595
  {
619
596
  style: [
@@ -624,17 +601,540 @@ var ConditionalWrapper = ({
624
601
  isVisible ? children : fallback
625
602
  );
626
603
  }
627
- return isVisible ? /* @__PURE__ */ React9.createElement(React9.Fragment, null, children) : /* @__PURE__ */ React9.createElement(React9.Fragment, null, fallback);
604
+ return isVisible ? /* @__PURE__ */ React8.createElement(React8.Fragment, null, children) : /* @__PURE__ */ React8.createElement(React8.Fragment, null, fallback);
628
605
  };
629
606
  ConditionalWrapper.displayName = "ConditionalWrapper";
630
607
 
608
+ // src/components/atoms/StatusDot.tsx
609
+ import React9, { useEffect, useRef } from "react";
610
+ import { View as View8, Animated as Animated3, StyleSheet as StyleSheet7 } from "react-native";
611
+ var sizeMap = {
612
+ sm: 8,
613
+ md: 12,
614
+ lg: 16
615
+ };
616
+ var StatusDot = ({
617
+ status = "offline",
618
+ pulse = false,
619
+ size = "md",
620
+ label,
621
+ style
622
+ }) => {
623
+ const theme = useTheme();
624
+ const pulseAnim = useRef(new Animated3.Value(1)).current;
625
+ const statusColors = {
626
+ online: theme.colors.success,
627
+ offline: theme.colors["muted-foreground"],
628
+ busy: theme.colors.error,
629
+ away: theme.colors.warning,
630
+ error: theme.colors.error
631
+ };
632
+ useEffect(() => {
633
+ if (pulse && (status === "online" || status === "busy")) {
634
+ const animation = Animated3.loop(
635
+ Animated3.sequence([
636
+ Animated3.timing(pulseAnim, {
637
+ toValue: 0.3,
638
+ duration: 1e3,
639
+ useNativeDriver: true
640
+ }),
641
+ Animated3.timing(pulseAnim, {
642
+ toValue: 1,
643
+ duration: 1e3,
644
+ useNativeDriver: true
645
+ })
646
+ ])
647
+ );
648
+ animation.start();
649
+ return () => animation.stop();
650
+ } else {
651
+ pulseAnim.setValue(1);
652
+ }
653
+ }, [pulse, status, pulseAnim]);
654
+ const dotSize = sizeMap[size];
655
+ const color = statusColors[status];
656
+ const dot = /* @__PURE__ */ React9.createElement(View8, { style: [styles7.wrapper, style] }, /* @__PURE__ */ React9.createElement(
657
+ Animated3.View,
658
+ {
659
+ style: [
660
+ styles7.dot,
661
+ {
662
+ width: dotSize,
663
+ height: dotSize,
664
+ borderRadius: dotSize / 2,
665
+ backgroundColor: color,
666
+ opacity: pulseAnim
667
+ }
668
+ ]
669
+ }
670
+ ));
671
+ if (label) {
672
+ return /* @__PURE__ */ React9.createElement(HStack, { spacing: theme.spacing[2], align: "center", style }, dot, /* @__PURE__ */ React9.createElement(Typography, { variant: "caption", style: { color: theme.colors.foreground } }, label));
673
+ }
674
+ return dot;
675
+ };
676
+ var styles7 = StyleSheet7.create({
677
+ wrapper: {
678
+ alignItems: "center",
679
+ justifyContent: "center"
680
+ },
681
+ dot: {}
682
+ });
683
+ StatusDot.displayName = "StatusDot";
684
+
685
+ // src/components/atoms/TrendIndicator.tsx
686
+ import React10 from "react";
687
+ import { StyleSheet as StyleSheet8 } from "react-native";
688
+ var sizeConfig = {
689
+ sm: { icon: 14, font: "xs" },
690
+ md: { icon: 18, font: "sm" },
691
+ lg: { icon: 22, font: "base" }
692
+ };
693
+ var TrendIndicator = ({
694
+ value,
695
+ direction = "neutral",
696
+ showValue = true,
697
+ size = "md",
698
+ style
699
+ }) => {
700
+ const theme = useTheme();
701
+ const config = sizeConfig[size];
702
+ const directionColors = {
703
+ up: theme.colors.success,
704
+ down: theme.colors.error,
705
+ neutral: theme.colors["muted-foreground"]
706
+ };
707
+ const color = directionColors[direction];
708
+ const iconName = direction === "up" ? "chevron-up" : direction === "down" ? "chevron-down" : "minus";
709
+ return /* @__PURE__ */ React10.createElement(HStack, { spacing: 4, align: "center", style }, /* @__PURE__ */ React10.createElement(Icon, { name: iconName, size: config.icon, color }), showValue && value !== void 0 && /* @__PURE__ */ React10.createElement(
710
+ Typography,
711
+ {
712
+ variant: "body",
713
+ style: [
714
+ styles8.value,
715
+ { color, fontSize: theme.typography.sizes[config.font] }
716
+ ]
717
+ },
718
+ Math.abs(value),
719
+ "%"
720
+ ));
721
+ };
722
+ var styles8 = StyleSheet8.create({
723
+ value: {
724
+ fontWeight: "500"
725
+ }
726
+ });
727
+ TrendIndicator.displayName = "TrendIndicator";
728
+
729
+ // src/components/atoms/TextHighlight.tsx
730
+ import React11 from "react";
731
+ import { Pressable, StyleSheet as StyleSheet9 } from "react-native";
732
+ var TextHighlight = ({
733
+ children,
734
+ highlightType = "mark",
735
+ isActive = true,
736
+ action,
737
+ actionPayload,
738
+ color,
739
+ style
740
+ }) => {
741
+ const theme = useTheme();
742
+ const eventBus = useEventBus();
743
+ const handlePress = () => {
744
+ if (action) {
745
+ eventBus.emit(`UI:${action}`, actionPayload);
746
+ }
747
+ };
748
+ const highlightColors = {
749
+ mark: { bg: theme.colors.warning + "40", fg: theme.colors.foreground },
750
+ code: { bg: theme.colors.muted, fg: theme.colors.foreground },
751
+ emphasis: { bg: theme.colors.primary + "20", fg: theme.colors.primary },
752
+ custom: { bg: (color || theme.colors.accent) + "30", fg: theme.colors.foreground }
753
+ };
754
+ const { bg, fg } = highlightColors[highlightType];
755
+ const content = /* @__PURE__ */ React11.createElement(
756
+ Typography,
757
+ {
758
+ variant: "body",
759
+ style: [
760
+ styles9.text,
761
+ isActive && {
762
+ backgroundColor: bg,
763
+ color: fg
764
+ },
765
+ highlightType === "code" && {
766
+ fontFamily: "monospace",
767
+ fontSize: theme.typography.sizes.sm
768
+ },
769
+ style
770
+ ]
771
+ },
772
+ children
773
+ );
774
+ if (action) {
775
+ return /* @__PURE__ */ React11.createElement(Pressable, { onPress: handlePress, style: styles9.pressable }, content);
776
+ }
777
+ return content;
778
+ };
779
+ var styles9 = StyleSheet9.create({
780
+ text: {
781
+ paddingHorizontal: 4,
782
+ paddingVertical: 1,
783
+ borderRadius: 4
784
+ },
785
+ pressable: {
786
+ alignSelf: "flex-start"
787
+ }
788
+ });
789
+ TextHighlight.displayName = "TextHighlight";
790
+
791
+ // src/components/atoms/AnimatedCounter.tsx
792
+ import React12, { useEffect as useEffect2, useRef as useRef2 } from "react";
793
+ import { Animated as Animated4, StyleSheet as StyleSheet10 } from "react-native";
794
+ var AnimatedCounter = ({
795
+ value,
796
+ duration = 800,
797
+ prefix = "",
798
+ suffix = "",
799
+ style,
800
+ textStyle
801
+ }) => {
802
+ const theme = useTheme();
803
+ const animatedValue = useRef2(new Animated4.Value(0)).current;
804
+ const displayRef = useRef2(0);
805
+ const [displayValue, setDisplayValue] = React12.useState(0);
806
+ useEffect2(() => {
807
+ animatedValue.setValue(displayRef.current);
808
+ Animated4.timing(animatedValue, {
809
+ toValue: value,
810
+ duration,
811
+ useNativeDriver: false
812
+ }).start();
813
+ const listener = animatedValue.addListener(({ value: v }) => {
814
+ const rounded = Math.round(v);
815
+ if (rounded !== displayRef.current) {
816
+ displayRef.current = rounded;
817
+ setDisplayValue(rounded);
818
+ }
819
+ });
820
+ return () => {
821
+ animatedValue.removeListener(listener);
822
+ };
823
+ }, [value, duration, animatedValue]);
824
+ return /* @__PURE__ */ React12.createElement(Animated4.View, { style: [styles10.container, style] }, /* @__PURE__ */ React12.createElement(
825
+ Animated4.Text,
826
+ {
827
+ style: [
828
+ styles10.text,
829
+ {
830
+ color: theme.colors.foreground,
831
+ fontSize: theme.typography.sizes["2xl"],
832
+ fontWeight: theme.typography.fontWeight.bold
833
+ },
834
+ textStyle
835
+ ]
836
+ },
837
+ prefix,
838
+ displayValue,
839
+ suffix
840
+ ));
841
+ };
842
+ var styles10 = StyleSheet10.create({
843
+ container: {
844
+ alignItems: "center",
845
+ justifyContent: "center"
846
+ },
847
+ text: {
848
+ textAlign: "center"
849
+ }
850
+ });
851
+ AnimatedCounter.displayName = "AnimatedCounter";
852
+
853
+ // src/components/atoms/TypewriterText.tsx
854
+ import React13, { useEffect as useEffect3, useRef as useRef3, useState } from "react";
855
+ import { Animated as Animated5, StyleSheet as StyleSheet11 } from "react-native";
856
+ var TypewriterText = ({
857
+ text,
858
+ speed = 50,
859
+ startDelay = 0,
860
+ onComplete,
861
+ showCursor = true,
862
+ style,
863
+ textStyle
864
+ }) => {
865
+ const theme = useTheme();
866
+ const [displayedText, setDisplayedText] = useState("");
867
+ const [isComplete, setIsComplete] = useState(false);
868
+ const cursorOpacity = useRef3(new Animated5.Value(1)).current;
869
+ const intervalRef = useRef3(null);
870
+ const timeoutRef = useRef3(null);
871
+ useEffect3(() => {
872
+ setDisplayedText("");
873
+ setIsComplete(false);
874
+ let charIndex = 0;
875
+ timeoutRef.current = setTimeout(() => {
876
+ intervalRef.current = setInterval(() => {
877
+ if (charIndex < text.length) {
878
+ setDisplayedText(text.slice(0, charIndex + 1));
879
+ charIndex++;
880
+ } else {
881
+ if (intervalRef.current) clearInterval(intervalRef.current);
882
+ setIsComplete(true);
883
+ onComplete?.();
884
+ }
885
+ }, speed);
886
+ }, startDelay);
887
+ return () => {
888
+ if (timeoutRef.current) clearTimeout(timeoutRef.current);
889
+ if (intervalRef.current) clearInterval(intervalRef.current);
890
+ };
891
+ }, [text, speed, startDelay, onComplete]);
892
+ useEffect3(() => {
893
+ if (showCursor && !isComplete) {
894
+ const blink = Animated5.loop(
895
+ Animated5.sequence([
896
+ Animated5.timing(cursorOpacity, {
897
+ toValue: 0,
898
+ duration: 500,
899
+ useNativeDriver: true
900
+ }),
901
+ Animated5.timing(cursorOpacity, {
902
+ toValue: 1,
903
+ duration: 500,
904
+ useNativeDriver: true
905
+ })
906
+ ])
907
+ );
908
+ blink.start();
909
+ return () => blink.stop();
910
+ }
911
+ }, [showCursor, isComplete, cursorOpacity]);
912
+ return /* @__PURE__ */ React13.createElement(HStack, { spacing: 0, align: "flex-end", style }, /* @__PURE__ */ React13.createElement(
913
+ Animated5.Text,
914
+ {
915
+ style: [
916
+ styles11.text,
917
+ {
918
+ color: theme.colors.foreground,
919
+ fontSize: theme.typography.sizes.base
920
+ },
921
+ textStyle
922
+ ]
923
+ },
924
+ displayedText
925
+ ), showCursor && !isComplete && /* @__PURE__ */ React13.createElement(
926
+ Animated5.Text,
927
+ {
928
+ style: [
929
+ styles11.cursor,
930
+ {
931
+ color: theme.colors.primary,
932
+ fontSize: theme.typography.sizes.base,
933
+ opacity: cursorOpacity
934
+ }
935
+ ]
936
+ },
937
+ "|"
938
+ ));
939
+ };
940
+ var styles11 = StyleSheet11.create({
941
+ text: {
942
+ fontWeight: "400"
943
+ },
944
+ cursor: {
945
+ fontWeight: "300",
946
+ marginLeft: 1
947
+ }
948
+ });
949
+ TypewriterText.displayName = "TypewriterText";
950
+
951
+ // src/components/atoms/ThemeToggle.tsx
952
+ import React14 from "react";
953
+ import { Pressable as Pressable2, StyleSheet as StyleSheet12 } from "react-native";
954
+ var sizeConfig2 = {
955
+ sm: { icon: 18, padding: 6 },
956
+ md: { icon: 24, padding: 10 },
957
+ lg: { icon: 30, padding: 14 }
958
+ };
959
+ var ThemeToggle = ({
960
+ size = "md",
961
+ showLabel = false,
962
+ style
963
+ }) => {
964
+ const theme = useTheme();
965
+ const { resolvedMode, toggleMode } = useThemeMode();
966
+ const config = sizeConfig2[size];
967
+ const isDark = resolvedMode === "dark";
968
+ const iconText = isDark ? "\u2600" : "\u263E";
969
+ const label = isDark ? "Light mode" : "Dark mode";
970
+ return /* @__PURE__ */ React14.createElement(
971
+ Pressable2,
972
+ {
973
+ onPress: toggleMode,
974
+ style: [
975
+ styles12.container,
976
+ {
977
+ padding: config.padding,
978
+ borderRadius: theme.borderRadius.full,
979
+ backgroundColor: theme.colors.secondary
980
+ },
981
+ style
982
+ ]
983
+ },
984
+ /* @__PURE__ */ React14.createElement(HStack, { spacing: theme.spacing[2], align: "center" }, /* @__PURE__ */ React14.createElement(Icon, { name: isDark ? "check" : "settings", size: config.icon, color: theme.colors.foreground }), /* @__PURE__ */ React14.createElement(Typography, { variant: "body", style: { color: theme.colors.foreground, fontSize: config.icon * 0.7 } }, iconText), showLabel && /* @__PURE__ */ React14.createElement(Typography, { variant: "caption", style: { color: theme.colors["muted-foreground"] } }, label))
985
+ );
986
+ };
987
+ var styles12 = StyleSheet12.create({
988
+ container: {
989
+ alignSelf: "flex-start"
990
+ }
991
+ });
992
+ ThemeToggle.displayName = "ThemeToggle";
993
+
994
+ // src/components/atoms/RangeSlider.tsx
995
+ import React15, { useRef as useRef4, useState as useState2 } from "react";
996
+ import { View as View9, PanResponder, StyleSheet as StyleSheet13 } from "react-native";
997
+ var THUMB_SIZE = 24;
998
+ var TRACK_HEIGHT = 4;
999
+ var RangeSlider = ({
1000
+ min = 0,
1001
+ max = 100,
1002
+ value: controlledValue,
1003
+ step = 1,
1004
+ action,
1005
+ actionPayload,
1006
+ onChange,
1007
+ showValue = false,
1008
+ label,
1009
+ disabled = false,
1010
+ style
1011
+ }) => {
1012
+ const theme = useTheme();
1013
+ const eventBus = useEventBus();
1014
+ const [internalValue, setInternalValue] = useState2(controlledValue ?? min);
1015
+ const trackWidth = useRef4(0);
1016
+ const currentValue = controlledValue ?? internalValue;
1017
+ const clamp = (v) => {
1018
+ const stepped = Math.round((v - min) / step) * step + min;
1019
+ return Math.max(min, Math.min(max, stepped));
1020
+ };
1021
+ const getFraction = () => (currentValue - min) / (max - min);
1022
+ const emitValue = (v) => {
1023
+ const clamped = clamp(v);
1024
+ setInternalValue(clamped);
1025
+ onChange?.(clamped);
1026
+ if (action) {
1027
+ eventBus.emit(`UI:${action}`, { ...actionPayload, value: clamped });
1028
+ }
1029
+ };
1030
+ const panResponder = useRef4(
1031
+ PanResponder.create({
1032
+ onStartShouldSetPanResponder: () => !disabled,
1033
+ onMoveShouldSetPanResponder: () => !disabled,
1034
+ onPanResponderGrant: (_, gestureState) => {
1035
+ const fraction2 = Math.max(0, Math.min(1, gestureState.x0 / (trackWidth.current || 1)));
1036
+ emitValue(fraction2 * (max - min) + min);
1037
+ },
1038
+ onPanResponderMove: (_, gestureState) => {
1039
+ const startFraction = getFraction();
1040
+ const deltaFraction = gestureState.dx / (trackWidth.current || 1);
1041
+ const newValue = (startFraction + deltaFraction) * (max - min) + min;
1042
+ emitValue(newValue);
1043
+ }
1044
+ })
1045
+ ).current;
1046
+ const handleLayout = (e) => {
1047
+ trackWidth.current = e.nativeEvent.layout.width;
1048
+ };
1049
+ const fraction = getFraction();
1050
+ const content = /* @__PURE__ */ React15.createElement(
1051
+ View9,
1052
+ {
1053
+ style: [styles13.trackContainer, disabled && { opacity: 0.5 }, style],
1054
+ onLayout: handleLayout,
1055
+ ...panResponder.panHandlers
1056
+ },
1057
+ /* @__PURE__ */ React15.createElement(
1058
+ View9,
1059
+ {
1060
+ style: [
1061
+ styles13.track,
1062
+ { backgroundColor: theme.colors.border }
1063
+ ]
1064
+ }
1065
+ ),
1066
+ /* @__PURE__ */ React15.createElement(
1067
+ View9,
1068
+ {
1069
+ style: [
1070
+ styles13.trackFill,
1071
+ {
1072
+ backgroundColor: theme.colors.primary,
1073
+ width: `${fraction * 100}%`
1074
+ }
1075
+ ]
1076
+ }
1077
+ ),
1078
+ /* @__PURE__ */ React15.createElement(
1079
+ View9,
1080
+ {
1081
+ style: [
1082
+ styles13.thumb,
1083
+ {
1084
+ backgroundColor: theme.colors.primary,
1085
+ borderColor: theme.colors.card,
1086
+ left: `${fraction * 100}%`,
1087
+ marginLeft: -THUMB_SIZE / 2,
1088
+ ...theme.shadows.sm
1089
+ }
1090
+ ]
1091
+ }
1092
+ )
1093
+ );
1094
+ if (label || showValue) {
1095
+ return /* @__PURE__ */ React15.createElement(VStack, { spacing: theme.spacing[2], style }, (label || showValue) && /* @__PURE__ */ React15.createElement(HStack, { spacing: 0, align: "center", style: styles13.header }, label && /* @__PURE__ */ React15.createElement(Typography, { variant: "caption", style: { color: theme.colors["muted-foreground"], flex: 1 } }, label), showValue && /* @__PURE__ */ React15.createElement(Typography, { variant: "body", style: { color: theme.colors.foreground, fontWeight: "500" } }, currentValue)), content);
1096
+ }
1097
+ return content;
1098
+ };
1099
+ var styles13 = StyleSheet13.create({
1100
+ trackContainer: {
1101
+ height: THUMB_SIZE + 8,
1102
+ justifyContent: "center",
1103
+ paddingHorizontal: THUMB_SIZE / 2
1104
+ },
1105
+ track: {
1106
+ height: TRACK_HEIGHT,
1107
+ borderRadius: TRACK_HEIGHT / 2,
1108
+ position: "absolute",
1109
+ left: THUMB_SIZE / 2,
1110
+ right: THUMB_SIZE / 2
1111
+ },
1112
+ trackFill: {
1113
+ height: TRACK_HEIGHT,
1114
+ borderRadius: TRACK_HEIGHT / 2,
1115
+ position: "absolute",
1116
+ left: THUMB_SIZE / 2
1117
+ },
1118
+ thumb: {
1119
+ width: THUMB_SIZE,
1120
+ height: THUMB_SIZE,
1121
+ borderRadius: THUMB_SIZE / 2,
1122
+ borderWidth: 3,
1123
+ position: "absolute"
1124
+ },
1125
+ header: {
1126
+ justifyContent: "space-between"
1127
+ }
1128
+ });
1129
+ RangeSlider.displayName = "RangeSlider";
1130
+
631
1131
  // src/components/atoms/game/Sprite.tsx
632
- import React10, { useMemo } from "react";
1132
+ import React16, { useMemo } from "react";
633
1133
  import {
634
- View as View9,
1134
+ View as View10,
635
1135
  Image as Image2,
636
1136
  TouchableOpacity as TouchableOpacity3,
637
- StyleSheet as StyleSheet8
1137
+ StyleSheet as StyleSheet14
638
1138
  } from "react-native";
639
1139
  var Sprite = ({
640
1140
  spritesheet,
@@ -675,13 +1175,13 @@ var Sprite = ({
675
1175
  { scaleX: flipX ? -1 : 1 },
676
1176
  { scaleY: flipY ? -1 : 1 }
677
1177
  ];
678
- const Container = action || onPress ? TouchableOpacity3 : View9;
679
- return /* @__PURE__ */ React10.createElement(
1178
+ const Container = action || onPress ? TouchableOpacity3 : View10;
1179
+ return /* @__PURE__ */ React16.createElement(
680
1180
  Container,
681
1181
  {
682
1182
  onPress: action || onPress ? handlePress : void 0,
683
1183
  style: [
684
- styles8.container,
1184
+ styles14.container,
685
1185
  {
686
1186
  width: frameWidth,
687
1187
  height: frameHeight,
@@ -692,8 +1192,8 @@ var Sprite = ({
692
1192
  style
693
1193
  ]
694
1194
  },
695
- /* @__PURE__ */ React10.createElement(
696
- View9,
1195
+ /* @__PURE__ */ React16.createElement(
1196
+ View10,
697
1197
  {
698
1198
  style: {
699
1199
  width: frameWidth * columns,
@@ -704,7 +1204,7 @@ var Sprite = ({
704
1204
  overflow: "hidden"
705
1205
  }
706
1206
  },
707
- /* @__PURE__ */ React10.createElement(
1207
+ /* @__PURE__ */ React16.createElement(
708
1208
  Image2,
709
1209
  {
710
1210
  source: spritesheet,
@@ -718,7 +1218,7 @@ var Sprite = ({
718
1218
  )
719
1219
  );
720
1220
  };
721
- var styles8 = StyleSheet8.create({
1221
+ var styles14 = StyleSheet14.create({
722
1222
  container: {
723
1223
  position: "absolute",
724
1224
  overflow: "hidden"
@@ -727,8 +1227,8 @@ var styles8 = StyleSheet8.create({
727
1227
  Sprite.displayName = "Sprite";
728
1228
 
729
1229
  // src/components/atoms/game/StateIndicator.tsx
730
- import React11 from "react";
731
- import { View as View10, Text as Text3, StyleSheet as StyleSheet9 } from "react-native";
1230
+ import React17 from "react";
1231
+ import { View as View11, Text as Text3, StyleSheet as StyleSheet15 } from "react-native";
732
1232
  var DEFAULT_STATE_STYLES = {
733
1233
  idle: { icon: "\u23F8", backgroundColor: "#6b7280" },
734
1234
  active: { icon: "\u25B6", backgroundColor: "#22c55e" },
@@ -763,11 +1263,11 @@ var StateIndicator = ({
763
1263
  const displayLabel = label || state.charAt(0).toUpperCase() + state.slice(1);
764
1264
  const sizeStyles = SIZE_STYLES[size];
765
1265
  const shouldAnimate = animated && state.toLowerCase() !== "idle" && state.toLowerCase() !== "done";
766
- return /* @__PURE__ */ React11.createElement(
767
- View10,
1266
+ return /* @__PURE__ */ React17.createElement(
1267
+ View11,
768
1268
  {
769
1269
  style: [
770
- styles9.container,
1270
+ styles15.container,
771
1271
  {
772
1272
  backgroundColor: config.backgroundColor,
773
1273
  paddingHorizontal: sizeStyles.padding,
@@ -777,8 +1277,8 @@ var StateIndicator = ({
777
1277
  style
778
1278
  ]
779
1279
  },
780
- /* @__PURE__ */ React11.createElement(Text3, { style: { fontSize: sizeStyles.fontSize, marginRight: 4 } }, config.icon),
781
- /* @__PURE__ */ React11.createElement(
1280
+ /* @__PURE__ */ React17.createElement(Text3, { style: { fontSize: sizeStyles.fontSize, marginRight: 4 } }, config.icon),
1281
+ /* @__PURE__ */ React17.createElement(
782
1282
  Text3,
783
1283
  {
784
1284
  style: {
@@ -791,7 +1291,7 @@ var StateIndicator = ({
791
1291
  )
792
1292
  );
793
1293
  };
794
- var styles9 = StyleSheet9.create({
1294
+ var styles15 = StyleSheet15.create({
795
1295
  container: {
796
1296
  flexDirection: "row",
797
1297
  alignItems: "center",
@@ -805,12 +1305,18 @@ export {
805
1305
  Radio,
806
1306
  Switch,
807
1307
  Textarea,
808
- Spinner,
809
1308
  Avatar,
810
1309
  Overlay,
811
1310
  Spacer,
812
1311
  ConditionalWrapper,
1312
+ StatusDot,
1313
+ TrendIndicator,
1314
+ TextHighlight,
1315
+ AnimatedCounter,
1316
+ TypewriterText,
1317
+ ThemeToggle,
1318
+ RangeSlider,
813
1319
  Sprite,
814
1320
  StateIndicator
815
1321
  };
816
- //# sourceMappingURL=chunk-DMLYJFYQ.js.map
1322
+ //# sourceMappingURL=chunk-BFRVXKSP.js.map