@dorsk/tsumikit 0.9.2 → 0.9.4

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.
@@ -16,6 +16,7 @@
16
16
  size = 'md',
17
17
  mono = false,
18
18
  uppercase = false,
19
+ border = true,
19
20
  active = false,
20
21
  removable = false,
21
22
  onremove,
@@ -29,6 +30,9 @@
29
30
  mono?: boolean;
30
31
  // Uppercase, letter-spaced label — for status tags/eyebrows.
31
32
  uppercase?: boolean;
33
+ // Borderless "soft" variant: tone-tinted fill pill with no ring. The
34
+ // default (`true`) keeps the outlined look for backwards compatibility.
35
+ border?: boolean;
32
36
  // Interactive "on" state for a toggle/count badge (`as="button"`): fills the
33
37
  // pill with its tone instead of just tinting the border.
34
38
  active?: boolean;
@@ -51,6 +55,7 @@
51
55
  class:badge-sm={size === 'sm'}
52
56
  class:mono
53
57
  class:uppercase
58
+ class:borderless={!border}
54
59
  class:active
55
60
  class:interactive={as === 'button'}
56
61
  {...rest}
@@ -109,6 +114,11 @@
109
114
  border-color: color-mix(in srgb, var(--info) 40%, transparent);
110
115
  background: color-mix(in srgb, var(--info) 12%, transparent);
111
116
  }
