@mks2508/mks-ui 0.2.1 → 0.3.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 (155) hide show
  1. package/dist/react-ui/hooks/Animation/UseAutoHeight.js +7 -7
  2. package/dist/react-ui/hooks/DOM/UseIsInView.js +3 -3
  3. package/dist/react-ui/hooks/Formatting/UseListFormat.d.ts +49 -0
  4. package/dist/react-ui/hooks/Formatting/UseListFormat.d.ts.map +1 -0
  5. package/dist/react-ui/hooks/Formatting/UseListFormat.js +105 -0
  6. package/dist/react-ui/hooks/State/UseControlledState.js +4 -4
  7. package/dist/react-ui/hooks/State/UseDataState.js +5 -5
  8. package/dist/react-ui/hooks/index.d.ts +2 -0
  9. package/dist/react-ui/hooks/index.d.ts.map +1 -1
  10. package/dist/react-ui/hooks/index.js +1 -0
  11. package/dist/react-ui/index.js +22 -2
  12. package/dist/react-ui/lib/get-strict-context.js +3 -3
  13. package/dist/react-ui/primitives/CountingNumber/index.js +3 -3
  14. package/dist/react-ui/primitives/Highlight/index.js +26 -26
  15. package/dist/react-ui/primitives/Slot/index.js +3 -3
  16. package/dist/react-ui/primitives/index.d.ts +1 -0
  17. package/dist/react-ui/primitives/index.d.ts.map +1 -1
  18. package/dist/react-ui/primitives/index.js +18 -0
  19. package/dist/react-ui/primitives/waapi/Morph/Morph.types.d.ts +76 -0
  20. package/dist/react-ui/primitives/waapi/Morph/Morph.types.d.ts.map +1 -0
  21. package/dist/react-ui/primitives/waapi/Morph/MorphContext.d.ts +11 -0
  22. package/dist/react-ui/primitives/waapi/Morph/MorphContext.d.ts.map +1 -0
  23. package/dist/react-ui/primitives/waapi/Morph/MorphContext.js +19 -0
  24. package/dist/react-ui/primitives/waapi/Morph/index.d.ts +23 -0
  25. package/dist/react-ui/primitives/waapi/Morph/index.d.ts.map +1 -0
  26. package/dist/react-ui/primitives/waapi/Morph/index.js +45 -0
  27. package/dist/react-ui/primitives/waapi/Morph/techniques/index.d.ts +12 -0
  28. package/dist/react-ui/primitives/waapi/Morph/techniques/index.d.ts.map +1 -0
  29. package/dist/react-ui/primitives/waapi/Morph/techniques/useCSSGridMorph.d.ts +38 -0
  30. package/dist/react-ui/primitives/waapi/Morph/techniques/useCSSGridMorph.d.ts.map +1 -0
  31. package/dist/react-ui/primitives/waapi/Morph/techniques/useCSSGridMorph.js +78 -0
  32. package/dist/react-ui/primitives/waapi/Morph/techniques/useFLIPClipPath.d.ts +23 -0
  33. package/dist/react-ui/primitives/waapi/Morph/techniques/useFLIPClipPath.d.ts.map +1 -0
  34. package/dist/react-ui/primitives/waapi/Morph/techniques/useFLIPClipPath.js +140 -0
  35. package/dist/react-ui/primitives/waapi/Morph/techniques/useViewTransitions.d.ts +28 -0
  36. package/dist/react-ui/primitives/waapi/Morph/techniques/useViewTransitions.d.ts.map +1 -0
  37. package/dist/react-ui/primitives/waapi/Morph/techniques/useViewTransitions.js +77 -0
  38. package/dist/react-ui/primitives/waapi/Morph/useMorph.d.ts +27 -0
  39. package/dist/react-ui/primitives/waapi/Morph/useMorph.d.ts.map +1 -0
  40. package/dist/react-ui/primitives/waapi/Morph/useMorph.js +86 -0
  41. package/dist/react-ui/primitives/waapi/Reorder/Reorder.types.d.ts +168 -0
  42. package/dist/react-ui/primitives/waapi/Reorder/Reorder.types.d.ts.map +1 -0
  43. package/dist/react-ui/primitives/waapi/Reorder/index.d.ts +25 -0
  44. package/dist/react-ui/primitives/waapi/Reorder/index.d.ts.map +1 -0
  45. package/dist/react-ui/primitives/waapi/Reorder/index.js +186 -0
  46. package/dist/react-ui/primitives/waapi/Reorder/useReorder.d.ts +26 -0
  47. package/dist/react-ui/primitives/waapi/Reorder/useReorder.d.ts.map +1 -0
  48. package/dist/react-ui/primitives/waapi/Reorder/useReorder.js +48 -0
  49. package/dist/react-ui/primitives/waapi/Reorder/useReorderPresence.d.ts +33 -0
  50. package/dist/react-ui/primitives/waapi/Reorder/useReorderPresence.d.ts.map +1 -0
  51. package/dist/react-ui/primitives/waapi/Reorder/useReorderPresence.js +137 -0
  52. package/dist/react-ui/primitives/waapi/Reorder/utils/separatorCoordination.d.ts +47 -0
  53. package/dist/react-ui/primitives/waapi/Reorder/utils/separatorCoordination.d.ts.map +1 -0
  54. package/dist/react-ui/primitives/waapi/Reorder/utils/separatorCoordination.js +72 -0
  55. package/dist/react-ui/primitives/waapi/SlidingNumber/SlidingNumber.styles.d.ts +10 -0
  56. package/dist/react-ui/primitives/waapi/SlidingNumber/SlidingNumber.styles.d.ts.map +1 -0
  57. package/dist/react-ui/primitives/waapi/SlidingNumber/SlidingNumber.types.d.ts +74 -0
  58. package/dist/react-ui/primitives/waapi/SlidingNumber/SlidingNumber.types.d.ts.map +1 -0
  59. package/dist/react-ui/primitives/waapi/SlidingNumber/index.d.ts +33 -0
  60. package/dist/react-ui/primitives/waapi/SlidingNumber/index.d.ts.map +1 -0
  61. package/dist/react-ui/primitives/waapi/SlidingNumber/index.js +354 -0
  62. package/dist/react-ui/primitives/waapi/SlidingText/SlidingText.styles.d.ts +25 -0
  63. package/dist/react-ui/primitives/waapi/SlidingText/SlidingText.styles.d.ts.map +1 -0
  64. package/dist/react-ui/primitives/waapi/SlidingText/SlidingText.types.d.ts +57 -0
  65. package/dist/react-ui/primitives/waapi/SlidingText/SlidingText.types.d.ts.map +1 -0
  66. package/dist/react-ui/primitives/waapi/SlidingText/index.d.ts +26 -0
  67. package/dist/react-ui/primitives/waapi/SlidingText/index.d.ts.map +1 -0
  68. package/dist/react-ui/primitives/waapi/SlidingText/index.js +105 -0
  69. package/dist/react-ui/primitives/waapi/core/animationConstants.d.ts +156 -0
  70. package/dist/react-ui/primitives/waapi/core/animationConstants.d.ts.map +1 -0
  71. package/dist/react-ui/primitives/waapi/core/animationConstants.js +180 -0
  72. package/dist/react-ui/primitives/waapi/core/index.d.ts +16 -0
  73. package/dist/react-ui/primitives/waapi/core/index.d.ts.map +1 -0
  74. package/dist/react-ui/primitives/waapi/core/index.js +5 -0
  75. package/dist/react-ui/primitives/waapi/core/types.d.ts +143 -0
  76. package/dist/react-ui/primitives/waapi/core/types.d.ts.map +1 -0
  77. package/dist/react-ui/primitives/waapi/core/useAnimationOrchestrator.d.ts +32 -0
  78. package/dist/react-ui/primitives/waapi/core/useAnimationOrchestrator.d.ts.map +1 -0
  79. package/dist/react-ui/primitives/waapi/core/useAnimationOrchestrator.js +322 -0
  80. package/dist/react-ui/primitives/waapi/core/useElementRegistry.d.ts +21 -0
  81. package/dist/react-ui/primitives/waapi/core/useElementRegistry.d.ts.map +1 -0
  82. package/dist/react-ui/primitives/waapi/core/useElementRegistry.js +65 -0
  83. package/dist/react-ui/primitives/waapi/core/useFLIPAnimation.d.ts +20 -0
  84. package/dist/react-ui/primitives/waapi/core/useFLIPAnimation.d.ts.map +1 -0
  85. package/dist/react-ui/primitives/waapi/core/useFLIPAnimation.js +99 -0
  86. package/dist/react-ui/primitives/waapi/core/usePositionCapture.d.ts +24 -0
  87. package/dist/react-ui/primitives/waapi/core/usePositionCapture.d.ts.map +1 -0
  88. package/dist/react-ui/primitives/waapi/core/usePositionCapture.js +75 -0
  89. package/dist/react-ui/primitives/waapi/index.d.ts +33 -0
  90. package/dist/react-ui/primitives/waapi/index.d.ts.map +1 -0
  91. package/dist/react-ui/primitives/waapi/index.js +18 -0
  92. package/dist/react-ui/ui/Accordion/index.js +3 -3
  93. package/dist/react-ui/ui/Button/index.js +8 -8
  94. package/dist/react-ui/ui/Combobox/index.js +2 -2
  95. package/dist/react-ui/ui/DataCard/DataCard.styles.d.ts +35 -0
  96. package/dist/react-ui/ui/DataCard/DataCard.styles.d.ts.map +1 -0
  97. package/dist/react-ui/ui/DataCard/DataCard.styles.js +114 -0
  98. package/dist/react-ui/ui/DataCard/DataCard.types.d.ts +135 -0
  99. package/dist/react-ui/ui/DataCard/DataCard.types.d.ts.map +1 -0
  100. package/dist/react-ui/ui/DataCard/index.d.ts +129 -0
  101. package/dist/react-ui/ui/DataCard/index.d.ts.map +1 -0
  102. package/dist/react-ui/ui/DataCard/index.js +276 -0
  103. package/dist/react-ui/ui/Menu/index.js +2 -2
  104. package/dist/react-ui/ui/Switch/index.js +3 -3
  105. package/dist/react-ui/ui/Tabs/index.js +3 -3
  106. package/dist/react-ui/ui/TextFlow/TextFlow.styles.d.ts +16 -0
  107. package/dist/react-ui/ui/TextFlow/TextFlow.styles.d.ts.map +1 -0
  108. package/dist/react-ui/ui/TextFlow/TextFlow.types.d.ts +101 -0
  109. package/dist/react-ui/ui/TextFlow/TextFlow.types.d.ts.map +1 -0
  110. package/dist/react-ui/ui/TextFlow/index.d.ts +26 -0
  111. package/dist/react-ui/ui/TextFlow/index.d.ts.map +1 -0
  112. package/dist/react-ui/ui/TextFlow/index.js +187 -0
  113. package/dist/react-ui/ui/index.d.ts +2 -1
  114. package/dist/react-ui/ui/index.d.ts.map +1 -1
  115. package/dist/react-ui/ui/index.js +3 -1
  116. package/package.json +6 -2
  117. package/src/react-ui/hooks/Formatting/UseListFormat.ts +134 -0
  118. package/src/react-ui/hooks/index.ts +3 -0
  119. package/src/react-ui/primitives/index.ts +3 -0
  120. package/src/react-ui/primitives/waapi/Morph/Morph.types.ts +106 -0
  121. package/src/react-ui/primitives/waapi/Morph/MorphContext.tsx +21 -0
  122. package/src/react-ui/primitives/waapi/Morph/index.tsx +56 -0
  123. package/src/react-ui/primitives/waapi/Morph/techniques/index.ts +12 -0
  124. package/src/react-ui/primitives/waapi/Morph/techniques/useCSSGridMorph.ts +88 -0
  125. package/src/react-ui/primitives/waapi/Morph/techniques/useFLIPClipPath.ts +175 -0
  126. package/src/react-ui/primitives/waapi/Morph/techniques/useViewTransitions.ts +86 -0
  127. package/src/react-ui/primitives/waapi/Morph/useMorph.ts +100 -0
  128. package/src/react-ui/primitives/waapi/Reorder/Reorder.types.ts +177 -0
  129. package/src/react-ui/primitives/waapi/Reorder/index.tsx +260 -0
  130. package/src/react-ui/primitives/waapi/Reorder/useReorder.ts +46 -0
  131. package/src/react-ui/primitives/waapi/Reorder/useReorderPresence.ts +208 -0
  132. package/src/react-ui/primitives/waapi/Reorder/utils/separatorCoordination.ts +104 -0
  133. package/src/react-ui/primitives/waapi/SlidingNumber/SlidingNumber.styles.ts +14 -0
  134. package/src/react-ui/primitives/waapi/SlidingNumber/SlidingNumber.types.ts +84 -0
  135. package/src/react-ui/primitives/waapi/SlidingNumber/index.tsx +474 -0
  136. package/src/react-ui/primitives/waapi/SlidingText/SlidingText.styles.ts +32 -0
  137. package/src/react-ui/primitives/waapi/SlidingText/SlidingText.types.ts +69 -0
  138. package/src/react-ui/primitives/waapi/SlidingText/index.tsx +140 -0
  139. package/src/react-ui/primitives/waapi/core/animationConstants.ts +215 -0
  140. package/src/react-ui/primitives/waapi/core/index.ts +53 -0
  141. package/src/react-ui/primitives/waapi/core/types.ts +200 -0
  142. package/src/react-ui/primitives/waapi/core/useAnimationOrchestrator.ts +429 -0
  143. package/src/react-ui/primitives/waapi/core/useElementRegistry.ts +80 -0
  144. package/src/react-ui/primitives/waapi/core/useFLIPAnimation.ts +137 -0
  145. package/src/react-ui/primitives/waapi/core/usePositionCapture.ts +105 -0
  146. package/src/react-ui/primitives/waapi/index.ts +116 -0
  147. package/src/react-ui/styles/animations.css +369 -0
  148. package/src/react-ui/ui/DataCard/DataCard.styles.ts +150 -0
  149. package/src/react-ui/ui/DataCard/DataCard.types.ts +146 -0
  150. package/src/react-ui/ui/DataCard/index.tsx +406 -0
  151. package/src/react-ui/ui/TextFlow/TextFlow.styles.ts +36 -0
  152. package/src/react-ui/ui/TextFlow/TextFlow.types.ts +118 -0
  153. package/src/react-ui/ui/TextFlow/index.tsx +276 -0
  154. package/src/react-ui/ui/index.ts +4 -1
  155. /package/dist/react-ui/components/MorphingPopover/{morphing-popover.module-CgbYV_HS.css → morphing-popover.module-BycNI8nU.css} +0 -0
