@fragment-build/ui 3.2.3 → 4.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/README.md +73 -0
- package/components/code-snippet/CodeSnippet.d.ts +9 -0
- package/components/code-snippet/CodeSnippet.js +14 -4
- package/components/code-snippet/CodeSnippet.js.map +1 -1
- package/components/code-snippet/code-snippet.css +18 -0
- package/components/segmented-control/SegmentedControl.d.ts +16 -0
- package/components/segmented-control/SegmentedControl.js +18 -0
- package/components/segmented-control/SegmentedControl.js.map +1 -0
- package/components/segmented-control/SegmentedControl.styles.d.ts +46 -0
- package/components/segmented-control/SegmentedControl.styles.js +20 -0
- package/components/segmented-control/SegmentedControl.styles.js.map +1 -0
- package/components/segmented-control/segmented-control.css +41 -0
- package/fragments/empty-state/EmptyState.d.ts +12 -0
- package/fragments/empty-state/EmptyState.js +12 -0
- package/fragments/empty-state/EmptyState.js.map +1 -0
- package/fragments/empty-state/EmptyState.styles.d.ts +55 -0
- package/fragments/empty-state/EmptyState.styles.js +23 -0
- package/fragments/empty-state/EmptyState.styles.js.map +1 -0
- package/fragments/empty-state/empty-state.css +39 -0
- package/fragments/form/FormCard.d.ts +14 -0
- package/fragments/form/FormCard.js +14 -0
- package/fragments/form/FormCard.js.map +1 -0
- package/fragments/form/FormCard.styles.d.ts +49 -0
- package/fragments/form/FormCard.styles.js +23 -0
- package/fragments/form/FormCard.styles.js.map +1 -0
- package/fragments/form/FormSection.d.ts +3 -1
- package/fragments/form/FormSection.js +2 -2
- package/fragments/form/FormSection.js.map +1 -1
- package/fragments/form/FormSection.styles.d.ts +6 -0
- package/fragments/form/FormSection.styles.js +2 -0
- package/fragments/form/FormSection.styles.js.map +1 -1
- package/fragments/form/form-card.css +42 -0
- package/fragments/form/form-section.css +22 -10
- package/fragments/form/form.css +1 -1
- package/fragments/navbar/navbar.css +2 -2
- package/fragments/page/PageHeader.d.ts +7 -2
- package/fragments/page/PageHeader.js +3 -3
- package/fragments/page/PageHeader.js.map +1 -1
- package/fragments/page/PageHeader.styles.d.ts +30 -21
- package/fragments/page/PageHeader.styles.js +10 -0
- package/fragments/page/PageHeader.styles.js.map +1 -1
- package/fragments/page/page-header.css +23 -3
- package/fragments/save-bar/SaveBar.d.ts +12 -0
- package/fragments/save-bar/SaveBar.js +15 -0
- package/fragments/save-bar/SaveBar.js.map +1 -0
- package/fragments/save-bar/SaveBar.styles.d.ts +37 -0
- package/fragments/save-bar/SaveBar.styles.js +16 -0
- package/fragments/save-bar/SaveBar.styles.js.map +1 -0
- package/fragments/save-bar/save-bar.css +28 -0
- package/fragments/shell/shell.css +8 -4
- package/fragments/sidebar/Sidebar.js +4 -1
- package/fragments/sidebar/Sidebar.js.map +1 -1
- package/fragments/sidebar/sidebar.css +52 -30
- package/fragments/stat/StatCard.d.ts +29 -0
- package/fragments/stat/StatCard.js +20 -0
- package/fragments/stat/StatCard.js.map +1 -0
- package/fragments/stat/StatCard.styles.d.ts +85 -0
- package/fragments/stat/StatCard.styles.js +26 -0
- package/fragments/stat/StatCard.styles.js.map +1 -0
- package/fragments/stat/stat-card.css +64 -0
- package/fragments/widget/Widget.d.ts +9 -2
- package/fragments/widget/Widget.js +4 -3
- package/fragments/widget/Widget.js.map +1 -1
- package/fragments/widget/Widget.styles.d.ts +51 -0
- package/fragments/widget/Widget.styles.js +12 -0
- package/fragments/widget/Widget.styles.js.map +1 -1
- package/fragments/widget/widget.css +49 -4
- package/index.css +138 -37
- package/index.d.ts +5 -0
- package/index.js +5 -0
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/code-snippet/code-snippet.css +18 -0
- package/src/components/segmented-control/segmented-control.css +41 -0
- package/src/fragments/empty-state/empty-state.css +39 -0
- package/src/fragments/form/form-card.css +42 -0
- package/src/fragments/form/form-section.css +22 -10
- package/src/fragments/form/form.css +1 -1
- package/src/fragments/navbar/navbar.css +2 -2
- package/src/fragments/page/page-header.css +23 -3
- package/src/fragments/save-bar/save-bar.css +28 -0
- package/src/fragments/shell/shell.css +8 -4
- package/src/fragments/sidebar/sidebar.css +52 -30
- package/src/fragments/stat/stat-card.css +64 -0
- package/src/fragments/widget/widget.css +49 -4
- package/src/index.css +138 -37
- package/src/theme.example.css +26 -0
- package/theme.example.css +26 -0
|
@@ -4,27 +4,30 @@
|
|
|
4
4
|
}
|
|
5
5
|
|
|
6
6
|
.fragment-sidebar__collapsed {
|
|
7
|
-
@apply fixed top-0 left-0 border-r border-border
|
|
7
|
+
@apply fixed top-0 left-0 border-r border-border bg-sidebar text-sidebar-foreground
|
|
8
|
+
flex flex-col h-screen gap-4 transition-all z-40;
|
|
8
9
|
}
|
|
9
10
|
|
|
10
11
|
.fragment-sidebar__collapsed-body {
|
|
11
|
-
@apply w-
|
|
12
|
+
@apply w-16 items-center flex flex-col gap-6 px-2 pt-5 overflow-y-auto flex-1;
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
.fragment-sidebar__collapsed-footer {
|
|
15
|
-
@apply w-
|
|
16
|
+
@apply w-16 items-center flex flex-col gap-3 px-2 pb-4;
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
.fragment-sidebar__expanded {
|
|
19
|
-
@apply fixed top-0 left-0 border-r border-border
|
|
20
|
+
@apply fixed top-0 left-0 border-r border-border bg-sidebar text-sidebar-foreground
|
|
21
|
+
flex flex-col h-screen gap-4 overflow-hidden transition-all z-40;
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
.fragment-sidebar__expanded-body {
|
|
23
|
-
@apply w-
|
|
25
|
+
@apply w-64 flex flex-col gap-6 px-3 pt-5 overflow-y-auto flex-1;
|
|
24
26
|
}
|
|
25
27
|
|
|
28
|
+
/* The footer is chrome (account, workspace), so it is tucked behind a hairline. */
|
|
26
29
|
.fragment-sidebar__expanded-footer {
|
|
27
|
-
@apply w-
|
|
30
|
+
@apply w-64 flex flex-col gap-2 px-3 pt-3 pb-4 border-t border-border;
|
|
28
31
|
}
|
|
29
32
|
|
|
30
33
|
.fragment-sidebar__placeholder {
|
|
@@ -32,15 +35,18 @@
|
|
|
32
35
|
}
|
|
33
36
|
|
|
34
37
|
.fragment-sidebar__layout-button-wrapper {
|
|
35
|
-
@apply fixed top-6 transition-all;
|
|
38
|
+
@apply fixed top-6 transition-all z-50;
|
|
36
39
|
}
|
|
37
40
|
|
|
38
41
|
.fragment-sidebar__layout-button {
|
|
39
|
-
@apply h-6! w-6
|
|
42
|
+
@apply h-6! w-6! min-w-6! bg-surface! border border-border shadow-sm text-muted;
|
|
43
|
+
& svg {
|
|
44
|
+
@apply size-3.5;
|
|
45
|
+
}
|
|
40
46
|
}
|
|
41
47
|
|
|
42
48
|
.fragment-sidebar__bottom-nav {
|
|
43
|
-
@apply fixed md:hidden z-50 bottom-0 bg-
|
|
49
|
+
@apply fixed md:hidden z-50 bottom-0 bg-sidebar text-sidebar-foreground flex w-full gap-2 px-2 py-1 border-t border-border;
|
|
44
50
|
& > *:nth-child(n+5):not(:last-child) {
|
|
45
51
|
@apply hidden;
|
|
46
52
|
}
|
|
@@ -67,7 +73,7 @@
|
|
|
67
73
|
.fragment-sidebar__collapsed-nav {
|
|
68
74
|
@apply flex flex-col gap-1;
|
|
69
75
|
& svg {
|
|
70
|
-
@apply size-
|
|
76
|
+
@apply size-[18px]! shrink-0 self-center;
|
|
71
77
|
}
|
|
72
78
|
}
|
|
73
79
|
|
|
@@ -104,26 +110,40 @@
|
|
|
104
110
|
}
|
|
105
111
|
|
|
106
112
|
.fragment-sidebar__custom-item {
|
|
107
|
-
@apply px-
|
|
113
|
+
@apply px-1;
|
|
108
114
|
}
|
|
109
115
|
|
|
110
116
|
.fragment-sidebar__nav {
|
|
111
|
-
@apply text-sm;
|
|
117
|
+
@apply text-sm flex flex-col gap-0.5;
|
|
118
|
+
|
|
119
|
+
/* Group label: quiet, so it organises the list without competing with it. */
|
|
120
|
+
& > .header {
|
|
121
|
+
@apply px-3 pb-1 text-xs font-medium text-muted;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.list-box {
|
|
125
|
+
@apply gap-0.5;
|
|
126
|
+
}
|
|
112
127
|
|
|
113
128
|
.list-box-item {
|
|
114
|
-
@apply px-3! pr-1! py-1! h-
|
|
129
|
+
@apply px-3! pr-1! py-1! h-9! gap-3! rounded-lg! font-normal text-sidebar-foreground/80;
|
|
130
|
+
&:hover, &[data-hovered="true"] {
|
|
131
|
+
background-color: var(--sidebar-default, var(--default)) !important;
|
|
132
|
+
@apply text-sidebar-foreground;
|
|
133
|
+
}
|
|
115
134
|
}
|
|
116
135
|
|
|
117
136
|
& svg {
|
|
118
|
-
@apply size-
|
|
137
|
+
@apply size-[18px] shrink-0 self-center;
|
|
119
138
|
}
|
|
120
139
|
}
|
|
121
140
|
|
|
122
141
|
.fragment-sidebar__accordion-trigger {
|
|
123
|
-
@apply w-full flex items-center gap-3 h-
|
|
124
|
-
text-foreground transition-colors;
|
|
142
|
+
@apply w-full flex items-center gap-3 h-9 px-3 pr-1 py-1 rounded-lg text-sm font-normal cursor-pointer
|
|
143
|
+
text-sidebar-foreground transition-colors;
|
|
125
144
|
&:hover, &[data-hovered="true"] {
|
|
126
|
-
|
|
145
|
+
/* `--default` is a page-level palette colour; opt out per-rail with `--sidebar-default`. */
|
|
146
|
+
background-color: var(--sidebar-default, var(--default)) !important;
|
|
127
147
|
}
|
|
128
148
|
& > .fragment-sidebar__accordion-label {
|
|
129
149
|
@apply flex-1 text-left;
|
|
@@ -131,7 +151,7 @@
|
|
|
131
151
|
}
|
|
132
152
|
|
|
133
153
|
.fragment-sidebar__accordion-trigger--active {
|
|
134
|
-
|
|
154
|
+
color: var(--sidebar-accent-soft-foreground, var(--accent-soft-foreground));
|
|
135
155
|
}
|
|
136
156
|
|
|
137
157
|
.fragment-sidebar__accordion-trigger .accordion__indicator {
|
|
@@ -149,7 +169,7 @@
|
|
|
149
169
|
@apply relative pl-7;
|
|
150
170
|
&::before {
|
|
151
171
|
content: '';
|
|
152
|
-
@apply absolute top-0 bottom-0 w-px bg-foreground opacity-15 rounded-full left-5;
|
|
172
|
+
@apply absolute top-0 bottom-0 w-px bg-sidebar-foreground opacity-15 rounded-full left-5;
|
|
153
173
|
}
|
|
154
174
|
.list-box {
|
|
155
175
|
@apply overflow-visible;
|
|
@@ -157,14 +177,16 @@
|
|
|
157
177
|
}
|
|
158
178
|
|
|
159
179
|
.fragment-sidebar__nav-item--active {
|
|
160
|
-
|
|
180
|
+
/* `--accent-soft` is translucent, so it composites over the rail, not the page. */
|
|
181
|
+
@apply bg-accent-soft! font-medium!;
|
|
182
|
+
color: var(--sidebar-accent-soft-foreground, var(--accent-soft-foreground)) !important;
|
|
161
183
|
}
|
|
162
184
|
|
|
163
185
|
.fragment-sidebar__sub-item {
|
|
164
186
|
@apply pl-8! relative;
|
|
165
187
|
&::before {
|
|
166
188
|
content: '';
|
|
167
|
-
@apply absolute -left-3 ml-px top-1/2 -translate-y-1/2 w-3 h-px bg-foreground opacity-15;
|
|
189
|
+
@apply absolute -left-3 ml-px top-1/2 -translate-y-1/2 w-3 h-px bg-sidebar-foreground opacity-15;
|
|
168
190
|
}
|
|
169
191
|
}
|
|
170
192
|
|
|
@@ -175,13 +197,13 @@
|
|
|
175
197
|
/* Layout modifier variants */
|
|
176
198
|
.fragment-sidebar--auto {
|
|
177
199
|
.fragment-sidebar__expanded {
|
|
178
|
-
@apply w-
|
|
200
|
+
@apply w-16 opacity-0 pointer-events-none xl:w-64 xl:opacity-100 xl:pointer-events-auto;
|
|
179
201
|
}
|
|
180
202
|
.fragment-sidebar__placeholder {
|
|
181
|
-
@apply w-
|
|
203
|
+
@apply w-16 opacity-0 pointer-events-none xl:w-64 xl:opacity-100 xl:pointer-events-auto;
|
|
182
204
|
}
|
|
183
205
|
.fragment-sidebar__layout-button-wrapper {
|
|
184
|
-
@apply left-
|
|
206
|
+
@apply left-16 translate-x-1/2 rotate-180 xl:left-64 xl:-translate-x-1/2 xl:rotate-0;
|
|
185
207
|
}
|
|
186
208
|
.fragment-sidebar__collapsed {
|
|
187
209
|
@apply xl:opacity-0;
|
|
@@ -190,13 +212,13 @@
|
|
|
190
212
|
|
|
191
213
|
.fragment-sidebar--collapsed {
|
|
192
214
|
.fragment-sidebar__expanded {
|
|
193
|
-
@apply w-
|
|
215
|
+
@apply w-16 opacity-0 pointer-events-none;
|
|
194
216
|
}
|
|
195
217
|
.fragment-sidebar__placeholder {
|
|
196
|
-
@apply w-
|
|
218
|
+
@apply w-16 opacity-0 pointer-events-none;
|
|
197
219
|
}
|
|
198
220
|
.fragment-sidebar__layout-button-wrapper {
|
|
199
|
-
@apply left-
|
|
221
|
+
@apply left-16 translate-x-1/2 rotate-180;
|
|
200
222
|
}
|
|
201
223
|
}
|
|
202
224
|
|
|
@@ -205,13 +227,13 @@
|
|
|
205
227
|
@apply opacity-0;
|
|
206
228
|
}
|
|
207
229
|
.fragment-sidebar__expanded {
|
|
208
|
-
@apply w-
|
|
230
|
+
@apply w-64;
|
|
209
231
|
}
|
|
210
232
|
.fragment-sidebar__placeholder {
|
|
211
|
-
@apply w-
|
|
233
|
+
@apply w-64;
|
|
212
234
|
}
|
|
213
235
|
.fragment-sidebar__layout-button-wrapper {
|
|
214
|
-
@apply left-
|
|
236
|
+
@apply left-64 -translate-x-1/2;
|
|
215
237
|
}
|
|
216
238
|
}
|
|
217
239
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export interface StatCardDelta {
|
|
2
|
+
/** Already formatted and signed, e.g. "+12%". */
|
|
3
|
+
value: React.ReactNode;
|
|
4
|
+
direction: 'up' | 'down' | 'flat';
|
|
5
|
+
/**
|
|
6
|
+
* Whether this direction is good news. Defaults to "up is good"; pass it explicitly for a
|
|
7
|
+
* number where down is the win (a bounce rate, a cost).
|
|
8
|
+
*/
|
|
9
|
+
sentiment?: 'positive' | 'negative' | 'neutral';
|
|
10
|
+
/** The period the change is measured against, e.g. "vs. previous 30 days". */
|
|
11
|
+
label?: React.ReactNode;
|
|
12
|
+
}
|
|
13
|
+
export interface StatCardProps {
|
|
14
|
+
label: React.ReactNode;
|
|
15
|
+
value: React.ReactNode;
|
|
16
|
+
icon?: React.ReactNode;
|
|
17
|
+
delta?: StatCardDelta;
|
|
18
|
+
/** One quiet line under the value. */
|
|
19
|
+
hint?: React.ReactNode;
|
|
20
|
+
/** Shown behind an info icon beside the label. */
|
|
21
|
+
help?: React.ReactNode;
|
|
22
|
+
/** Accessible name of the info icon. */
|
|
23
|
+
helpLabel?: string;
|
|
24
|
+
isLoading?: boolean;
|
|
25
|
+
/** Marks the card as the one the view is about: a lifted surface and a larger value. */
|
|
26
|
+
emphasis?: boolean;
|
|
27
|
+
className?: string;
|
|
28
|
+
}
|
|
29
|
+
export declare const StatCard: React.FC<StatCardProps>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
/**
|
|
4
|
+
* A single headline number: label, value, an optional change against a named period and a hint.
|
|
5
|
+
*/
|
|
6
|
+
import { Card, Skeleton, Tooltip } from '@heroui/react';
|
|
7
|
+
import { IconArrowDownRight, IconArrowUpRight, IconInfoCircle, IconMinus } from '@tabler/icons-react';
|
|
8
|
+
import { statCard } from './StatCard.styles';
|
|
9
|
+
const deltaIcon = {
|
|
10
|
+
up: IconArrowUpRight,
|
|
11
|
+
down: IconArrowDownRight,
|
|
12
|
+
flat: IconMinus,
|
|
13
|
+
};
|
|
14
|
+
export const StatCard = ({ label, value, icon, delta, hint, help, helpLabel = 'More information', isLoading, emphasis, className, }) => {
|
|
15
|
+
const sentiment = delta?.sentiment ?? (delta?.direction === 'up' ? 'positive' : delta?.direction === 'down' ? 'negative' : 'neutral');
|
|
16
|
+
const v = statCard({ emphasis, sentiment });
|
|
17
|
+
const DeltaIcon = delta ? deltaIcon[delta.direction] : null;
|
|
18
|
+
return (_jsxs(Card, { className: v.base({ className }), children: [_jsxs("div", { className: v.top(), children: [_jsxs("span", { className: v.label(), children: [label, help && (_jsxs(Tooltip, { delay: 0, children: [_jsx(Tooltip.Trigger, { className: v.help(), "aria-label": helpLabel, tabIndex: 0, children: _jsx(IconInfoCircle, { size: 14, stroke: 1.75 }) }), _jsx(Tooltip.Content, { className: "max-w-xs", children: help })] }))] }), icon && _jsx("span", { className: v.icon(), children: icon })] }), isLoading ? (_jsx(Skeleton, { className: v.skeleton() })) : (_jsxs("div", { className: v.valueRow(), children: [_jsx("span", { className: v.value(), children: value }), delta && DeltaIcon && (_jsxs("span", { className: v.delta(), children: [_jsx(DeltaIcon, { size: 14, stroke: 2 }), delta.value] }))] })), (hint || delta?.label) && !isLoading && (_jsx("p", { className: v.hint(), children: hint ?? delta?.label }))] }));
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=StatCard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StatCard.js","sourceRoot":"","sources":["../../src/fragments/stat/StatCard.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACtG,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAgC7C,MAAM,SAAS,GAAG;IAChB,EAAE,EAAE,gBAAgB;IACpB,IAAI,EAAE,kBAAkB;IACxB,IAAI,EAAE,SAAS;CACP,CAAC;AAEX,MAAM,CAAC,MAAM,QAAQ,GAA4B,CAAC,EAChD,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,GAAG,kBAAkB,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,GACtG,EAAE,EAAE;IACH,MAAM,SAAS,GAAG,KAAK,EAAE,SAAS,IAAI,CACpC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,EAAE,SAAS,KAAK,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAC9F,CAAC;IACF,MAAM,CAAC,GAAG,QAAQ,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC;IAC5C,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAE5D,OAAO,CACL,MAAC,IAAI,IAAC,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,CAAC,aACpC,eAAK,SAAS,EAAE,CAAC,CAAC,GAAG,EAAE,aACrB,gBAAM,SAAS,EAAE,CAAC,CAAC,KAAK,EAAE,aACvB,KAAK,EACL,IAAI,IAAI,CACP,MAAC,OAAO,IAAC,KAAK,EAAE,CAAC,aACf,KAAC,OAAO,CAAC,OAAO,IAAC,SAAS,EAAE,CAAC,CAAC,IAAI,EAAE,gBAAc,SAAS,EAAE,QAAQ,EAAE,CAAC,YACtE,KAAC,cAAc,IAAC,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,GAAI,GAC1B,EAClB,KAAC,OAAO,CAAC,OAAO,IAAC,SAAS,EAAC,UAAU,YAAE,IAAI,GAAmB,IACtD,CACX,IACI,EACN,IAAI,IAAI,eAAM,SAAS,EAAE,CAAC,CAAC,IAAI,EAAE,YAAG,IAAI,GAAQ,IAC7C,EACL,SAAS,CAAC,CAAC,CAAC,CACX,KAAC,QAAQ,IAAC,SAAS,EAAE,CAAC,CAAC,QAAQ,EAAE,GAAI,CACtC,CAAC,CAAC,CAAC,CACF,eAAK,SAAS,EAAE,CAAC,CAAC,QAAQ,EAAE,aAC1B,eAAM,SAAS,EAAE,CAAC,CAAC,KAAK,EAAE,YAAG,KAAK,GAAQ,EACzC,KAAK,IAAI,SAAS,IAAI,CACrB,gBAAM,SAAS,EAAE,CAAC,CAAC,KAAK,EAAE,aACxB,KAAC,SAAS,IAAC,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,GAAI,EACjC,KAAK,CAAC,KAAK,IACP,CACR,IACG,CACP,EACA,CAAC,IAAI,IAAI,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,SAAS,IAAI,CACvC,YAAG,SAAS,EAAE,CAAC,CAAC,IAAI,EAAE,YAAG,IAAI,IAAI,KAAK,EAAE,KAAK,GAAK,CACnD,IACI,CACR,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
export declare const statCard: import("tailwind-variants").TVReturnType<{
|
|
2
|
+
emphasis: {
|
|
3
|
+
true: {
|
|
4
|
+
base: string;
|
|
5
|
+
};
|
|
6
|
+
};
|
|
7
|
+
sentiment: {
|
|
8
|
+
positive: {
|
|
9
|
+
delta: string;
|
|
10
|
+
};
|
|
11
|
+
negative: {
|
|
12
|
+
delta: string;
|
|
13
|
+
};
|
|
14
|
+
neutral: {
|
|
15
|
+
delta: string;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
}, {
|
|
19
|
+
base: string;
|
|
20
|
+
top: string;
|
|
21
|
+
label: string;
|
|
22
|
+
help: string;
|
|
23
|
+
icon: string;
|
|
24
|
+
valueRow: string;
|
|
25
|
+
value: string;
|
|
26
|
+
delta: string;
|
|
27
|
+
hint: string;
|
|
28
|
+
skeleton: string;
|
|
29
|
+
}, undefined, {
|
|
30
|
+
emphasis: {
|
|
31
|
+
true: {
|
|
32
|
+
base: string;
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
sentiment: {
|
|
36
|
+
positive: {
|
|
37
|
+
delta: string;
|
|
38
|
+
};
|
|
39
|
+
negative: {
|
|
40
|
+
delta: string;
|
|
41
|
+
};
|
|
42
|
+
neutral: {
|
|
43
|
+
delta: string;
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
}, {
|
|
47
|
+
base: string;
|
|
48
|
+
top: string;
|
|
49
|
+
label: string;
|
|
50
|
+
help: string;
|
|
51
|
+
icon: string;
|
|
52
|
+
valueRow: string;
|
|
53
|
+
value: string;
|
|
54
|
+
delta: string;
|
|
55
|
+
hint: string;
|
|
56
|
+
skeleton: string;
|
|
57
|
+
}, import("tailwind-variants").TVReturnTypeLike<{
|
|
58
|
+
emphasis: {
|
|
59
|
+
true: {
|
|
60
|
+
base: string;
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
sentiment: {
|
|
64
|
+
positive: {
|
|
65
|
+
delta: string;
|
|
66
|
+
};
|
|
67
|
+
negative: {
|
|
68
|
+
delta: string;
|
|
69
|
+
};
|
|
70
|
+
neutral: {
|
|
71
|
+
delta: string;
|
|
72
|
+
};
|
|
73
|
+
};
|
|
74
|
+
}, {
|
|
75
|
+
base: string;
|
|
76
|
+
top: string;
|
|
77
|
+
label: string;
|
|
78
|
+
help: string;
|
|
79
|
+
icon: string;
|
|
80
|
+
valueRow: string;
|
|
81
|
+
value: string;
|
|
82
|
+
delta: string;
|
|
83
|
+
hint: string;
|
|
84
|
+
skeleton: string;
|
|
85
|
+
}>>;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { tv } from 'tailwind-variants';
|
|
2
|
+
export const statCard = tv({
|
|
3
|
+
slots: {
|
|
4
|
+
base: 'fragment-stat-card',
|
|
5
|
+
top: 'fragment-stat-card__top',
|
|
6
|
+
label: 'fragment-stat-card__label',
|
|
7
|
+
help: 'fragment-stat-card__help',
|
|
8
|
+
icon: 'fragment-stat-card__icon',
|
|
9
|
+
valueRow: 'fragment-stat-card__value-row',
|
|
10
|
+
value: 'fragment-stat-card__value',
|
|
11
|
+
delta: 'fragment-stat-card__delta',
|
|
12
|
+
hint: 'fragment-stat-card__hint',
|
|
13
|
+
skeleton: 'fragment-stat-card__skeleton',
|
|
14
|
+
},
|
|
15
|
+
variants: {
|
|
16
|
+
emphasis: {
|
|
17
|
+
true: { base: 'fragment-stat-card--emphasis' },
|
|
18
|
+
},
|
|
19
|
+
sentiment: {
|
|
20
|
+
positive: { delta: 'fragment-stat-card__delta--positive' },
|
|
21
|
+
negative: { delta: 'fragment-stat-card__delta--negative' },
|
|
22
|
+
neutral: { delta: 'fragment-stat-card__delta--neutral' },
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
//# sourceMappingURL=StatCard.styles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StatCard.styles.js","sourceRoot":"","sources":["../../src/fragments/stat/StatCard.styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,mBAAmB,CAAC;AAEvC,MAAM,CAAC,MAAM,QAAQ,GAAG,EAAE,CAAC;IACzB,KAAK,EAAE;QACL,IAAI,EAAE,oBAAoB;QAC1B,GAAG,EAAE,yBAAyB;QAC9B,KAAK,EAAE,2BAA2B;QAClC,IAAI,EAAE,0BAA0B;QAChC,IAAI,EAAE,0BAA0B;QAChC,QAAQ,EAAE,+BAA+B;QACzC,KAAK,EAAE,2BAA2B;QAClC,KAAK,EAAE,2BAA2B;QAClC,IAAI,EAAE,0BAA0B;QAChC,QAAQ,EAAE,8BAA8B;KACzC;IACD,QAAQ,EAAE;QACR,QAAQ,EAAE;YACR,IAAI,EAAE,EAAE,IAAI,EAAE,8BAA8B,EAAE;SAC/C;QACD,SAAS,EAAE;YACT,QAAQ,EAAE,EAAE,KAAK,EAAE,qCAAqC,EAAE;YAC1D,QAAQ,EAAE,EAAE,KAAK,EAAE,qCAAqC,EAAE;YAC1D,OAAO,EAAE,EAAE,KAAK,EAAE,oCAAoC,EAAE;SACzD;KACF;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
@layer components {
|
|
2
|
+
.fragment-stat-card {
|
|
3
|
+
@apply p-4 gap-2 min-w-0;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.fragment-stat-card__top {
|
|
7
|
+
@apply flex items-center justify-between gap-2;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.fragment-stat-card__label {
|
|
11
|
+
@apply flex items-center gap-1 text-xs font-medium text-muted min-w-0;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.fragment-stat-card__help {
|
|
15
|
+
@apply inline-flex text-muted/70 hover:text-foreground cursor-help rounded-full outline-none
|
|
16
|
+
focus-visible:ring-2 focus-visible:ring-focus;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.fragment-stat-card__icon {
|
|
20
|
+
@apply flex size-8 shrink-0 items-center justify-center rounded-lg bg-default text-muted;
|
|
21
|
+
& svg {
|
|
22
|
+
@apply size-4;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.fragment-stat-card__value-row {
|
|
27
|
+
@apply flex flex-wrap items-baseline gap-x-2 gap-y-1;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/* Proportional figures: a standalone number with tabular digits looks loosely set. */
|
|
31
|
+
.fragment-stat-card__value {
|
|
32
|
+
@apply text-2xl font-semibold tracking-tight text-foreground truncate;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.fragment-stat-card__delta {
|
|
36
|
+
@apply inline-flex items-center gap-0.5 rounded-md px-1.5 py-0.5 text-xs font-medium;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.fragment-stat-card__delta--positive {
|
|
40
|
+
@apply bg-success-soft text-success-soft-foreground;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.fragment-stat-card__delta--negative {
|
|
44
|
+
@apply bg-danger-soft text-danger-soft-foreground;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.fragment-stat-card__delta--neutral {
|
|
48
|
+
@apply bg-default text-muted;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.fragment-stat-card__hint {
|
|
52
|
+
@apply text-xs text-muted;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.fragment-stat-card__skeleton {
|
|
56
|
+
@apply h-8 w-24 rounded-lg;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.fragment-stat-card--emphasis {
|
|
60
|
+
.fragment-stat-card__value {
|
|
61
|
+
@apply text-3xl;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -8,8 +8,15 @@ export interface WidgetProps {
|
|
|
8
8
|
startContent?: React.ReactNode;
|
|
9
9
|
endContent?: React.ReactNode;
|
|
10
10
|
};
|
|
11
|
-
title?:
|
|
12
|
-
|
|
11
|
+
title?: React.ReactNode;
|
|
12
|
+
/** One line under the title saying what the widget measures. */
|
|
13
|
+
description?: React.ReactNode;
|
|
14
|
+
/** Pinned to the bottom of the card, behind a hairline: a "view all" link, a timestamp. */
|
|
15
|
+
footer?: React.ReactNode;
|
|
16
|
+
size?: 'sm' | 'md' | 'lg' | 'full';
|
|
17
|
+
/** `none` lets a table or a list run edge to edge inside the card. */
|
|
18
|
+
padding?: 'none' | 'sm' | 'md';
|
|
13
19
|
variant?: CardProps['variant'];
|
|
20
|
+
className?: string;
|
|
14
21
|
}
|
|
15
22
|
export declare const Widget: React.FC<WidgetProps>;
|
|
@@ -5,8 +5,9 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
5
5
|
*/
|
|
6
6
|
import { Card } from '@heroui/react';
|
|
7
7
|
import { widget } from './Widget.styles';
|
|
8
|
-
export const Widget = ({ children, title, header, variant, ...props }) => {
|
|
9
|
-
const
|
|
10
|
-
|
|
8
|
+
export const Widget = ({ children, title, description, header, footer, variant, className, ...props }) => {
|
|
9
|
+
const v = widget(props);
|
|
10
|
+
const hasHeader = !!(title || description || header?.startContent || header?.endContent);
|
|
11
|
+
return (_jsxs(Card, { className: v.base({ className }), variant: variant, children: [hasHeader && (_jsxs(Card.Header, { className: v.header(), children: [header?.startContent && _jsx("div", { className: v.headerStartContent(), children: header.startContent }), _jsxs("div", { className: v.heading(), children: [title && _jsx("h3", { className: v.title(), children: title }), description && _jsx("p", { className: v.description(), children: description })] }), header?.endContent && _jsx("div", { className: v.headerEndContent(), children: header.endContent })] })), _jsx(Card.Content, { className: v.content(), children: children }), footer && _jsx(Card.Footer, { className: v.footer(), children: footer })] }));
|
|
11
12
|
};
|
|
12
13
|
//# sourceMappingURL=Widget.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Widget.js","sourceRoot":"","sources":["../../src/fragments/widget/Widget.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAa,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"Widget.js","sourceRoot":"","sources":["../../src/fragments/widget/Widget.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAa,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAoBzC,MAAM,CAAC,MAAM,MAAM,GAA0B,CAAC,EAC5C,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,KAAK,EAC3E,EAAE,EAAE;IACH,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IACxB,MAAM,SAAS,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI,WAAW,IAAI,MAAM,EAAE,YAAY,IAAI,MAAM,EAAE,UAAU,CAAC,CAAC;IAEzF,OAAO,CACL,MAAC,IAAI,IAAC,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,OAAO,aACrD,SAAS,IAAI,CACZ,MAAC,IAAI,CAAC,MAAM,IAAC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,aAC/B,MAAM,EAAE,YAAY,IAAI,cAAK,SAAS,EAAE,CAAC,CAAC,kBAAkB,EAAE,YAAG,MAAM,CAAC,YAAY,GAAO,EAC5F,eAAK,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE,aACxB,KAAK,IAAI,aAAI,SAAS,EAAE,CAAC,CAAC,KAAK,EAAE,YAAG,KAAK,GAAM,EAC/C,WAAW,IAAI,YAAG,SAAS,EAAE,CAAC,CAAC,WAAW,EAAE,YAAG,WAAW,GAAK,IAC5D,EACL,MAAM,EAAE,UAAU,IAAI,cAAK,SAAS,EAAE,CAAC,CAAC,gBAAgB,EAAE,YAAG,MAAM,CAAC,UAAU,GAAO,IAC1E,CACf,EACD,KAAC,IAAI,CAAC,OAAO,IAAC,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE,YACjC,QAAQ,GACI,EACd,MAAM,IAAI,KAAC,IAAI,CAAC,MAAM,IAAC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,YAAG,MAAM,GAAe,IAChE,CACR,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -9,12 +9,29 @@ export declare const widget: import("tailwind-variants").TVReturnType<{
|
|
|
9
9
|
lg: {
|
|
10
10
|
base: string;
|
|
11
11
|
};
|
|
12
|
+
full: {
|
|
13
|
+
base: string;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
padding: {
|
|
17
|
+
none: {
|
|
18
|
+
base: string;
|
|
19
|
+
};
|
|
20
|
+
sm: {
|
|
21
|
+
base: string;
|
|
22
|
+
};
|
|
23
|
+
md: {};
|
|
12
24
|
};
|
|
13
25
|
}, {
|
|
14
26
|
base: string;
|
|
15
27
|
header: string;
|
|
28
|
+
headerStartContent: string;
|
|
29
|
+
heading: string;
|
|
30
|
+
title: string;
|
|
31
|
+
description: string;
|
|
16
32
|
headerEndContent: string;
|
|
17
33
|
content: string;
|
|
34
|
+
footer: string;
|
|
18
35
|
}, undefined, {
|
|
19
36
|
size: {
|
|
20
37
|
sm: {
|
|
@@ -26,12 +43,29 @@ export declare const widget: import("tailwind-variants").TVReturnType<{
|
|
|
26
43
|
lg: {
|
|
27
44
|
base: string;
|
|
28
45
|
};
|
|
46
|
+
full: {
|
|
47
|
+
base: string;
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
padding: {
|
|
51
|
+
none: {
|
|
52
|
+
base: string;
|
|
53
|
+
};
|
|
54
|
+
sm: {
|
|
55
|
+
base: string;
|
|
56
|
+
};
|
|
57
|
+
md: {};
|
|
29
58
|
};
|
|
30
59
|
}, {
|
|
31
60
|
base: string;
|
|
32
61
|
header: string;
|
|
62
|
+
headerStartContent: string;
|
|
63
|
+
heading: string;
|
|
64
|
+
title: string;
|
|
65
|
+
description: string;
|
|
33
66
|
headerEndContent: string;
|
|
34
67
|
content: string;
|
|
68
|
+
footer: string;
|
|
35
69
|
}, import("tailwind-variants").TVReturnTypeLike<{
|
|
36
70
|
size: {
|
|
37
71
|
sm: {
|
|
@@ -43,10 +77,27 @@ export declare const widget: import("tailwind-variants").TVReturnType<{
|
|
|
43
77
|
lg: {
|
|
44
78
|
base: string;
|
|
45
79
|
};
|
|
80
|
+
full: {
|
|
81
|
+
base: string;
|
|
82
|
+
};
|
|
83
|
+
};
|
|
84
|
+
padding: {
|
|
85
|
+
none: {
|
|
86
|
+
base: string;
|
|
87
|
+
};
|
|
88
|
+
sm: {
|
|
89
|
+
base: string;
|
|
90
|
+
};
|
|
91
|
+
md: {};
|
|
46
92
|
};
|
|
47
93
|
}, {
|
|
48
94
|
base: string;
|
|
49
95
|
header: string;
|
|
96
|
+
headerStartContent: string;
|
|
97
|
+
heading: string;
|
|
98
|
+
title: string;
|
|
99
|
+
description: string;
|
|
50
100
|
headerEndContent: string;
|
|
51
101
|
content: string;
|
|
102
|
+
footer: string;
|
|
52
103
|
}>>;
|
|
@@ -3,18 +3,30 @@ export const widget = tv({
|
|
|
3
3
|
slots: {
|
|
4
4
|
base: 'fragment-widget',
|
|
5
5
|
header: 'fragment-widget__header',
|
|
6
|
+
headerStartContent: 'fragment-widget__header-start',
|
|
7
|
+
heading: 'fragment-widget__heading',
|
|
8
|
+
title: 'fragment-widget__title',
|
|
9
|
+
description: 'fragment-widget__description',
|
|
6
10
|
headerEndContent: 'fragment-widget__header-end',
|
|
7
11
|
content: 'fragment-widget__content',
|
|
12
|
+
footer: 'fragment-widget__footer',
|
|
8
13
|
},
|
|
9
14
|
variants: {
|
|
10
15
|
size: {
|
|
11
16
|
sm: { base: 'fragment-widget--sm' },
|
|
12
17
|
md: { base: 'fragment-widget--md' },
|
|
13
18
|
lg: { base: 'fragment-widget--lg' },
|
|
19
|
+
full: { base: 'fragment-widget--full' },
|
|
20
|
+
},
|
|
21
|
+
padding: {
|
|
22
|
+
none: { base: 'fragment-widget--flush' },
|
|
23
|
+
sm: { base: 'fragment-widget--padding-sm' },
|
|
24
|
+
md: {},
|
|
14
25
|
},
|
|
15
26
|
},
|
|
16
27
|
defaultVariants: {
|
|
17
28
|
size: 'sm',
|
|
29
|
+
padding: 'md',
|
|
18
30
|
},
|
|
19
31
|
});
|
|
20
32
|
//# sourceMappingURL=Widget.styles.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Widget.styles.js","sourceRoot":"","sources":["../../src/fragments/widget/Widget.styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,mBAAmB,CAAC;AAEvC,MAAM,CAAC,MAAM,MAAM,GAAG,EAAE,CAAC;IACvB,KAAK,EAAE;QACL,IAAI,EAAE,iBAAiB;QACvB,MAAM,EAAE,yBAAyB;QACjC,gBAAgB,EAAE,6BAA6B;QAC/C,OAAO,EAAE,0BAA0B;
|
|
1
|
+
{"version":3,"file":"Widget.styles.js","sourceRoot":"","sources":["../../src/fragments/widget/Widget.styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,mBAAmB,CAAC;AAEvC,MAAM,CAAC,MAAM,MAAM,GAAG,EAAE,CAAC;IACvB,KAAK,EAAE;QACL,IAAI,EAAE,iBAAiB;QACvB,MAAM,EAAE,yBAAyB;QACjC,kBAAkB,EAAE,+BAA+B;QACnD,OAAO,EAAE,0BAA0B;QACnC,KAAK,EAAE,wBAAwB;QAC/B,WAAW,EAAE,8BAA8B;QAC3C,gBAAgB,EAAE,6BAA6B;QAC/C,OAAO,EAAE,0BAA0B;QACnC,MAAM,EAAE,yBAAyB;KAClC;IACD,QAAQ,EAAE;QACR,IAAI,EAAE;YACJ,EAAE,EAAE,EAAE,IAAI,EAAE,qBAAqB,EAAE;YACnC,EAAE,EAAE,EAAE,IAAI,EAAE,qBAAqB,EAAE;YACnC,EAAE,EAAE,EAAE,IAAI,EAAE,qBAAqB,EAAE;YACnC,IAAI,EAAE,EAAE,IAAI,EAAE,uBAAuB,EAAE;SACxC;QACD,OAAO,EAAE;YACP,IAAI,EAAE,EAAE,IAAI,EAAE,wBAAwB,EAAE;YACxC,EAAE,EAAE,EAAE,IAAI,EAAE,6BAA6B,EAAE;YAC3C,EAAE,EAAE,EAAE;SACP;KACF;IACD,eAAe,EAAE;QACf,IAAI,EAAE,IAAI;QACV,OAAO,EAAE,IAAI;KACd;CACF,CAAC,CAAC"}
|