@umituz/web-design-system 6.0.1 → 6.1.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.
Files changed (28) hide show
  1. package/dist/styles.css +1 -1
  2. package/package.json +4 -3
  3. package/src/__tests__/charts/ActivityHeatmap.test.tsx +48 -0
  4. package/src/__tests__/charts/BarChart.test.tsx +91 -0
  5. package/src/__tests__/charts/ChartPrimitives.test.tsx +90 -0
  6. package/src/__tests__/charts/Donut.test.tsx +51 -0
  7. package/src/__tests__/charts/LineChart.test.tsx +81 -0
  8. package/src/__tests__/layout-components.test.tsx +100 -0
  9. package/src/presentation/molecules/TabNav.tsx +46 -0
  10. package/src/presentation/molecules/index.ts +3 -0
  11. package/src/presentation/organisms/AuditLogList.tsx +58 -0
  12. package/src/presentation/organisms/charts/ActivityHeatmap.tsx +58 -0
  13. package/src/presentation/organisms/charts/BarChart.tsx +143 -0
  14. package/src/presentation/organisms/charts/ChartCard.tsx +39 -0
  15. package/src/presentation/organisms/charts/ChartTip.tsx +18 -0
  16. package/src/presentation/organisms/charts/Donut.tsx +100 -0
  17. package/src/presentation/organisms/charts/HBars.tsx +31 -0
  18. package/src/presentation/organisms/charts/Legend.tsx +21 -0
  19. package/src/presentation/organisms/charts/LineChart.tsx +244 -0
  20. package/src/presentation/organisms/charts/Sparkline.tsx +35 -0
  21. package/src/presentation/organisms/charts/index.ts +17 -0
  22. package/src/presentation/organisms/charts/utils.ts +57 -0
  23. package/src/presentation/organisms/index.ts +6 -0
  24. package/src/presentation/templates/PageHeader.tsx +103 -33
  25. package/src/presentation/templates/SectionHeader.tsx +54 -0
  26. package/src/presentation/templates/index.ts +4 -1
  27. package/src/styles/charts.css +455 -0
  28. package/src/styles/compile.css +1 -0
@@ -1,32 +1,46 @@
1
-
2
- import { forwardRef, type HTMLAttributes } from 'react';
3
- import { type ReactNode } from 'react';
1
+ import { forwardRef, type HTMLAttributes, type ReactNode } from 'react';
2
+ import { Link } from 'react-router';
4
3
  import { cn } from '../../infrastructure/utils';
5
4
  import type { BaseProps } from '../../domain/types';
6
5
 
7
6
  export type TextAlign = 'left' | 'center' | 'right';
8
7
  export type HeaderSize = 'small' | 'medium' | 'large';
9
8
 
9
+ export interface PageHeaderCrumb {
10
+ label: string;
11
+ to?: string;
12
+ }
13
+
10
14
  export interface PageHeaderProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'>, BaseProps {
11
- title: ReactNode;
12
- subtitle?: string;
15
+ title?: ReactNode;
16
+ subtitle?: ReactNode;
17
+ description?: ReactNode;
18
+ kicker?: ReactNode;
19
+ breadcrumbs?: ReactNode | readonly PageHeaderCrumb[];
20
+ meta?: ReactNode;
13
21
  align?: TextAlign;
14
22
  size?: HeaderSize;
15
23
  actions?: ReactNode;
16
24
  }
17
25
 
