@human-synthesis/norns-ui 0.2.1 → 0.2.3

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@human-synthesis/norns-ui",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "description": "UI library for the Norns ecosystem — Pug + Civet components on Tailwind v4.",
5
5
  "license": "MIT",
6
6
  "author": "Daniel Teodoroiu (https://humansynthesis.ai)",
@@ -16,6 +16,7 @@
16
16
  target!="{target}"
17
17
  rel!="{rel}"
18
18
  class!="{classes}"
19
+ aria-label!="{ariaLabel}"
19
20
  aria-disabled!="{disabled || loading ? 'true' : undefined}"
20
21
  )
21
22
  | {@render body()}
@@ -25,6 +26,7 @@
25
26
  class!="{classes}"
26
27
  disabled!="{disabled || loading}"
27
28
  onclick!="{onclick}"
29
+ aria-label!="{ariaLabel}"
28
30
  aria-busy!="{loading ? 'true' : undefined}"
29
31
  )
30
32
  | {@render body()}
@@ -44,6 +46,9 @@
44
46
  href
45
47
  target
46
48
  rel
49
+ // Icon-only buttons (icon set, no children) have no accessible name
50
+ // without this — always pass ariaLabel for those.
51
+ ariaLabel
47
52
  children
48
53
  leading
49
54
  trailing
@@ -8,6 +8,7 @@ input(
8
8
  disabled!="{disabled}"
9
9
  readonly!="{readonly}"
10
10
  autocomplete!="{autocomplete}"
11
+ aria-label!="{ariaLabel}"
11
12
  aria-invalid!="{hasError ? 'true' : undefined}"
12
13
  aria-describedby!="{describedBy}"
13
14
  class!="{classes}"
@@ -28,6 +29,9 @@ input(
28
29
  disabled = false
29
30
  readonly = false
30
31
  autocomplete
32
+ // A control with no visible label (a toolbar search box) still needs
33
+ // an accessible name — a placeholder is not a label (v6 U-12).
34
+ ariaLabel
31
35
  error: explicitError = false
32
36
  class: extra = ''
33
37
  } .= $props()
@@ -4,6 +4,9 @@
4
4
  | {tag}
5
5
  button.chip-remove(type="button" aria-label!="{`Remove ${tag}`}" onclick!="{(e) => { e.stopPropagation(); remove(i) }}")
6
6
  Icon(name="lucide:x" size="size-3")
7
+ //- The draft box is NOT the form value — posting it would submit
8
+ //- half-typed text and drop every committed chip. `name` rides a
9
+ //- hidden input carrying the committed tags instead (v6 U-11).
7
10
  input.tags-input-field(
8
11
  bind:this!="{inputEl}"
9
12
  bind:value!="{draft}"
@@ -12,10 +15,12 @@
12
15
  disabled!="{disabled}"
13
16
  onkeydown!="{onKey}"
14
17
  onblur!="{commitOnBlur ? commit : undefined}"
15
- name!="{name}"
16
18
  id!="{resolvedId}"
19
+ aria-label!="{ariaLabel}"
17
20
  aria-invalid!="{hasError ? 'true' : undefined}"
18
21
  )
22
+ +if('name')
23
+ input(type="hidden" name!="{name}" value!="{value.join(',')}")
19
24
 
20
25
  <script>
21
26
  import { cn } from '@human-synthesis/norns-ui/cn'
@@ -29,8 +34,10 @@
29
34
  commitOnBlur = true
30
35
  separators = [',', 'Enter']
31
36
  disabled = false
37
+ // Form value: committed tags, comma-joined, on a hidden input.
32
38
  name
33
39
  id: providedId
40
+ ariaLabel
34
41
  error: explicitError = false
35
42
  class: extra = ''
36
43
  } .= $props()
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "library": "@human-synthesis/norns-ui",
3
- "version": "0.2.0",
3
+ "version": "0.2.3",
4
4
  "counts": {
5
5
  "components": 78,
6
6
  "motion": 5,
@@ -372,6 +372,11 @@
372
372
  "type": "string",
373
373
  "required": false
374
374
  },
375
+ {
376
+ "name": "ariaLabel",
377
+ "type": "string",
378
+ "required": false
379
+ },
375
380
  {
376
381
  "name": "class",
377
382
  "type": "string",
@@ -773,6 +778,31 @@
773
778
  "type": "boolean",
774
779
  "required": false
775
780
  },
781
+ {
782
+ "name": "value",
783
+ "type": "string",
784
+ "required": false
785
+ },
786
+ {
787
+ "name": "name",
788
+ "type": "string",
789
+ "required": false
790
+ },
791
+ {
792
+ "name": "id",
793
+ "type": "string",
794
+ "required": false
795
+ },
796
+ {
797
+ "name": "required",
798
+ "type": "boolean",
799
+ "required": false
800
+ },
801
+ {
802
+ "name": "disabled",
803
+ "type": "boolean",
804
+ "required": false
805
+ },
776
806
  {
777
807
  "name": "error",
778
808
  "type": "boolean",
@@ -1850,6 +1880,47 @@
1850
1880
  "type": "InputSize",
1851
1881
  "required": false
1852
1882
  },
