@dorsk/tsumikit 0.78.0 → 0.80.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 (90) hide show
  1. package/dist/components/atoms/Artwork.svelte +5 -3
  2. package/dist/components/atoms/Badge.svelte +2 -5
  3. package/dist/components/atoms/Button.svelte +327 -17
  4. package/dist/components/atoms/Button.svelte.d.ts +4 -1
  5. package/dist/components/atoms/Card.svelte +160 -12
  6. package/dist/components/atoms/Checkbox.svelte +181 -3
  7. package/dist/components/atoms/Gauge.svelte +2 -2
  8. package/dist/components/atoms/Input.svelte +41 -3
  9. package/dist/components/atoms/Kbd.svelte +1 -1
  10. package/dist/components/atoms/Link.svelte +61 -0
  11. package/dist/components/atoms/Progress.svelte +75 -2
  12. package/dist/components/atoms/Progress.svelte.d.ts +1 -0
  13. package/dist/components/atoms/SegmentedProgress.svelte +2 -2
  14. package/dist/components/atoms/Select.svelte +39 -3
  15. package/dist/components/atoms/Skeleton.svelte +54 -3
  16. package/dist/components/atoms/Skeleton.svelte.d.ts +1 -0
  17. package/dist/components/atoms/Slider.svelte +8 -6
  18. package/dist/components/atoms/Spinner.svelte +152 -3
  19. package/dist/components/atoms/Spinner.svelte.d.ts +1 -1
  20. package/dist/components/atoms/Swatch.svelte +1 -1
  21. package/dist/components/atoms/Switch.svelte +138 -2
  22. package/dist/components/atoms/Textarea.svelte +42 -3
  23. package/dist/components/atoms/Thinking.svelte +130 -0
  24. package/dist/components/atoms/Thinking.svelte.d.ts +15 -0
  25. package/dist/components/layouts/AppShell.svelte +6 -6
  26. package/dist/components/layouts/MasterDetail.svelte +3 -3
  27. package/dist/components/layouts/NavBar.svelte +4 -4
  28. package/dist/components/layouts/NavSection.svelte +1 -1
  29. package/dist/components/layouts/ResizablePanel.svelte +7 -7
  30. package/dist/components/layouts/TabBar.svelte +2 -2
  31. package/dist/components/molecules/Accordion.svelte +2 -2
  32. package/dist/components/molecules/AttachmentList.svelte +2 -2
  33. package/dist/components/molecules/CapBar.svelte +2 -2
  34. package/dist/components/molecules/CodeBlock.svelte +5 -5
  35. package/dist/components/molecules/Combobox.svelte +3 -3
  36. package/dist/components/molecules/CopyButton.svelte +146 -5
  37. package/dist/components/molecules/Drawer.svelte +8 -8
  38. package/dist/components/molecules/EmojiPicker.svelte +1 -1
  39. package/dist/components/molecules/Field.svelte +55 -1
  40. package/dist/components/molecules/FileButton.svelte +20 -6
  41. package/dist/components/molecules/FilterInput.svelte +4 -4
  42. package/dist/components/molecules/GitRef.svelte +2 -2
  43. package/dist/components/molecules/GlyphStack.svelte +21 -3
  44. package/dist/components/molecules/InputGroup.svelte +3 -3
  45. package/dist/components/molecules/LookPicker.svelte +87 -0
  46. package/dist/components/molecules/LookPicker.svelte.d.ts +17 -0
  47. package/dist/components/molecules/Modal.svelte +5 -5
  48. package/dist/components/molecules/MotionSettings.svelte +166 -0
  49. package/dist/components/molecules/MotionSettings.svelte.d.ts +18 -0
  50. package/dist/components/molecules/OptionButton.svelte +8 -3
  51. package/dist/components/molecules/Pagination.svelte +3 -1
  52. package/dist/components/molecules/Popover.svelte +18 -11
  53. package/dist/components/molecules/Prose.svelte +6 -6
  54. package/dist/components/molecules/RadialMenu.svelte +3 -3
  55. package/dist/components/molecules/RadioGroup.svelte +67 -4
  56. package/dist/components/molecules/RichSelect.svelte +6 -4
  57. package/dist/components/molecules/SectionHeader.svelte +1 -1
  58. package/dist/components/molecules/SeekSlider.svelte +6 -6
  59. package/dist/components/molecules/SegmentedControl.svelte +7 -7
  60. package/dist/components/molecules/SortableList.svelte +2 -2
  61. package/dist/components/molecules/SplitButton.svelte +1 -1
  62. package/dist/components/molecules/Tabs.svelte +160 -7
  63. package/dist/components/molecules/ThemePicker.svelte +1 -1
  64. package/dist/components/molecules/Timestamp.svelte +1 -1
  65. package/dist/components/molecules/Toggle.svelte +5 -3
  66. package/dist/components/molecules/Tooltip.svelte +2 -2
  67. package/dist/components/molecules/VolumeSlider.svelte +3 -3
  68. package/dist/components/organisms/ConversationFeed.svelte +1 -1
  69. package/dist/components/organisms/ConversationPanel.svelte +3 -3
  70. package/dist/components/organisms/DataTable.svelte +18 -16
  71. package/dist/fx.d.ts +149 -0
  72. package/dist/fx.js +111 -0
  73. package/dist/fx.md +58 -0
  74. package/dist/index.d.ts +8 -2
  75. package/dist/index.js +8 -2
  76. package/dist/looks/README.md +101 -0
  77. package/dist/looks/depth.css +939 -0
  78. package/dist/looks/editorial.css +545 -0
  79. package/dist/looks/tactile.css +871 -0
  80. package/dist/pointer.d.ts +3 -0
  81. package/dist/pointer.js +40 -0
  82. package/dist/stores/fx.svelte.d.ts +17 -0
  83. package/dist/stores/fx.svelte.js +64 -0
  84. package/dist/stores/theme.svelte.d.ts +8 -2
  85. package/dist/stores/theme.svelte.js +33 -7
  86. package/dist/styles/themes.css +249 -249
  87. package/dist/styles/tokens.css +37 -2
  88. package/dist/theme-mode.d.ts +31 -0
  89. package/dist/theme-mode.js +19 -0
  90. package/package.json +3 -2