117
+ /* Soft variant: drop the ring, keep the tinted fill. Transparent (not
118
+ `border: 0`) so layout/baseline matches the outlined default exactly. */
119
+ .borderless {
120
+ border-color: transparent;
121
+ }
112
122
  .mono {
113
123
  font-family: var(--font-mono);
114
124
  font-weight: var(--fw-normal);
@@ -6,6 +6,7 @@ type $$ComponentProps = {
6
6
  size?: 'sm' | 'md';
7
7
  mono?: boolean;
8
8
  uppercase?: boolean;
9
+ border?: boolean;
9
10
  active?: boolean;
10
11
  removable?: boolean;
11
12
  onremove?: (e: MouseEvent) => void;
@@ -43,6 +43,12 @@
43
43
  pause: '<rect x="14" y="3" width="5" height="18" rx="1" /><rect x="5" y="3" width="5" height="18" rx="1" />',
44
44
  stop: '<rect width="18" height="18" x="3" y="3" rx="2" />',
45
45
 
46
+ // — media types —
47
+ music: '<path d="M9 18V5l12-2v13" /><circle cx="6" cy="18" r="3" /><circle cx="18" cy="16" r="3" />',
48
+ tv: '<path d="m17 2-5 5-5-5" /><rect width="20" height="15" x="2" y="7" rx="2" />',
49
+ film: '<rect width="18" height="18" x="3" y="3" rx="2" /><path d="M7 3v18" /><path d="M3 7.5h4" /><path d="M3 12h18" /><path d="M3 16.5h4" /><path d="M17 3v18" /><path d="M17 7.5h4" /><path d="M17 16.5h4" />',
50
+ disc: '<circle cx="12" cy="12" r="10" /><circle cx="12" cy="12" r="2" />',
51
+
46
52
  // — files / content —
47
53
  file: '<path d="M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z" /><path d="M14 2v5a1 1 0 0 0 1 1h5" />',
48
54
  'file-text': '<path d="M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z" /><path d="M14 2v5a1 1 0 0 0 1 1h5" /><path d="M10 9H8" /><path d="M16 13H8" /><path d="M16 17H8" />',
@@ -55,6 +61,8 @@
55
61
 
56
62
  // — objects / status —
57
63
  link: '<path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" /><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" />',
64
+ unlink: '<path d="m18.84 12.25 1.72-1.71h-.02a5.004 5.004 0 0 0-.12-7.07 5.006 5.006 0 0 0-6.95 0l-1.72 1.71" /><path d="m5.17 11.75-1.71 1.71a5.004 5.004 0 0 0 .12 7.07 5.006 5.006 0 0 0 6.95 0l1.71-1.71" /><line x1="8" x2="8" y1="2" y2="5" /><line x1="2" x2="5" y1="8" y2="8" /><line x1="16" x2="16" y1="19" y2="22" /><line x1="19" x2="22" y1="16" y2="16" />',
65
+ 'text-cursor': '<path d="M17 22h-1a4 4 0 0 1-4-4V6a4 4 0 0 1 4-4h1" /><path d="M7 22h1a4 4 0 0 0 4-4" /><path d="M7 2h1a4 4 0 0 1 4 4" />',
58
66
  tag: '<path d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z" /><circle cx="7.5" cy="7.5" r=".5" fill="currentColor" />',
59
67
  bookmark: '<path d="M17 3a2 2 0 0 1 2 2v15a1 1 0 0 1-1.496.868l-4.512-2.578a2 2 0 0 0-1.984 0l-4.512 2.578A1 1 0 0 1 5 20V5a2 2 0 0 1 2-2z" />',
60
68
  star: '<path d="M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z" />',
@@ -103,6 +111,7 @@
103
111
  name,
104
112
  size,
105
113
  label,
114
+ spin = false,
106
115
  children,
107
116
  ...rest
108
117
  }: {
@@ -111,6 +120,9 @@
111
120
  /** Explicit pixel size. Omit to track the surrounding text (1em) — best
112
121
  * for icons sitting inline with a label. */
113
122
  size?: number;
123
+ /** Continuously rotate the glyph (e.g. `name="loader"` as a spinner). The
124
+ * global prefers-reduced-motion rule halts it for motion-sensitive users. */
125
+ spin?: boolean;
114
126
  /** When set, the icon is exposed to AT with this label; otherwise it is
115
127
  * decorative (aria-hidden) and the parent control carries the label. */
116
128
  label?: string;
@@ -126,6 +138,7 @@
126
138
  <svg
127
139
  data-tsu="Icon"
128
140
  class="icon"
141
+ class:spin
129
142
  style={size ? `font-size: ${size}px` : undefined}
130
143
  viewBox="0 0 24 24"
131
144
  fill={filled ? 'currentColor' : 'none'}
@@ -152,4 +165,17 @@
152
165
  width: 1em;
153
166
  height: 1em;
154
167
  }
168
+ .icon.spin {
169
+ animation: icon-spin 0.7s linear infinite;
170
+ }
171
+ @keyframes icon-spin {
172
+ to {
173
+ transform: rotate(360deg);
174
+ }
175
+ }
176
+ @media (prefers-reduced-motion: reduce) {
177
+ .icon.spin {
178
+ animation: none;
179
+ }
180
+ }
155
181
  </style>
@@ -30,6 +30,10 @@ declare const ICONS: {
30
30
  readonly play: "<path d=\"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z\" />";
31
31
  readonly pause: "<rect x=\"14\" y=\"3\" width=\"5\" height=\"18\" rx=\"1\" /><rect x=\"5\" y=\"3\" width=\"5\" height=\"18\" rx=\"1\" />";
32
32
  readonly stop: "<rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" />";
33
+ readonly music: "<path d=\"M9 18V5l12-2v13\" /><circle cx=\"6\" cy=\"18\" r=\"3\" /><circle cx=\"18\" cy=\"16\" r=\"3\" />";
34
+ readonly tv: "<path d=\"m17 2-5 5-5-5\" /><rect width=\"20\" height=\"15\" x=\"2\" y=\"7\" rx=\"2\" />";
35
+ readonly film: "<rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" /><path d=\"M7 3v18\" /><path d=\"M3 7.5h4\" /><path d=\"M3 12h18\" /><path d=\"M3 16.5h4\" /><path d=\"M17 3v18\" /><path d=\"M17 7.5h4\" /><path d=\"M17 16.5h4\" />";
36
+ readonly disc: "<circle cx=\"12\" cy=\"12\" r=\"10\" /><circle cx=\"12\" cy=\"12\" r=\"2\" />";
33
37
  readonly file: "<path d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\" /><path d=\"M14 2v5a1 1 0 0 0 1 1h5\" />";
34
38
  readonly 'file-text': "<path d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\" /><path d=\"M14 2v5a1 1 0 0 0 1 1h5\" /><path d=\"M10 9H8\" /><path d=\"M16 13H8\" /><path d=\"M16 17H8\" />";
35
39
  readonly folder: "<path d=\"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z\" />";
@@ -39,6 +43,8 @@ declare const ICONS: {
39
43
  readonly list: "<path d=\"M3 5h.01\" /><path d=\"M3 12h.01\" /><path d=\"M3 19h.01\" /><path d=\"M8 5h13\" /><path d=\"M8 12h13\" /><path d=\"M8 19h13\" />";
40
44
  readonly grid: "<rect width=\"7\" height=\"7\" x=\"3\" y=\"3\" rx=\"1\" /><rect width=\"7\" height=\"7\" x=\"14\" y=\"3\" rx=\"1\" /><rect width=\"7\" height=\"7\" x=\"14\" y=\"14\" rx=\"1\" /><rect width=\"7\" height=\"7\" x=\"3\" y=\"14\" rx=\"1\" />";
41
45
  readonly link: "<path d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\" /><path d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\" />";
46
+ readonly unlink: "<path d=\"m18.84 12.25 1.72-1.71h-.02a5.004 5.004 0 0 0-.12-7.07 5.006 5.006 0 0 0-6.95 0l-1.72 1.71\" /><path d=\"m5.17 11.75-1.71 1.71a5.004 5.004 0 0 0 .12 7.07 5.006 5.006 0 0 0 6.95 0l1.71-1.71\" /><line x1=\"8\" x2=\"8\" y1=\"2\" y2=\"5\" /><line x1=\"2\" x2=\"5\" y1=\"8\" y2=\"8\" /><line x1=\"16\" x2=\"16\" y1=\"19\" y2=\"22\" /><line x1=\"19\" x2=\"22\" y1=\"16\" y2=\"16\" />";
47
+ readonly 'text-cursor': "<path d=\"M17 22h-1a4 4 0 0 1-4-4V6a4 4 0 0 1 4-4h1\" /><path d=\"M7 22h1a4 4 0 0 0 4-4\" /><path d=\"M7 2h1a4 4 0 0 1 4 4\" />";
42
48
  readonly tag: "<path d=\"M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z\" /><circle cx=\"7.5\" cy=\"7.5\" r=\".5\" fill=\"currentColor\" />";
43
49
  readonly bookmark: "<path d=\"M17 3a2 2 0 0 1 2 2v15a1 1 0 0 1-1.496.868l-4.512-2.578a2 2 0 0 0-1.984 0l-4.512 2.578A1 1 0 0 1 5 20V5a2 2 0 0 1 2-2z\" />";
44
50
  readonly star: "<path d=\"M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z\" />";
@@ -76,6 +82,9 @@ type $$ComponentProps = {
76
82
  /** Explicit pixel size. Omit to track the surrounding text (1em) — best
77
83
  * for icons sitting inline with a label. */
78
84
  size?: number;
85
+ /** Continuously rotate the glyph (e.g. `name="loader"` as a spinner). The
86
+ * global prefers-reduced-motion rule halts it for motion-sensitive users. */
87
+ spin?: boolean;
79
88
  /** When set, the icon is exposed to AT with this label; otherwise it is
80
89
  * decorative (aria-hidden) and the parent control carries the label. */
81
90
  label?: string;
@@ -0,0 +1,22 @@
1
+ <script lang="ts">
2
+ // Inline loading spinner — a spinning `loader` glyph. Tracks the surrounding
3
+ // text size by default (1em), or pass an explicit pixel `size`. The spin
4
+ // animation is owned by Icon and is halted under prefers-reduced-motion, so
5
+ // motion-sensitive users see a static glyph instead.
6
+ import Icon from './Icon.svelte';
7
+
8
+ let {
9
+ size,
10
+ label = 'Loading',
11
+ ...rest
12
+ }: {
13
+ /** Explicit pixel size. Omit to track the surrounding text (1em). */
14
+ size?: number;
15
+ /** AT label announcing the busy state. Set to undefined to make the
16
+ * spinner decorative when an ancestor already conveys the loading state. */
17
+ label?: string;
18
+ [key: string]: unknown;
19
+ } = $props();
20
+ </script>
21
+
22
+ <Icon name="loader" spin {size} {label} data-tsu="Spinner" {...rest} />
@@ -0,0 +1,11 @@
1
+ type $$ComponentProps = {
2
+ /** Explicit pixel size. Omit to track the surrounding text (1em). */
3
+ size?: number;
4
+ /** AT label announcing the busy state. Set to undefined to make the
5
+ * spinner decorative when an ancestor already conveys the loading state. */
6
+ label?: string;
7
+ [key: string]: unknown;
8
+ };
9
+ declare const Spinner: import("svelte").Component<$$ComponentProps, {}, "">;
10
+ type Spinner = ReturnType<typeof Spinner>;
11
+ export default Spinner;
package/dist/index.d.ts CHANGED
@@ -13,6 +13,7 @@ export { default as Link } from './components/atoms/Link.svelte';
13
13
  export { default as Progress } from './components/atoms/Progress.svelte';
14
14
  export { default as Select } from './components/atoms/Select.svelte';
15
15
  export { default as Slider } from './components/atoms/Slider.svelte';
16
+ export { default as Spinner } from './components/atoms/Spinner.svelte';
16
17
  export { default as Switch } from './components/atoms/Switch.svelte';
17
18
  export { default as Text } from './components/atoms/Text.svelte';
18
19
  export { default as Textarea } from './components/atoms/Textarea.svelte';
package/dist/index.js CHANGED
@@ -18,6 +18,7 @@ export { default as Link } from './components/atoms/Link.svelte';
18
18
  export { default as Progress } from './components/atoms/Progress.svelte';
19
19
  export { default as Select } from './components/atoms/Select.svelte';
20
20
  export { default as Slider } from './components/atoms/Slider.svelte';
21
+ export { default as Spinner } from './components/atoms/Spinner.svelte';
21
22
  export { default as Switch } from './components/atoms/Switch.svelte';
22
23
  // ---- atoms ----
23
24
  export { default as Text } from './components/atoms/Text.svelte';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dorsk/tsumikit",
3
- "version": "0.9.2",
3
+ "version": "0.9.4",
4
4
  "description": "Minimal, dependency-free Svelte 5 + pure-CSS UI kit. Token-driven atoms, molecules & layouts with theming out of the box.",
5
5
  "type": "module",
6
6
  "license": "MIT",