1883
+ {
1884
+ "name": "name",
1885
+ "type": "string",
1886
+ "required": false
1887
+ },
1888
+ {
1889
+ "name": "id",
1890
+ "type": "string",
1891
+ "required": false
1892
+ },
1893
+ {
1894
+ "name": "placeholder",
1895
+ "type": "string",
1896
+ "required": false
1897
+ },
1898
+ {
1899
+ "name": "required",
1900
+ "type": "boolean",
1901
+ "required": false
1902
+ },
1903
+ {
1904
+ "name": "disabled",
1905
+ "type": "boolean",
1906
+ "required": false
1907
+ },
1908
+ {
1909
+ "name": "readonly",
1910
+ "type": "boolean",
1911
+ "required": false
1912
+ },
1913
+ {
1914
+ "name": "autocomplete",
1915
+ "type": "string",
1916
+ "required": false
1917
+ },
1918
+ {
1919
+ "name": "ariaLabel",
1920
+ "type": "string",
1921
+ "required": false,
1922
+ "doc": "Accessible name for a control with no visible label (a placeholder is not a label)."
1923
+ },
1853
1924
  {
1854
1925
  "name": "error",
1855
1926
  "type": "boolean",
@@ -2487,6 +2558,26 @@
2487
2558
  "type": "string",
2488
2559
  "required": false
2489
2560
  },
2561
+ {
2562
+ "name": "name",
2563
+ "type": "string",
2564
+ "required": false
2565
+ },
2566
+ {
2567
+ "name": "id",
2568
+ "type": "string",
2569
+ "required": false
2570
+ },
2571
+ {
2572
+ "name": "required",
2573
+ "type": "boolean",
2574
+ "required": false
2575
+ },
2576
+ {
2577
+ "name": "disabled",
2578
+ "type": "boolean",
2579
+ "required": false
2580
+ },
2490
2581
  {
2491
2582
  "name": "error",
2492
2583
  "type": "boolean",
@@ -2588,6 +2679,26 @@
2588
2679
  "type": "string | number | string[]",
2589
2680
  "required": false
2590
2681
  },
2682
+ {
2683
+ "name": "name",
2684
+ "type": "string",
2685
+ "required": false
2686
+ },
2687
+ {
2688
+ "name": "id",
2689
+ "type": "string",
2690
+ "required": false
2691
+ },
2692
+ {
2693
+ "name": "required",
2694
+ "type": "boolean",
2695
+ "required": false
2696
+ },
2697
+ {
2698
+ "name": "disabled",
2699
+ "type": "boolean",
2700
+ "required": false
2701
+ },
2591
2702
  {
2592
2703
  "name": "error",
2593
2704
  "type": "boolean",
@@ -2943,6 +3054,31 @@
2943
3054
  "type": "boolean",
2944
3055
  "required": false
2945
3056
  },