26
+ const isCrumbList = (
27
+ value: ReactNode | readonly PageHeaderCrumb[]
28
+ ): value is readonly PageHeaderCrumb[] =>
29
+ Array.isArray(value) &&
30
+ value.every((item) => typeof item === 'object' && item !== null && 'label' in item);
31
+
18
32
  const sizeClasses: Record<HeaderSize, { title: string; subtitle: string }> = {
19
33
  small: {
20
- title: 'text-2xl md:text-3xl font-bold',
21
- subtitle: 'text-base md:text-lg',
34
+ title: 'text-xl sm:text-2xl font-bold tracking-tight',
35
+ subtitle: 'text-xs sm:text-sm',
22
36
  },
23
37
  medium: {
24
- title: 'text-3xl md:text-4xl font-bold',
25
- subtitle: 'text-lg md:text-xl',
38
+ title: 'text-2xl sm:text-3xl font-bold tracking-tight',
39
+ subtitle: 'text-sm sm:text-base',
26
40
  },
27
41
  large: {
28
- title: 'text-4xl md:text-5xl lg:text-6xl font-bold',
29
- subtitle: 'text-lg md:text-xl',
42
+ title: 'text-3xl sm:text-4xl lg:text-5xl font-bold tracking-tight',
43
+ subtitle: 'text-base sm:text-lg',
30
44
  },
31
45
  };
32
46
 
@@ -36,36 +50,92 @@ const alignClasses: Record<TextAlign, string> = {
36
50
  right: 'text-right',
37
51
  };
38
52
 