@@ -123,7 +123,9 @@
123
123
  indLeft = left;
124
124
  indWidth = width;
125
125
  ind.style.width = `${width}px`;
126
- if (!animate || !placed || width === 0) {
126
+ const fx = getComputedStyle(ind).getPropertyValue('--tabs-fx').trim();
127
+ const still = globalThis.matchMedia?.('(prefers-reduced-motion: reduce)').matches ?? false;
128
+ if (!animate || !placed || width === 0 || still) {
127
129
  ind.style.transition = 'none';
128
130
  ind.style.translate = `${left}px 0`;
129
131
  ind.style.scale = '1 1';
@@ -132,6 +134,22 @@
132
134
  placed = true;
133
135
  return;
134
136
  }
137
+ if (fx === 'stretch' && typeof ind.animate === 'function') {
138
+ const lo = Math.min(prevLeft, left);
139
+ const hi = Math.max(prevLeft + prevWidth, left + width);
140
+ const ease = (name: string) => getComputedStyle(ind).getPropertyValue(name).trim() || 'ease-out';
141
+ ind.style.translate = `${left}px 0`;
142
+ ind.style.scale = '1 1';
143
+ ind.animate(
144
+ [
145
+ { translate: `${prevLeft}px 0`, scale: `${prevWidth / width} 1`, easing: ease('--ease-out') },
146
+ { translate: `${lo}px 0`, scale: `${(hi - lo) / width} 1`, offset: 0.4, easing: ease('--ease-spring') },
147
+ { translate: `${left}px 0`, scale: '1 1' }
148
+ ],
149
+ { duration: 280 }
150
+ );
151
+ return;
152
+ }
135
153
  ind.style.transition = 'none';
136
154
  ind.style.translate = `${prevLeft}px 0`;
137
155
  ind.style.scale = `${prevWidth / width} 1`;
@@ -152,6 +170,14 @@
152
170
  return () => ro.disconnect();
153
171
  });
154
172
 
173
+ function inkFrom(e: MouseEvent) {
174
+ const el = e.currentTarget as HTMLElement;
175
+ const r = el.getBoundingClientRect();
176
+ const pointer = e.detail > 0;
177
+ el.style.setProperty('--ink-x', pointer ? `${e.clientX - r.left}px` : '50%');
178
+ el.style.setProperty('--ink-y', pointer ? `${e.clientY - r.top}px` : '50%');
179
+ }
180
+
155
181
  function select(id: string, focus = false) {
156
182
  if (tabs.find((t) => t.id === id)?.disabled) return;
157
183
  if (value !== id) playSound('click', sound);
@@ -161,7 +187,11 @@
161
187
  // The list scrolls when it is too narrow, so keyboard selection has to
162
188
  // bring the tab back into view or it moves somewhere unseen.
163
189
  el?.scrollIntoView({ block: 'nearest', inline: 'nearest' });
164
- if (focus) el?.focus();
190
+ if (focus) {
191
+ el?.style.removeProperty('--ink-x');
192
+ el?.style.removeProperty('--ink-y');
193
+ el?.focus();
194
+ }
165
195
  });
