@human-synthesis/norns-ui 0.2.2 → 0.2.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@human-synthesis/norns-ui",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
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)",
@@ -14,14 +14,14 @@
14
14
  +if('!col.sortable')
15
15
  | {col.label ?? col.key}
16
16
  tbody
17
- +if('rows.length === 0')
17
+ +if('list.length === 0')
18
18
  tr.data-table-empty
19
19
  td(colspan!="{columns.length}")
20
20
  +if('empty')
21
21
  | {@render empty()}
22
22
  +if('!empty')
23
23
  | {emptyMessage}
24
- +each('rows as row, i')
24
+ +each('list as row, i')
25
25
  tr(onclick!="{onrowclick ? () => onrowclick(row, i) : undefined}" class!="{onrowclick ? 'data-table-row-clickable' : ''}")
26
26
  +each('columns as col')
27
27
  td(class!="{col.cellClass ?? ''}")
@@ -36,7 +36,8 @@
36
36
 
37
37
  {
38
38
  columns = []
39
- rows = []
39
+ rows = undefined
40
+ data = undefined
40
41
  striped = false
41
42
  dense = false
42
43
  stickyHeader = false
@@ -49,6 +50,10 @@
49
50
  class: extra = ''
50
51
  } .= $props()
51
52
 
53
+ // the spec generator binds queries to `data` (the palette-wide channel);
54
+ // hand-written callers keep `rows` — either works, `rows` wins
55
+ list := rows ?? data ?? []
56
+
52
57
  wrapClasses := cn
53
58
  'data-table-root'
54
59
  striped && 'data-table-striped'
@@ -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.2",
3
+ "version": "0.2.3",
4
4
  "counts": {
5
5
  "components": 78,
6
6
  "motion": 5,
@@ -778,6 +778,31 @@
778
778
  "type": "boolean",
779
779
  "required": false
780
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
+ },
781
806
  {
782
807
  "name": "error",
783
808
  "type": "boolean",
@@ -1019,6 +1044,12 @@
1019
1044
  "type": "Record<string, unknown>[]",
1020
1045
  "required": false
1021
1046
  },
1047
+ {
1048
+ "name": "data",
1049
+ "type": "Record<string, unknown>[]",
1050
+ "required": false,
1051
+ "doc": "Alias for `rows` — the prop a generated Page binds a Query result to."
1052
+ },
1022
1053
  {
1023
1054
  "name": "striped",
1024
1055
  "type": "boolean",
@@ -1855,6 +1886,47 @@
1855
1886
  "type": "InputSize",
1856
1887
  "required": false
1857
1888
  },
1889
+ {
1890
+ "name": "name",
1891
+ "type": "string",
1892
+ "required": false
1893
+ },
1894
+ {
1895
+ "name": "id",
1896
+ "type": "string",
1897
+ "required": false
1898
+ },
1899
+ {
1900
+ "name": "placeholder",
1901
+ "type": "string",
1902
+ "required": false
1903
+ },
1904
+ {
1905
+ "name": "required",
1906
+ "type": "boolean",
1907
+ "required": false
1908
+ },
1909
+ {
1910
+ "name": "disabled",
1911
+ "type": "boolean",
1912
+ "required": false
1913
+ },
1914
+ {
1915
+ "name": "readonly",
1916
+ "type": "boolean",
1917
+ "required": false
1918
+ },
1919
+ {
1920
+ "name": "autocomplete",
1921
+ "type": "string",
1922
+ "required": false
1923
+ },
1924
+ {
1925
+ "name": "ariaLabel",
1926
+ "type": "string",
1927
+ "required": false,
1928
+ "doc": "Accessible name for a control with no visible label (a placeholder is not a label)."
1929
+ },
1858
1930
  {
1859
1931
  "name": "error",
1860
1932
  "type": "boolean",
@@ -2492,6 +2564,26 @@
2492
2564
  "type": "string",
2493
2565
  "required": false
2494
2566
  },
