@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.
Files changed (45) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +91 -2
  3. package/package.json +92 -4
  4. package/src/lib/api/client.ts +155 -0
  5. package/src/lib/api/index.ts +3 -0
  6. package/src/lib/api/schema.gen.ts +1176 -0
  7. package/src/lib/api/stream.ts +54 -0
  8. package/src/lib/context.ts +96 -0
  9. package/src/lib/i18n/de.json +160 -0
  10. package/src/lib/i18n/en.json +160 -0
  11. package/src/lib/i18n/index.ts +50 -0
  12. package/src/lib/index.ts +10 -0
  13. package/src/lib/kit/Badge.svelte +26 -0
  14. package/src/lib/kit/Button.svelte +49 -0
  15. package/src/lib/kit/Card.svelte +16 -0
  16. package/src/lib/kit/DataTable.svelte +239 -0
  17. package/src/lib/kit/EmptyState.svelte +24 -0
  18. package/src/lib/kit/ErrorState.svelte +22 -0
  19. package/src/lib/kit/Icon.svelte +12 -0
  20. package/src/lib/kit/Input.svelte +22 -0
  21. package/src/lib/kit/LoadingState.svelte +15 -0
  22. package/src/lib/kit/PageHeader.svelte +32 -0
  23. package/src/lib/kit/PageShell.svelte +16 -0
  24. package/src/lib/kit/Select.svelte +49 -0
  25. package/src/lib/kit/Spinner.svelte +59 -0
  26. package/src/lib/kit/Tabs.svelte +63 -0
  27. package/src/lib/kit/data-table.ts +24 -0
  28. package/src/lib/kit/icons.ts +41 -0
  29. package/src/lib/kit/index.ts +21 -0
  30. package/src/lib/kit/tabs.ts +13 -0
  31. package/src/lib/kit/utils.ts +49 -0
  32. package/src/lib/pages/index.ts +8 -0
  33. package/src/lib/pages/node/Diagnostics.svelte +205 -0
  34. package/src/lib/pages/node/Endpoints.svelte +82 -0
  35. package/src/lib/pages/node/Fabrics.svelte +169 -0
  36. package/src/lib/pages/node/HostWarnings.svelte +41 -0
  37. package/src/lib/pages/node/Pair.svelte +186 -0
  38. package/src/lib/pages/node/Selection.svelte +407 -0
  39. package/src/lib/pages/node/Status.svelte +67 -0
  40. package/src/lib/pages/node/fields.ts +32 -0
  41. package/src/lib/qr.ts +58 -0
  42. package/src/lib/store.svelte.ts +293 -0
  43. package/src/lib/theme/ha-bridge.ts +156 -0
  44. package/src/lib/theme/index.ts +1 -0
  45. 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
+ }