166
196
  }
167
197
  // Step to the next non-disabled tab in a direction, wrapping around.
@@ -236,7 +266,10 @@
236
266
  class="tab closable"
237
267
  class:selected={value === t.id}
238
268
  class:disabled={t.disabled}
239
- onclick={() => select(t.id)}
269
+ onclick={(e) => {
270
+ inkFrom(e);
271
+ select(t.id);
272
+ }}
240
273
  onauxclick={(e) => onauxclick(e, t.id)}
241
274
  >
242
275
  {@render body(t)}
@@ -268,7 +301,10 @@
268
301
  tabindex={stop?.id === t.id ? 0 : -1}
269
302
  class="tab"
270
303
  class:selected={value === t.id}
271
- onclick={() => select(t.id)}
304
+ onclick={(e) => {
305
+ inkFrom(e);
306
+ select(t.id);
307
+ }}
272
308
  >
273
309
  {@render body(t)}
274
310
  </button>
@@ -297,7 +333,7 @@
297
333
  flex: 1 1 auto;
298
334
  min-width: 0;
299
335
  gap: var(--sp-1);
300
- border-bottom: 1px solid var(--border);
336
+ border-bottom: var(--edge-width) solid var(--surface-edge);
301
337
  overflow-x: auto;
302
338
  overflow-y: hidden;
303
339
  scrollbar-width: thin;
@@ -330,7 +366,7 @@
330
366
  font-weight: var(--fw-medium);
331
367
  --icon-size: var(--control-icon-md);
332
368
  border-bottom: 2px solid transparent;
333
- margin-bottom: -1px;
369
+ margin-bottom: calc(-1 * var(--edge-width));
334
370
  max-width: var(--tab-max-width, none);
335
371
  transition:
336
372
  color var(--dur-fast) var(--ease),
@@ -373,7 +409,7 @@
373
409
  align-items: center;
374
410
  gap: var(--sp-1);
375
411
  padding-inline-start: var(--sp-2);
376
- border-bottom: 1px solid var(--border);
412
+ border-bottom: var(--edge-width) solid var(--surface-edge);
377
413
  }
378
414
  .tabpanel {
379
415
  padding-top: var(--sp-4);
@@ -389,4 +425,121 @@
389
425
  outline-offset: var(--focus-ring-offset);
390
426
  border-radius: var(--r-sm);
391
427
  }
