@lyeve-labs/ui-kit 0.9.1 → 0.10.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 (61) hide show
  1. package/dist/components/AccordionItem.svelte +1 -1
  2. package/dist/components/Alert.svelte +42 -15
  3. package/dist/components/Alert.svelte.d.ts +2 -2
  4. package/dist/components/Autocomplete.svelte +32 -12
  5. package/dist/components/Avatar.svelte +4 -8
  6. package/dist/components/Badge.svelte +4 -4
  7. package/dist/components/Badge.svelte.d.ts +2 -2
  8. package/dist/components/Banner.svelte +10 -9
  9. package/dist/components/Banner.svelte.d.ts +2 -2
  10. package/dist/components/Breadcrumb.svelte +4 -1
  11. package/dist/components/Button.svelte +4 -2
  12. package/dist/components/Button.svelte.d.ts +1 -0
  13. package/dist/components/Card.svelte +1 -1
  14. package/dist/components/Checkbox.svelte +7 -4
  15. package/dist/components/Checkbox.svelte.d.ts +1 -0
  16. package/dist/components/DatePicker.svelte +19 -11
  17. package/dist/components/Drawer.svelte +13 -2
  18. package/dist/components/Dropdown.svelte +1 -1
  19. package/dist/components/FileInput.svelte +14 -5
  20. package/dist/components/Indicator.svelte +3 -3
  21. package/dist/components/Indicator.svelte.d.ts +2 -2
  22. package/dist/components/Input.svelte +17 -8
  23. package/dist/components/Modal.svelte +11 -2
  24. package/dist/components/MultiSelect.svelte +33 -12
  25. package/dist/components/NumberInput.svelte +68 -13
  26. package/dist/components/NumberInput.svelte.d.ts +3 -0
  27. package/dist/components/Pagination.svelte +1 -1
  28. package/dist/components/Progress.svelte +4 -3
  29. package/dist/components/Progress.svelte.d.ts +2 -2
  30. package/dist/components/Radio.svelte +6 -3
  31. package/dist/components/Radio.svelte.d.ts +1 -0
  32. package/dist/components/RadioGroup.svelte +6 -5
  33. package/dist/components/SearchInput.svelte +64 -49
  34. package/dist/components/SearchInput.svelte.d.ts +3 -0
  35. package/dist/components/Select.svelte +29 -12
  36. package/dist/components/Select.svelte.d.ts +2 -0
  37. package/dist/components/StepIndicator.svelte +7 -5
  38. package/dist/components/Table.svelte +3 -1
  39. package/dist/components/Tabs.svelte +1 -1
  40. package/dist/components/Tag.svelte +3 -3
  41. package/dist/components/Tag.svelte.d.ts +2 -2
  42. package/dist/components/Textarea.svelte +28 -16
  43. package/dist/components/Textarea.svelte.d.ts +1 -0
  44. package/dist/components/ThemeToggle.svelte +1 -1
  45. package/dist/components/Toaster.svelte +34 -12
  46. package/dist/components/Toggle.svelte +6 -3
  47. package/dist/components/Toggle.svelte.d.ts +1 -0
  48. package/dist/components/dialog/Dialog.svelte +1 -1
  49. package/dist/index.d.ts +1 -1
  50. package/dist/index.js +3 -1
  51. package/dist/internal/field.d.ts +48 -0
  52. package/dist/internal/field.js +62 -0
  53. package/dist/internal/tone.d.ts +27 -0
  54. package/dist/internal/tone.js +29 -0
  55. package/dist/stores/toast.svelte.d.ts +6 -1
  56. package/dist/stores/toast.svelte.js +1 -1
  57. package/dist/styles/theme.css +30 -4
  58. package/dist/utils/broken-image.d.ts +21 -0
  59. package/dist/utils/broken-image.js +40 -0
  60. package/package.json +6 -5
  61. package/src/lib/styles/theme.css +30 -4