3057
+ {
3058
+ "name": "value",
3059
+ "type": "string",
3060
+ "required": false
3061
+ },
3062
+ {
3063
+ "name": "name",
3064
+ "type": "string",
3065
+ "required": false
3066
+ },
3067
+ {
3068
+ "name": "id",
3069
+ "type": "string",
3070
+ "required": false
3071
+ },
3072
+ {
3073
+ "name": "required",
3074
+ "type": "boolean",
3075
+ "required": false
3076
+ },
3077
+ {
3078
+ "name": "disabled",
3079
+ "type": "boolean",
3080
+ "required": false
3081
+ },
2946
3082
  {
2947
3083
  "name": "error",
2948
3084
  "type": "boolean",
@@ -3134,13 +3270,20 @@
3134
3270
  {
3135
3271
  "name": "name",
3136
3272
  "type": "string",
3137
- "required": false
3273
+ "required": false,
3274
+ "doc": "Form field name — rides a hidden input carrying the committed tags, comma-joined."
3138
3275
  },
3139
3276
  {
3140
3277
  "name": "id",
3141
3278
  "type": "string",
3142
3279
  "required": false
3143
3280
  },
3281
+ {
3282
+ "name": "ariaLabel",
3283
+ "type": "string",
3284
+ "required": false,
3285
+ "doc": "Accessible name for the tag-entry box when there is no visible label."
3286
+ },
3144
3287
  {
3145
3288
  "name": "error",
3146
3289
  "type": "boolean",
@@ -3171,6 +3314,36 @@
3171
3314
  "type": "number",
3172
3315
  "required": false
3173
3316
  },
3317
+ {
3318
+ "name": "name",
3319
+ "type": "string",
3320
+ "required": false
3321
+ },
3322
+ {
3323
+ "name": "id",
3324
+ "type": "string",
3325
+ "required": false
3326
+ },
3327
+ {
3328
+ "name": "placeholder",
3329
+ "type": "string",
3330
+ "required": false
3331
+ },
3332
+ {
3333
+ "name": "required",
3334
+ "type": "boolean",
3335
+ "required": false
3336
+ },
3337
+ {
3338
+ "name": "disabled",
3339
+ "type": "boolean",
3340
+ "required": false
3341
+ },
3342
+ {
3343
+ "name": "readonly",
3344
+ "type": "boolean",
3345
+ "required": false
3346
+ },
3174
3347
  {
3175
3348
  "name": "error",
3176
3349
  "type": "boolean",
@@ -25,6 +25,12 @@ export type BtnProps = Omit<HTMLButtonAttributes, 'class' | 'children'> & {
25
25
  href?: string;
26
26
  target?: string;
27
27
  rel?: string;
28
+ /**
29
+ * Accessible name, rendered as `aria-label`. Required in practice for
30
+ * icon-only buttons (`icon` set, no `children`), which otherwise have
31
+ * no accessible name at all.
32
+ */
33
+ ariaLabel?: string;
28
34
  class?: string;
29
35
  children?: Snippet;
30
36
  leading?: Snippet;
@@ -3,6 +3,11 @@ import type { HTMLInputAttributes } from 'svelte/elements';
3
3
 
4
4
  export type CheckboxProps = Omit<HTMLInputAttributes, 'class' | 'type' | 'checked'> & {
5
5
  checked?: boolean;
6
+ value?: string;
7
+ name?: string;
8
+ id?: string;
9
+ required?: boolean;
10
+ disabled?: boolean;
6
11
  error?: boolean;
7
12
  class?: string;
8
13
  };
@@ -20,6 +20,15 @@ export type InputProps = Omit<HTMLInputAttributes, 'class' | 'type' | 'size' | '
20
20
  value?: string | number;
21
21
  type?: InputType;
22
22
  size?: InputSize;
23
+ name?: string;
24
+ id?: string;
25
+ placeholder?: string;
26
+ required?: boolean;
27
+ disabled?: boolean;
28
+ readonly?: boolean;
29
+ autocomplete?: string;
30
+ /** Accessible name for a control with no visible label (a placeholder is not a label). */
31
+ ariaLabel?: string;
23
32
  /** Force the error styling regardless of the parent Field's error state. */
24
33
  error?: boolean;
25
34
  class?: string;
@@ -5,6 +5,10 @@ export type RadioProps = Omit<HTMLInputAttributes, 'class' | 'type'> & {
5
5
  /** Two-way bound shared group value — pass `bind:group={selected}` from parent. */
6
6
  group?: string;
7
7
  value?: string;
8
+ name?: string;
9
+ id?: string;
10
+ required?: boolean;
11
+ disabled?: boolean;
8
12
  error?: boolean;
9
13
  class?: string;
10
14
  };
@@ -3,6 +3,10 @@ import type { HTMLSelectAttributes } from 'svelte/elements';
3
3
 
4
4
  export type SelectProps = Omit<HTMLSelectAttributes, 'class' | 'value' | 'children'> & {
5
5
  value?: string | number | string[];
6
+ name?: string;
7
+ id?: string;
8
+ required?: boolean;
9
+ disabled?: boolean;
6
10
  error?: boolean;
7
11
  class?: string;
8
12
  /** `<option>` children. Pass via Pug body. */
@@ -3,6 +3,11 @@ import type { HTMLInputAttributes } from 'svelte/elements';
3
3
 
4
4
  export type SwitchProps = Omit<HTMLInputAttributes, 'class' | 'type' | 'checked' | 'role'> & {
5
5
  checked?: boolean;
6
+ value?: string;
7
+ name?: string;
8
+ id?: string;
9
+ required?: boolean;
10
+ disabled?: boolean;
6
11
  error?: boolean;
7
12
  class?: string;
8
13
  };
@@ -7,8 +7,11 @@ export type TagsInputProps = {
7
7
  commitOnBlur?: boolean;
8
8
  separators?: string[];
9
9
  disabled?: boolean;
10
+ /** Form field name — rides a hidden input carrying the committed tags, comma-joined. */
10
11
  name?: string;
11
12
  id?: string;
13
+ /** Accessible name for the tag-entry box when there is no visible label. */
14
+ ariaLabel?: string;
12
15
  error?: boolean;
13
16
  class?: string;
14
17
  };
@@ -4,6 +4,12 @@ import type { HTMLTextareaAttributes } from 'svelte/elements';
4
4
  export type TextareaProps = Omit<HTMLTextareaAttributes, 'class' | 'value' | 'rows'> & {
5
5
  value?: string;
6
6
  rows?: number;
7
+ name?: string;
8
+ id?: string;
9
+ placeholder?: string;
10
+ required?: boolean;
11
+ disabled?: boolean;
12
+ readonly?: boolean;
7
13
  error?: boolean;
8
14
  class?: string;
9
15
  };