428
+
429
+ /* Sliding pill: a raised pill glides behind the selected tab with a slight overshoot. */
430
+ .tabs:not(:global([data-fx-tabs]:not([data-fx-tabs='pill'])) *),
431
+ :global([data-fx-tabs='pill']) .tabs:not(:global([data-fx-tabs='pill'] [data-fx-tabs]:not([data-fx-tabs='pill'])) *) {
432
+ --tabs-fx: pill;
433
+ & .tablist {
434
+ isolation: isolate;
435
+ flex: 0 1 auto;
436
+ padding: 3px;
437
+ border-bottom: 0;
438
+ border-radius: var(--r-pill);
439
+ background: var(--surface-fill-2);
440
+ box-shadow: inset 0 0 0 var(--edge-width) var(--surface-edge);
441
+ }
442
+ & .actions {
443
+ border-bottom: 0;
444
+ }
445
+ & .tab {
446
+ min-height: calc(var(--control-md) - 6px);
447
+ margin-bottom: 0;
448
+ border-bottom: 0;
449
+ border-radius: var(--r-pill);
450
+ }
451
+ & .tab.selected {
452
+ color: var(--text);
453
+ }
454
+ & .tablist:not(.placed) .tab.selected {
455
+ background: var(--surface);
456
+ }
457
+ & .tab.selected:focus-visible {
458
+ outline: none;
459
+ }
460
+ & .indicator {
461
+ top: 3px;
462
+ bottom: 3px;
463
+ z-index: -1;
464
+ height: auto;
465
+ border-radius: var(--r-pill);
466
+ background: var(--surface);
467
+ box-shadow:
468
+ 0 0 0 var(--edge-width) color-mix(in srgb, var(--accent) 35%, var(--surface-edge)),
469
+ 0 1px 3px color-mix(in srgb, var(--text) 14%, transparent);
470
+ transition-timing-function: var(--ease-spring-bounce);
471
+ }
472
+ & .tablist:has(.tab.selected:focus-visible) .indicator {
473
+ box-shadow:
474
+ 0 0 0 2px var(--accent),
475
+ 0 1px 3px color-mix(in srgb, var(--text) 14%, transparent);
476
+ }
477
+ }
478
+ /* Stretch line: the script stretches the line across both tabs, then lets the tail catch up. */
479
+ :global([data-fx-tabs='stretch']) .tabs:not(:global([data-fx-tabs='stretch'] [data-fx-tabs]:not([data-fx-tabs='stretch'])) *) {
480
+ --tabs-fx: stretch;
481
+ }
482
+ /* Ink blot: a tint spreads from the click point and a short mark springs in under the label. */
483
+ :global([data-fx-tabs='ink']) .tabs:not(:global([data-fx-tabs='ink'] [data-fx-tabs]:not([data-fx-tabs='ink'])) *) {
484
+ --tabs-fx: ink;
485
+ & .indicator {
486
+ display: none;
487
+ }
488
+ & .tab {
489
+ position: relative;
490
+ isolation: isolate;
491
+ overflow: hidden;
492
+ border-radius: var(--r-md) var(--r-md) 0 0;
493
+ }
494
+ & .tab::before,
495
+ & .tab::after {
496
+ content: '';
497
+ position: absolute;
498
+ pointer-events: none;
499
+ }
500
+ & .tab::before {
501
+ left: var(--ink-x, 50%);
502
+ top: var(--ink-y, 50%);
503
+ z-index: -1;
504
+ width: 260%;
505
+ aspect-ratio: 1;
506
+ translate: -50% -50%;
507
+ border-radius: var(--r-pill);
508
+ background: radial-gradient(
509
+ circle closest-side,
510
+ color-mix(in srgb, var(--accent) 22%, transparent) 0 55%,
511
+ color-mix(in srgb, var(--accent) 14%, transparent) 80%,
512
+ transparent
513
+ );
514
+ scale: 0;
515
+ opacity: 0;
516
+ transition-property: opacity, scale;
517
+ transition-duration: var(--dur-exit), var(--dur-instant);
518
+ transition-delay: var(--dur-instant), var(--dur-exit);
519
+ transition-timing-function: ease;
520
+ }
521
+ & .tab.selected::before {
522
+ scale: 1;
523
+ opacity: 1;
524
+ transition-duration: var(--dur-fast), var(--dur-slow);
525
+ transition-delay: var(--dur-instant);
526
+ transition-timing-function: ease, var(--ease-out);
527
+ }
528
+ & .tab::after {
529
+ inset: auto 30% 4px;
530
+ height: 2px;
531
+ border-radius: var(--r-xs);
532
+ background: var(--accent);
533
+ opacity: 0;
534
+ scale: 0.2 1;
535
+ transition-property: opacity, scale;
536
+ transition-duration: var(--dur-exit-fast);
537
+ }
538
+ & .tab.selected::after {
539
+ opacity: 1;
540
+ scale: 1 1;
541
+ transition-duration: var(--dur-fast), var(--dur-spring);
542
+ transition-timing-function: ease, var(--ease-spring-bounce);
543
+ }
544
+ }
392
545
  </style>
@@ -257,7 +257,7 @@
257
257
  margin-top: var(--sp-2);
258
258
  padding: var(--sp-1) var(--sp-2);
259
259
  border: 2px solid transparent;
260
- border-top: 1px solid var(--border);
260
+ border-top: var(--edge-width) solid var(--surface-edge);
261
261
  border-radius: var(--r-md);
262
262
  background: none;
263
263
  color: inherit;
