@sukramj/fabric-ui 0.0.0-stage → 0.1.1
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/LICENSE +202 -0
- package/README.md +91 -2
- package/package.json +92 -4
- package/src/lib/api/client.ts +155 -0
- package/src/lib/api/index.ts +3 -0
- package/src/lib/api/schema.gen.ts +1176 -0
- package/src/lib/api/stream.ts +54 -0
- package/src/lib/context.ts +96 -0
- package/src/lib/i18n/de.json +160 -0
- package/src/lib/i18n/en.json +160 -0
- package/src/lib/i18n/index.ts +50 -0
- package/src/lib/index.ts +10 -0
- package/src/lib/kit/Badge.svelte +26 -0
- package/src/lib/kit/Button.svelte +49 -0
- package/src/lib/kit/Card.svelte +16 -0
- package/src/lib/kit/DataTable.svelte +239 -0
- package/src/lib/kit/EmptyState.svelte +24 -0
- package/src/lib/kit/ErrorState.svelte +22 -0
- package/src/lib/kit/Icon.svelte +12 -0
- package/src/lib/kit/Input.svelte +22 -0
- package/src/lib/kit/LoadingState.svelte +15 -0
- package/src/lib/kit/PageHeader.svelte +32 -0
- package/src/lib/kit/PageShell.svelte +16 -0
- package/src/lib/kit/Select.svelte +49 -0
- package/src/lib/kit/Spinner.svelte +59 -0
- package/src/lib/kit/Tabs.svelte +63 -0
- package/src/lib/kit/data-table.ts +24 -0
- package/src/lib/kit/icons.ts +41 -0
- package/src/lib/kit/index.ts +21 -0
- package/src/lib/kit/tabs.ts +13 -0
- package/src/lib/kit/utils.ts +49 -0
- package/src/lib/pages/index.ts +8 -0
- package/src/lib/pages/node/Diagnostics.svelte +205 -0
- package/src/lib/pages/node/Endpoints.svelte +82 -0
- package/src/lib/pages/node/Fabrics.svelte +169 -0
- package/src/lib/pages/node/HostWarnings.svelte +41 -0
- package/src/lib/pages/node/Pair.svelte +186 -0
- package/src/lib/pages/node/Selection.svelte +407 -0
- package/src/lib/pages/node/Status.svelte +67 -0
- package/src/lib/pages/node/fields.ts +32 -0
- package/src/lib/qr.ts +58 -0
- package/src/lib/store.svelte.ts +293 -0
- package/src/lib/theme/ha-bridge.ts +156 -0
- package/src/lib/theme/index.ts +1 -0
- package/src/lib/theme/tokens.css +292 -0
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The design tokens of go-fabric-ui. Components read only the --ha-*
|
|
3
|
+
* consumption tokens, named after Home Assistant's CSS variables, so a page
|
|
4
|
+
* sits next to a Home Assistant panel without re-skinning.
|
|
5
|
+
*
|
|
6
|
+
* - :root / html.dark — the standalone palette, light and dark (`.dark`
|
|
7
|
+
* on <html> flips it).
|
|
8
|
+
* - html[data-skin="ha"] — the tokens resolve from Home Assistant's own
|
|
9
|
+
* variables (var(--primary-color, …)); ha-bridge.ts copies the live values
|
|
10
|
+
* onto :root inside an Ingress frame, and the literals are the defaults.
|
|
11
|
+
* - the palette remap recolours plain Tailwind palette utilities under the
|
|
12
|
+
* HA skin.
|
|
13
|
+
* - .table-reflow turns a data table into cards on a phone.
|
|
14
|
+
*
|
|
15
|
+
* Ported from openccu-loom assets/ui/src/app.css at b40b289a: :56-104
|
|
16
|
+
* (tokens, dark block), :106-142 (HA skin, HA dark), :144-152 (base
|
|
17
|
+
* colours), :154-240 (palette remap), :339-423 (reflow, hide-narrow). The
|
|
18
|
+
* values are verbatim. This file holds plain CSS: import it after Tailwind
|
|
19
|
+
* (see ui/README.md).
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/* HA-style semantic CSS variables. Components prefer these tokens
|
|
23
|
+
* over hard-coded slate utility classes so a future theme picker
|
|
24
|
+
* can re-skin the SPA without touching component markup. */
|
|
25
|
+
:root {
|
|
26
|
+
/* Primary tracks brand-500/600. */
|
|
27
|
+
--ha-primary-color: oklch(54.5% 0.11 184.7);
|
|
28
|
+
--ha-primary-color-hover: oklch(51.1% 0.096 186.391);
|
|
29
|
+
/* Page ground for the base document paint. In the standalone skin the body equals
|
|
30
|
+
* the card bg, so this matches --ha-card-background-color below. */
|
|
31
|
+
--ha-primary-background-color: #ffffff;
|
|
32
|
+
--ha-card-background-color: #ffffff;
|
|
33
|
+
--ha-secondary-background-color: #fafafa;
|
|
34
|
+
--ha-divider-color: #e0e0e0;
|
|
35
|
+
--ha-primary-text-color: #1f2937;
|
|
36
|
+
--ha-secondary-text-color: #64748b;
|
|
37
|
+
--ha-disabled-text-color: #9ca3af;
|
|
38
|
+
--ha-error-color: #dc2626;
|
|
39
|
+
--ha-warning-color: #d97706;
|
|
40
|
+
--ha-success-color: #059669;
|
|
41
|
+
/* Info is deliberately blue (Tailwind sky-600) so it stays
|
|
42
|
+
* distinguishable from the teal primary. */
|
|
43
|
+
--ha-info-color: oklch(58.8% 0.158 241.966);
|
|
44
|
+
--ha-elevation-card: 0 1px 2px 0 rgb(0 0 0 / 0.04);
|
|
45
|
+
--ha-elevation-modal: 0 10px 25px -5px rgb(0 0 0 / 0.15);
|
|
46
|
+
--ha-radius-card: 12px;
|
|
47
|
+
--ha-radius-control: 8px;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
html.dark {
|
|
51
|
+
/* Dark surfaces need a lighter teal for AA text/icon contrast:
|
|
52
|
+
* primary := teal-400, hover := teal-300. */
|
|
53
|
+
--ha-primary-color: oklch(77.7% 0.152 181.912);
|
|
54
|
+
--ha-primary-color-hover: oklch(85.5% 0.138 181.071);
|
|
55
|
+
/* The page ground equals the card in dark too. */
|
|
56
|
+
--ha-primary-background-color: #0f172a;
|
|
57
|
+
--ha-card-background-color: #0f172a;
|
|
58
|
+
--ha-secondary-background-color: #111827;
|
|
59
|
+
--ha-divider-color: #1f2937;
|
|
60
|
+
--ha-primary-text-color: #e5e7eb;
|
|
61
|
+
--ha-secondary-text-color: #94a3b8;
|
|
62
|
+
--ha-disabled-text-color: #475569;
|
|
63
|
+
--ha-error-color: #f87171;
|
|
64
|
+
--ha-warning-color: #fbbf24;
|
|
65
|
+
--ha-success-color: #34d399;
|
|
66
|
+
/* Info stays blue on dark too (Tailwind sky-400). */
|
|
67
|
+
--ha-info-color: oklch(74.6% 0.16 232.661);
|
|
68
|
+
--ha-elevation-card: 0 1px 2px 0 rgb(0 0 0 / 0.30);
|
|
69
|
+
--ha-elevation-modal: 0 10px 25px -5px rgb(0 0 0 / 0.50);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/* Home-Assistant skin. When data-skin="ha" the --ha-* consumption tokens
|
|
73
|
+
* resolve from HA's own CSS variables (var(--primary-color, …)); the
|
|
74
|
+
* ha-bridge copies HA's real values onto :root when embedded so the live
|
|
75
|
+
* theme wins, and the literals below are the standalone HA-default
|
|
76
|
+
* fallback. The standalone values above are untouched. */
|
|
77
|
+
html[data-skin="ha"] {
|
|
78
|
+
--ha-primary-color: var(--primary-color, #009ac7);
|
|
79
|
+
--ha-primary-color-hover: color-mix(in srgb, var(--ha-primary-color) 88%, #000);
|
|
80
|
+
--ha-primary-background-color: var(--primary-background-color, #fafafa);
|
|
81
|
+
--ha-card-background-color: var(--card-background-color, #ffffff);
|
|
82
|
+
--ha-secondary-background-color: var(--secondary-background-color, #e5e5e5);
|
|
83
|
+
--ha-divider-color: var(--divider-color, rgba(0, 0, 0, 0.12));
|
|
84
|
+
--ha-primary-text-color: var(--primary-text-color, #141414);
|
|
85
|
+
--ha-secondary-text-color: var(--secondary-text-color, #727272);
|
|
86
|
+
--ha-disabled-text-color: var(--disabled-text-color, #bdbdbd);
|
|
87
|
+
--ha-error-color: var(--error-color, #db4437);
|
|
88
|
+
--ha-warning-color: var(--warning-color, #ffa600);
|
|
89
|
+
--ha-success-color: var(--success-color, #43a047);
|
|
90
|
+
--ha-info-color: var(--info-color, #039be5);
|
|
91
|
+
--ha-radius-card: var(--ha-card-border-radius, 12px);
|
|
92
|
+
--ha-elevation-card: var(--ha-card-box-shadow, none); /* HA cards are flat */
|
|
93
|
+
--ha-elevation-modal: var(--ha-card-box-shadow, 0 8px 24px rgba(0, 0, 0, 0.18));
|
|
94
|
+
--font-sans: var(--ha-font-family-body, "Roboto", "Noto", "Helvetica Neue", Arial, sans-serif);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
html[data-skin="ha"].dark {
|
|
98
|
+
/* --ha-primary-color keeps inheriting HA's --primary-color — HA holds
|
|
99
|
+
* its accent across light/dark, so only the neutrals/hover flip here. */
|
|
100
|
+
--ha-primary-color-hover: color-mix(in srgb, var(--ha-primary-color) 88%, #fff);
|
|
101
|
+
--ha-primary-background-color: var(--primary-background-color, #111111);
|
|
102
|
+
--ha-card-background-color: var(--card-background-color, #1c1c1c);
|
|
103
|
+
--ha-secondary-background-color: var(--secondary-background-color, #282828);
|
|
104
|
+
--ha-divider-color: var(--divider-color, rgba(225, 225, 225, 0.12));
|
|
105
|
+
--ha-primary-text-color: var(--primary-text-color, #e1e1e1);
|
|
106
|
+
--ha-secondary-text-color: var(--secondary-text-color, #9b9b9b);
|
|
107
|
+
--ha-disabled-text-color: var(--disabled-text-color, #6f6f6f);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/* Base document colours track the theme tokens so the boot paint and any
|
|
111
|
+
* overscroll / rubber-band area never flash white in dark mode. The inline
|
|
112
|
+
* pre-paint script in index.html sets `.dark` before the first paint, so
|
|
113
|
+
* these already resolve to the dark values on the very first frame. */
|
|
114
|
+
html,
|
|
115
|
+
body {
|
|
116
|
+
background-color: var(--ha-primary-background-color);
|
|
117
|
+
color: var(--ha-primary-text-color);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/* Tailwind v4 compiles palette utilities (bg-slate-500, text-red-600, …)
|
|
121
|
+
* to color: var(--color-slate-500) etc. Overriding the --color-* scale
|
|
122
|
+
* under the HA skin therefore recolours every plain palette utility to
|
|
123
|
+
* HA's neutrals/error/warning/success/primary without a per-file sweep.
|
|
124
|
+
* The ramps are monotonic so `dark:` variants pick the right step; no
|
|
125
|
+
* .dark variant of this block is needed. The standalone skin keeps Tailwind's defaults
|
|
126
|
+
*. Opacity-modified utilities are inlined by
|
|
127
|
+
* Tailwind and do NOT follow this — those are rewritten to color-mix(). */
|
|
128
|
+
html[data-skin="ha"] {
|
|
129
|
+
/* neutral ramp -> HA neutral greys (light steps light, dark steps dark;
|
|
130
|
+
anchors: 900=#1c1c1c dark card, 950=#141414 HA neutral-05,
|
|
131
|
+
500=#727272 HA secondary-text, 200=#e5e5e5 HA secondary-bg) */
|
|
132
|
+
--color-slate-50: #fafafa;
|
|
133
|
+
--color-slate-100: #f2f2f2;
|
|
134
|
+
--color-slate-200: #e5e5e5;
|
|
135
|
+
--color-slate-300: #d6d6d6;
|
|
136
|
+
--color-slate-400: #b3b3b3;
|
|
137
|
+
--color-slate-500: #727272;
|
|
138
|
+
--color-slate-600: #565656;
|
|
139
|
+
--color-slate-700: #3d3d3d;
|
|
140
|
+
--color-slate-800: #282828;
|
|
141
|
+
--color-slate-900: #1c1c1c;
|
|
142
|
+
--color-slate-950: #141414;
|
|
143
|
+
/* error ramp -> HA #db4437 at 500 */
|
|
144
|
+
--color-red-50: #fdeceb;
|
|
145
|
+
--color-red-100: #f9d3d0;
|
|
146
|
+
--color-red-200: #f2aaa4;
|
|
147
|
+
--color-red-300: #ea8078;
|
|
148
|
+
--color-red-400: #e15d53;
|
|
149
|
+
--color-red-500: #db4437;
|
|
150
|
+
--color-red-600: #c33a2e;
|
|
151
|
+
--color-red-700: #a12f25;
|
|
152
|
+
--color-red-800: #7e251d;
|
|
153
|
+
--color-red-900: #5c1a15;
|
|
154
|
+
--color-red-950: #3a100d;
|
|
155
|
+
/* warning ramp -> HA #ffa600 at 500 */
|
|
156
|
+
--color-amber-50: #fff6e5;
|
|
157
|
+
--color-amber-100: #ffe9bf;
|
|
158
|
+
--color-amber-200: #ffd480;
|
|
159
|
+
--color-amber-300: #ffc040;
|
|
160
|
+
--color-amber-400: #ffb01a;
|
|
161
|
+
--color-amber-500: #ffa600;
|
|
162
|
+
--color-amber-600: #e69500;
|
|
163
|
+
--color-amber-700: #b87700;
|
|
164
|
+
--color-amber-800: #8a5900;
|
|
165
|
+
--color-amber-900: #5c3b00;
|
|
166
|
+
--color-amber-950: #3d2700;
|
|
167
|
+
/* success ramp -> HA #43a047 at 500 (apply to BOTH green and emerald) */
|
|
168
|
+
--color-green-50: #ecf5ec;
|
|
169
|
+
--color-green-100: #cfe6d0;
|
|
170
|
+
--color-green-200: #a3d0a5;
|
|
171
|
+
--color-green-300: #77ba7a;
|
|
172
|
+
--color-green-400: #57ac5b;
|
|
173
|
+
--color-green-500: #43a047;
|
|
174
|
+
--color-green-600: #3a8c3e;
|
|
175
|
+
--color-green-700: #2f7132;
|
|
176
|
+
--color-green-800: #245726;
|
|
177
|
+
--color-green-900: #193d1b;
|
|
178
|
+
--color-green-950: #0f2611;
|
|
179
|
+
--color-emerald-50: #ecf5ec;
|
|
180
|
+
--color-emerald-100: #cfe6d0;
|
|
181
|
+
--color-emerald-200: #a3d0a5;
|
|
182
|
+
--color-emerald-300: #77ba7a;
|
|
183
|
+
--color-emerald-400: #57ac5b;
|
|
184
|
+
--color-emerald-500: #43a047;
|
|
185
|
+
--color-emerald-600: #3a8c3e;
|
|
186
|
+
--color-emerald-700: #2f7132;
|
|
187
|
+
--color-emerald-800: #245726;
|
|
188
|
+
--color-emerald-900: #193d1b;
|
|
189
|
+
--color-emerald-950: #0f2611;
|
|
190
|
+
/* brand ramp -> HA primary #009ac7 at 500 (anchors: 50=#dff3fc primary-90,
|
|
191
|
+
400=#18bcf2 primary-50) */
|
|
192
|
+
--color-brand-50: #dff3fc;
|
|
193
|
+
--color-brand-100: #bfe7f8;
|
|
194
|
+
--color-brand-200: #80cff1;
|
|
195
|
+
--color-brand-300: #40b7ea;
|
|
196
|
+
--color-brand-400: #18bcf2;
|
|
197
|
+
--color-brand-500: #009ac7;
|
|
198
|
+
--color-brand-600: #0089b2;
|
|
199
|
+
--color-brand-700: #006e8f;
|
|
200
|
+
--color-brand-800: #00536c;
|
|
201
|
+
--color-brand-900: #003849;
|
|
202
|
+
--color-brand-950: #002733;
|
|
203
|
+
/* violet has a single decorative use -> fold onto brand so it is not an
|
|
204
|
+
off-theme purple */
|
|
205
|
+
--color-violet-500: #009ac7;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/* ──────────────────────────────────────────────────────────────────
|
|
209
|
+
* Responsive "table → cards" reflow. A wide data table tagged
|
|
210
|
+
* `.table-reflow` keeps its normal tabular layout from sm upward, and on
|
|
211
|
+
* phones (<640px, matching Tailwind's sm breakpoint) collapses each row
|
|
212
|
+
* into a bordered card: the header row is hidden and every cell prints
|
|
213
|
+
* its column name from `data-label`. Cells flagged `.reflow-title` become
|
|
214
|
+
* the card heading; `.reflow-actions` right-aligns a button row. This
|
|
215
|
+
* keeps a single markup source for both layouts.
|
|
216
|
+
* ────────────────────────────────────────────────────────────────── */
|
|
217
|
+
@media (max-width: 639px) {
|
|
218
|
+
.table-reflow thead {
|
|
219
|
+
position: absolute;
|
|
220
|
+
width: 1px;
|
|
221
|
+
height: 1px;
|
|
222
|
+
margin: -1px;
|
|
223
|
+
padding: 0;
|
|
224
|
+
overflow: hidden;
|
|
225
|
+
clip: rect(0 0 0 0);
|
|
226
|
+
white-space: nowrap;
|
|
227
|
+
border: 0;
|
|
228
|
+
}
|
|
229
|
+
.table-reflow tr {
|
|
230
|
+
display: block;
|
|
231
|
+
margin-bottom: 0.625rem;
|
|
232
|
+
padding: 0.25rem 0.875rem;
|
|
233
|
+
border: 1px solid var(--ha-divider-color);
|
|
234
|
+
border-radius: var(--ha-radius-card);
|
|
235
|
+
background-color: var(--ha-card-background-color);
|
|
236
|
+
}
|
|
237
|
+
.table-reflow td {
|
|
238
|
+
display: flex;
|
|
239
|
+
align-items: baseline;
|
|
240
|
+
justify-content: space-between;
|
|
241
|
+
gap: 1rem;
|
|
242
|
+
width: auto !important;
|
|
243
|
+
padding: 0.375rem 0 !important;
|
|
244
|
+
border: 0 !important;
|
|
245
|
+
text-align: right;
|
|
246
|
+
white-space: normal;
|
|
247
|
+
overflow-wrap: anywhere;
|
|
248
|
+
}
|
|
249
|
+
.table-reflow td:not(:last-child) {
|
|
250
|
+
border-bottom: 1px solid var(--ha-divider-color) !important;
|
|
251
|
+
}
|
|
252
|
+
.table-reflow td::before {
|
|
253
|
+
content: attr(data-label);
|
|
254
|
+
flex: 0 0 auto;
|
|
255
|
+
margin-right: 0.5rem;
|
|
256
|
+
font-weight: 600;
|
|
257
|
+
text-align: left;
|
|
258
|
+
color: var(--ha-secondary-text-color);
|
|
259
|
+
}
|
|
260
|
+
.table-reflow td.reflow-title {
|
|
261
|
+
justify-content: flex-start;
|
|
262
|
+
font-weight: 600;
|
|
263
|
+
font-size: 0.95rem;
|
|
264
|
+
}
|
|
265
|
+
.table-reflow td.reflow-title::before {
|
|
266
|
+
content: none;
|
|
267
|
+
}
|
|
268
|
+
.table-reflow td.reflow-actions {
|
|
269
|
+
justify-content: flex-end;
|
|
270
|
+
}
|
|
271
|
+
.table-reflow td.reflow-actions::before {
|
|
272
|
+
content: none;
|
|
273
|
+
}
|
|
274
|
+
.table-reflow td[data-label=""]::before {
|
|
275
|
+
content: none;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/* ──────────────────────────────────────────────────────────────────
|
|
280
|
+
* `.hide-narrow` collapses a whole data-table column away below the lg
|
|
281
|
+
* breakpoint (1024px), in both the tabular and the card-reflow layouts.
|
|
282
|
+
* Applied to a column's <th> (via headClass) and <td> (via cellClass) so
|
|
283
|
+
* header and cells disappear together — no dangling header, no misaligned
|
|
284
|
+
* grid. Used for secondary columns that would crowd a phone or tablet.
|
|
285
|
+
* The `!important` beats the reflow rule's `display: flex` on <td>.
|
|
286
|
+
* ────────────────────────────────────────────────────────────────── */
|
|
287
|
+
@media (max-width: 1023px) {
|
|
288
|
+
.table-reflow th.hide-narrow,
|
|
289
|
+
.table-reflow td.hide-narrow {
|
|
290
|
+
display: none !important;
|
|
291
|
+
}
|
|
292
|
+
}
|