@syscore/ui-library 1.25.0 → 2.0.0
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/client/components/ui/app-bar.tsx +299 -0
- package/client/components/ui/banner.tsx +108 -0
- package/client/components/ui/bottom-navigation.tsx +223 -0
- package/client/components/ui/card.tsx +108 -26
- package/client/components/ui/date-picker.tsx +188 -0
- package/client/components/ui/empty-state.tsx +197 -0
- package/client/components/ui/file-upload.tsx +214 -0
- package/client/components/ui/footer.tsx +179 -0
- package/client/components/ui/layout.tsx +381 -0
- package/client/components/ui/sidebar.tsx +11 -5
- package/client/components/ui/stepper.tsx +148 -0
- package/client/components/ui/system-bar.tsx +119 -0
- package/client/components/ui/timeline.tsx +181 -0
- package/client/global.css +2304 -41
- package/client/ui/AppBar/app-bar.stories.tsx +280 -0
- package/client/ui/Banner/banner.stories.tsx +238 -0
- package/client/ui/BottomNavigation/bottom-navigation.stories.tsx +285 -0
- package/client/ui/Card.stories.tsx +285 -168
- package/client/ui/DatePicker/DatePicker.stories.tsx +293 -0
- package/client/ui/EmptyState/empty-state.stories.tsx +251 -0
- package/client/ui/FileUpload/FileUpload.stories.tsx +218 -0
- package/client/ui/Footer/footer.stories.tsx +194 -0
- package/client/ui/Layout.stories.tsx +1481 -0
- package/client/ui/Stepper/Stepper.stories.tsx +344 -0
- package/client/ui/SystemBar/system-bar.stories.tsx +179 -0
- package/client/ui/Timeline/timeline.stories.tsx +404 -0
- package/dist/index.cjs.js +1 -1
- package/dist/index.d.ts +219 -0
- package/dist/index.es.js +1504 -99
- package/package.json +1 -1
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { cn } from "@/lib/utils";
|
|
3
|
+
|
|
4
|
+
// ─── Context ──────────────────────────────────────────────────────────────────
|
|
5
|
+
|
|
6
|
+
interface TimelineContextValue {
|
|
7
|
+
direction: "vertical" | "horizontal";
|
|
8
|
+
side: "start" | "end" | "alternate";
|
|
9
|
+
align: "center" | "start";
|
|
10
|
+
density: "default" | "compact";
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const TimelineContext = React.createContext<TimelineContextValue>({
|
|
14
|
+
direction: "vertical",
|
|
15
|
+
side: "alternate",
|
|
16
|
+
align: "center",
|
|
17
|
+
density: "default",
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
// ─── Timeline Root ────────────────────────────────────────────────────────────
|
|
21
|
+
|
|
22
|
+
export interface TimelineProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
23
|
+
/**
|
|
24
|
+
* Layout direction.
|
|
25
|
+
* - "vertical" → items stack top-to-bottom (default)
|
|
26
|
+
* - "horizontal" → items flow left-to-right
|
|
27
|
+
*/
|
|
28
|
+
direction?: "vertical" | "horizontal";
|
|
29
|
+
/**
|
|
30
|
+
* Which side content renders on relative to the stem.
|
|
31
|
+
* - "alternate" → alternates left / right (default)
|
|
32
|
+
* - "end" → all content on the right (vertical) or below (horizontal)
|
|
33
|
+
* - "start" → all content on the left (vertical) or above (horizontal)
|
|
34
|
+
*/
|
|
35
|
+
side?: "start" | "end" | "alternate";
|
|
36
|
+
/**
|
|
37
|
+
* Vertical alignment of content inside each item.
|
|
38
|
+
* - "center" → content is centered on the dot (default)
|
|
39
|
+
* - "start" → content aligns to the top of the dot
|
|
40
|
+
*/
|
|
41
|
+
align?: "center" | "start";
|
|
42
|
+
/**
|
|
43
|
+
* Reduces spacing between items.
|
|
44
|
+
*/
|
|
45
|
+
density?: "default" | "compact";
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const Timeline = React.forwardRef<HTMLDivElement, TimelineProps>(
|
|
49
|
+
(
|
|
50
|
+
{
|
|
51
|
+
className,
|
|
52
|
+
children,
|
|
53
|
+
direction = "vertical",
|
|
54
|
+
side = "alternate",
|
|
55
|
+
align = "center",
|
|
56
|
+
density = "default",
|
|
57
|
+
...props
|
|
58
|
+
},
|
|
59
|
+
ref
|
|
60
|
+
) => (
|
|
61
|
+
<TimelineContext.Provider value={{ direction, side, align, density }}>
|
|
62
|
+
<div
|
|
63
|
+
ref={ref}
|
|
64
|
+
className={cn(
|
|
65
|
+
"timeline",
|
|
66
|
+
direction === "horizontal" && "timeline--horizontal",
|
|
67
|
+
`timeline--side-${side}`,
|
|
68
|
+
`timeline--align-${align}`,
|
|
69
|
+
density === "compact" && "timeline--compact",
|
|
70
|
+
className
|
|
71
|
+
)}
|
|
72
|
+
{...props}
|
|
73
|
+
>
|
|
74
|
+
{children}
|
|
75
|
+
</div>
|
|
76
|
+
</TimelineContext.Provider>
|
|
77
|
+
)
|
|
78
|
+
);
|
|
79
|
+
Timeline.displayName = "Timeline";
|
|
80
|
+
|
|
81
|
+
// ─── TimelineItem ─────────────────────────────────────────────────────────────
|
|
82
|
+
|
|
83
|
+
export interface TimelineItemProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
84
|
+
/**
|
|
85
|
+
* Background color of the dot — any CSS color or var() token.
|
|
86
|
+
*/
|
|
87
|
+
dotColor?: string;
|
|
88
|
+
/**
|
|
89
|
+
* Size of the dot.
|
|
90
|
+
* - "x-small" → 12px
|
|
91
|
+
* - "small" → 16px (default)
|
|
92
|
+
* - "default" → 24px
|
|
93
|
+
* - "large" → 32px
|
|
94
|
+
* - "x-large" → 40px
|
|
95
|
+
*/
|
|
96
|
+
size?: "x-small" | "small" | "default" | "large" | "x-large";
|
|
97
|
+
/**
|
|
98
|
+
* When true the dot background is filled with `dotColor`
|
|
99
|
+
* (instead of just a border ring).
|
|
100
|
+
*/
|
|
101
|
+
fillDot?: boolean;
|
|
102
|
+
/**
|
|
103
|
+
* Completely hides the dot and stem connector.
|
|
104
|
+
*/
|
|
105
|
+
hideDot?: boolean;
|
|
106
|
+
/**
|
|
107
|
+
* Icon rendered inside the dot. Pass any React node.
|
|
108
|
+
* For best results use with size="large" or size="x-large".
|
|
109
|
+
*/
|
|
110
|
+
icon?: React.ReactNode;
|
|
111
|
+
/**
|
|
112
|
+
* Content rendered on the opposite side of the stem from the main content.
|
|
113
|
+
* Equivalent to Vuetify's v-slot:opposite.
|
|
114
|
+
*/
|
|
115
|
+
opposite?: React.ReactNode;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const TimelineItem = React.forwardRef<HTMLDivElement, TimelineItemProps>(
|
|
119
|
+
(
|
|
120
|
+
{
|
|
121
|
+
className,
|
|
122
|
+
children,
|
|
123
|
+
dotColor,
|
|
124
|
+
size = "small",
|
|
125
|
+
fillDot = false,
|
|
126
|
+
hideDot = false,
|
|
127
|
+
icon,
|
|
128
|
+
opposite,
|
|
129
|
+
...props
|
|
130
|
+
},
|
|
131
|
+
ref
|
|
132
|
+
) => {
|
|
133
|
+
const { align } = React.useContext(TimelineContext);
|
|
134
|
+
|
|
135
|
+
return (
|
|
136
|
+
<div
|
|
137
|
+
ref={ref}
|
|
138
|
+
className={cn(
|
|
139
|
+
"timeline-item",
|
|
140
|
+
`timeline-item--size-${size}`,
|
|
141
|
+
fillDot && "timeline-item--fill-dot",
|
|
142
|
+
hideDot && "timeline-item--hide-dot",
|
|
143
|
+
align === "start" && "timeline-item--align-start",
|
|
144
|
+
className
|
|
145
|
+
)}
|
|
146
|
+
{...props}
|
|
147
|
+
>
|
|
148
|
+
{/* Opposite slot */}
|
|
149
|
+
<div className="timeline-item-opposite">
|
|
150
|
+
{opposite}
|
|
151
|
+
</div>
|
|
152
|
+
|
|
153
|
+
{/* Stem + dot column */}
|
|
154
|
+
<div className="timeline-item-stem">
|
|
155
|
+
<div className="timeline-item-stem-line timeline-item-stem-line--before" />
|
|
156
|
+
{!hideDot && (
|
|
157
|
+
<div
|
|
158
|
+
className="timeline-item-dot"
|
|
159
|
+
style={dotColor ? { backgroundColor: dotColor, borderColor: dotColor } : undefined}
|
|
160
|
+
>
|
|
161
|
+
{icon && (
|
|
162
|
+
<span className="timeline-item-dot-icon">{icon}</span>
|
|
163
|
+
)}
|
|
164
|
+
</div>
|
|
165
|
+
)}
|
|
166
|
+
<div className="timeline-item-stem-line timeline-item-stem-line--after" />
|
|
167
|
+
</div>
|
|
168
|
+
|
|
169
|
+
{/* Main content */}
|
|
170
|
+
<div className="timeline-item-body">
|
|
171
|
+
{children}
|
|
172
|
+
</div>
|
|
173
|
+
</div>
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
);
|
|
177
|
+
TimelineItem.displayName = "TimelineItem";
|
|
178
|
+
|
|
179
|
+
// ─── Exports ──────────────────────────────────────────────────────────────────
|
|
180
|
+
|
|
181
|
+
export { Timeline, TimelineItem };
|