@@ -226,7 +226,7 @@
226
226
  .ts-mode {
227
227
  flex: 1;
228
228
  padding: var(--sp-1) var(--sp-2);
229
- border: 1px solid var(--border-strong);
229
+ border: var(--edge-width) solid var(--btn-edge);
230
230
  border-radius: var(--r-sm);
231
231
  background: transparent;
232
232
  color: var(--text-muted);
@@ -82,15 +82,16 @@
82
82
  font-weight: var(--fw-medium);
83
83
  line-height: var(--lh-none);
84
84
  --icon-size: var(--control-icon-sm);
85
- background: var(--bg-elevated-2);
85
+ background: var(--surface-fill-2);
86
86
  color: var(--text-muted);
87
- border: 1px solid var(--border);
87
+ border: var(--edge-width) solid var(--surface-edge);
88
88
  white-space: nowrap;
89
89
  user-select: none;
90
90
  transition:
91
91
  background var(--dur-fast) var(--ease),
92
92
  border-color var(--dur-fast) var(--ease),
93
93
  color var(--dur-fast) var(--ease),
94
+ translate var(--dur-fast) var(--ease),
94
95
  scale var(--dur-fast) var(--ease-out);
95
96
  }
96
97
  .toggle:disabled {
@@ -125,7 +126,8 @@
125
126
  }
126
127
  @media (hover: hover) and (pointer: fine) {
127
128
  .toggle:hover:not(:disabled) {
128
- border-color: var(--border-strong);
129
+ border-color: var(--surface-edge-strong);
130
+ translate: 0 calc(-1 * var(--hover-lift));
129
131
  }
130
132
  }
131
133
  .toggle:active:not(:disabled) {
@@ -206,9 +206,9 @@
206
206
  padding: var(--sp-1) var(--sp-2);
207
207
  background: var(--bg-elevated-2);
208
208
  color: var(--text);
209
- border: 1px solid var(--border-strong);
209
+ border: var(--edge-width) solid var(--raised-edge);
210
210
  border-radius: var(--r-sm);
211
- box-shadow: var(--shadow-md);
211
+ box-shadow: var(--raised-shadow);
212
212
  font-size: var(--fs-xs);
213
213
  line-height: var(--lh-snug);
214
214
  white-space: normal;
@@ -306,7 +306,7 @@
306
306
  height: var(--vol-track);
307
307
  margin-top: calc(var(--vol-track) / -2);
308
308
  border-radius: var(--r-pill);
309
- background: var(--bg-elevated-2);
309
+ background: var(--track-fill);
310
310
  overflow: hidden;
311
311
  }
312
312
  .vol--vertical .vol-track {
@@ -354,7 +354,7 @@
354
354
  border-radius: var(--r-pill);
355
355
  background: var(--vol-accent);
356
356
  border: 2px solid var(--bg);
357
- box-shadow: var(--shadow-sm);
357
+ box-shadow: var(--thumb-shadow);
358
358
  transform: translate(-50%, -50%);
359
359
  scale: 0.6;
360
360
  opacity: 0;
@@ -375,7 +375,7 @@
375
375
  .vol-slab:not([aria-disabled='true']):hover .vol-thumb {
376
376
  opacity: 1;
377
377
  scale: 1;
378
- box-shadow: var(--shadow-sm), var(--vol-halo);
378
+ box-shadow: var(--thumb-shadow), var(--vol-halo);
379
379
  }
380
380
  .vol--dragging .vol-thumb {
381
381
  scale: 1.15;
@@ -181,6 +181,6 @@
181
181
  margin-inline: auto;
182
182
  z-index: 1;
183
183
  border-radius: var(--r-pill);
184
- box-shadow: var(--shadow-md);
184
+ box-shadow: var(--raised-shadow);
185
185
  }
186
186
  </style>
@@ -45,7 +45,7 @@
45
45
  gap: var(--sp-2);
46
46
  min-width: 0;
47
47
  padding: var(--sp-2) var(--sp-3);
48
- border-bottom: 1px solid var(--border);
48
+ border-bottom: var(--edge-width) solid var(--surface-edge);
49
49
  }
50
50
  .panel-body {
51
51
  flex: 1;
@@ -55,12 +55,12 @@
55
55
  }
56
56
  .panel-status {
57
57
  flex: none;
58
- border-top: 1px solid var(--border);
58
+ border-top: var(--edge-width) solid var(--surface-edge);
59
59
  }
60
60
  .panel-composer {
61
61
  flex: none;
62
62
  padding: var(--sp-2) var(--sp-3) var(--sp-3);
63
- border-top: 1px solid var(--border);
63
+ border-top: var(--edge-width) solid var(--surface-edge);
64
64
  }
