@dorsk/tsumikit 0.1.1 → 0.2.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 (48) hide show
  1. package/README.md +4 -2
  2. package/dist/clipboard.d.ts +1 -0
  3. package/dist/clipboard.js +30 -0
  4. package/dist/components/atoms/Badge.svelte +65 -3
  5. package/dist/components/atoms/Badge.svelte.d.ts +4 -0
  6. package/dist/components/atoms/Button.svelte +80 -8
  7. package/dist/components/atoms/Button.svelte.d.ts +4 -0
  8. package/dist/components/atoms/Checkbox.svelte +7 -1
  9. package/dist/components/atoms/Checkbox.svelte.d.ts +2 -0
  10. package/dist/components/atoms/Dot.svelte +67 -0
  11. package/dist/components/atoms/Dot.svelte.d.ts +12 -0
  12. package/dist/components/atoms/Input.svelte +28 -2
  13. package/dist/components/atoms/Input.svelte.d.ts +5 -1
  14. package/dist/components/atoms/Select.svelte +9 -2
  15. package/dist/components/atoms/Select.svelte.d.ts +2 -0
  16. package/dist/components/atoms/Slider.svelte +5 -4
  17. package/dist/components/atoms/Switch.svelte +6 -1
  18. package/dist/components/atoms/Switch.svelte.d.ts +1 -0
  19. package/dist/components/atoms/Textarea.svelte +26 -1
  20. package/dist/components/atoms/Textarea.svelte.d.ts +4 -0
  21. package/dist/components/layouts/AppShell.svelte +15 -8
  22. package/dist/components/molecules/Accordion.svelte +6 -3
  23. package/dist/components/molecules/CopyButton.svelte +2 -26
  24. package/dist/components/molecules/FileButton.svelte +45 -3
  25. package/dist/components/molecules/IconButton.svelte +23 -3
  26. package/dist/components/molecules/IconButton.svelte.d.ts +2 -0
  27. package/dist/components/molecules/Modal.svelte +15 -4
  28. package/dist/components/molecules/Modal.svelte.d.ts +3 -0
  29. package/dist/components/molecules/OptionButton.svelte +28 -30
  30. package/dist/components/molecules/Popover.svelte +46 -25
  31. package/dist/components/molecules/Popover.svelte.d.ts +7 -2
  32. package/dist/components/molecules/SelectButton.svelte +20 -16
  33. package/dist/components/molecules/Tabs.svelte +26 -7
  34. package/dist/components/molecules/Tabs.svelte.d.ts +2 -0
  35. package/dist/components/molecules/Toggle.svelte +30 -15
  36. package/dist/components/molecules/Tooltip.svelte +41 -28
  37. package/dist/components/molecules/Tooltip.svelte.d.ts +1 -1
  38. package/dist/components/organisms/DataTable.svelte +85 -4
  39. package/dist/components/organisms/DataTable.svelte.d.ts +6 -0
  40. package/dist/floating.d.ts +10 -0
  41. package/dist/floating.js +56 -0
  42. package/dist/index.d.ts +2 -1
  43. package/dist/index.js +2 -1
  44. package/dist/styles/app.css +14 -234
  45. package/dist/styles/variables.css +1 -1
  46. package/package.json +1 -1
  47. package/dist/components/atoms/Chip.svelte +0 -53
  48. package/dist/components/atoms/Chip.svelte.d.ts +0 -11
@@ -1,5 +1,7 @@
1
1
  /*
2
- * Base reset + element defaults + reusable global classes.
2
+ * Base reset + element defaults + a small generic utility layer + the
3
+ * syntax-highlight token mapping (which must be global to reach {@html} output).
4
+ * Component styling lives in each component's own scoped <style>, never here.
3
5
  * Consumes ONLY tokens from variables.css — never a raw color/size.
4
6
  * Mobile-first: base styles target phones; `min-width` queries enhance up.
5
7
  */
@@ -96,7 +98,10 @@ pre {
96
98
  border-radius: var(--r-pill);
97
99
  }
98
100
 
