@mks2508/mks-ui 0.2.1 → 0.3.2
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.
- package/dist/react-ui/hooks/Animation/UseAutoHeight.js +7 -7
- package/dist/react-ui/hooks/DOM/UseIsInView.js +3 -3
- package/dist/react-ui/hooks/Formatting/UseListFormat.d.ts +49 -0
- package/dist/react-ui/hooks/Formatting/UseListFormat.d.ts.map +1 -0
- package/dist/react-ui/hooks/Formatting/UseListFormat.js +105 -0
- package/dist/react-ui/hooks/State/UseControlledState.js +4 -4
- package/dist/react-ui/hooks/State/UseDataState.js +5 -5
- package/dist/react-ui/hooks/index.d.ts +2 -0
- package/dist/react-ui/hooks/index.d.ts.map +1 -1
- package/dist/react-ui/hooks/index.js +1 -0
- package/dist/react-ui/index.js +22 -1
- package/dist/react-ui/lib/get-strict-context.js +3 -3
- package/dist/react-ui/primitives/CountingNumber/index.js +3 -3
- package/dist/react-ui/primitives/Highlight/index.js +26 -26
- package/dist/react-ui/primitives/Slot/index.js +3 -3
- package/dist/react-ui/primitives/index.d.ts +1 -0
- package/dist/react-ui/primitives/index.d.ts.map +1 -1
- package/dist/react-ui/primitives/index.js +18 -0
- package/dist/react-ui/primitives/waapi/Morph/Morph.types.d.ts +76 -0
- package/dist/react-ui/primitives/waapi/Morph/Morph.types.d.ts.map +1 -0
- package/dist/react-ui/primitives/waapi/Morph/MorphContext.d.ts +11 -0
- package/dist/react-ui/primitives/waapi/Morph/MorphContext.d.ts.map +1 -0
- package/dist/react-ui/primitives/waapi/Morph/MorphContext.js +19 -0
- package/dist/react-ui/primitives/waapi/Morph/index.d.ts +23 -0
- package/dist/react-ui/primitives/waapi/Morph/index.d.ts.map +1 -0
- package/dist/react-ui/primitives/waapi/Morph/index.js +45 -0
- package/dist/react-ui/primitives/waapi/Morph/techniques/index.d.ts +12 -0
- package/dist/react-ui/primitives/waapi/Morph/techniques/index.d.ts.map +1 -0
- package/dist/react-ui/primitives/waapi/Morph/techniques/useCSSGridMorph.d.ts +38 -0
- package/dist/react-ui/primitives/waapi/Morph/techniques/useCSSGridMorph.d.ts.map +1 -0
- package/dist/react-ui/primitives/waapi/Morph/techniques/useCSSGridMorph.js +78 -0
- package/dist/react-ui/primitives/waapi/Morph/techniques/useFLIPClipPath.d.ts +23 -0
- package/dist/react-ui/primitives/waapi/Morph/techniques/useFLIPClipPath.d.ts.map +1 -0
- package/dist/react-ui/primitives/waapi/Morph/techniques/useFLIPClipPath.js +140 -0
- package/dist/react-ui/primitives/waapi/Morph/techniques/useViewTransitions.d.ts +28 -0
- package/dist/react-ui/primitives/waapi/Morph/techniques/useViewTransitions.d.ts.map +1 -0
- package/dist/react-ui/primitives/waapi/Morph/techniques/useViewTransitions.js +77 -0
- package/dist/react-ui/primitives/waapi/Morph/useMorph.d.ts +27 -0
- package/dist/react-ui/primitives/waapi/Morph/useMorph.d.ts.map +1 -0
- package/dist/react-ui/primitives/waapi/Morph/useMorph.js +86 -0
- package/dist/react-ui/primitives/waapi/Reorder/Reorder.types.d.ts +168 -0
- package/dist/react-ui/primitives/waapi/Reorder/Reorder.types.d.ts.map +1 -0
- package/dist/react-ui/primitives/waapi/Reorder/index.d.ts +25 -0
- package/dist/react-ui/primitives/waapi/Reorder/index.d.ts.map +1 -0
- package/dist/react-ui/primitives/waapi/Reorder/index.js +186 -0
- package/dist/react-ui/primitives/waapi/Reorder/useReorder.d.ts +26 -0
- package/dist/react-ui/primitives/waapi/Reorder/useReorder.d.ts.map +1 -0
- package/dist/react-ui/primitives/waapi/Reorder/useReorder.js +48 -0
- package/dist/react-ui/primitives/waapi/Reorder/useReorderPresence.d.ts +33 -0
- package/dist/react-ui/primitives/waapi/Reorder/useReorderPresence.d.ts.map +1 -0
- package/dist/react-ui/primitives/waapi/Reorder/useReorderPresence.js +137 -0
- package/dist/react-ui/primitives/waapi/Reorder/utils/separatorCoordination.d.ts +47 -0
- package/dist/react-ui/primitives/waapi/Reorder/utils/separatorCoordination.d.ts.map +1 -0
- package/dist/react-ui/primitives/waapi/Reorder/utils/separatorCoordination.js +72 -0
- package/dist/react-ui/primitives/waapi/SlidingNumber/SlidingNumber.styles.d.ts +10 -0
- package/dist/react-ui/primitives/waapi/SlidingNumber/SlidingNumber.styles.d.ts.map +1 -0
- package/dist/react-ui/primitives/waapi/SlidingNumber/SlidingNumber.types.d.ts +74 -0
- package/dist/react-ui/primitives/waapi/SlidingNumber/SlidingNumber.types.d.ts.map +1 -0
- package/dist/react-ui/primitives/waapi/SlidingNumber/index.d.ts +33 -0
- package/dist/react-ui/primitives/waapi/SlidingNumber/index.d.ts.map +1 -0
- package/dist/react-ui/primitives/waapi/SlidingNumber/index.js +354 -0
- package/dist/react-ui/primitives/waapi/SlidingText/SlidingText.styles.d.ts +25 -0
- package/dist/react-ui/primitives/waapi/SlidingText/SlidingText.styles.d.ts.map +1 -0
- package/dist/react-ui/primitives/waapi/SlidingText/SlidingText.types.d.ts +57 -0
- package/dist/react-ui/primitives/waapi/SlidingText/SlidingText.types.d.ts.map +1 -0
- package/dist/react-ui/primitives/waapi/SlidingText/index.d.ts +26 -0
- package/dist/react-ui/primitives/waapi/SlidingText/index.d.ts.map +1 -0
- package/dist/react-ui/primitives/waapi/SlidingText/index.js +105 -0
- package/dist/react-ui/primitives/waapi/core/animationConstants.d.ts +156 -0
- package/dist/react-ui/primitives/waapi/core/animationConstants.d.ts.map +1 -0
- package/dist/react-ui/primitives/waapi/core/animationConstants.js +180 -0
- package/dist/react-ui/primitives/waapi/core/index.d.ts +16 -0
- package/dist/react-ui/primitives/waapi/core/index.d.ts.map +1 -0
- package/dist/react-ui/primitives/waapi/core/index.js +5 -0
- package/dist/react-ui/primitives/waapi/core/types.d.ts +143 -0
- package/dist/react-ui/primitives/waapi/core/types.d.ts.map +1 -0
- package/dist/react-ui/primitives/waapi/core/useAnimationOrchestrator.d.ts +32 -0
- package/dist/react-ui/primitives/waapi/core/useAnimationOrchestrator.d.ts.map +1 -0
- package/dist/react-ui/primitives/waapi/core/useAnimationOrchestrator.js +322 -0
- package/dist/react-ui/primitives/waapi/core/useElementRegistry.d.ts +21 -0
- package/dist/react-ui/primitives/waapi/core/useElementRegistry.d.ts.map +1 -0
- package/dist/react-ui/primitives/waapi/core/useElementRegistry.js +65 -0
- package/dist/react-ui/primitives/waapi/core/useFLIPAnimation.d.ts +20 -0
- package/dist/react-ui/primitives/waapi/core/useFLIPAnimation.d.ts.map +1 -0
- package/dist/react-ui/primitives/waapi/core/useFLIPAnimation.js +99 -0
- package/dist/react-ui/primitives/waapi/core/usePositionCapture.d.ts +24 -0
- package/dist/react-ui/primitives/waapi/core/usePositionCapture.d.ts.map +1 -0
- package/dist/react-ui/primitives/waapi/core/usePositionCapture.js +75 -0
- package/dist/react-ui/primitives/waapi/index.d.ts +33 -0
- package/dist/react-ui/primitives/waapi/index.d.ts.map +1 -0
- package/dist/react-ui/primitives/waapi/index.js +18 -0
- package/dist/react-ui/ui/Accordion/index.js +3 -3
- package/dist/react-ui/ui/Button/index.js +8 -8
- package/dist/react-ui/ui/Combobox/index.js +2 -2
- package/dist/react-ui/ui/DataCard/DataCard.styles.d.ts +35 -0
- package/dist/react-ui/ui/DataCard/DataCard.styles.d.ts.map +1 -0
- package/dist/react-ui/ui/DataCard/DataCard.styles.js +114 -0
- package/dist/react-ui/ui/DataCard/DataCard.types.d.ts +135 -0
- package/dist/react-ui/ui/DataCard/DataCard.types.d.ts.map +1 -0
- package/dist/react-ui/ui/DataCard/index.d.ts +129 -0
- package/dist/react-ui/ui/DataCard/index.d.ts.map +1 -0
- package/dist/react-ui/ui/DataCard/index.js +276 -0
- package/dist/react-ui/ui/Menu/index.js +2 -2
- package/dist/react-ui/ui/Switch/index.js +3 -3
- package/dist/react-ui/ui/Tabs/index.js +3 -3
- package/dist/react-ui/ui/TextFlow/TextFlow.styles.d.ts +16 -0
- package/dist/react-ui/ui/TextFlow/TextFlow.styles.d.ts.map +1 -0
- package/dist/react-ui/ui/TextFlow/TextFlow.types.d.ts +101 -0
- package/dist/react-ui/ui/TextFlow/TextFlow.types.d.ts.map +1 -0
- package/dist/react-ui/ui/TextFlow/index.d.ts +26 -0
- package/dist/react-ui/ui/TextFlow/index.d.ts.map +1 -0
- package/dist/react-ui/ui/TextFlow/index.js +187 -0
- package/dist/react-ui/ui/index.d.ts +2 -0
- package/dist/react-ui/ui/index.d.ts.map +1 -1
- package/dist/react-ui/ui/index.js +3 -0
- package/package.json +6 -2
- package/src/react-ui/hooks/Formatting/UseListFormat.ts +134 -0
- package/src/react-ui/hooks/index.ts +3 -0
- package/src/react-ui/primitives/index.ts +3 -0
- package/src/react-ui/primitives/waapi/Morph/Morph.types.ts +106 -0
- package/src/react-ui/primitives/waapi/Morph/MorphContext.tsx +21 -0
- package/src/react-ui/primitives/waapi/Morph/index.tsx +56 -0
- package/src/react-ui/primitives/waapi/Morph/techniques/index.ts +12 -0
- package/src/react-ui/primitives/waapi/Morph/techniques/useCSSGridMorph.ts +88 -0
- package/src/react-ui/primitives/waapi/Morph/techniques/useFLIPClipPath.ts +175 -0
- package/src/react-ui/primitives/waapi/Morph/techniques/useViewTransitions.ts +86 -0
- package/src/react-ui/primitives/waapi/Morph/useMorph.ts +100 -0
- package/src/react-ui/primitives/waapi/Reorder/Reorder.types.ts +177 -0
- package/src/react-ui/primitives/waapi/Reorder/index.tsx +260 -0
- package/src/react-ui/primitives/waapi/Reorder/useReorder.ts +46 -0
- package/src/react-ui/primitives/waapi/Reorder/useReorderPresence.ts +208 -0
- package/src/react-ui/primitives/waapi/Reorder/utils/separatorCoordination.ts +104 -0
- package/src/react-ui/primitives/waapi/SlidingNumber/SlidingNumber.styles.ts +14 -0
- package/src/react-ui/primitives/waapi/SlidingNumber/SlidingNumber.types.ts +84 -0
- package/src/react-ui/primitives/waapi/SlidingNumber/index.tsx +474 -0
- package/src/react-ui/primitives/waapi/SlidingText/SlidingText.styles.ts +32 -0
- package/src/react-ui/primitives/waapi/SlidingText/SlidingText.types.ts +69 -0
- package/src/react-ui/primitives/waapi/SlidingText/index.tsx +140 -0
- package/src/react-ui/primitives/waapi/core/animationConstants.ts +215 -0
- package/src/react-ui/primitives/waapi/core/index.ts +53 -0
- package/src/react-ui/primitives/waapi/core/types.ts +200 -0
- package/src/react-ui/primitives/waapi/core/useAnimationOrchestrator.ts +429 -0
- package/src/react-ui/primitives/waapi/core/useElementRegistry.ts +80 -0
- package/src/react-ui/primitives/waapi/core/useFLIPAnimation.ts +137 -0
- package/src/react-ui/primitives/waapi/core/usePositionCapture.ts +105 -0
- package/src/react-ui/primitives/waapi/index.ts +116 -0
- package/src/react-ui/styles/animations.css +369 -0
- package/src/react-ui/ui/DataCard/DataCard.styles.ts +150 -0
- package/src/react-ui/ui/DataCard/DataCard.types.ts +146 -0
- package/src/react-ui/ui/DataCard/index.tsx +406 -0
- package/src/react-ui/ui/TextFlow/TextFlow.styles.ts +36 -0
- package/src/react-ui/ui/TextFlow/TextFlow.types.ts +118 -0
- package/src/react-ui/ui/TextFlow/index.tsx +276 -0
- package/src/react-ui/ui/index.ts +4 -0
- /package/dist/react-ui/components/MorphingPopover/{morphing-popover.module-CgbYV_HS.css → morphing-popover.module-BycNI8nU.css} +0 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { cva } from 'class-variance-authority';
|
|
2
|
+
import type { StyleSlots } from '@/core/types';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Visual regions for: DataCard component family.
|
|
6
|
+
* Each slot maps to: customizable visual region.
|
|
7
|
+
*/
|
|
8
|
+
export type DataCardSlot =
|
|
9
|
+
| 'root' // Main card container
|
|
10
|
+
| 'bracket' // Corner bracket decoration
|
|
11
|
+
| 'header' // Top section with title/description
|
|
12
|
+
| 'value' // Animated number display
|
|
13
|
+
| 'label' // Text labels
|
|
14
|
+
| 'toggle' // Switch/checkbox control
|
|
15
|
+
| 'actions' // Action buttons container
|
|
16
|
+
| 'footer'; // Bottom section
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Base style slots for: DataCard.
|
|
20
|
+
* Uses glassmorphism pattern from: Synthwave Dark design system.
|
|
21
|
+
*/
|
|
22
|
+
export const dataCardStyles: StyleSlots<DataCardSlot> = {
|
|
23
|
+
root: 'group/data-card relative isolate rounded-xl transition-all duration-300',
|
|
24
|
+
|
|
25
|
+
bracket: 'absolute pointer-events-none transition-opacity duration-300',
|
|
26
|
+
|
|
27
|
+
header: 'flex flex-col gap-1.5 px-5 pt-5 pb-2',
|
|
28
|
+
|
|
29
|
+
value: 'flex items-baseline gap-1 tabular-nums tracking-tight',
|
|
30
|
+
|
|
31
|
+
label: 'text-sm font-medium',
|
|
32
|
+
|
|
33
|
+
toggle: 'flex items-center justify-between gap-3',
|
|
34
|
+
|
|
35
|
+
actions: 'flex items-center gap-2',
|
|
36
|
+
|
|
37
|
+
footer: 'mt-auto px-5 pb-4 pt-2',
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* CVA variants for: DataCard root.
|
|
42
|
+
* Combines glassmorphism with Synthwave Dark color scheme.
|
|
43
|
+
*/
|
|
44
|
+
export const dataCardVariants = cva(dataCardStyles.root, {
|
|
45
|
+
variants: {
|
|
46
|
+
// Size variants - control padding and spacing
|
|
47
|
+
size: {
|
|
48
|
+
compact: {
|
|
49
|
+
root: 'p-3',
|
|
50
|
+
header: 'gap-1 px-3 pt-3 pb-1.5',
|
|
51
|
+
footer: 'px-3 pb-1.5 pt-1',
|
|
52
|
+
},
|
|
53
|
+
default: {
|
|
54
|
+
root: 'p-4',
|
|
55
|
+
header: 'gap-1.5 px-4 pt-4 pb-2',
|
|
56
|
+
footer: 'px-4 pb-2 pt-2',
|
|
57
|
+
},
|
|
58
|
+
spacious: {
|
|
59
|
+
root: 'p-6',
|
|
60
|
+
header: 'gap-2 px-6 pt-6 pb-3',
|
|
61
|
+
footer: 'px-6 pb-3 pt-2',
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
|
|
65
|
+
// Visual variants - control colors and borders
|
|
66
|
+
variant: {
|
|
67
|
+
default: [
|
|
68
|
+
'bg-white/5',
|
|
69
|
+
'backdrop-blur-lg',
|
|
70
|
+
'border border-white/10',
|
|
71
|
+
'hover:bg-white/10',
|
|
72
|
+
'shadow-lg shadow-black/20',
|
|
73
|
+
].join(' '),
|
|
74
|
+
|
|
75
|
+
accent: [
|
|
76
|
+
'bg-cyan-500/10',
|
|
77
|
+
'backdrop-blur-lg',
|
|
78
|
+
'border border-cyan-400/30',
|
|
79
|
+
'hover:bg-cyan-500/20',
|
|
80
|
+
'shadow-cyan-500/20 shadow-lg',
|
|
81
|
+
].join(' '),
|
|
82
|
+
|
|
83
|
+
success: [
|
|
84
|
+
'bg-emerald-500/10',
|
|
85
|
+
'backdrop-blur-lg',
|
|
86
|
+
'border border-emerald-400/30',
|
|
87
|
+
'hover:bg-emerald-500/20',
|
|
88
|
+
'shadow-emerald-500/20 shadow-lg',
|
|
89
|
+
].join(' '),
|
|
90
|
+
|
|
91
|
+
warning: [
|
|
92
|
+
'bg-amber-500/10',
|
|
93
|
+
'backdrop-blur-lg',
|
|
94
|
+
'border border-amber-400/30',
|
|
95
|
+
'hover:bg-amber-500/20',
|
|
96
|
+
'shadow-amber-500/20 shadow-lg',
|
|
97
|
+
].join(' '),
|
|
98
|
+
|
|
99
|
+
destructive: [
|
|
100
|
+
'bg-red-500/10',
|
|
101
|
+
'backdrop-blur-lg',
|
|
102
|
+
'border border-red-400/30',
|
|
103
|
+
'hover:bg-red-500/20',
|
|
104
|
+
'shadow-red-500/20 shadow-lg',
|
|
105
|
+
].join(' '),
|
|
106
|
+
},
|
|
107
|
+
|
|
108
|
+
// Glass effect toggle
|
|
109
|
+
glass: {
|
|
110
|
+
true: [
|
|
111
|
+
'backdrop-blur-lg',
|
|
112
|
+
'bg-white/10',
|
|
113
|
+
'border border-white/20',
|
|
114
|
+
'shadow-xl',
|
|
115
|
+
].join(' '),
|
|
116
|
+
false: '',
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
|
|
120
|
+
defaultVariants: {
|
|
121
|
+
variant: 'default',
|
|
122
|
+
size: 'default',
|
|
123
|
+
glass: true,
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* CVA variants for bracket visibility animation.
|
|
129
|
+
*/
|
|
130
|
+
export const bracketVariants = cva(dataCardStyles.bracket, {
|
|
131
|
+
variants: {
|
|
132
|
+
animate: {
|
|
133
|
+
true: 'opacity-60 group-hover/data-card:opacity-100 transition-opacity',
|
|
134
|
+
false: 'opacity-50',
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
defaultVariants: {
|
|
138
|
+
animate: true,
|
|
139
|
+
},
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* State-specific styles for DataCard interactions.
|
|
144
|
+
*/
|
|
145
|
+
export const dataCardStateStyles = {
|
|
146
|
+
hovered: 'scale-[1.02]',
|
|
147
|
+
pressed: 'scale-[0.98]',
|
|
148
|
+
disabled: 'opacity-50 pointer-events-none',
|
|
149
|
+
};
|
|
150
|
+
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import type { VariantProps } from 'class-variance-authority';
|
|
2
|
+
import type { SlotOverrides } from '@/core/types';
|
|
3
|
+
import type { dataCardVariants, DataCardSlot } from './DataCard.styles';
|
|
4
|
+
export type { DataCardSlot } from './DataCard.styles';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Available visual variants for DataCard.
|
|
8
|
+
* - 'default' - Standard glassmorphism with neutral borders
|
|
9
|
+
* - 'accent' - Cyan accent with primary glow
|
|
10
|
+
* - 'success' - Green accent for positive data
|
|
11
|
+
* - 'warning' - Amber accent for warnings
|
|
12
|
+
* - 'destructive' - Red accent for critical data
|
|
13
|
+
*/
|
|
14
|
+
export type DataCardVariant = 'default' | 'accent' | 'success' | 'warning' | 'destructive';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Size variants affecting padding and spacing.
|
|
18
|
+
* - 'compact' - Dense layout for dashboards
|
|
19
|
+
* - 'default' - Standard balanced spacing
|
|
20
|
+
* - 'spacious' - More breathing room
|
|
21
|
+
*/
|
|
22
|
+
export type DataCardSize = 'compact' | 'default' | 'spacious';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Interaction state for state-based styling.
|
|
26
|
+
* Similar to Button's IButtonState pattern.
|
|
27
|
+
*/
|
|
28
|
+
export interface IDataCardState {
|
|
29
|
+
/** Whether card content is hovered. */
|
|
30
|
+
hovered: boolean;
|
|
31
|
+
/** Whether card is pressed/active. */
|
|
32
|
+
pressed: boolean;
|
|
33
|
+
/** Whether card is disabled. */
|
|
34
|
+
disabled: boolean;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Configuration for DataCard behavior and animation.
|
|
39
|
+
* Extends IBaseConfig with card-specific settings.
|
|
40
|
+
*/
|
|
41
|
+
export interface IDataCardConfig {
|
|
42
|
+
/** Enable/disable corner bracket animations. */
|
|
43
|
+
animateBrackets?: boolean;
|
|
44
|
+
/** Spring stiffness for number counter. */
|
|
45
|
+
counterStiffness?: number;
|
|
46
|
+
/** Spring damping for number counter. */
|
|
47
|
+
counterDamping?: number;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Props for DataCard root component.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```tsx
|
|
55
|
+
* <DataCard variant="accent" size="default">
|
|
56
|
+
* <DataCardValue number={1234} />
|
|
57
|
+
* <DataCardToggle />
|
|
58
|
+
* </DataCard>
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
export interface IDataCardProps
|
|
62
|
+
extends VariantProps<typeof dataCardVariants> {
|
|
63
|
+
/** Visual style variant. */
|
|
64
|
+
variant?: DataCardVariant;
|
|
65
|
+
/** Size variant affecting spacing. */
|
|
66
|
+
size?: DataCardSize;
|
|
67
|
+
/** Whether card is disabled. */
|
|
68
|
+
disabled?: boolean;
|
|
69
|
+
/** Override classes for card visual regions. */
|
|
70
|
+
slots?: SlotOverrides<DataCardSlot>;
|
|
71
|
+
/** Behavioral and animation configuration. */
|
|
72
|
+
config?: IDataCardConfig;
|
|
73
|
+
/** CSS class or function returning class based on card state. */
|
|
74
|
+
className?: string | ((state: IDataCardState) => string | undefined);
|
|
75
|
+
/** CSS styles or function returning styles based on card state. */
|
|
76
|
+
style?: React.CSSProperties | ((state: IDataCardState) => React.CSSProperties | undefined);
|
|
77
|
+
/** Enable glassmorphism effect (default: true). */
|
|
78
|
+
glass?: boolean;
|
|
79
|
+
/** Show corner brackets (default: true). */
|
|
80
|
+
showBrackets?: boolean;
|
|
81
|
+
/** Child elements. */
|
|
82
|
+
children?: React.ReactNode;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Props for DataCardValue - displays animated number.
|
|
87
|
+
*/
|
|
88
|
+
export interface IDataCardValueProps {
|
|
89
|
+
/** Target number to animate to. */
|
|
90
|
+
number: number;
|
|
91
|
+
/** Label displayed above: number. */
|
|
92
|
+
label?: string;
|
|
93
|
+
/** Unit/suffix displayed after: number. */
|
|
94
|
+
unit?: string;
|
|
95
|
+
/** Decimal places for precision. */
|
|
96
|
+
decimalPlaces?: number;
|
|
97
|
+
/** Pad number with leading zeros. */
|
|
98
|
+
padStart?: boolean;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Props for DataCardLabel - title/description text.
|
|
103
|
+
*/
|
|
104
|
+
export interface IDataCardLabelProps extends React.ComponentProps<'div'> {
|
|
105
|
+
/** Primary title text. */
|
|
106
|
+
title?: string;
|
|
107
|
+
/** Secondary description text. */
|
|
108
|
+
description?: string;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Props for DataCardToggle - interactive switch element.
|
|
113
|
+
*/
|
|
114
|
+
export interface IDataCardToggleProps {
|
|
115
|
+
/** Whether toggle is checked. */
|
|
116
|
+
checked?: boolean;
|
|
117
|
+
/** Callback when toggle state changes. */
|
|
118
|
+
onCheckedChange?: (checked: boolean) => void;
|
|
119
|
+
/** Icon to show when checked (on). */
|
|
120
|
+
checkedIcon?: React.ReactNode;
|
|
121
|
+
/** Icon to show when unchecked (off). */
|
|
122
|
+
uncheckedIcon?: React.ReactNode;
|
|
123
|
+
/** Label for: toggle. */
|
|
124
|
+
label?: string;
|
|
125
|
+
/** Override classes for toggle regions. */
|
|
126
|
+
slots?: SlotOverrides<DataCardSlot>;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Props for DataCardActions - action button container.
|
|
131
|
+
*/
|
|
132
|
+
export interface IDataCardActionsProps extends React.ComponentProps<'div'> {
|
|
133
|
+
/** Alignment of action buttons. */
|
|
134
|
+
align?: 'start' | 'center' | 'end';
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Props for DataCardBracket - decorative corner element.
|
|
139
|
+
*/
|
|
140
|
+
export interface IDataCardBracketProps extends React.ComponentProps<'div'> {
|
|
141
|
+
/** Position of: bracket. */
|
|
142
|
+
position: 'tl' | 'tr' | 'bl' | 'br';
|
|
143
|
+
/** Optional variant override for: this bracket. */
|
|
144
|
+
variant?: 'default' | 'accent';
|
|
145
|
+
}
|
|
146
|
+
|
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { motion, useMotionValue, useSpring } from 'motion/react';
|
|
5
|
+
import { cn } from '@/react-ui/lib/utils';
|
|
6
|
+
import { getStrictContext } from '@/react-ui/lib/get-strict-context';
|
|
7
|
+
import { useControlledState } from '@/react-ui/hooks/State/UseControlledState';
|
|
8
|
+
|
|
9
|
+
// Import from existing components
|
|
10
|
+
import { CornerBracket } from '@/react-ui/ui/CornerBracket';
|
|
11
|
+
import { CountingNumber } from '@/react-ui/primitives/CountingNumber';
|
|
12
|
+
import { Switch, SwitchThumb } from '@/react-ui/ui/Switch';
|
|
13
|
+
|
|
14
|
+
import { dataCardVariants, dataCardStyles, bracketVariants, dataCardStateStyles } from './DataCard.styles';
|
|
15
|
+
import type { SlotOverrides } from '@/core/types';
|
|
16
|
+
import type {
|
|
17
|
+
IDataCardProps,
|
|
18
|
+
IDataCardValueProps,
|
|
19
|
+
IDataCardLabelProps,
|
|
20
|
+
IDataCardToggleProps,
|
|
21
|
+
IDataCardActionsProps,
|
|
22
|
+
IDataCardBracketProps,
|
|
23
|
+
IDataCardState,
|
|
24
|
+
DataCardSlot,
|
|
25
|
+
} from './DataCard.types';
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Context type for DataCard state management.
|
|
29
|
+
*/
|
|
30
|
+
type DataCardContextType = {
|
|
31
|
+
/** Current variant of: card. */
|
|
32
|
+
variant: IDataCardProps['variant'];
|
|
33
|
+
/** Current size of: card. */
|
|
34
|
+
size: IDataCardProps['size'];
|
|
35
|
+
/** Whether card is disabled. */
|
|
36
|
+
disabled: boolean;
|
|
37
|
+
/** Whether glass effect is enabled. */
|
|
38
|
+
glass: boolean;
|
|
39
|
+
/** Slot overrides from parent. */
|
|
40
|
+
slots?: SlotOverrides<DataCardSlot>;
|
|
41
|
+
/** Update interaction state. */
|
|
42
|
+
setState: React.Dispatch<React.SetStateAction<IDataCardState>>;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const [DataCardProvider, useDataCard] =
|
|
46
|
+
getStrictContext<DataCardContextType>('DataCardContext');
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* DataCard — comprehensive showcase component demonstrating mks-ui patterns.
|
|
50
|
+
*
|
|
51
|
+
* Features:
|
|
52
|
+
* - Slot overrides for customization
|
|
53
|
+
* - State-based styling (hover, pressed, disabled)
|
|
54
|
+
* - CVA variants (size, color variant)
|
|
55
|
+
* - asChild composition pattern
|
|
56
|
+
* - Motion/animation integration
|
|
57
|
+
* - Custom render functions
|
|
58
|
+
* - Form field integration
|
|
59
|
+
* - Icon composition
|
|
60
|
+
* - Glassmorphism effects
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```tsx
|
|
64
|
+
* <DataCard variant="accent" size="default">
|
|
65
|
+
* <DataCardValue number={1234} />
|
|
66
|
+
* <DataCardToggle />
|
|
67
|
+
* </DataCard>
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
function DataCard({
|
|
71
|
+
variant = 'default',
|
|
72
|
+
size = 'default',
|
|
73
|
+
disabled = false,
|
|
74
|
+
glass = true,
|
|
75
|
+
showBrackets = true,
|
|
76
|
+
className,
|
|
77
|
+
style,
|
|
78
|
+
slots,
|
|
79
|
+
config,
|
|
80
|
+
children,
|
|
81
|
+
...props
|
|
82
|
+
}: IDataCardProps) {
|
|
83
|
+
const [state, setState] = React.useState<IDataCardState>({
|
|
84
|
+
hovered: false,
|
|
85
|
+
pressed: false,
|
|
86
|
+
disabled: disabled ?? false,
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
const contextValue: DataCardContextType = React.useMemo(
|
|
90
|
+
() => ({ variant, size, disabled: disabled ?? false, glass, slots, setState }),
|
|
91
|
+
[variant, size, disabled, glass, slots]
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
const computedClassName = React.useMemo(() => {
|
|
95
|
+
if (typeof className === 'function') {
|
|
96
|
+
return className(state);
|
|
97
|
+
}
|
|
98
|
+
return className;
|
|
99
|
+
}, [className, state]);
|
|
100
|
+
|
|
101
|
+
const computedStyle = React.useMemo(() => {
|
|
102
|
+
if (typeof style === 'function') {
|
|
103
|
+
return style(state);
|
|
104
|
+
}
|
|
105
|
+
return style;
|
|
106
|
+
}, [style, state]);
|
|
107
|
+
|
|
108
|
+
return (
|
|
109
|
+
<DataCardProvider value={contextValue}>
|
|
110
|
+
<motion.div
|
|
111
|
+
data-slot="data-card"
|
|
112
|
+
data-variant={variant}
|
|
113
|
+
data-size={size}
|
|
114
|
+
data-disabled={disabled || undefined}
|
|
115
|
+
aria-disabled={disabled || undefined}
|
|
116
|
+
className={cn(
|
|
117
|
+
dataCardVariants({ variant, size, glass }),
|
|
118
|
+
slots?.root,
|
|
119
|
+
computedClassName,
|
|
120
|
+
state.hovered && dataCardStateStyles.hovered,
|
|
121
|
+
state.pressed && dataCardStateStyles.pressed,
|
|
122
|
+
disabled && dataCardStateStyles.disabled
|
|
123
|
+
)}
|
|
124
|
+
style={computedStyle}
|
|
125
|
+
onHoverStart={() => setState((prev) => ({ ...prev, hovered: true }))}
|
|
126
|
+
onHoverEnd={() => setState((prev) => ({ ...prev, hovered: false }))}
|
|
127
|
+
onTapStart={() => setState((prev) => ({ ...prev, pressed: true }))}
|
|
128
|
+
onTap={() => setState((prev) => ({ ...prev, pressed: false }))}
|
|
129
|
+
onTapCancel={() => setState((prev) => ({ ...prev, pressed: false }))}
|
|
130
|
+
{...props}
|
|
131
|
+
>
|
|
132
|
+
{showBrackets && (
|
|
133
|
+
<>
|
|
134
|
+
<DataCardBracket
|
|
135
|
+
position="tl"
|
|
136
|
+
variant={variant === 'accent' ? 'accent' : 'default'}
|
|
137
|
+
/>
|
|
138
|
+
<DataCardBracket
|
|
139
|
+
position="tr"
|
|
140
|
+
variant={variant === 'accent' ? 'accent' : 'default'}
|
|
141
|
+
/>
|
|
142
|
+
<DataCardBracket
|
|
143
|
+
position="bl"
|
|
144
|
+
variant={variant === 'accent' ? 'accent' : 'default'}
|
|
145
|
+
/>
|
|
146
|
+
<DataCardBracket
|
|
147
|
+
position="br"
|
|
148
|
+
variant={variant === 'accent' ? 'accent' : 'default'}
|
|
149
|
+
/>
|
|
150
|
+
</>
|
|
151
|
+
)}
|
|
152
|
+
{children}
|
|
153
|
+
</motion.div>
|
|
154
|
+
</DataCardProvider>
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* DataCardValue — displays animated number with CountingNumber.
|
|
160
|
+
*
|
|
161
|
+
* @example
|
|
162
|
+
* ```tsx
|
|
163
|
+
* <DataCardValue
|
|
164
|
+
* number={1234}
|
|
165
|
+
* label="Active Users"
|
|
166
|
+
* unit="users"
|
|
167
|
+
* />
|
|
168
|
+
* ```
|
|
169
|
+
*/
|
|
170
|
+
function DataCardValue({
|
|
171
|
+
number,
|
|
172
|
+
label,
|
|
173
|
+
unit,
|
|
174
|
+
decimalPlaces = 0,
|
|
175
|
+
padStart = false,
|
|
176
|
+
}: IDataCardValueProps) {
|
|
177
|
+
const { variant, size } = useDataCard();
|
|
178
|
+
|
|
179
|
+
return (
|
|
180
|
+
<div data-slot="data-card-value" className={cn(dataCardStyles.value)}>
|
|
181
|
+
{label && (
|
|
182
|
+
<span className="text-muted-foreground text-xs uppercase tracking-wider font-mono">
|
|
183
|
+
{label}
|
|
184
|
+
</span>
|
|
185
|
+
)}
|
|
186
|
+
<CountingNumber
|
|
187
|
+
number={number}
|
|
188
|
+
decimalPlaces={decimalPlaces}
|
|
189
|
+
padStart={padStart}
|
|
190
|
+
transition={{
|
|
191
|
+
stiffness: variant === 'accent' ? 150 : 90,
|
|
192
|
+
damping: variant === 'accent' ? 20 : 10,
|
|
193
|
+
}}
|
|
194
|
+
className={
|
|
195
|
+
size === 'compact'
|
|
196
|
+
? 'text-3xl font-bold'
|
|
197
|
+
: size === 'spacious'
|
|
198
|
+
? 'text-5xl font-bold'
|
|
199
|
+
: 'text-4xl font-bold'
|
|
200
|
+
}
|
|
201
|
+
/>
|
|
202
|
+
{unit && (
|
|
203
|
+
<span className="text-muted-foreground text-lg ml-1">{unit}</span>
|
|
204
|
+
)}
|
|
205
|
+
</div>
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* DataCardLabel — displays title and description.
|
|
211
|
+
*
|
|
212
|
+
* @example
|
|
213
|
+
* ```tsx
|
|
214
|
+
* <DataCardLabel
|
|
215
|
+
* title="Revenue"
|
|
216
|
+
* description="This month"
|
|
217
|
+
* />
|
|
218
|
+
* ```
|
|
219
|
+
*/
|
|
220
|
+
function DataCardLabel({
|
|
221
|
+
title,
|
|
222
|
+
description,
|
|
223
|
+
className,
|
|
224
|
+
...props
|
|
225
|
+
}: IDataCardLabelProps) {
|
|
226
|
+
const { slots } = useDataCard();
|
|
227
|
+
|
|
228
|
+
return (
|
|
229
|
+
<div
|
|
230
|
+
data-slot="data-card-label"
|
|
231
|
+
className={cn(
|
|
232
|
+
dataCardStyles.label,
|
|
233
|
+
slots?.label,
|
|
234
|
+
className
|
|
235
|
+
)}
|
|
236
|
+
{...props}
|
|
237
|
+
>
|
|
238
|
+
{title && (
|
|
239
|
+
<h3 className="text-foreground font-semibold">{title}</h3>
|
|
240
|
+
)}
|
|
241
|
+
{description && (
|
|
242
|
+
<p className="text-muted-foreground text-sm">{description}</p>
|
|
243
|
+
)}
|
|
244
|
+
</div>
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* DataCardToggle — interactive switch element.
|
|
250
|
+
*
|
|
251
|
+
* Uses asChild pattern for composition with Switch component.
|
|
252
|
+
*
|
|
253
|
+
* @example
|
|
254
|
+
* ```tsx
|
|
255
|
+
* <DataCardToggle
|
|
256
|
+
* checked={enabled}
|
|
257
|
+
* onCheckedChange={setEnabled}
|
|
258
|
+
* label="Enable notifications"
|
|
259
|
+
* checkedIcon={<BellIcon />}
|
|
260
|
+
* uncheckedIcon={<BellOffIcon />}
|
|
261
|
+
* />
|
|
262
|
+
* ```
|
|
263
|
+
*/
|
|
264
|
+
function DataCardToggle({
|
|
265
|
+
checked,
|
|
266
|
+
onCheckedChange,
|
|
267
|
+
checkedIcon,
|
|
268
|
+
uncheckedIcon,
|
|
269
|
+
label,
|
|
270
|
+
}: IDataCardToggleProps) {
|
|
271
|
+
const { disabled, variant, size, glass, slots } = useDataCard();
|
|
272
|
+
|
|
273
|
+
return (
|
|
274
|
+
<div data-slot="data-card-toggle" className={cn(dataCardStyles.toggle, slots?.toggle)}>
|
|
275
|
+
{label && <span className="text-sm text-muted-foreground">{label}</span>}
|
|
276
|
+
<Switch
|
|
277
|
+
checked={checked}
|
|
278
|
+
onCheckedChange={onCheckedChange}
|
|
279
|
+
disabled={disabled}
|
|
280
|
+
>
|
|
281
|
+
<SwitchThumb />
|
|
282
|
+
{checkedIcon && (
|
|
283
|
+
<div className="text-primary">{checkedIcon}</div>
|
|
284
|
+
)}
|
|
285
|
+
{!checkedIcon && (
|
|
286
|
+
<div className="text-muted-foreground">{uncheckedIcon}</div>
|
|
287
|
+
)}
|
|
288
|
+
</Switch>
|
|
289
|
+
</div>
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* DataCardActions — container for action buttons.
|
|
295
|
+
*
|
|
296
|
+
* @example
|
|
297
|
+
* ```tsx
|
|
298
|
+
* <DataCardActions align="end">
|
|
299
|
+
* <Button size="sm">Edit</Button>
|
|
300
|
+
* <Button size="sm" variant="ghost">Delete</Button>
|
|
301
|
+
* </DataCardActions>
|
|
302
|
+
* ```
|
|
303
|
+
*/
|
|
304
|
+
function DataCardActions({
|
|
305
|
+
align = 'end',
|
|
306
|
+
className,
|
|
307
|
+
children,
|
|
308
|
+
...props
|
|
309
|
+
}: IDataCardActionsProps) {
|
|
310
|
+
const { variant, size, glass, slots } = useDataCard();
|
|
311
|
+
|
|
312
|
+
return (
|
|
313
|
+
<div
|
|
314
|
+
data-slot="data-card-actions"
|
|
315
|
+
data-align={align}
|
|
316
|
+
className={cn(
|
|
317
|
+
dataCardStyles.actions,
|
|
318
|
+
align === 'center' && 'justify-center',
|
|
319
|
+
align === 'start' && 'justify-start',
|
|
320
|
+
align === 'end' && 'justify-end',
|
|
321
|
+
slots?.actions,
|
|
322
|
+
className
|
|
323
|
+
)}
|
|
324
|
+
{...props}
|
|
325
|
+
>
|
|
326
|
+
{children}
|
|
327
|
+
</div>
|
|
328
|
+
);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* DataCardBracket — decorative corner bracket.
|
|
333
|
+
*
|
|
334
|
+
* Wraps CornerBracket with motion animations.
|
|
335
|
+
*
|
|
336
|
+
* @example
|
|
337
|
+
* ```tsx
|
|
338
|
+
* <DataCardBracket position="tl" variant="accent" />
|
|
339
|
+
* ```
|
|
340
|
+
*/
|
|
341
|
+
function DataCardBracket({
|
|
342
|
+
position,
|
|
343
|
+
variant = 'default',
|
|
344
|
+
className,
|
|
345
|
+
}: IDataCardBracketProps) {
|
|
346
|
+
const { size, glass, slots } = useDataCard();
|
|
347
|
+
|
|
348
|
+
const sizeMap = {
|
|
349
|
+
compact: 16,
|
|
350
|
+
default: 20,
|
|
351
|
+
spacious: 24,
|
|
352
|
+
} as const;
|
|
353
|
+
|
|
354
|
+
return (
|
|
355
|
+
<div className={cn(dataCardStyles.bracket, slots?.bracket, className)}>
|
|
356
|
+
<CornerBracket
|
|
357
|
+
position={position}
|
|
358
|
+
variant={variant}
|
|
359
|
+
size={sizeMap[size ?? 'default']}
|
|
360
|
+
/>
|
|
361
|
+
</div>
|
|
362
|
+
);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* Hook to access DataCard context.
|
|
367
|
+
* Must be used within DataCard provider.
|
|
368
|
+
*
|
|
369
|
+
* @returns The current DataCard context
|
|
370
|
+
*
|
|
371
|
+
* @example
|
|
372
|
+
* ```tsx
|
|
373
|
+
* function MyComponent() {
|
|
374
|
+
* const { variant, size, disabled } = useDataCard();
|
|
375
|
+
* return <div>Current variant: {variant}</div>;
|
|
376
|
+
* }
|
|
377
|
+
* ```
|
|
378
|
+
*/
|
|
379
|
+
export { useDataCard };
|
|
380
|
+
|
|
381
|
+
export {
|
|
382
|
+
DataCard,
|
|
383
|
+
DataCardValue,
|
|
384
|
+
DataCardLabel,
|
|
385
|
+
DataCardToggle,
|
|
386
|
+
DataCardActions,
|
|
387
|
+
DataCardBracket,
|
|
388
|
+
dataCardVariants,
|
|
389
|
+
};
|
|
390
|
+
|
|
391
|
+
// Re-export types
|
|
392
|
+
export type {
|
|
393
|
+
IDataCardProps,
|
|
394
|
+
IDataCardValueProps,
|
|
395
|
+
IDataCardLabelProps,
|
|
396
|
+
IDataCardToggleProps,
|
|
397
|
+
IDataCardActionsProps,
|
|
398
|
+
IDataCardBracketProps,
|
|
399
|
+
IDataCardState,
|
|
400
|
+
IDataCardConfig,
|
|
401
|
+
DataCardVariant,
|
|
402
|
+
DataCardSize,
|
|
403
|
+
DataCardSlot,
|
|
404
|
+
} from './DataCard.types';
|
|
405
|
+
|
|
406
|
+
export { dataCardStyles } from './DataCard.styles';
|