65
65
  .panel-status + .panel-composer {
66
66
  border-top: 0;
@@ -239,6 +239,7 @@
239
239
  <th
240
240
  scope="col"
241
241
  data-hide-below={col.hideBelow}
242
+ class:dt-sortable={col.sortable && !headerSnippets[col.key]}
242
243
  style:width={col.width}
243
244
  style:text-align={col.align ?? 'left'}
244
245
  aria-sort={col.sortable
@@ -363,7 +364,7 @@
363
364
  width: 100%;
364
365
  overflow-x: auto;
365
366
  -webkit-overflow-scrolling: touch;
366
- border: 1px solid var(--border);
367
+ border: var(--edge-width) solid var(--surface-edge);
367
368
  border-radius: var(--r-lg);
368
369
  container-type: inline-size;
369
370
  }
@@ -382,7 +383,7 @@
382
383
  th,
383
384
  td {
384
385
  padding: var(--sp-2) var(--sp-3);
385
- border-bottom: 1px solid var(--border);
386
+ border-bottom: var(--edge-width) solid var(--surface-edge);
386
387
  }
387
388
  .dt.sm th,
388
389
  .dt.sm td {
@@ -394,7 +395,7 @@
394
395
  color: var(--text-muted);
395
396
  text-transform: uppercase;
396
397
  letter-spacing: 0.04em;
397
- background: var(--bg-elevated-2);
398
+ background: var(--surface-fill-2);
398
399
  white-space: nowrap;
399
400
  }
400
401
  .dt.sticky th {
@@ -430,6 +431,15 @@
430
431
  color: inherit;
431
432
  cursor: pointer;
432
433
  }
434
+ th.dt-sortable {
435
+ position: relative;
436
+ }
437
+ /* The whole header cell is the sort hit area. */
438
+ .dt-sort::after {
439
+ content: '';
440
+ position: absolute;
441
+ inset: 0;
442
+ }
433
443
  .dt-arrow {
434
444
  display: inline-block;
435
445
  opacity: 0.4;
@@ -527,17 +537,9 @@
527
537
  tbody tr:last-child td :global(.checkbox::before) {
528
538
  inset-block-end: 0;
529
539
  }
530
- /* Sort slab: inline-end stays at 0 so it never reaches the next header
531
- cell, and the inline-start reach stays inside the cell's own padding. */
532
- .dt-sort {
533
- position: relative;
534
- }
535
- .dt-sort::before {
536
- content: '';
537
- position: absolute;
538
- inset-block: var(--touch-slab);
539
- inset-inline-start: var(--touch-slab);
540
- inset-inline-end: 0;
540
+ /* The cell overlay grows vertically to the compact target, never sideways. */
541
+ .dt-sort::after {
542
+ inset-block: min(0px, calc((100% - var(--touch-target-compact)) / 2));
541
543
  }
542
544
  }
543
545
  @container (max-width: 30rem) {
@@ -587,7 +589,7 @@
587
589
  align-items: baseline;
588
590
  gap: var(--sp-1) var(--sp-3);
589
591
  padding: var(--sp-3);
590
- border-bottom: 1px solid var(--border);
592
+ border-bottom: var(--edge-width) solid var(--surface-edge);
591
593
  }
592
594
  [data-stacked] tbody tr:last-child {
593
595
  border-bottom: none;
@@ -679,7 +681,7 @@
679
681
  .dt-more {
680
682
  text-align: center;
681
683
  padding: var(--sp-2);
682
- border-top: 1px solid var(--border);
684
+ border-top: var(--edge-width) solid var(--surface-edge);
683
685
  }
684
686
  .dt-more-btn {
685
687
  border: 0;
package/dist/fx.d.ts ADDED
@@ -0,0 +1,149 @@
1
+ export declare const FX: {
2
+ readonly hover: {
3
+ readonly label: "Button hover";
4
+ readonly variants: readonly [{
5
+ readonly id: "smoke";
6
+ readonly label: "Smoke";
7
+ }, {
8
+ readonly id: "ember";
9
+ readonly label: "Ember";
10
+ }, {
11
+ readonly id: "aurora";
12
+ readonly label: "Aurora";
13
+ }, {
14
+ readonly id: "none";
15
+ readonly label: "Off";
16
+ }];
17
+ };
18
+ readonly check: {
19
+ readonly label: "Checkbox";
20
+ readonly variants: readonly [{
21
+ readonly id: "draw";
22
+ readonly label: "Draw";
23
+ }, {
24
+ readonly id: "pop";
25
+ readonly label: "Pop";
26
+ }, {
27
+ readonly id: "confetti";
28
+ readonly label: "Confetti";
29
+ }, {
30
+ readonly id: "morph";
31
+ readonly label: "Morph";
32
+ }, {
33
+ readonly id: "none";
34
+ readonly label: "Off";
35
+ }];
36
+ };
37
+ readonly radio: {
38
+ readonly label: "Radio";
39
+ readonly variants: readonly [{
40
+ readonly id: "spring";
41
+ readonly label: "Spring";
42
+ }, {
43
+ readonly id: "liquid";
44
+ readonly label: "Liquid";
45
+ }, {
46
+ readonly id: "none";
47
+ readonly label: "Off";
48
+ }];
49
+ };
50
+ readonly switch: {
51
+ readonly label: "Switch";
52
+ readonly variants: readonly [{
53
+ readonly id: "squash";
54
+ readonly label: "Squash";
55
+ }, {
56
+ readonly id: "glow";
57
+ readonly label: "Glow";
58
+ }, {
59
+ readonly id: "calm";
60
+ readonly label: "Calm";
61
+ }, {
62
+ readonly id: "none";
63
+ readonly label: "Off";
64
+ }];
65
+ };
66
+ readonly focus: {
67
+ readonly label: "Input focus";
68
+ readonly variants: readonly [{
69
+ readonly id: "bloom";
70
+ readonly label: "Bloom";
71
+ }, {
72
+ readonly id: "label";
73
+ readonly label: "Spring label";
74
+ }, {
75
+ readonly id: "none";
76
+ readonly label: "Off";
77
+ }];
78
+ };
79
+ readonly tabs: {
80
+ readonly label: "Tabs";
81
+ readonly variants: readonly [{
82
+ readonly id: "pill";
83
+ readonly label: "Pill";
84
+ }, {
85
+ readonly id: "stretch";
86
+ readonly label: "Stretch";
87
+ }, {
88
+ readonly id: "ink";
89
+ readonly label: "Ink";
90
+ }, {
91
+ readonly id: "none";
92
+ readonly label: "Off";
93
+ }];
94
+ };
95
+ readonly copy: {
96
+ readonly label: "Copy";
97
+ readonly variants: readonly [{
98
+ readonly id: "burst";
99
+ readonly label: "Burst";
100
+ }, {
101
+ readonly id: "tick";
102
+ readonly label: "Tick";
103
+ }, {
104
+ readonly id: "none";
105
+ readonly label: "Off";
106
+ }];
107
+ };
108
+ readonly link: {
109
+ readonly label: "Link hover";
110
+ readonly variants: readonly [{
111
+ readonly id: "sweep";
112
+ readonly label: "Sweep";
113
+ }, {
114
+ readonly id: "highlight";
115
+ readonly label: "Highlight";
116
+ }, {
117
+ readonly id: "none";
118
+ readonly label: "Off";
119
+ }];
120
+ };
121
+ readonly card: {
122
+ readonly label: "Card hover";
123
+ readonly variants: readonly [{
124
+ readonly id: "spotlight";
125
+ readonly label: "Spotlight";
126
+ }, {
127
+ readonly id: "orbit";
128
+ readonly label: "Orbit";
129
+ }, {
130
+ readonly id: "none";
131
+ readonly label: "Off";
132
+ }];
133
+ };
134
+ };
135
+ export type FxFamily = keyof typeof FX;
136
+ export type FxVariant<F extends FxFamily = FxFamily> = (typeof FX)[F]['variants'][number]['id'];
137
+ export type FxSettings = {
138
+ [F in FxFamily]: FxVariant<F>;
139
+ };
140
+ export declare const FX_FAMILIES: FxFamily[];
141
+ export declare const DEFAULT_FX: FxSettings;
142
+ export declare function fxAttr(family: FxFamily): `data-fx-${FxFamily}`;
143
+ export declare function isFxVariant<F extends FxFamily>(family: F, v: unknown): v is FxVariant<F>;
144
+ /** Settings from an untrusted blob: unknown families are dropped, unknown
145
+ * variants fall back to `defaults`. */
146
+ export declare function parseFx(raw: unknown, defaults?: FxSettings): FxSettings;
147
+ export declare function fxDiff(settings: FxSettings): Partial<FxSettings>;
148
+ /** Inline <head> script painting the persisted `data-fx-*` before first paint. */
149
+ export declare function fxPrepaint(key: string): string;