@@ -15,6 +15,21 @@
15
15
 
16
16
  @import 'tailwindcss';
17
17
 
18
+ /*
19
+ * Tailwind scans the importing app's own source and, by default, skips
20
+ * node_modules. Without this line it never reads the kit's components, so it
21
+ * emits the tokens above and not one of the utility classes those components
22
+ * are built from. The kit appeared to work only because a host app happened to
23
+ * use the same class names in its own pages: whatever the app never wrote for
24
+ * itself was missing from the kit's components too, and two apps with different
25
+ * pages lost different parts of the same component. Every class the kit needs
26
+ * now comes from the kit.
27
+ *
28
+ * The path is relative to this file and resolves to the package's dist/, which
29
+ * is present in every published tarball.
30
+ */
31
+ @source '../../../dist';
32
+
18
33
  /* ── Soft Dark · default palette ─────────────────────────────────────────── */
19
34
  @theme {
20
35
  --color-ink: #0b1422;
@@ -23,15 +38,20 @@
23
38
  --color-line: #1e2d40;
24
39
  --color-fg: #e6e8ee;
25
40
  --color-muted: #9aa1ad;
26
- --color-faint: #525866;
41
+ /* #525866 failed WCAG AA against surface/ink (~2.5:1); every caption and
42
+ * metadata label uses faint, so one token fix clears the systemic
43
+ * violation. #8b94a7 sits at ~5.6:1 on surface and ~5.9:1 on ink. */
44
+ --color-faint: #8b94a7;
27
45
 
28
46
  --color-brand: #00d4ff;
29
47
  --color-brand-light: #5fd9f4;
30
48
  --color-brand-deep: #0099c4;
31
49
  --color-violet: #7c6aef;
32
50
 
33
- --color-success: #15803d;
34
- --color-warn: #b45309;
51
+ /* #15803d and #b45309 sit at ~3.7:1 on ink, below the 4.5:1 AA floor
52
+ * for the text-size status labels that use them. */
53
+ --color-success: #22c55e;
54
+ --color-warn: #f59e0b;
35
55
  --color-danger: #b91c1c;
36
56
 
37
57
  /* ── Radius ─────────────────────────────────────────────────── */
@@ -91,6 +111,10 @@
91
111
  --spacing-section: 3rem; /* 48px - section gap */
92
112
  --spacing-input-x: 0.75rem; /* 12px - input horizontal padding */
93
113
  --spacing-input-y: 0.5rem; /* 8px - input vertical padding */
114
+ /* 38px - the height of every single-line control. Stated once so an Input,
115
+ * a Select and a NumberInput sitting in the same row line up. Derived from
116
+ * the 13px/1.25 control text plus input-y padding and a 1px border. */
117
+ --spacing-control: 2.375rem;
94
118
  --spacing-stack: 1rem; /* 16px - default vertical stack gap */
95
119
  --spacing-inline: 0.5rem; /* 8px - default inline gap */
96
120
  }
