@dorsk/tsumikit 0.2.9 → 0.2.10

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.
@@ -87,6 +87,11 @@
87
87
 
88
88
  export type IconName = keyof typeof ICONS;
89
89
 
90
+ /** True when `s` is a registered glyph name (vs. e.g. a raw emoji string). */
91
+ export function isIconName(s: string): s is IconName {
92
+ return s in ICONS;
93
+ }
94
+
90
95
  // Glyphs that read better filled than stroked.
91
96
  const FILLED = new Set<IconName>(['stop', 'star', 'live']);
92
97
  </script>
@@ -67,6 +67,8 @@ declare const ICONS: {
67
67
  readonly 'alert-circle': "<circle cx=\"12\" cy=\"12\" r=\"10\" /><line x1=\"12\" x2=\"12\" y1=\"8\" y2=\"12\" /><line x1=\"12\" x2=\"12.01\" y1=\"16\" y2=\"16\" />";
68
68
  };
69
69
  export type IconName = keyof typeof ICONS;
70
+ /** True when `s` is a registered glyph name (vs. e.g. a raw emoji string). */
71
+ export declare function isIconName(s: string): s is IconName;
70
72
  import type { Snippet } from 'svelte';
71
73
  type $$ComponentProps = {
72
74
  /** Named glyph from the registry. Omit when supplying `children`. */
@@ -2,13 +2,14 @@
2
2
  // File-picker button. A real <input type="file"> visually hidden inside a
3
3
  // <label> styled as a button — so it's keyboard-focusable and works with zero
4
4
  // JS to open the dialog. Emits the chosen files via `onfiles`. Dependency-free.
5
- import Icon from '../atoms/Icon.svelte';
5
+ import Icon, { isIconName } from '../atoms/Icon.svelte';
6
6
  import type { IconName } from '../atoms/Icon.svelte';
7
7
 
8
8
  let {
9
9
  onfiles,
10
10
  label = 'Choose file',
11
- icon = 'upload',
11
+ icon = '📎',
12
+ iconOnly = false,
12
13
  accept,
13
14
  multiple = false,
14
15
  disabled = false,
@@ -17,7 +18,12 @@
17
18
  }: {
18
19
  onfiles: (files: File[]) => void;
19
20
  label?: string;
20
- icon?: IconName;
21
+ /** A registered glyph name (rendered as SVG) or any string such as an
22
+ * emoji (rendered as text). Defaults to the 📎 paperclip emoji. */
23
+ icon?: IconName | (string & {});
24
+ /** Hide the label visually, showing only the icon. The label is kept for
25
+ * assistive tech (and used as the accessible name). */
26
+ iconOnly?: boolean;
21
27
  accept?: string;
22
28
  multiple?: boolean;
23
29
  disabled?: boolean;
@@ -37,7 +43,9 @@
37
43
  class="file-btn {klass}"
38
44
  class:primary={variant === 'primary'}
39
45
  class:ghost={variant === 'ghost'}
46
+ class:icon-only={iconOnly}
40
47
  class:disabled
48
+ aria-label={iconOnly ? label : undefined}
41
49
  >
42
50
  <input
43
51
  class="sr-only"
@@ -47,8 +55,12 @@
47
55
  {disabled}
48
56
  onchange={onchange}
49
57
  />
50
- <Icon name={icon} />
51
- <span>{label}</span>
58
+ {#if isIconName(icon)}
59
+ <Icon name={icon} />
60
+ {:else}
61
+ <span class="emoji" aria-hidden="true">{icon}</span>
62
+ {/if}
63
+ <span class:sr-only={iconOnly}>{label}</span>
52
64
  </label>
53
65
 
54
66
  <style>
@@ -80,6 +92,18 @@
80
92
  .file-btn:hover:not(.disabled) {
81
93
  border-color: var(--accent);
82
94
  }
95
+ /* icon-only: square it up and drop the label gap. */
96
+ .file-btn.icon-only {
97
+ gap: 0;
98
+ padding: var(--sp-2);
99
+ aspect-ratio: 1;
100
+ }
101
+ /* Emoji glyph tracks the text size like the SVG Icon does (1em). */
102
+ .emoji {
103
+ display: inline-flex;
104
+ font-size: 1em;
105
+ line-height: 1;
106
+ }
83
107
  .file-btn.primary {
84
108
  background: var(--accent);
85
109
  border-color: var(--accent);
@@ -2,7 +2,12 @@ import type { IconName } from '../atoms/Icon.svelte';
2
2
  type $$ComponentProps = {
3
3
  onfiles: (files: File[]) => void;
4
4
  label?: string;
5
- icon?: IconName;
5
+ /** A registered glyph name (rendered as SVG) or any string such as an
6
+ * emoji (rendered as text). Defaults to the 📎 paperclip emoji. */
7
+ icon?: IconName | (string & {});
8
+ /** Hide the label visually, showing only the icon. The label is kept for
9
+ * assistive tech (and used as the accessible name). */
10
+ iconOnly?: boolean;
6
11
  accept?: string;
7
12
  multiple?: boolean;
8
13
  disabled?: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dorsk/tsumikit",
3
- "version": "0.2.9",
3
+ "version": "0.2.10",
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",