2567
+ {
2568
+ "name": "name",
2569
+ "type": "string",
2570
+ "required": false
2571
+ },
2572
+ {
2573
+ "name": "id",
2574
+ "type": "string",
2575
+ "required": false
2576
+ },
2577
+ {
2578
+ "name": "required",
2579
+ "type": "boolean",
2580
+ "required": false
2581
+ },
2582
+ {
2583
+ "name": "disabled",
2584
+ "type": "boolean",
2585
+ "required": false
2586
+ },
2495
2587
  {
2496
2588
  "name": "error",
2497
2589
  "type": "boolean",
@@ -2593,6 +2685,26 @@
2593
2685
  "type": "string | number | string[]",
2594
2686
  "required": false
2595
2687
  },
2688
+ {
2689
+ "name": "name",
2690
+ "type": "string",
2691
+ "required": false
2692
+ },
2693
+ {
2694
+ "name": "id",
2695
+ "type": "string",
2696
+ "required": false
2697
+ },
2698
+ {
2699
+ "name": "required",
2700
+ "type": "boolean",
2701
+ "required": false
2702
+ },
2703
+ {
2704
+ "name": "disabled",
2705
+ "type": "boolean",
2706
+ "required": false
2707
+ },
2596
2708
  {
2597
2709
  "name": "error",
2598
2710
  "type": "boolean",
@@ -2948,6 +3060,31 @@
2948
3060
  "type": "boolean",
2949
3061
  "required": false
2950
3062
  },
3063
+ {
3064
+ "name": "value",
3065
+ "type": "string",
3066
+ "required": false
3067
+ },
3068
+ {
3069
+ "name": "name",
3070
+ "type": "string",
3071
+ "required": false
3072
+ },
3073
+ {
3074
+ "name": "id",
3075
+ "type": "string",
3076
+ "required": false
3077
+ },
3078
+ {
3079
+ "name": "required",
3080
+ "type": "boolean",
3081
+ "required": false
3082
+ },
3083
+ {
3084
+ "name": "disabled",
3085
+ "type": "boolean",
3086
+ "required": false
3087
+ },
2951
3088
  {
2952
3089
  "name": "error",
2953
3090
  "type": "boolean",
@@ -3139,13 +3276,20 @@
3139
3276
  {
3140
3277
  "name": "name",
3141
3278
  "type": "string",
3142
- "required": false
3279
+ "required": false,
3280
+ "doc": "Form field name — rides a hidden input carrying the committed tags, comma-joined."
3143
3281
  },
3144
3282
  {
3145
3283
  "name": "id",
3146
3284
  "type": "string",
3147
3285
  "required": false
3148
3286
  },
3287
+ {
3288
+ "name": "ariaLabel",
3289
+ "type": "string",
3290
+ "required": false,
3291
+ "doc": "Accessible name for the tag-entry box when there is no visible label."
3292
+ },
3149
3293
  {
3150
3294
  "name": "error",
3151
3295
  "type": "boolean",
@@ -3176,6 +3320,36 @@
3176
3320
  "type": "number",
3177
3321
  "required": false
3178
3322
  },
3323
+ {
3324
+ "name": "name",
3325
+ "type": "string",
3326
+ "required": false
3327
+ },
3328
+ {
3329
+ "name": "id",
3330
+ "type": "string",
3331
+ "required": false
3332
+ },
3333
+ {
3334
+ "name": "placeholder",
3335
+ "type": "string",
3336
+ "required": false
3337
+ },
3338
+ {
3339
+ "name": "required",
3340
+ "type": "boolean",
3341
+ "required": false
3342
+ },
3343
+ {
3344
+ "name": "disabled",
3345
+ "type": "boolean",
3346
+ "required": false
3347
+ },
3348
+ {
3349
+ "name": "readonly",
3350
+ "type": "boolean",
3351
+ "required": false
3352
+ },
3179
3353
  {
3180
3354
  "name": "error",
3181
3355
  "type": "boolean",
@@ -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
  };
@@ -12,6 +12,8 @@ export type DataTableColumn = {
12
12
  export type DataTableProps = {
13
13
  columns?: DataTableColumn[];
14
14
  rows?: Record<string, unknown>[];
15
+ /** Alias for `rows` — the prop a generated Page binds a Query result to. */
16
+ data?: Record<string, unknown>[];
15
17
  striped?: boolean;
16
18
  dense?: boolean;
17
19
  stickyHeader?: boolean;
@@ -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
  };