@@ -103,7 +127,9 @@ html[data-theme='light'] {
103
127
  --color-line: #d6d9e0;
104
128
  --color-fg: #111827;
105
129
  --color-muted: #525866;
106
- --color-faint: #9aa1ad;
130
+ /* #9aa1ad on white is ~3.1:1, below the 4.5:1 AA floor; #6b7280 sits
131
+ * at ~4.8:1 while staying visually tertiary. */
132
+ --color-faint: #6b7280;
107
133
 
108
134
  --color-brand: #007ea6;
109
135
  --color-brand-light: #00b4dd;
@@ -0,0 +1,21 @@
1
+ import type { Action } from 'svelte/action';
2
+ /**
3
+ * Reports that an image inside `node` could not be decoded.
4
+ *
5
+ * The obvious place for this is an `onerror` handler on the `<img>` itself,
6
+ * and that is what breaks. Svelte's server renderer stamps
7
+ * `onload="this.__e=event"` and `onerror="this.__e=event"` onto any `<img>`,
8
+ * `<iframe>`, `<link>` or `<script>` carrying an `onload`/`onerror` handler, a
9
+ * spread or a `use:` directive, so events that fire before hydration can be
10
+ * replayed afterwards. Consumers serve this kit under a `script-src` policy
11
+ * with a nonce and no `unsafe-inline`, and a nonce never covers an event
12
+ * handler attribute, so the browser blocks that snippet and logs a violation
13
+ * for every element it rendered. Hydration then strips the attributes, which
14
+ * is why the markup looks innocent by the time anyone inspects it.
15
+ *
16
+ * Attaching from a wrapper element keeps the `<img>` free of all three, so the
17
+ * server sends no inline handler at all. `error` does not bubble, hence the
18
+ * capture phase, and an image that already failed fires nothing more, so its
19
+ * settled state is read once on attach.
20
+ */
21
+ export declare const brokenImage: Action<HTMLElement, () => void>;
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Reports that an image inside `node` could not be decoded.
3
+ *
4
+ * The obvious place for this is an `onerror` handler on the `<img>` itself,
5
+ * and that is what breaks. Svelte's server renderer stamps
6
+ * `onload="this.__e=event"` and `onerror="this.__e=event"` onto any `<img>`,
7
+ * `<iframe>`, `<link>` or `<script>` carrying an `onload`/`onerror` handler, a
8
+ * spread or a `use:` directive, so events that fire before hydration can be
9
+ * replayed afterwards. Consumers serve this kit under a `script-src` policy
10
+ * with a nonce and no `unsafe-inline`, and a nonce never covers an event
11
+ * handler attribute, so the browser blocks that snippet and logs a violation
12
+ * for every element it rendered. Hydration then strips the attributes, which
13
+ * is why the markup looks innocent by the time anyone inspects it.
14
+ *
15
+ * Attaching from a wrapper element keeps the `<img>` free of all three, so the
16
+ * server sends no inline handler at all. `error` does not bubble, hence the
17
+ * capture phase, and an image that already failed fires nothing more, so its
18
+ * settled state is read once on attach.
19
+ */
20
+ export const brokenImage = (node, onBroken) => {
21
+ let notify = onBroken;
22
+ const flag = (event) => {
23
+ if (event.target instanceof HTMLImageElement)
24
+ notify();
25
+ };
26
+ node.addEventListener('error', flag, true);
27
+ // An <img> with no src is also `complete` at zero width, so the src has to be
28
+ // part of the test or every placeholder reports itself broken.
29
+ const img = node.querySelector('img');
30
+ if (img?.getAttribute('src') && img.complete && img.naturalWidth === 0)
31
+ notify();
32
+ return {
33
+ update(next) {
34
+ notify = next;
35
+ },
36
+ destroy() {
37
+ node.removeEventListener('error', flag, true);
38
+ },
39
+ };
40
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lyeve-labs/ui-kit",
3
- "version": "0.9.1",
3
+ "version": "0.10.0",
4
4
  "description": "A clean, accessible, palette-aware Svelte 5 component library. The design system behind LyEve.",
5
5
  "license": "MIT",
6
6
  "author": "LyEve Labs <hello@lyeve.com>",
@@ -28,8 +28,10 @@
28
28
  "node": ">=20"
29
29
  },
30
30
  "scripts": {
31
- "build": "svelte-package && publint && node scripts/check-dist.mjs",
32
- "package": "svelte-package && publint",
31
+ "build": "pnpm version:check && svelte-package && publint && node scripts/check-dist.mjs",
32
+ "version:sync": "node scripts/sync-version.mjs",
33
+ "version:check": "node scripts/sync-version.mjs --check",
34
+ "package": "pnpm version:check && svelte-package && publint",
33
35
  "prepublishOnly": "pnpm package",
34
36
  "check": "svelte-check --tsconfig ./tsconfig.json",
35
37
  "check:watch": "svelte-check --tsconfig ./tsconfig.json --watch",
@@ -59,8 +61,7 @@
59
61
  "svelte": "^5.0.0"
60
62
  },
61
63
  "publishConfig": {
62
- "access": "public",
63
- "provenance": false
64
+ "access": "public"
64
65
  },
65
66
  "dependencies": {
66
67
  "@lucide/svelte": "^0.511.0"
@@ -15,6 +15,21 @@
15
15
 
16
16
  @import 'tailwindcss';
17
17
 
18
+ /*
19
+ * Tailwind scans the importing app's own source and, by default, skips
20
+ * node_modules. Without this line it never reads the kit's components, so it
21
+ * emits the tokens above and not one of the utility classes those components
22
+ * are built from. The kit appeared to work only because a host app happened to
23
+ * use the same class names in its own pages: whatever the app never wrote for
24
+ * itself was missing from the kit's components too, and two apps with different
25
+ * pages lost different parts of the same component. Every class the kit needs
26
+ * now comes from the kit.
27
+ *
28
+ * The path is relative to this file and resolves to the package's dist/, which
29
+ * is present in every published tarball.
30
+ */
31
+ @source '../../../dist';
32
+
18
33
  /* ── Soft Dark · default palette ─────────────────────────────────────────── */
19
34
  @theme {
20
35
  --color-ink: #0b1422;
@@ -23,15 +38,20 @@
23
38
  --color-line: #1e2d40;
24
39
  --color-fg: #e6e8ee;
25
40
  --color-muted: #9aa1ad;
26
- --color-faint: #525866;
41
+ /* #525866 failed WCAG AA against surface/ink (~2.5:1); every caption and
42
+ * metadata label uses faint, so one token fix clears the systemic
43
+ * violation. #8b94a7 sits at ~5.6:1 on surface and ~5.9:1 on ink. */
44
+ --color-faint: #8b94a7;
27
45
 
28
46
  --color-brand: #00d4ff;
29
47
  --color-brand-light: #5fd9f4;
30
48
  --color-brand-deep: #0099c4;
31
49
  --color-violet: #7c6aef;
32
50
 
33
- --color-success: #15803d;
34
- --color-warn: #b45309;
51
+ /* #15803d and #b45309 sit at ~3.7:1 on ink, below the 4.5:1 AA floor
52
+ * for the text-size status labels that use them. */
53
+ --color-success: #22c55e;
54
+ --color-warn: #f59e0b;
35
55
  --color-danger: #b91c1c;
36
56
 
37
57
  /* ── Radius ─────────────────────────────────────────────────── */
@@ -91,6 +111,10 @@
91
111
  --spacing-section: 3rem; /* 48px - section gap */
92
112
  --spacing-input-x: 0.75rem; /* 12px - input horizontal padding */
93
113
  --spacing-input-y: 0.5rem; /* 8px - input vertical padding */
114
+ /* 38px - the height of every single-line control. Stated once so an Input,
115
+ * a Select and a NumberInput sitting in the same row line up. Derived from
116
+ * the 13px/1.25 control text plus input-y padding and a 1px border. */
117
+ --spacing-control: 2.375rem;
94
118
  --spacing-stack: 1rem; /* 16px - default vertical stack gap */
95
119
  --spacing-inline: 0.5rem; /* 8px - default inline gap */
96
120
  }
@@ -103,7 +127,9 @@ html[data-theme='light'] {
103
127
  --color-line: #d6d9e0;
104
128
  --color-fg: #111827;
105
129
  --color-muted: #525866;
106
- --color-faint: #9aa1ad;
130
+ /* #9aa1ad on white is ~3.1:1, below the 4.5:1 AA floor; #6b7280 sits
131
+ * at ~4.8:1 while staying visually tertiary. */
132
+ --color-faint: #6b7280;
107
133
 
108
134
  --color-brand: #007ea6;
109
135
  --color-brand-light: #00b4dd;