39
- const getAlignFlexClass = (align: TextAlign, hasActions: boolean): string => {
40
- if (!hasActions) return '';
41
- return align === 'center'
42
- ? 'flex justify-center'
43
- : align === 'right'
44
- ? 'flex justify-end'
45
- : 'flex justify-start';
46
- };
47
-
48
53
  export const PageHeader = forwardRef<HTMLDivElement, PageHeaderProps>(
49
- ({ title, subtitle, align = 'center', size = 'large', actions, className, ...props }, ref) => {
54
+ (
55
+ {
56
+ title,
57
+ subtitle,
58
+ description,
59
+ kicker,
60
+ breadcrumbs,
61
+ meta,
62
+ align = 'left',
63
+ size = 'small',
64
+ actions,
65
+ className,
66
+ ...props
67
+ },
68
+ ref
69
+ ) => {
70
+ const desc = subtitle ?? description;
71
+
72
+ const crumbNode =
73
+ breadcrumbs === undefined
74
+ ? undefined
75
+ : isCrumbList(breadcrumbs)
76
+ ? breadcrumbs.map((crumb, index) => (
77
+ <span key={`${crumb.label}-${index}`} className="inline-flex items-center gap-1">
78
+ {index > 0 && <span className="opacity-40 select-none">/</span>}
79
+ {crumb.to !== undefined ? (
80
+ <Link to={crumb.to} className="hover:underline hover:text-foreground transition-colors">
81
+ {crumb.label}
82
+ </Link>
83
+ ) : (
84
+ <span>{crumb.label}</span>
85
+ )}
86
+ </span>
87
+ ))
88
+ : breadcrumbs;
89
+
50
90
  return (
51
91
  <div
52
92
  ref={ref}
53
- className={cn('mb-6 md:mb-12', alignClasses[align], className)}
93
+ className={cn(
94
+ 'flex flex-col gap-2 mb-6',
95
+ alignClasses[align],
96
+ className
97
+ )}
54
98
  {...props}
55
99
  >
56
- <h1 className={cn(sizeClasses[size].title, 'text-text-primary mb-4')}>
57
- {title}
58
- </h1>
59
- {subtitle && (
60
- <p className={cn(sizeClasses[size].subtitle, 'text-text-secondary')}>
61
- {subtitle}
62
- </p>
63
- )}
64
- {actions && (
65
- <div className={cn('mt-6 md:mt-8', getAlignFlexClass(align, true))}>
66
- {actions}
100
+ {crumbNode !== undefined && (
101
+ <div className="flex items-center gap-1.5 text-xs text-muted-foreground mb-1">
102
+ {crumbNode}
67
103
  </div>
68
104
  )}
105
+
106
+ <div className="flex flex-wrap items-start justify-between gap-3">
107
+ <div className="min-w-0 flex-1">
108
+ {kicker !== undefined && (
109
+ <p className="text-[11px] font-semibold uppercase tracking-wider text-muted-foreground mb-1">
110
+ {kicker}
111
+ </p>
112
+ )}
113
+
114
+ {title !== undefined && (
115
+ <h1 className={cn(sizeClasses[size].title, 'text-foreground')}>
116
+ {title}
117
+ </h1>
118
+ )}
119
+
120
+ {desc !== undefined && (
121
+ <p className={cn(sizeClasses[size].subtitle, 'text-muted-foreground mt-1 leading-relaxed')}>
122
+ {desc}
123
+ </p>
124
+ )}
125
+
126
+ {meta !== undefined && (
127
+ <div className="flex flex-wrap items-center gap-2 mt-2 text-xs text-muted-foreground">
128
+ {meta}
129
+ </div>
130
+ )}
131
+ </div>
132
+
133
+ {actions && (
134
+ <div className="flex flex-wrap items-center gap-2 shrink-0">
135
+ {actions}
136
+ </div>
137
+ )}
138
+ </div>
69
139
  </div>
70
140
  );
71
141
  }
@@ -0,0 +1,54 @@
1
+ import { forwardRef, type HTMLAttributes, type ReactNode } from 'react';
2
+ import { cn } from '../../infrastructure/utils';
3
+ import type { BaseProps } from '../../domain/types';
4
+
5
+ export interface SectionHeaderProps
6
+ extends Omit<HTMLAttributes<HTMLDivElement>, 'title'>,
7
+ BaseProps {
8
+ kicker?: ReactNode;
9
+ title?: ReactNode;
10
+ subtitle?: ReactNode;
11
+ description?: ReactNode;
12
+ actions?: ReactNode;
13
+ }
14
+
15
+ export const SectionHeader = forwardRef<HTMLDivElement, SectionHeaderProps>(
16
+ ({ kicker, title, subtitle, description, actions, className, ...props }, ref) => {
17
+ const desc = subtitle ?? description;
18
+ return (
19
+ <div
20
+ ref={ref}
21
+ className={cn(
22
+ 'flex flex-wrap items-start justify-between gap-3 mb-3.5',
23
+ className
24
+ )}
25
+ {...props}
26
+ >
27
+ <div className="min-w-0">
28
+ {kicker && (
29
+ <p className="text-[11px] font-semibold uppercase tracking-wider text-muted-foreground mb-1">
30
+ {kicker}
31
+ </p>
32
+ )}
33
+ {title && (
34
+ <h2 className="text-base sm:text-lg font-semibold tracking-tight text-foreground">
35
+ {title}
36
+ </h2>
37
+ )}
38
+ {desc && (
39
+ <p className="text-xs sm:text-sm text-muted-foreground mt-0.5 leading-relaxed">
40
+ {desc}
41
+ </p>
42
+ )}
43
+ </div>
44
+ {actions && (
45
+ <div className="flex flex-wrap items-center gap-2 shrink-0">
46
+ {actions}
47
+ </div>
48
+ )}
49
+ </div>
50
+ );
51
+ }
52
+ );
53
+
54
+ SectionHeader.displayName = 'SectionHeader';
@@ -11,7 +11,10 @@ export { PageLayout } from './PageLayout';
11
11
  export type { PageLayoutProps, MaxWidth } from './PageLayout';
12
12
 
13
13
  export { PageHeader } from './PageHeader';
14
- export type { PageHeaderProps, TextAlign, HeaderSize } from './PageHeader';
14
+ export type { PageHeaderProps, PageHeaderCrumb, TextAlign, HeaderSize } from './PageHeader';
15
+
16
+ export { SectionHeader } from './SectionHeader';
17
+ export type { SectionHeaderProps } from './SectionHeader';
15
18
 
16
19
  export { ProjectSkeleton } from './ProjectSkeleton';
17
20
  export type { ProjectSkeletonProps } from './ProjectSkeleton';
@@ -0,0 +1,455 @@
1
+ :root {
2
+ --udb-chart-1: #357344;
3
+ --udb-chart-2: #b06e22;
4
+ --udb-chart-3: #3e5f80;
5
+ --udb-chart-4: #7a6ba8;
6
+ --udb-chart-5: #8a5a3b;
7
+ --udb-chart-6: #5e7d5a;
8
+ --udb-chart-7: #a8b5a0;
9
+ --udb-chart-8: #c9862f;
10
+ }
11
+ .udb-chartcard {
12
+ display: flex;
13
+ flex-direction: column;
14
+ min-width: 0;
15
+ background: var(--color-card);
16
+ border: 1px solid var(--color-border);
17
+ border-radius: var(--radius-lg);
18
+ box-shadow: var(--shadow-sm);
19
+ }
20
+ .udb-chartcard__head {
21
+ display: flex;
22
+ align-items: flex-start;
23
+ justify-content: space-between;
24
+ gap: var(--udb-space-3);
25
+ padding: 14px 18px 4px;
26
+ flex-wrap: wrap;
27
+ }
28
+ .udb-chartcard__heading {
29
+ min-width: 0;
30
+ }
31
+ .udb-chartcard__title {
32
+ font-size: var(--udb-font-size-md);
33
+ font-weight: 600;
34
+ color: var(--color-foreground);
35
+ }
36
+ .udb-chartcard__sub {
37
+ font-size: var(--udb-font-size-sm);
38
+ color: var(--color-muted-foreground);
39
+ margin-top: 1px;
40
+ }
41
+ .udb-chartcard__tools {
42
+ display: flex;
43
+ align-items: center;
44
+ gap: 12px;
45
+ flex-wrap: wrap;
46
+ }
47
+ .udb-chartcard__body {
48
+ padding: 10px 14px 14px;
49
+ min-width: 0;
50
+ }
51
+ .udb-chartcard__body svg {
52
+ display: block;
53
+ width: 100%;
54
+ height: auto;
55
+ }
56
+ .udb-chartcard__plot {
57
+ position: relative;
58
+ }
59
+ .udb-chartlegend {
60
+ display: flex;
61
+ flex-wrap: wrap;
62
+ gap: 5px 14px;
63
+ }
64
+ .udb-chartlegend__item {
65
+ display: inline-flex;
66
+ align-items: center;
67
+ gap: 6px;
68
+ font-size: var(--udb-font-size-sm);
69
+ color: var(--color-foreground);
70
+ white-space: nowrap;
71
+ }
72
+ .udb-chartlegend__dot {
73
+ width: 8px;
74
+ height: 8px;
75
+ border-radius: 2.5px;
76
+ flex: none;
77
+ }
78
+ .udb-chartlegend__value {
79
+ font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
80
+ color: var(--color-muted-foreground);
81
+ font-size: var(--udb-font-size-xs);
82
+ }
83
+ .udb-chartlegend__hint {
84
+ color: var(--color-muted-foreground);
85
+ font-size: var(--udb-font-size-xs);
86
+ }
87
+ .udb-charttip {
88
+ position: absolute;
89
+ pointer-events: none;
90
+ background: var(--color-foreground);
91
+ color: var(--color-background);
92
+ border-radius: var(--radius-md);
93
+ padding: 7px 10px;
94
+ font-size: var(--udb-font-size-sm);
95
+ box-shadow: var(--shadow-lg);
96
+ z-index: 30;
97
+ min-width: 120px;
98
+ transform: translate(-50%, calc(-100% - 10px));
99
+ }
100
+ .udb-charttip__title {
101
+ font-weight: 600;
102
+ margin-bottom: 2px;
103
+ white-space: nowrap;
104
+ }
105
+ .udb-charttip__row {
106
+ display: flex;
107
+ align-items: center;
108
+ gap: 6px;
109
+ justify-content: space-between;
110
+ font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
111
+ font-size: var(--udb-font-size-xs);
112
+ }
113
+ .udb-charttip__row b {
114
+ font-weight: 600;
115
+ }
116
+ .udb-charttip__label {
117
+ display: inline-flex;
118
+ align-items: center;
119
+ gap: 5px;
120
+ }
121
+ .udb-hbars {
122
+ display: flex;
123
+ flex-direction: column;
124
+ gap: 10px;
125
+ }
126
+ .udb-hbars__row {
127
+ display: grid;
128
+ grid-template-columns: minmax(120px, 1.2fr) 2fr auto;
129
+ align-items: center;
130
+ gap: 12px;
131
+ }
132
+ .udb-hbars__label {
133
+ min-width: 0;
134
+ }
135
+ .udb-hbars__name {
136
+ font-weight: 600;
137
+ font-size: var(--udb-font-size-sm);
138
+ overflow: hidden;
139
+ text-overflow: ellipsis;
140
+ white-space: nowrap;
141
+ color: var(--color-foreground);
142
+ }
143
+ .udb-hbars__sub {
144
+ font-size: var(--udb-font-size-xs);
145
+ color: var(--color-muted-foreground);
146
+ }
147
+ .udb-hbars__track {
148
+ height: 8px;
149
+ background: var(--color-border);
150
+ border-radius: 999px;
151
+ overflow: hidden;
152
+ }
153
+ .udb-hbars__fill {
154
+ height: 100%;
155
+ background: var(--color-primary);
156
+ border-radius: 999px;
157
+ }
158
+ .udb-hbars__value {
159
+ font-size: var(--udb-font-size-sm);
160
+ color: var(--color-foreground);
161
+ text-align: right;
162
+ font-variant-numeric: tabular-nums;
163
+ }
164
+ .udb-barchart {
165
+ position: relative;
166
+ display: flex;
167
+ align-items: flex-end;
168
+ gap: 3px;
169
+ width: 100%;
170
+ }
171
+ .udb-barchart__goal {
172
+ position: absolute;
173
+ left: 0;
174
+ right: 0;
175
+ z-index: 5;
176
+ pointer-events: none;
177
+ border-top: 1.5px dashed var(--udb-chart-goal, #d97706);
178
+ }
179
+ .udb-barchart__goallabel {
180
+ position: absolute;
181
+ right: 0;
182
+ bottom: 2px;
183
+ padding: 0 4px;
184
+ border: 1px solid var(--udb-chart-goal, #d97706);
185
+ border-radius: var(--udb-radius-pill);
186
+ background: var(--color-card);
187
+ font-size: var(--udb-font-size-xs);
188
+ line-height: 16px;
189
+ color: var(--udb-chart-goal, #d97706);
190
+ }
191
+ .udb-barchart__col {
192
+ position: relative;
193
+ display: flex;
194
+ flex: 1;
195
+ align-items: flex-end;
196
+ min-width: 0;
197
+ height: 100%;
198
+ }
199
+ .udb-barchart__bars {
200
+ display: flex;
201
+ align-items: flex-end;
202
+ justify-content: center;
203
+ gap: 2px;
204
+ width: 100%;
205
+ height: 100%;
206
+ }
207
+ .udb-barchart__bars .udb-barchart__bar {
208
+ flex: 1;
209
+ width: auto;
210
+ }
211
+ .udb-barchart__bar {
212
+ width: 100%;
213
+ min-height: 2px;
214
+ border-radius: 3px 3px 0 0;
215
+ transition: opacity 150ms ease, height 300ms ease;
216
+ }
217
+ .udb-barchart__bars--stacked {
218
+ flex-direction: column-reverse;
219
+ align-items: center;
220
+ justify-content: flex-end;
221
+ gap: 0;
222
+ }
223
+ .udb-barchart__bars--stacked .udb-barchart__bar {
224
+ flex: none;
225
+ width: 100%;
226
+ border-radius: 0;
227
+ }
228
+ .udb-barchart__bars--stacked .udb-barchart__bar:last-child {
229
+ border-radius: 3px 3px 0 0;
230
+ }
231
+ .udb-barchart__tip {
232
+ position: absolute;
233
+ bottom: calc(100% + 6px);
234
+ left: 50%;
235
+ z-index: 10;
236
+ padding: 4px 8px;
237
+ white-space: nowrap;
238
+ pointer-events: none;
239
+ border: 1px solid var(--color-border);
240
+ border-radius: var(--radius-sm);
241
+ background: var(--color-card);
242
+ box-shadow: var(--shadow-sm);
243
+ font-size: var(--udb-font-size-xs);
244
+ color: var(--color-muted-foreground);
245
+ }
246
+ .udb-barchart__tiptitle {
247
+ font-weight: var(--font-weight-medium);
248
+ color: var(--color-foreground);
249
+ }
250
+ .udb-barchart__tiprow {
251
+ display: flex;
252
+ align-items: center;
253
+ justify-content: space-between;
254
+ gap: 10px;
255
+ }
256
+ .udb-barchart__tiprow--total {
257
+ margin-top: 3px;
258
+ padding-top: 3px;
259
+ border-top: 1px solid var(--color-border);
260
+ }
261
+ .udb-barchart__tiplabel {
262
+ display: inline-flex;
263
+ align-items: center;
264
+ gap: 5px;
265
+ }
266
+ .udb-barchart__tip b {
267
+ margin-right: 4px;
268
+ font-weight: var(--font-weight-medium);
269
+ color: var(--color-foreground);
270
+ }
271
+ .udb-donut {
272
+ display: flex;
273
+ align-items: center;
274
+ gap: 20px;
275
+ }
276
+ .udb-donut__wrap {
277
+ position: relative;
278
+ flex-shrink: 0;
279
+ }
280
+ .udb-donut__seg {
281
+ cursor: pointer;
282
+ transition: stroke-width 150ms ease, opacity 150ms ease;
283
+ }
284
+ .udb-donut__center {
285
+ position: absolute;
286
+ inset: 0;
287
+ display: flex;
288
+ flex-direction: column;
289
+ align-items: center;
290
+ justify-content: center;
291
+ }
292
+ .udb-donut__value {
293
+ font-size: var(--udb-font-size-lg);
294
+ font-weight: var(--font-weight-bold);
295
+ color: var(--color-foreground);
296
+ font-variant-numeric: tabular-nums;
297
+ }
298
+ .udb-donut__label {
299
+ margin-top: 2px;
300
+ font-size: var(--udb-font-size-xs);
301
+ color: var(--color-muted-foreground);
302
+ }
303
+ .udb-donut__list {
304
+ display: flex;
305
+ min-width: 0;
306
+ flex: 1;
307
+ flex-direction: column;
308
+ gap: 6px;
309
+ }
310
+ .udb-donut__item {
311
+ display: flex;
312
+ align-items: center;
313
+ justify-content: space-between;
314
+ gap: 8px;
315
+ padding: 4px 6px;
316
+ border-radius: var(--radius-sm);
317
+ }
318
+ .udb-donut__item:hover {
319
+ background: var(--color-muted);
320
+ }
321
+ .udb-donut__itemlabel {
322
+ display: flex;
323
+ min-width: 0;
324
+ align-items: center;
325
+ gap: 8px;
326
+ font-size: var(--udb-font-size-sm);
327
+ color: var(--color-foreground);
328
+ }
329
+ .udb-donut__dot {
330
+ width: 8px;
331
+ height: 8px;
332
+ flex-shrink: 0;
333
+ border-radius: 3px;
334
+ }
335
+ .udb-donut__itemvalue {
336
+ flex-shrink: 0;
337
+ font-size: var(--udb-font-size-sm);
338
+ font-weight: var(--font-weight-medium);
339
+ color: var(--color-foreground);
340
+ font-variant-numeric: tabular-nums;
341
+ }
342
+ .udb-donut__pct {
343
+ margin-left: 6px;
344
+ color: var(--color-muted-foreground);
345
+ }
346
+ .udb-linechart {
347
+ position: relative;
348
+ width: 100%;
349
+ user-select: none;
350
+ }
351
+ .udb-linechart__svg {
352
+ display: block;
353
+ width: 100%;
354
+ }
355
+ .udb-linechart__axis {
356
+ fill: var(--color-muted-foreground);
357
+ font-size: var(--udb-font-size-xs);
358
+ font-family: var(--font-sans);
359
+ }
360
+ .udb-linechart__grid {
361
+ stroke: var(--color-border);
362
+ stroke-width: 1;
363
+ }
364
+ .udb-linechart__band {
365
+ fill: var(--color-primary);
366
+ opacity: 0.08;
367
+ }
368
+ .udb-linechart__crosshair {
369
+ stroke: var(--udb-border-strong);
370
+ stroke-width: 1;
371
+ stroke-dasharray: 3 3;
372
+ }
373
+ .udb-linechart__tip {
374
+ position: absolute;
375
+ top: 8px;
376
+ z-index: 10;
377
+ min-width: 132px;
378
+ padding: 8px;
379
+ pointer-events: none;
380
+ border: 1px solid var(--color-border);
381
+ border-radius: var(--radius-md);
382
+ background: var(--color-card);
383
+ box-shadow: var(--shadow-md);
384
+ }
385
+ .udb-linechart__tiptitle {
386
+ margin-bottom: 4px;
387
+ font-size: var(--udb-font-size-xs);
388
+ color: var(--color-muted-foreground);
389
+ }
390
+ .udb-linechart__tiprow {
391
+ display: flex;
392
+ align-items: center;
393
+ justify-content: space-between;
394
+ gap: 12px;
395
+ font-size: var(--udb-font-size-sm);
396
+ }
397
+ .udb-linechart__tiprow span {
398
+ display: flex;
399
+ align-items: center;
400
+ gap: 6px;
401
+ color: var(--color-muted-foreground);
402
+ }
403
+ .udb-linechart__tiprow b {
404
+ font-weight: var(--font-weight-medium);
405
+ color: var(--color-foreground);
406
+ font-variant-numeric: tabular-nums;
407
+ }
408
+ .udb-linechart__swatch {
409
+ display: inline-block;
410
+ width: 12px;
411
+ height: 3px;
412
+ border-radius: 999px;
413
+ }
414
+ .udb-linechart__legendhost {
415
+ margin-top: 4px;
416
+ padding: 0 8px;
417
+ }
418
+ .udb-heatmap {
419
+ display: grid;
420
+ grid-auto-flow: column;
421
+ grid-template-rows: repeat(7, minmax(0, 1fr));
422
+ gap: 4px;
423
+ }
424
+ .udb-heatmap__cell {
425
+ width: 14px;
426
+ height: 14px;
427
+ border-radius: 3px;
428
+ transition: background-color 150ms ease;
429
+ }
430
+ .udb-heatmap__cell--l0 {
431
+ background: color-mix(in oklab, var(--color-muted) 40%, transparent);
432
+ }
433
+ .udb-heatmap__cell--l1 {
434
+ background: color-mix(in oklab, var(--color-primary) 20%, var(--color-card));
435
+ }
436
+ .udb-heatmap__cell--l2 {
437
+ background: color-mix(in oklab, var(--color-primary) 40%, var(--color-card));
438
+ }
439
+ .udb-heatmap__cell--l3 {
440
+ background: color-mix(in oklab, var(--color-primary) 70%, var(--color-card));
441
+ }
442
+ .udb-heatmap__cell--l4 {
443
+ background: var(--color-primary);
444
+ }
445
+ .udb-heatmap__sr {
446
+ position: absolute;
447
+ width: 1px;
448
+ height: 1px;
449
+ padding: 0;
450
+ margin: -1px;
451
+ overflow: hidden;
452
+ clip: rect(0, 0, 0, 0);
453
+ white-space: nowrap;
454
+ border-width: 0;
455
+ }
@@ -2,6 +2,7 @@
2
2
  @import "tailwindcss";
3
3
  @import "tw-animate-css";
4
4
  @import "./theme.css";
5
+ @import "./charts.css";
5
6
  @source "../src";
6
7
 
7
8
  @media (max-width: 767.98px) {