99
- /* ---------- layout primitives ---------- */
101
+ /* ---------- generic utilities ----------
102
+ * Small, content-agnostic helpers (NOT component styling — components own that in
103
+ * their own scope). Layout components (Container/Stack/Cluster/AutoGrid) are the
104
+ * recommended API; these stay for ad-hoc markup and as documented escape hatches. */
100
105
  .container {
101
106
  width: 100%;
102
107
  max-width: var(--content-max);
@@ -121,11 +126,10 @@ pre {
121
126
  .spacer {
122
127
  flex: 1;
123
128
  }
124
- .muted {
125
- color: var(--text-muted);
126
- }
127
129
  .faint {
128
- color: var(--text-faint);
130
+ /* `--faint-color` lets a parent retint slotted `.faint` text via inheritance
131
+ (custom props cross the slot boundary, so no :global needed). */
132
+ color: var(--faint-color, var(--text-faint));
129
133
  }
130
134
  .mono {
131
135
  font-family: var(--font-mono);
@@ -139,14 +143,6 @@ pre {
139
143
  .nowrap {
140
144
  white-space: nowrap;
141
145
  }
142
- /* Intrinsically responsive grid — no media queries: columns are at least
143
- --col-min wide and fill the row, wrapping when they can't. Set --col-min to
144
- tune. This adapts to the available space, so it works inside any container. */
145
- .auto-grid {
146
- display: grid;
147
- grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--col-min, 14rem)), 1fr));
148
- gap: var(--sp-4);
149
- }
150
146
  /* Opt a wrapper into container queries so descendants can respond to THIS box's
151
147
  width (not the viewport). Pair with `@container (…)` in a component's scope,
152
148
  or with the .cq-* utilities below. */
@@ -178,12 +174,10 @@ pre {
178
174
  }
179
175
  }
180
176
 
181
- /* ---------- control modifiers ----------
182
- * The Button atom owns .btn + its variants in its scoped style. What stays
183
- * global are the icon-sizing rule (used by raw aria-hidden svgs too) and the
184
- * string-passed modifiers (.btn-icon / .btn-control*) that ride on a
185
- * Button-rendered element and so can't live in one component's scope. */
186
- .btn svg,
177
+ /* ---------- icon sizing ----------
178
+ * Components own their own button/control styling in scope (Button, IconButton,
179
+ * Modal, Toaster, Dot, …). This single rule stays global because it also sizes
180
+ * raw decorative SVGs that callers drop in outside any component. */
187
181
  .icon,