@@ -0,0 +1,36 @@
1
+ import { cva, type VariantProps } from 'class-variance-authority';
2
+ import type { StyleSlots } from '@/core/types';
3
+
4
+ /**
5
+ * Style slots for TextFlow component
6
+ */
7
+ export type TextFlowSlot = 'root' | 'token' | 'separator' | 'overflow' | 'placeholder';
8
+
9
+ /**
10
+ * Base styles for TextFlow component
11
+ */
12
+ export const textFlowBaseStyles: StyleSlots<TextFlowSlot> = {
13
+ root: 'waapi-animated-tokens-container',
14
+ token: 'waapi-token-wrapper',
15
+ separator: 'waapi-token-separator',
16
+ overflow: 'waapi-token-overflow',
17
+ placeholder: 'waapi-token-placeholder',
18
+ };
19
+
20
+ /**
21
+ * CVA variants for TextFlow root container
22
+ */
23
+ export const textFlowVariants = cva({
24
+ base: 'waapi-animated-tokens-container',
25
+ variants: {
26
+ inline: {
27
+ true: 'waapi-animated-tokens-container--inline',
28
+ false: '',
29
+ },
30
+ },
31
+ defaultVariants: {
32
+ inline: false,
33
+ },
34
+ });
35
+
36
+ export type TextFlowVariants = VariantProps<typeof textFlowVariants>;
@@ -0,0 +1,118 @@
1
+ import type { CSSProperties } from 'react';
2
+
3
+ /**
4
+ * Token individual para TextFlow
5
+ */
6
+ export interface IToken {
7
+ /** Identificador único del token */
8
+ id: string;
9
+ /** Texto a mostrar */
10
+ text: string;
11
+ }
12
+
13
+ /**
14
+ * Modo de transición para cambios de texto en separadores
15
+ */
16
+ export type SeparatorTransitionMode = 'none' | 'fade' | 'slide';
17
+
18
+ /**
19
+ * Tipos de lista para Intl.ListFormat
20
+ */
21
+ export type ListFormatType = 'conjunction' | 'disjunction' | 'unit';
22
+
23
+ /**
24
+ * Estilos de lista para Intl.ListFormat
25
+ */
26
+ export type ListFormatStyle = 'long' | 'short' | 'narrow';
27
+
28
+ /**
29
+ * Configuración de separadores entre tokens
30
+ */
31
+ export interface ISeparatorConfig {
32
+ /** Texto del separador. Si se omite, usa Intl.ListFormat */
33
+ value?: string;
34
+ /** Locale para Intl.ListFormat */
35
+ locale?: string;
36
+ /** Tipo de lista para Intl.ListFormat */
37
+ listType?: ListFormatType;
38
+ /** Estilo de lista para Intl.ListFormat */
39
+ listStyle?: ListFormatStyle;
40
+ /** Modo de transición cuando el texto del separador cambia */
41
+ transition?: SeparatorTransitionMode;
42
+ /** Duración de la transición en ms */
43
+ duration?: number;
44
+ /** Clase CSS adicional para separadores */
45
+ className?: string;
46
+ }
47
+
48
+ /**
49
+ * Configuración del indicador de overflow (+N more)
50
+ */
51
+ export interface IOverflowConfig {
52
+ /** Prefijo antes del número */
53
+ prefix?: string;
54
+ /** Texto después del número */
55
+ label?: string;
56
+ /** Separador mostrado antes del overflow */
57
+ separator?: string;
58
+ /** Mostrar separador antes del overflow */
59
+ showSeparator?: boolean;
60
+ /** Clase CSS adicional para el overflow */
61
+ className?: string;
62
+ }
63
+
64
+ /**
65
+ * Configuración de animación de texto
66
+ */
67
+ export interface ITextAnimationConfig {
68
+ /** Modo de animación del texto */
69
+ mode?: 'character' | 'word';
70
+ /** Dirección de entrada del texto */
71
+ direction?: 'vertical' | 'horizontal';
72
+ /** Delay entre caracteres/palabras en ms */
73
+ stagger?: number;
74
+ /** Duración de animación en ms */
75
+ duration?: number;
76
+ /** Habilitar efecto blur durante animación */
77
+ blur?: boolean;
78
+ /** Animar cambios de ancho del contenedor */
79
+ widthAnimation?: boolean;
80
+ }
81
+
82
+ /**
83
+ * Props for TextFlow component
84
+ *
85
+ * TextFlow renders an animated list of tokens with locale-aware separators,
86
+ * smooth FLIP animations, and overflow handling.
87
+ */
88
+ export interface ITextFlowProps {
89
+ /** Array de tokens a mostrar */
90
+ tokens: IToken[];
91
+
92
+ /** Texto placeholder cuando no hay tokens */
93
+ placeholder?: string;
94
+
95
+ /** Máximo de tokens visibles. El resto se muestra como "+N" */
96
+ maxVisible?: number;
97
+
98
+ /** Configuración de separadores */
99
+ separator?: ISeparatorConfig;
100
+
101
+ /** Configuración del indicador de overflow */
102
+ overflow?: IOverflowConfig;
103
+
104
+ /** Configuración de animación de texto */
105
+ animation?: ITextAnimationConfig;
106
+
107
+ /** Modo inline para uso en botones/selects */
108
+ inline?: boolean;
109
+
110
+ /** Clase CSS para el contenedor principal */
111
+ className?: string;
112
+
113
+ /** Clase CSS para cada token */
114
+ tokenClassName?: string;
115
+
116
+ /** Clase CSS para el placeholder */
117
+ placeholderClassName?: string;
118
+ }
@@ -0,0 +1,276 @@
1
+ "use client";
2
+
3
+ import React, { useMemo, useCallback } from 'react';
4
+ import { SlidingText } from '@/react-ui/primitives/waapi/SlidingText';
5
+ import { Reorder } from '@/react-ui/primitives/waapi/Reorder';
6
+ import { useListFormat } from '@/react-ui/hooks/Formatting/UseListFormat';
7
+ import type {
8
+ ITextFlowProps,
9
+ IToken,
10
+ ISeparatorConfig,
11
+ IOverflowConfig,
12
+ ITextAnimationConfig,
13
+ SeparatorTransitionMode,
14
+ ListFormatType,
15
+ ListFormatStyle,
16
+ } from './TextFlow.types';
17
+ import { cn } from '@/react-ui/lib/utils';
18
+
19
+ // Default configurations
20
+ const DEFAULT_SEPARATOR: Required<Omit<ISeparatorConfig, 'value' | 'locale' | 'className'>> = {
21
+ listType: 'conjunction',
22
+ listStyle: 'long',
23
+ transition: 'none',
24
+ duration: 200,
25
+ };
26
+
27
+ const DEFAULT_OVERFLOW: Required<Omit<IOverflowConfig, 'separator' | 'className'>> = {
28
+ prefix: '+',
29
+ label: ' more',
30
+ showSeparator: true,
31
+ };
32
+
33
+ const DEFAULT_ANIMATION: Required<ITextAnimationConfig> = {
34
+ mode: 'character',
35
+ direction: 'vertical',
36
+ stagger: 15,
37
+ duration: 200,
38
+ blur: true,
39
+ widthAnimation: false,
40
+ };
41
+
42
+ /**
43
+ * TextFlow - Locale-aware animated token list component
44
+ *
45
+ * Built on the Reorder primitive, provides smooth FLIP animations for token lists
46
+ * with proper locale-aware separators using Intl.ListFormat.
47
+ *
48
+ * @example
49
+ * ```tsx
50
+ * // Basic usage
51
+ * <TextFlow tokens={tokens} />
52
+ *
53
+ * // Spanish multiselect with transition
54
+ * <TextFlow
55
+ * tokens={tokens}
56
+ * maxVisible={2}
57
+ * inline
58
+ * separator={{ locale: 'es', transition: 'fade' }}
59
+ * overflow={{ prefix: '+', label: ' más' }}
60
+ * />
61
+ * ```
62
+ */
63
+ export const TextFlow: React.FC<ITextFlowProps> = ({
64
+ tokens,
65
+ placeholder = 'No tokens',
66
+ maxVisible,
67
+ separator: separatorConfig,
68
+ overflow: overflowConfig,
69
+ animation: animationConfig,
70
+ inline = false,
71
+ className = '',
72
+ tokenClassName = '',
73
+ placeholderClassName = '',
74
+ }) => {
75
+ // Merge configs with defaults
76
+ const separator: Required<Omit<ISeparatorConfig, 'value' | 'locale' | 'className'>> & Pick<ISeparatorConfig, 'value' | 'locale' | 'className'> = {
77
+ ...DEFAULT_SEPARATOR,
78
+ ...separatorConfig,
79
+ };
80
+
81
+ const overflow: Required<Omit<IOverflowConfig, 'separator' | 'className'>> & Pick<IOverflowConfig, 'separator' | 'className'> = {
82
+ ...DEFAULT_OVERFLOW,
83
+ ...overflowConfig,
84
+ };
85
+
86
+ const animation: Required<ITextAnimationConfig> = {
87
+ ...DEFAULT_ANIMATION,
88
+ ...animationConfig,
89
+ };
90
+
91
+ // Track exiting token IDs with REF
92
+ const exitingIdsRef = React.useRef<Set<string>>(new Set());
93
+
94
+ // Visible tokens
95
+ const visibleTokens = useMemo(
96
+ () => (maxVisible ? tokens.slice(0, maxVisible) : tokens),
97
+ [tokens, maxVisible]
98
+ );
99
+
100
+ const overflowCount = useMemo(
101
+ () => (maxVisible ? Math.max(0, tokens.length - maxVisible) : 0),
102
+ [tokens.length, maxVisible]
103
+ );
104
+
105
+ // Locale-aware list formatting via useListFormat hook
106
+ const listParts = useListFormat(
107
+ visibleTokens.map(t => t.text),
108
+ {
109
+ locale: separator.locale,
110
+ type: separator.listType,
111
+ style: separator.listStyle,
112
+ separator: separator.value,
113
+ hasOverflow: overflowCount > 0,
114
+ }
115
+ );
116
+
117
+ // Separator visibility logic
118
+ const shouldShowSeparator = useCallback((tokenIndex: number): boolean => {
119
+ const isLastToken = tokenIndex >= visibleTokens.length - 1;
120
+ return !isLastToken;
121
+ }, [visibleTokens.length]);
122
+
123
+ const handleItemExit = useCallback((id: string) => {
124
+ exitingIdsRef.current.add(id);
125
+ }, []);
126
+
127
+ const handleItemEnter = useCallback((id: string) => {
128
+ // Animation triggered automatically
129
+ }, []);
130
+
131
+ const showPlaceholder = tokens.length === 0 && !!placeholder;
132
+
133
+ // Build children from list parts
134
+ const tokenElements = useMemo(() => {
135
+ let elementIndex = 0;
136
+
137
+ return listParts.map((part, partIndex) => {
138
+ if (part.type === 'element') {
139
+ const token = visibleTokens[part.index];
140
+ if (!token) return null;
141
+
142
+ const isExiting = exitingIdsRef.current.has(token.id);
143
+ elementIndex++;
144
+
145
+ return (
146
+ <span
147
+ key={token.id}
148
+ className={cn('waapi-token-wrapper', tokenClassName)}
149
+ data-reorder-id={token.id}
150
+ >
151
+ <SlidingText
152
+ text={token.text}
153
+ mode={isExiting ? 'none' : animation.mode}
154
+ direction={animation.direction}
155
+ staggerDelay={animation.stagger}
156
+ duration={animation.duration}
157
+ blur={animation.blur}
158
+ widthAnimation={!isExiting && animation.widthAnimation}
159
+ initial={isExiting ? false : 'initial'}
160
+ animate="animate"
161
+ />
162
+ </span>
163
+ );
164
+ }
165
+
166
+ // Separator (literal)
167
+ const prevToken = visibleTokens[part.index];
168
+ if (!prevToken) return null;
169
+
170
+ const tokenIndex = part.index;
171
+ const showSep = shouldShowSeparator(tokenIndex);
172
+
173
+ if (!showSep) return null;
174
+
175
+ const separatorKey = `sep-${prevToken.id}`;
176
+
177
+ return (
178
+ <span
179
+ key={separatorKey}
180
+ className={cn('waapi-token-separator', separator.className ?? '')}
181
+ >
182
+ {part.value}
183
+ </span>
184
+ );
185
+ }).filter(Boolean);
186
+ }, [listParts, visibleTokens, tokenClassName, animation, separator, shouldShowSeparator]);
187
+
188
+ // Overflow element
189
+ const overflowElement = useMemo(() => {
190
+ if (overflowCount === 0) return null;
191
+
192
+ return (
193
+ <div
194
+ key="overflow-counter"
195
+ data-reorder-id="overflow-counter"
196
+ className={cn('waapi-token-overflow', overflow.className ?? '')}
197
+ >
198
+ {overflow.showSeparator && overflow.separator && (
199
+ <span className={cn('waapi-token-separator', separator.className ?? '')}>
200
+ {overflow.separator}
201
+ </span>
202
+ )}
203
+ {overflow.prefix !== '' && (
204
+ <span className={cn('waapi-token-separator', separator.className ?? '')}>
205
+ {overflow.prefix}
206
+ </span>
207
+ )}
208
+ <SlidingText
209
+ text={String(overflowCount)}
210
+ mode="character"
211
+ duration={animation.duration}
212
+ blur={animation.blur}
213
+ initial="initial"
214
+ animate="animate"
215
+ />
216
+ {overflow.label && overflow.label !== '' && (
217
+ <SlidingText
218
+ text={overflow.label}
219
+ mode={animation.mode}
220
+ direction={animation.direction}
221
+ staggerDelay={animation.stagger}
222
+ duration={animation.duration}
223
+ blur={animation.blur}
224
+ initial="initial"
225
+ animate="animate"
226
+ />
227
+ )}
228
+ </div>
229
+ );
230
+ }, [overflowCount, overflow, separator, animation]);
231
+
232
+ return (
233
+ <div
234
+ role="text"
235
+ className={cn(
236
+ 'waapi-animated-tokens-container',
237
+ inline && 'waapi-animated-tokens-container--inline',
238
+ className
239
+ )}
240
+ >
241
+ {showPlaceholder && (
242
+ <SlidingText
243
+ key="placeholder"
244
+ text={placeholder}
245
+ mode="word"
246
+ direction="vertical"
247
+ blur={true}
248
+ duration={150}
249
+ initial="initial"
250
+ animate="animate"
251
+ className={cn('waapi-token-placeholder', placeholderClassName)}
252
+ />
253
+ )}
254
+
255
+ <Reorder
256
+ layout={inline ? 'inline-horizontal' : 'horizontal'}
257
+ onItemExit={handleItemExit}
258
+ onItemEnter={handleItemEnter}
259
+ >
260
+ {tokenElements}
261
+ {overflowElement}
262
+ </Reorder>
263
+ </div>
264
+ );
265
+ };
266
+
267
+ TextFlow.displayName = 'TextFlow';
268
+
269
+ export type {
270
+ ITextFlowProps,
271
+ IToken,
272
+ ISeparatorConfig,
273
+ IOverflowConfig,
274
+ ITextAnimationConfig,
275
+ SeparatorTransitionMode,
276
+ };
@@ -31,4 +31,7 @@ export * from './InputGroup';
31
31
  export * from './Label';
32
32
  export * from './Select';
33
33
  export * from './Separator';
34
- export * from './Textarea';
34
+ export * from './DataCard';
35
+
36
+ // WAAPI-based components
37
+ export * from './TextFlow';