@aspect-ops/exon-ui 0.2.1 → 0.2.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/components/AspectRatio/AspectRatio.svelte +1 -0
- package/dist/components/Card/FlipCard.svelte +155 -0
- package/dist/components/Card/FlipCard.svelte.d.ts +13 -0
- package/dist/components/Card/index.d.ts +1 -0
- package/dist/components/Card/index.js +1 -0
- package/dist/components/Container/Container.svelte +1 -0
- package/dist/components/DataTable/DataTable.svelte +460 -0
- package/dist/components/DataTable/DataTable.svelte.d.ts +49 -0
- package/dist/components/DataTable/index.d.ts +2 -0
- package/dist/components/DataTable/index.js +1 -0
- package/dist/components/DoughnutChart/DoughnutChart.svelte +20 -2
- package/dist/components/Icon/Icon.svelte +15 -18
- package/dist/components/Icon/Icon.svelte.d.ts +2 -1
- package/dist/components/Menu/MenuContent.svelte +1 -0
- package/dist/components/Menu/MenuSubContent.svelte +1 -0
- package/dist/components/Mermaid/Mermaid.svelte +121 -7
- package/dist/components/Mermaid/Mermaid.svelte.d.ts +10 -0
- package/dist/components/PageHeader/PageHeader.svelte +140 -0
- package/dist/components/PageHeader/PageHeader.svelte.d.ts +30 -0
- package/dist/components/PageHeader/index.d.ts +1 -0
- package/dist/components/PageHeader/index.js +1 -0
- package/dist/components/StatCircle/StatCircle.svelte +172 -0
- package/dist/components/StatCircle/StatCircle.svelte.d.ts +19 -0
- package/dist/components/StatCircle/index.d.ts +1 -0
- package/dist/components/StatCircle/index.js +1 -0
- package/dist/components/StatsCard/StatsCard.svelte +301 -0
- package/dist/components/StatsCard/StatsCard.svelte.d.ts +32 -0
- package/dist/components/StatsCard/index.d.ts +2 -0
- package/dist/components/StatsCard/index.js +1 -0
- package/dist/components/StatusBadge/StatusBadge.svelte +221 -0
- package/dist/components/StatusBadge/StatusBadge.svelte.d.ts +22 -0
- package/dist/components/StatusBadge/index.d.ts +2 -0
- package/dist/components/StatusBadge/index.js +1 -0
- package/dist/components/StatusBanner/StatusBanner.svelte +325 -0
- package/dist/components/StatusBanner/StatusBanner.svelte.d.ts +13 -0
- package/dist/components/StatusBanner/index.d.ts +1 -0
- package/dist/components/StatusBanner/index.js +1 -0
- package/dist/index.d.ts +8 -2
- package/dist/index.js +7 -1
- package/dist/types/data-display.d.ts +72 -0
- package/dist/types/feedback.d.ts +10 -0
- package/dist/types/index.d.ts +2 -2
- package/package.json +3 -2
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* StatsCard - A clickable card for displaying statistics with optional trends
|
|
4
|
+
* Commonly used for dashboard stat summaries and filter toggles
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
type ColorVariant = 'default' | 'primary' | 'success' | 'warning' | 'error';
|
|
8
|
+
|
|
9
|
+
interface TrendData {
|
|
10
|
+
value: number;
|
|
11
|
+
direction: 'up' | 'down';
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface Props {
|
|
15
|
+
/** Label text displayed above the value */
|
|
16
|
+
label: string;
|
|
17
|
+
/** The numeric or string value to display */
|
|
18
|
+
value: number | string;
|
|
19
|
+
/** Color variant for the value text */
|
|
20
|
+
color?: ColorVariant;
|
|
21
|
+
/** Optional icon snippet rendered before the value */
|
|
22
|
+
icon?: import('svelte').Snippet;
|
|
23
|
+
/** Whether this card is in selected/active state */
|
|
24
|
+
selected?: boolean;
|
|
25
|
+
/** Click handler - makes the card interactive */
|
|
26
|
+
onclick?: (event: MouseEvent) => void;
|
|
27
|
+
/** Optional trend indicator showing change direction and percentage */
|
|
28
|
+
trend?: TrendData;
|
|
29
|
+
/** Show loading skeleton instead of content */
|
|
30
|
+
loading?: boolean;
|
|
31
|
+
/** Additional CSS classes */
|
|
32
|
+
class?: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
let {
|
|
36
|
+
label,
|
|
37
|
+
value,
|
|
38
|
+
color = 'default',
|
|
39
|
+
icon,
|
|
40
|
+
selected = false,
|
|
41
|
+
onclick,
|
|
42
|
+
trend,
|
|
43
|
+
loading = false,
|
|
44
|
+
class: className = ''
|
|
45
|
+
}: Props = $props();
|
|
46
|
+
|
|
47
|
+
const isClickable = $derived(!!onclick);
|
|
48
|
+
</script>
|
|
49
|
+
|
|
50
|
+
{#if loading}
|
|
51
|
+
<div class="stats-card stats-card--loading {className}">
|
|
52
|
+
<div class="stats-card__skeleton-label"></div>
|
|
53
|
+
<div class="stats-card__skeleton-value"></div>
|
|
54
|
+
</div>
|
|
55
|
+
{:else}
|
|
56
|
+
<button
|
|
57
|
+
type="button"
|
|
58
|
+
class="stats-card stats-card--{color} {className}"
|
|
59
|
+
class:stats-card--selected={selected}
|
|
60
|
+
class:stats-card--clickable={isClickable}
|
|
61
|
+
{onclick}
|
|
62
|
+
disabled={!isClickable}
|
|
63
|
+
>
|
|
64
|
+
<div class="stats-card__label">{label}</div>
|
|
65
|
+
<div class="stats-card__content">
|
|
66
|
+
{#if icon}
|
|
67
|
+
<span class="stats-card__icon">
|
|
68
|
+
{@render icon()}
|
|
69
|
+
</span>
|
|
70
|
+
{/if}
|
|
71
|
+
<span class="stats-card__value">{value}</span>
|
|
72
|
+
{#if trend}
|
|
73
|
+
<span
|
|
74
|
+
class="stats-card__trend"
|
|
75
|
+
class:stats-card__trend--up={trend.direction === 'up'}
|
|
76
|
+
class:stats-card__trend--down={trend.direction === 'down'}
|
|
77
|
+
>
|
|
78
|
+
<svg
|
|
79
|
+
class="stats-card__trend-icon"
|
|
80
|
+
viewBox="0 0 20 20"
|
|
81
|
+
fill="currentColor"
|
|
82
|
+
aria-hidden="true"
|
|
83
|
+
>
|
|
84
|
+
{#if trend.direction === 'up'}
|
|
85
|
+
<path
|
|
86
|
+
fill-rule="evenodd"
|
|
87
|
+
d="M5.293 9.707a1 1 0 010-1.414l4-4a1 1 0 011.414 0l4 4a1 1 0 01-1.414 1.414L11 7.414V15a1 1 0 11-2 0V7.414L6.707 9.707a1 1 0 01-1.414 0z"
|
|
88
|
+
clip-rule="evenodd"
|
|
89
|
+
/>
|
|
90
|
+
{:else}
|
|
91
|
+
<path
|
|
92
|
+
fill-rule="evenodd"
|
|
93
|
+
d="M14.707 10.293a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 111.414-1.414L9 12.586V5a1 1 0 012 0v7.586l2.293-2.293a1 1 0 011.414 0z"
|
|
94
|
+
clip-rule="evenodd"
|
|
95
|
+
/>
|
|
96
|
+
{/if}
|
|
97
|
+
</svg>
|
|
98
|
+
<span class="stats-card__trend-value">{trend.value}%</span>
|
|
99
|
+
</span>
|
|
100
|
+
{/if}
|
|
101
|
+
</div>
|
|
102
|
+
</button>
|
|
103
|
+
{/if}
|
|
104
|
+
|
|
105
|
+
<style>
|
|
106
|
+
.stats-card {
|
|
107
|
+
display: flex;
|
|
108
|
+
flex-direction: column;
|
|
109
|
+
align-items: flex-start;
|
|
110
|
+
padding: var(--space-lg, 1rem);
|
|
111
|
+
background: var(--color-bg-card, #ffffff);
|
|
112
|
+
border-radius: var(--radius-lg, 0.5rem);
|
|
113
|
+
border: 2px solid transparent;
|
|
114
|
+
box-shadow: var(--shadow-sm, 0 1px 2px 0 rgb(0 0 0 / 0.05));
|
|
115
|
+
font-family: inherit;
|
|
116
|
+
text-align: left;
|
|
117
|
+
width: 100%;
|
|
118
|
+
transition:
|
|
119
|
+
box-shadow 0.2s ease,
|
|
120
|
+
border-color 0.2s ease,
|
|
121
|
+
transform 0.1s ease;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/* Reset button styles */
|
|
125
|
+
button.stats-card {
|
|
126
|
+
cursor: default;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
button.stats-card:disabled {
|
|
130
|
+
opacity: 1;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/* Clickable state */
|
|
134
|
+
.stats-card--clickable {
|
|
135
|
+
cursor: pointer;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
.stats-card--clickable:hover {
|
|
139
|
+
box-shadow: var(--shadow-md, 0 4px 6px -1px rgb(0 0 0 / 0.1));
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.stats-card--clickable:active {
|
|
143
|
+
transform: scale(0.98);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/* Selected state */
|
|
147
|
+
.stats-card--selected {
|
|
148
|
+
border-color: var(--color-primary, #3b82f6);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/* Label */
|
|
152
|
+
.stats-card__label {
|
|
153
|
+
font-size: var(--text-sm, 0.875rem);
|
|
154
|
+
color: var(--color-text-muted, #6b7280);
|
|
155
|
+
margin-bottom: var(--space-xs, 0.25rem);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/* Content wrapper */
|
|
159
|
+
.stats-card__content {
|
|
160
|
+
display: flex;
|
|
161
|
+
align-items: baseline;
|
|
162
|
+
gap: var(--space-sm, 0.5rem);
|
|
163
|
+
flex-wrap: wrap;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/* Icon */
|
|
167
|
+
.stats-card__icon {
|
|
168
|
+
display: flex;
|
|
169
|
+
align-items: center;
|
|
170
|
+
color: inherit;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.stats-card__icon :global(svg) {
|
|
174
|
+
width: 1.5rem;
|
|
175
|
+
height: 1.5rem;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/* Value */
|
|
179
|
+
.stats-card__value {
|
|
180
|
+
font-size: var(--text-2xl, 1.5rem);
|
|
181
|
+
font-weight: 700;
|
|
182
|
+
line-height: 1.2;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/* Color variants for value */
|
|
186
|
+
.stats-card--default .stats-card__value {
|
|
187
|
+
color: var(--color-text, #1f2937);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.stats-card--primary .stats-card__value {
|
|
191
|
+
color: var(--color-primary, #3b82f6);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
.stats-card--success .stats-card__value {
|
|
195
|
+
color: var(--color-success, #22c55e);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
.stats-card--warning .stats-card__value {
|
|
199
|
+
color: var(--color-warning, #f59e0b);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
.stats-card--error .stats-card__value {
|
|
203
|
+
color: var(--color-error, #ef4444);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/* Trend indicator */
|
|
207
|
+
.stats-card__trend {
|
|
208
|
+
display: inline-flex;
|
|
209
|
+
align-items: center;
|
|
210
|
+
gap: 0.125rem;
|
|
211
|
+
font-size: var(--text-sm, 0.875rem);
|
|
212
|
+
font-weight: 500;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
.stats-card__trend--up {
|
|
216
|
+
color: var(--color-success, #22c55e);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
.stats-card__trend--down {
|
|
220
|
+
color: var(--color-error, #ef4444);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
.stats-card__trend-icon {
|
|
224
|
+
width: 1rem;
|
|
225
|
+
height: 1rem;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/* Loading skeleton */
|
|
229
|
+
.stats-card--loading {
|
|
230
|
+
pointer-events: none;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
.stats-card__skeleton-label,
|
|
234
|
+
.stats-card__skeleton-value {
|
|
235
|
+
background: linear-gradient(
|
|
236
|
+
90deg,
|
|
237
|
+
var(--color-bg-muted, #e5e7eb) 25%,
|
|
238
|
+
var(--color-bg-skeleton-shine, #f3f4f6) 50%,
|
|
239
|
+
var(--color-bg-muted, #e5e7eb) 75%
|
|
240
|
+
);
|
|
241
|
+
background-size: 200% 100%;
|
|
242
|
+
animation: skeleton-shimmer 1.5s ease-in-out infinite;
|
|
243
|
+
border-radius: var(--radius-sm, 0.25rem);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
.stats-card__skeleton-label {
|
|
247
|
+
width: 60%;
|
|
248
|
+
height: 0.875rem;
|
|
249
|
+
margin-bottom: var(--space-sm, 0.5rem);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
.stats-card__skeleton-value {
|
|
253
|
+
width: 40%;
|
|
254
|
+
height: 1.75rem;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
@keyframes skeleton-shimmer {
|
|
258
|
+
0% {
|
|
259
|
+
background-position: 200% 0;
|
|
260
|
+
}
|
|
261
|
+
100% {
|
|
262
|
+
background-position: -200% 0;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/* Dark mode support */
|
|
267
|
+
:global([data-theme='dark']) .stats-card {
|
|
268
|
+
background: var(--color-bg-card-dark, #1f2937);
|
|
269
|
+
box-shadow: var(--shadow-sm-dark, 0 1px 2px 0 rgb(0 0 0 / 0.2));
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
:global([data-theme='dark']) .stats-card--clickable:hover {
|
|
273
|
+
box-shadow: var(--shadow-md-dark, 0 4px 6px -1px rgb(0 0 0 / 0.3));
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
:global([data-theme='dark']) .stats-card__label {
|
|
277
|
+
color: var(--color-text-muted-dark, #9ca3af);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
:global([data-theme='dark']) .stats-card--default .stats-card__value {
|
|
281
|
+
color: var(--color-text-dark, #f9fafb);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
:global([data-theme='dark']) .stats-card__skeleton-label,
|
|
285
|
+
:global([data-theme='dark']) .stats-card__skeleton-value {
|
|
286
|
+
background: linear-gradient(
|
|
287
|
+
90deg,
|
|
288
|
+
var(--color-bg-muted-dark, #374151) 25%,
|
|
289
|
+
var(--color-bg-skeleton-shine-dark, #4b5563) 50%,
|
|
290
|
+
var(--color-bg-muted-dark, #374151) 75%
|
|
291
|
+
);
|
|
292
|
+
background-size: 200% 100%;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/* Touch target for mobile - ensure 44px minimum */
|
|
296
|
+
@media (pointer: coarse) {
|
|
297
|
+
.stats-card {
|
|
298
|
+
min-height: 2.75rem;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
</style>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StatsCard - A clickable card for displaying statistics with optional trends
|
|
3
|
+
* Commonly used for dashboard stat summaries and filter toggles
|
|
4
|
+
*/
|
|
5
|
+
type ColorVariant = 'default' | 'primary' | 'success' | 'warning' | 'error';
|
|
6
|
+
interface TrendData {
|
|
7
|
+
value: number;
|
|
8
|
+
direction: 'up' | 'down';
|
|
9
|
+
}
|
|
10
|
+
interface Props {
|
|
11
|
+
/** Label text displayed above the value */
|
|
12
|
+
label: string;
|
|
13
|
+
/** The numeric or string value to display */
|
|
14
|
+
value: number | string;
|
|
15
|
+
/** Color variant for the value text */
|
|
16
|
+
color?: ColorVariant;
|
|
17
|
+
/** Optional icon snippet rendered before the value */
|
|
18
|
+
icon?: import('svelte').Snippet;
|
|
19
|
+
/** Whether this card is in selected/active state */
|
|
20
|
+
selected?: boolean;
|
|
21
|
+
/** Click handler - makes the card interactive */
|
|
22
|
+
onclick?: (event: MouseEvent) => void;
|
|
23
|
+
/** Optional trend indicator showing change direction and percentage */
|
|
24
|
+
trend?: TrendData;
|
|
25
|
+
/** Show loading skeleton instead of content */
|
|
26
|
+
loading?: boolean;
|
|
27
|
+
/** Additional CSS classes */
|
|
28
|
+
class?: string;
|
|
29
|
+
}
|
|
30
|
+
declare const StatsCard: import("svelte").Component<Props, {}, "">;
|
|
31
|
+
type StatsCard = ReturnType<typeof StatsCard>;
|
|
32
|
+
export default StatsCard;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as StatsCard } from './StatsCard.svelte';
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* StatusBadge - A color-coded badge for displaying status values
|
|
4
|
+
* Automatically maps common status strings to semantic colors
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
type ColorVariant = 'success' | 'warning' | 'error' | 'info' | 'default';
|
|
8
|
+
|
|
9
|
+
interface Props {
|
|
10
|
+
/** The status text to display */
|
|
11
|
+
status: string;
|
|
12
|
+
/** Custom color mapping from status strings to color variants */
|
|
13
|
+
colorMap?: Record<string, ColorVariant>;
|
|
14
|
+
/** Size of the badge */
|
|
15
|
+
size?: 'sm' | 'md' | 'lg';
|
|
16
|
+
/** Show a dot indicator before the text */
|
|
17
|
+
dot?: boolean;
|
|
18
|
+
/** Transform text to uppercase */
|
|
19
|
+
uppercase?: boolean;
|
|
20
|
+
/** Additional CSS classes */
|
|
21
|
+
class?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
let {
|
|
25
|
+
status,
|
|
26
|
+
colorMap,
|
|
27
|
+
size = 'md',
|
|
28
|
+
dot = false,
|
|
29
|
+
uppercase = false,
|
|
30
|
+
class: className = ''
|
|
31
|
+
}: Props = $props();
|
|
32
|
+
|
|
33
|
+
// Default color mappings (case-insensitive)
|
|
34
|
+
const defaultColorMap: Record<string, ColorVariant> = {
|
|
35
|
+
// Success states
|
|
36
|
+
active: 'success',
|
|
37
|
+
approved: 'success',
|
|
38
|
+
completed: 'success',
|
|
39
|
+
success: 'success',
|
|
40
|
+
done: 'success',
|
|
41
|
+
verified: 'success',
|
|
42
|
+
confirmed: 'success',
|
|
43
|
+
|
|
44
|
+
// Warning states
|
|
45
|
+
pending: 'warning',
|
|
46
|
+
'in progress': 'warning',
|
|
47
|
+
in_progress: 'warning',
|
|
48
|
+
'on hold': 'warning',
|
|
49
|
+
on_hold: 'warning',
|
|
50
|
+
processing: 'warning',
|
|
51
|
+
draft: 'warning',
|
|
52
|
+
|
|
53
|
+
// Error states
|
|
54
|
+
rejected: 'error',
|
|
55
|
+
failed: 'error',
|
|
56
|
+
error: 'error',
|
|
57
|
+
cancelled: 'error',
|
|
58
|
+
inactive: 'error',
|
|
59
|
+
expired: 'error',
|
|
60
|
+
overdue: 'error',
|
|
61
|
+
|
|
62
|
+
// Info states
|
|
63
|
+
applied: 'info',
|
|
64
|
+
new: 'info',
|
|
65
|
+
'to do': 'info',
|
|
66
|
+
todo: 'info',
|
|
67
|
+
open: 'info',
|
|
68
|
+
submitted: 'info'
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
// Compute the color variant based on status
|
|
72
|
+
const colorVariant = $derived(() => {
|
|
73
|
+
const normalizedStatus = status.toLowerCase().trim();
|
|
74
|
+
|
|
75
|
+
// Check custom colorMap first (case-insensitive)
|
|
76
|
+
if (colorMap) {
|
|
77
|
+
const customKey = Object.keys(colorMap).find((key) => key.toLowerCase() === normalizedStatus);
|
|
78
|
+
if (customKey) return colorMap[customKey];
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Fall back to default mappings
|
|
82
|
+
return defaultColorMap[normalizedStatus] || 'default';
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
const displayText = $derived(uppercase ? status.toUpperCase() : status);
|
|
86
|
+
</script>
|
|
87
|
+
|
|
88
|
+
<span
|
|
89
|
+
class="status-badge status-badge--{colorVariant()} status-badge--{size} {className}"
|
|
90
|
+
class:status-badge--uppercase={uppercase}
|
|
91
|
+
>
|
|
92
|
+
{#if dot}
|
|
93
|
+
<span class="status-badge__dot"></span>
|
|
94
|
+
{/if}
|
|
95
|
+
<span class="status-badge__text">{displayText}</span>
|
|
96
|
+
</span>
|
|
97
|
+
|
|
98
|
+
<style>
|
|
99
|
+
.status-badge {
|
|
100
|
+
display: inline-flex;
|
|
101
|
+
align-items: center;
|
|
102
|
+
gap: var(--space-xs, 0.25rem);
|
|
103
|
+
border-radius: var(--radius-full, 9999px);
|
|
104
|
+
font-family: inherit;
|
|
105
|
+
font-weight: 600;
|
|
106
|
+
line-height: 1;
|
|
107
|
+
white-space: nowrap;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/* Sizes */
|
|
111
|
+
.status-badge--sm {
|
|
112
|
+
padding: var(--space-xs, 0.125rem) var(--space-sm, 0.375rem);
|
|
113
|
+
font-size: var(--text-xs, 0.625rem);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.status-badge--md {
|
|
117
|
+
padding: var(--space-xs, 0.25rem) var(--space-sm, 0.5rem);
|
|
118
|
+
font-size: var(--text-xs, 0.75rem);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.status-badge--lg {
|
|
122
|
+
padding: var(--space-sm, 0.375rem) var(--space-md, 0.75rem);
|
|
123
|
+
font-size: var(--text-sm, 0.875rem);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/* Color variants - using soft/muted backgrounds */
|
|
127
|
+
.status-badge--default {
|
|
128
|
+
background: var(--color-bg-muted, #f3f4f6);
|
|
129
|
+
color: var(--color-text-muted, #6b7280);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.status-badge--success {
|
|
133
|
+
background: var(--color-success-soft, #dcfce7);
|
|
134
|
+
color: var(--color-success-text, #166534);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.status-badge--warning {
|
|
138
|
+
background: var(--color-warning-soft, #fef3c7);
|
|
139
|
+
color: var(--color-warning-text, #92400e);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.status-badge--error {
|
|
143
|
+
background: var(--color-error-soft, #fee2e2);
|
|
144
|
+
color: var(--color-error-text, #991b1b);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.status-badge--info {
|
|
148
|
+
background: var(--color-info-soft, #dbeafe);
|
|
149
|
+
color: var(--color-info-text, #1e40af);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/* Dot indicator */
|
|
153
|
+
.status-badge__dot {
|
|
154
|
+
width: 0.375rem;
|
|
155
|
+
height: 0.375rem;
|
|
156
|
+
border-radius: 50%;
|
|
157
|
+
flex-shrink: 0;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.status-badge--sm .status-badge__dot {
|
|
161
|
+
width: 0.25rem;
|
|
162
|
+
height: 0.25rem;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.status-badge--lg .status-badge__dot {
|
|
166
|
+
width: 0.5rem;
|
|
167
|
+
height: 0.5rem;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
.status-badge--default .status-badge__dot {
|
|
171
|
+
background: var(--color-text-muted, #6b7280);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
.status-badge--success .status-badge__dot {
|
|
175
|
+
background: var(--color-success, #22c55e);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
.status-badge--warning .status-badge__dot {
|
|
179
|
+
background: var(--color-warning, #f59e0b);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
.status-badge--error .status-badge__dot {
|
|
183
|
+
background: var(--color-error, #ef4444);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.status-badge--info .status-badge__dot {
|
|
187
|
+
background: var(--color-info, #3b82f6);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/* Uppercase modifier */
|
|
191
|
+
.status-badge--uppercase .status-badge__text {
|
|
192
|
+
text-transform: uppercase;
|
|
193
|
+
letter-spacing: 0.025em;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/* Dark mode support */
|
|
197
|
+
:global([data-theme='dark']) .status-badge--default {
|
|
198
|
+
background: var(--color-bg-muted-dark, #374151);
|
|
199
|
+
color: var(--color-text-muted-dark, #9ca3af);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
:global([data-theme='dark']) .status-badge--success {
|
|
203
|
+
background: var(--color-success-soft-dark, #064e3b);
|
|
204
|
+
color: var(--color-success-text-dark, #6ee7b7);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
:global([data-theme='dark']) .status-badge--warning {
|
|
208
|
+
background: var(--color-warning-soft-dark, #78350f);
|
|
209
|
+
color: var(--color-warning-text-dark, #fcd34d);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
:global([data-theme='dark']) .status-badge--error {
|
|
213
|
+
background: var(--color-error-soft-dark, #7f1d1d);
|
|
214
|
+
color: var(--color-error-text-dark, #fca5a5);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
:global([data-theme='dark']) .status-badge--info {
|
|
218
|
+
background: var(--color-info-soft-dark, #1e3a8a);
|
|
219
|
+
color: var(--color-info-text-dark, #93c5fd);
|
|
220
|
+
}
|
|
221
|
+
</style>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StatusBadge - A color-coded badge for displaying status values
|
|
3
|
+
* Automatically maps common status strings to semantic colors
|
|
4
|
+
*/
|
|
5
|
+
type ColorVariant = 'success' | 'warning' | 'error' | 'info' | 'default';
|
|
6
|
+
interface Props {
|
|
7
|
+
/** The status text to display */
|
|
8
|
+
status: string;
|
|
9
|
+
/** Custom color mapping from status strings to color variants */
|
|
10
|
+
colorMap?: Record<string, ColorVariant>;
|
|
11
|
+
/** Size of the badge */
|
|
12
|
+
size?: 'sm' | 'md' | 'lg';
|
|
13
|
+
/** Show a dot indicator before the text */
|
|
14
|
+
dot?: boolean;
|
|
15
|
+
/** Transform text to uppercase */
|
|
16
|
+
uppercase?: boolean;
|
|
17
|
+
/** Additional CSS classes */
|
|
18
|
+
class?: string;
|
|
19
|
+
}
|
|
20
|
+
declare const StatusBadge: import("svelte").Component<Props, {}, "">;
|
|
21
|
+
type StatusBadge = ReturnType<typeof StatusBadge>;
|
|
22
|
+
export default StatusBadge;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as StatusBadge } from './StatusBadge.svelte';
|