188
182
  svg[aria-hidden='true'] {
189
183
  flex: none;
@@ -192,221 +186,14 @@ svg[aria-hidden='true'] {
192
186
  min-width: 1em;
193
187
  min-height: 1em;
194
188
  }
195
- .btn-icon {
196
- min-height: 2.25rem;
197
- min-width: 2.25rem;
198
- padding: var(--sp-2);
199
- }
200
- .btn-icon-inline {
201
- min-height: 0;
202
- min-width: 0;
203
- padding: 0 var(--sp-1);
204
- border: none;
205
- background: none;
206
- color: var(--text-muted);
207
- }
208
- .btn-icon-inline:hover:not(:disabled) {
209
- border: none;
210
- background: none;
211
- color: var(--text);
212
- }
213
- .btn-icon-inline.hover-danger:hover:not(:disabled) {
214
- color: var(--danger);
215
- }
216
- /* Uniform-height control: icon buttons, inputs and action buttons sharing a
217
- toolbar/composer row line up exactly. Square icon variant: .btn-control-square. */
218
- .btn-control {
219
- display: inline-flex;
220
- align-items: center;
221
- justify-content: center;
222
- gap: var(--sp-2);
223
- height: var(--control-height);
224
- min-height: var(--control-height);
225
- padding: 0 var(--sp-3);
226
- border: 1px solid var(--border-strong);
227
- border-radius: var(--r-md);
228
- background: var(--surface);
229
- color: var(--text);
230
- font-weight: var(--fw-medium);
231
- font-size: var(--fs-sm);
232
- line-height: 1;
233
- white-space: nowrap;
234
- transition:
235
- background 0.12s var(--ease),
236
- border-color 0.12s var(--ease),
237
- opacity 0.12s var(--ease);
238
- user-select: none;
239
- }
240
- .btn-control:hover:not(:disabled) {
241
- border-color: var(--accent);
242
- }
243
- .btn-control:disabled {
244
- opacity: 0.45;
245
- cursor: not-allowed;
246
- }
247
- .btn-control.btn-primary {
248
- background: var(--accent);
249
- border-color: var(--accent);
250
- color: var(--text-on-accent);
251
- }
252
- .btn-control.btn-primary:hover:not(:disabled) {
253
- border-color: var(--accent);
254
- filter: brightness(1.08);
255
- }
256
- .btn-control-square {
257
- width: var(--control-height);
258
- padding: 0;
259
- flex: none;
260
- }
261
-
262
- /* ---------- status dots ---------- */
263
- .dot {
264
- width: 0.55rem;
265
- height: 0.55rem;
266
- border-radius: var(--r-pill);
267
- flex: none;
268
- display: inline-block;
269
- }
270
- .dot-active {
271
- background: var(--dot-active);
272
- box-shadow: 0 0 6px var(--dot-active);
273
- }
274
- .dot-stale {
275
- background: var(--dot-stale);
276
- }
277
- .dot-dead {
278
- background: var(--dot-dead);
279
- }
280
- .dot-hibernated {
281
- background: var(--dot-hibernated);
282
- }
283
-
284
- /* ---------- modal / bottom sheet ---------- */
285
- .overlay {
286
- position: fixed;
287
- inset: 0;
288
- background: rgba(0, 0, 0, 0.55);
289
- z-index: var(--z-modal);
290
- display: flex;
291
- align-items: flex-end;
292
- justify-content: center;
293
- }
294
- @media (min-width: 640px) {
295
- .overlay {
296
- align-items: center;
297
- padding: var(--sp-6);
298
- }
299
- }
300
- .sheet {
301
- width: 100%;
302
- max-width: 34rem;
303
- max-height: calc(100dvh - var(--safe-top) - var(--sp-6));
304
- display: flex;
305
- flex-direction: column;
306
- background: var(--bg-elevated);
307
- border: 1px solid var(--border);
308
- border-radius: var(--r-lg) var(--r-lg) 0 0;
309
- box-shadow: var(--shadow-lg);
310
- animation: sheet-up 0.18s var(--ease);
311
- padding-bottom: var(--safe-bottom);
312
- }
313
- @media (min-width: 640px) {
314
- .sheet {
315
- border-radius: var(--r-lg);
316
- padding-bottom: 0;
317
- }
318
- }
319
- @keyframes sheet-up {
320
- from {
321
- transform: translateY(8%);
322
- opacity: 0.4;
323
- }
324
- }
325
- .sheet-head {
326
- display: flex;
327
- align-items: center;
328
- gap: var(--sp-2);
329
- padding: var(--sp-4);
330
- border-bottom: 1px solid var(--border);
331
- }
332
- .sheet-title {
333
- font-size: var(--fs-lg);
334
- font-weight: var(--fw-semibold);
335
- }
336
- .sheet-body {
337
- padding: var(--sp-4);
338
- overflow-y: auto;
339
- -webkit-overflow-scrolling: touch;
340
- }
341
- .sheet-foot {
342
- display: flex;
343
- gap: var(--sp-2);
344
- padding: var(--sp-4);
345
- border-top: 1px solid var(--border);
346
- }
347
-
348
- /* ---------- toast ---------- */
349
- .toast-wrap {
350
- position: fixed;
351
- left: 50%;
352
- transform: translateX(-50%);
353
- bottom: calc(var(--safe-bottom) + var(--sp-4));
354
- z-index: var(--z-toast);
355
- display: flex;
356
- flex-direction: column;
357
- gap: var(--sp-2);
358
- width: calc(100% - var(--sp-8));
359
- max-width: 30rem;
360
- pointer-events: none;
361
- }
362
- .toast-wrap .toast {
363
- pointer-events: auto;
364
- width: 100%;
365
- text-align: left;
366
- color: inherit;
367
- cursor: pointer;
368
- background: var(--bg-elevated-2);
369
- border: 1px solid var(--border-strong);
370
- border-radius: var(--r-md);
371
- padding: var(--sp-3) var(--sp-4);
372
- box-shadow: var(--shadow-md);
373
- font-size: var(--fs-sm);
374
- animation: sheet-up 0.18s var(--ease);
375
- }
376
- .toast-wrap .toast-err {
377
- border-color: var(--danger);
378
- color: var(--danger);
379
- }
380
- .toast-wrap .toast-ok {
381
- border-color: var(--accent);
382
- }
383
189
 
384
190
  /* ---------- misc ---------- */
385
- .empty {
386
- text-align: center;
387
- color: var(--text-faint);
388
- padding: var(--sp-10) var(--sp-4);
389
- }
390
191
  .divider {
391
192
  height: 1px;
392
193
  background: var(--border);
393
194
  border: 0;
394
195
  margin: var(--sp-2) 0;
395
196
  }
396
- .spin {
397
- width: 1.1rem;
398
- height: 1.1rem;
399
- border: 2px solid var(--border-strong);
400
- border-top-color: var(--accent);
401
- border-radius: 50%;
402
- animation: spin 0.7s linear infinite;
403
- display: inline-block;
404
- }
405
- @keyframes spin {
406
- to {
407
- transform: rotate(360deg);
408
- }
409
- }
410
197
  .sr-only {
411
198
  position: absolute;
412
199
  width: 1px;
@@ -505,13 +292,6 @@ svg[aria-hidden='true'] {
505
292
  outline: 2px solid Highlight;
506
293
  outline-offset: 2px;
507
294
  }
508
- /* Status tints/borders drawn with color-mix collapse to the system palette;
509
- force a readable border so badges/cards keep their edges. */
510
- .dot,
511
- .btn-control,
512
- .btn-icon {
513
- forced-color-adjust: auto;
514
- }
515
295
  }
516
296
 
517
297
  /* Stronger separators when the user asks for more contrast. */
@@ -162,7 +162,7 @@
162
162
  --shadow-lg: 0 12px 40px rgba(0, 0, 0, 0.55);
163
163
 
164
164
  /* ---- Controls (CCT-250 item 1) — shared height for icon buttons + inputs
165
- so toolbars/composers line up. `.btn-control` (app.css) consumes it. */
165
+ so toolbars/composers line up. Button's `control` variant consumes it. */
166
166
  --control-height: 2.75rem;
167
167
 
168
168
  /* ---- Layout ---- */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dorsk/tsumikit",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
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",
@@ -1,53 +0,0 @@
1
- <script lang="ts">
2
- // Small inline label primitive — a flat, rounded tag for secondary metadata
3
- // (status, model/effort, cwd). Lighter than a Badge: no tone palette, just the
4
- // muted pill. Polymorphic via `as`; an `as="button"` chip is interactive
5
- // (hover affordance). `mono` switches to the monospace family (paths, ids).
6
- import type { Snippet } from 'svelte';
7
-
8
- let {
9
- as = 'span',
10
- mono = false,
11
- class: klass = '',
12
- children,
13
- ...rest
14
- }: {
15
- as?: 'span' | 'button';
16
- mono?: boolean;
17
- class?: string;
18
- children?: Snippet;
19
- [key: string]: unknown;
20
- } = $props();
21
- </script>
22
-
23
- <svelte:element this={as} class="chip {klass}" class:mono class:interactive={as === 'button'} {...rest}>
24
- {@render children?.()}
25
- </svelte:element>
26
-
27
- <style>
28
- .chip {
29
- display: inline-flex;
30
- align-items: center;
31
- gap: var(--sp-1);
32
- font-size: var(--fs-xs);
33
- color: var(--text-muted);
34
- background: var(--bg-elevated-2);
35
- border: 1px solid var(--border);
36
- border-radius: var(--r-pill);
37
- padding: 0.1rem var(--sp-2);
38
- max-width: 100%;
39
- }
40
- .mono {
41
- font-family: var(--font-mono);
42
- }
43
- .interactive {
44
- cursor: pointer;
45
- transition:
46
- border-color 0.12s var(--ease),
47
- color 0.12s var(--ease);
48
- }
49
- .interactive:hover {
50
- border-color: var(--border-strong);
51
- color: var(--text);
52
- }
53
- </style>
@@ -1,11 +0,0 @@
1
- import type { Snippet } from 'svelte';
2
- type $$ComponentProps = {
3
- as?: 'span' | 'button';
4
- mono?: boolean;
5
- class?: string;
6
- children?: Snippet;
7
- [key: string]: unknown;
8
- };
9
- declare const Chip: import("svelte").Component<$$ComponentProps, {}, "">;
10
- type Chip = ReturnType<typeof Chip>;
11
- export default Chip;