@sveltia/ui 0.26.10 → 0.27.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.
@@ -24,6 +24,7 @@
24
24
  role = 'button',
25
25
  name = undefined,
26
26
  value = undefined,
27
+ valueType = typeof value,
27
28
  hidden = false,
28
29
  disabled = false,
29
30
  readonly = false,
@@ -64,6 +65,10 @@
64
65
  aria-disabled={disabled}
65
66
  aria-readonly={readonly}
66
67
  aria-pressed={pressed}
68
+ data-type={valueType}
69
+ data-name={name}
70
+ data-label={label}
71
+ data-value={value}
67
72
  use:activateKeyShortcuts={keyShortcuts}
68
73
  >
69
74
  {@render startIcon?.()}
@@ -31,8 +31,10 @@
31
31
  showOk = true,
32
32
  showCancel = true,
33
33
  okLabel = '',
34
+ okShortcuts = undefined,
34
35
  okDisabled = false,
35
36
  cancelLabel = '',
37
+ cancelShortcuts = undefined,
36
38
  cancelDisabled = false,
37
39
  focusInput = true,
38
40
  children,
@@ -138,6 +140,7 @@
138
140
  <Button
139
141
  variant="primary"
140
142
  label={okLabel || $_('_sui.ok')}
143
+ keyShortcuts={okShortcuts}
141
144
  disabled={okDisabled}
142
145
  onclick={() => {
143
146
  modal?.close('ok');
@@ -148,6 +151,7 @@
148
151
  <Button
149
152
  variant="secondary"
150
153
  label={cancelLabel || $_('_sui.cancel')}
154
+ keyShortcuts={cancelShortcuts}
151
155
  disabled={cancelDisabled}
152
156
  onclick={() => {
153
157
  modal?.close('cancel');
@@ -57,8 +57,6 @@
57
57
  {value}
58
58
  {hidden}
59
59
  {disabled}
60
- data-type={typeof value}
61
- data-label={label}
62
60
  data-search-value={searchValue}
63
61
  onChange={(event) => {
64
62
  selected = event.detail.selected;
@@ -20,8 +20,10 @@
20
20
  * attribute.
21
21
  * @property {boolean} [checked] Whether to check the widget. An alias of the `aria-checked`
22
22
  * attribute.
23
- * @property {string} [name] The `name` attribute on the `<button>` element.
24
- * @property {string} [value] The `value` attribute on the `<button>` element.
23
+ * @property {string} [name] The `data-name` attribute on the `<button>` element.
24
+ * @property {any} [value] The `data-value` attribute on the `<button>` element.
25
+ * @property {string} [valueType] Data type of the `value`. Typically `string`, `number` or
26
+ * `boolean`. Default: auto detect.
25
27
  * @property {string} [label] Text label displayed next to the checkbox.
26
28
  * @property {Snippet} [children] Primary slot content.
27
29
  * @property {Snippet} [default] Default slot content.
@@ -40,6 +42,7 @@
40
42
  disabled = false,
41
43
  name = undefined,
42
44
  value = undefined,
45
+ valueType = undefined,
43
46
  label = undefined,
44
47
  children,
45
48
  onChange,
@@ -77,6 +80,7 @@
77
80
  {disabled}
78
81
  {name}
79
82
  {value}
83
+ {valueType}
80
84
  aria-checked={checked}
81
85
  aria-labelledby="{id}-label"
82
86
  onclick={(event) => {
@@ -29,13 +29,18 @@ declare const Radio: import("svelte").Component<{
29
29
  */
30
30
  checked?: boolean | undefined;
31
31
  /**
32
- * The `name` attribute on the `<button>` element.
32
+ * The `data-name` attribute on the `<button>` element.
33
33
  */
34
34
  name?: string | undefined;
35
35
  /**
36
- * The `value` attribute on the `<button>` element.
36
+ * The `data-value` attribute on the `<button>` element.
37
37
  */
38
- value?: string | undefined;
38
+ value?: any;
39
+ /**
40
+ * Data type of the `value`. Typically `string`, `number` or
41
+ * `boolean`. Default: auto detect.
42
+ */
43
+ valueType?: string | undefined;
39
44
  /**
40
45
  * Text label displayed next to the checkbox.
41
46
  */
@@ -77,13 +82,18 @@ type Props = {
77
82
  */
78
83
  checked?: boolean | undefined;
79
84
  /**
80
- * The `name` attribute on the `<button>` element.
85
+ * The `data-name` attribute on the `<button>` element.
81
86
  */
82
87
  name?: string | undefined;
83
88
  /**
84
- * The `value` attribute on the `<button>` element.
89
+ * The `data-value` attribute on the `<button>` element.
90
+ */
91
+ value?: any;
92
+ /**
93
+ * Data type of the `value`. Typically `string`, `number` or
94
+ * `boolean`. Default: auto detect.
85
95
  */
86
- value?: string | undefined;
96
+ valueType?: string | undefined;
87
97
  /**
88
98
  * Text label displayed next to the checkbox.
89
99
  */
@@ -7,6 +7,7 @@
7
7
  -->
8
8
  <script>
9
9
  import { _ } from 'svelte-i18n';
10
+ import { getSelectedItemDetail } from '../../services/select.svelte';
10
11
  import Button from '../button/button.svelte';
11
12
  import Icon from '../icon/icon.svelte';
12
13
  import Listbox from '../listbox/listbox.svelte';
@@ -69,11 +70,11 @@
69
70
  const selected = popupContent?.querySelector(selectedSelector);
70
71
 
71
72
  const target = /** @type {HTMLButtonElement} */ (
72
- popupContent?.querySelector(`[role="option"][value="${value}"]`)
73
+ popupContent?.querySelector(`[role="option"][data-value="${value}"]`)
73
74
  );
74
75
 
75
76
  if (target) {
76
- label = target.dataset.label || target.textContent || target.value;
77
+ label = target.dataset.label || target.dataset.value || target.textContent || '';
77
78
 
78
79
  if (selected !== target) {
79
80
  selected?.setAttribute('aria-selected', 'false');
@@ -87,19 +88,12 @@
87
88
  * @param {HTMLButtonElement} target Selected option.
88
89
  */
89
90
  const _onSelect = (target) => {
90
- // @todo support more types
91
- // @ts-ignore
92
- value = target.dataset.type === 'number' ? Number(target.value) : target.value;
91
+ const detail = getSelectedItemDetail(target);
92
+
93
+ value = detail.value;
94
+
93
95
  _onChange();
94
- onChange?.(
95
- new CustomEvent('Change', {
96
- detail: {
97
- target: inputElement,
98
- name: target.name,
99
- value,
100
- },
101
- }),
102
- );
96
+ onChange?.(new CustomEvent('Change', { detail }));
103
97
  };
104
98
 
105
99
  $effect(() => {
@@ -150,7 +144,7 @@
150
144
  bind:element={inputElement}
151
145
  role="combobox"
152
146
  {id}
153
- {value}
147
+ value={value === undefined ? '' : String(value)}
154
148
  {hidden}
155
149
  {disabled}
156
150
  {readonly}
@@ -11,7 +11,7 @@
11
11
 
12
12
  /**
13
13
  * @typedef {object} Props
14
- * @property {{ label: string, value: string, searchValue?: string }[]} options Available options.
14
+ * @property {{ label: string, value: any, searchValue?: string }[]} options Available options.
15
15
  * @property {string[]} [values] Selected option values.
16
16
  * @property {number} [max] Maximum number of selectable options.
17
17
  * @property {string} [class] The `class` attribute on the wrapper element.
@@ -9,7 +9,7 @@ declare const SelectTags: import("svelte").Component<{
9
9
  */
10
10
  options: {
11
11
  label: string;
12
- value: string;
12
+ value: any;
13
13
  searchValue?: string;
14
14
  }[];
15
15
  /**
@@ -67,7 +67,7 @@ type Props = {
67
67
  */
68
68
  options: {
69
69
  label: string;
70
- value: string;
70
+ value: any;
71
71
  searchValue?: string;
72
72
  }[];
73
73
  /**
@@ -4,6 +4,7 @@
4
4
 
5
5
  import { generateElementId } from '@sveltia/utils/element';
6
6
  import { sleep } from '@sveltia/utils/misc';
7
+ import { getSelectedItemDetail } from './select.svelte';
7
8
 
8
9
  /**
9
10
  * @type {{ [role: string]: {
@@ -328,12 +329,7 @@ class Group {
328
329
  });
329
330
 
330
331
  this.parent.dispatchEvent(
331
- new CustomEvent('Change', {
332
- detail: {
333
- value: /** @type {any} */ (newTarget).value,
334
- name: /** @type {any} */ (newTarget).name,
335
- },
336
- }),
332
+ new CustomEvent('Change', { detail: getSelectedItemDetail(newTarget) }),
337
333
  );
338
334
  }
339
335
 
@@ -0,0 +1,2 @@
1
+ export function getSelectedItemDetail(target: HTMLElement): SelectedItemDetail;
2
+ import type { SelectedItemDetail } from '../typedefs';
@@ -0,0 +1,28 @@
1
+ /**
2
+ * @import { SelectedItemDetail } from '../typedefs';
3
+ */
4
+
5
+ /**
6
+ * Get the detail of the selected element.
7
+ * @param {HTMLElement} target Element to get the detail from.
8
+ * @returns {SelectedItemDetail} Detail of the selected element.
9
+ */
10
+ export const getSelectedItemDetail = (target) => {
11
+ const { type = 'string', name, label } = target.dataset;
12
+ /** @type {any} */
13
+ let { value } = target.dataset;
14
+
15
+ if (type === 'number') {
16
+ value = Number(value);
17
+
18
+ if (Number.isNaN(value)) {
19
+ value = null;
20
+ }
21
+ } else if (type === 'boolean') {
22
+ value = value === 'true';
23
+ } else if (type === 'string') {
24
+ value = value ? String(value) : '';
25
+ }
26
+
27
+ return { target, type, name, label, value };
28
+ };
@@ -16,13 +16,18 @@ export type ButtonProps = {
16
16
  */
17
17
  role?: string | undefined;
18
18
  /**
19
- * The `name` attribute on the `<button>` element.
19
+ * The `data-name` attribute on the `<button>` element.
20
20
  */
21
21
  name?: string | undefined;
22
22
  /**
23
- * The `value` attribute on the `<button>` element.
23
+ * The `data-value` attribute on the `<button>` element.
24
24
  */
25
- value?: string | undefined;
25
+ value?: any;
26
+ /**
27
+ * Data type of the `value`. Typically `string`, `number` or
28
+ * `boolean`. Default: auto detect.
29
+ */
30
+ valueType?: string | undefined;
26
31
  /**
27
32
  * Whether to hide the widget. An alias of the `aria-hidden` attribute.
28
33
  */
@@ -221,6 +226,12 @@ export type DialogProps = {
221
226
  * Text label displayed on the OK button.
222
227
  */
223
228
  okLabel?: string | undefined;
229
+ /**
230
+ * Keyboard shortcuts for the OK button. An alias of the
231
+ * `aria-keyshortcuts` attribute. Accepts the special `Accel` key, which will be replaced with
232
+ * `Control` or `Meta` depending on the user’s operating system.
233
+ */
234
+ okShortcuts?: string | undefined;
224
235
  /**
225
236
  * Whether to disable the OK button.
226
237
  */
@@ -229,6 +240,12 @@ export type DialogProps = {
229
240
  * Text label displayed on the Cancel button.
230
241
  */
231
242
  cancelLabel?: string | undefined;
243
+ /**
244
+ * Keyboard shortcuts for the Cancel button. An alias of the
245
+ * `aria-keyshortcuts` attribute. Accepts the special `Accel` key, which will be replaced with
246
+ * `Control` or `Meta` depending on the user’s operating system.
247
+ */
248
+ cancelShortcuts?: string | undefined;
232
249
  /**
233
250
  * Whether to disable the Cancel button.
234
251
  */
@@ -366,7 +383,7 @@ export type ComboboxProps = {
366
383
  /**
367
384
  * Selected option’s value.
368
385
  */
369
- value?: string | undefined;
386
+ value?: any;
370
387
  /**
371
388
  * Whether to make the `combobox` editable.
372
389
  */
@@ -677,6 +694,28 @@ export type TextEditorStore = {
677
694
  */
678
695
  convertMarkdown: () => Promise<void>;
679
696
  };
697
+ export type SelectedItemDetail = {
698
+ /**
699
+ * Element to get the detail from.
700
+ */
701
+ target: HTMLElement;
702
+ /**
703
+ * Data type of the `value`. Typically `string`, `number` or `boolean`.
704
+ */
705
+ type: string;
706
+ /**
707
+ * The `data-name` attribute on the element.
708
+ */
709
+ name: string | undefined;
710
+ /**
711
+ * The `data-label` attribute on the element.
712
+ */
713
+ label: string | undefined;
714
+ /**
715
+ * The `data-value` attribute on the element. Casted to the `valueType`.
716
+ */
717
+ value: any;
718
+ };
680
719
  import type { Snippet } from 'svelte';
681
720
  import type { LexicalNode } from 'lexical';
682
721
  import type { Transformer } from '@lexical/markdown';
package/dist/typedefs.js CHANGED
@@ -10,8 +10,10 @@
10
10
  * @property {string} [class] The `class` attribute on the `<button>` element.
11
11
  * @property {'button' | 'submit' | 'reset'} [type] The `type` attribute on the `<button>` element.
12
12
  * @property {string} [role] The `role` attribute on the `<button>` element.
13
- * @property {string} [name] The `name` attribute on the `<button>` element.
14
- * @property {string} [value] The `value` attribute on the `<button>` element.
13
+ * @property {string} [name] The `data-name` attribute on the `<button>` element.
14
+ * @property {any} [value] The `data-value` attribute on the `<button>` element.
15
+ * @property {string} [valueType] Data type of the `value`. Typically `string`, `number` or
16
+ * `boolean`. Default: auto detect.
15
17
  * @property {boolean} [hidden] Whether to hide the widget. An alias of the `aria-hidden` attribute.
16
18
  * @property {boolean} [disabled] Whether to disable the widget. An alias of the `aria-disabled`
17
19
  * attribute.
@@ -76,8 +78,14 @@
76
78
  * @property {boolean} [showOk] Whether to show the OK button on the footer.
77
79
  * @property {boolean} [showCancel] Whether to show the Cancel button on the footer.
78
80
  * @property {string} [okLabel] Text label displayed on the OK button.
81
+ * @property {string} [okShortcuts] Keyboard shortcuts for the OK button. An alias of the
82
+ * `aria-keyshortcuts` attribute. Accepts the special `Accel` key, which will be replaced with
83
+ * `Control` or `Meta` depending on the user’s operating system.
79
84
  * @property {boolean} [okDisabled] Whether to disable the OK button.
80
85
  * @property {string} [cancelLabel] Text label displayed on the Cancel button.
86
+ * @property {string} [cancelShortcuts] Keyboard shortcuts for the Cancel button. An alias of the
87
+ * `aria-keyshortcuts` attribute. Accepts the special `Accel` key, which will be replaced with
88
+ * `Control` or `Meta` depending on the user’s operating system.
81
89
  * @property {boolean} [cancelDisabled] Whether to disable the Cancel button.
82
90
  * @property {boolean} [focusInput] Whether to automatically focus the first input field or primary
83
91
  * action button. Default: `true`. If `false`, the `<dialog>` gets focused.
@@ -126,7 +134,7 @@
126
134
  * `aria-required` attribute.
127
135
  * @property {boolean} [invalid] Whether to mark the widget invalid. An alias of the `aria-invalid`
128
136
  * attribute.
129
- * @property {string} [value] Selected option’s value.
137
+ * @property {any} [value] Selected option’s value.
130
138
  * @property {boolean} [editable] Whether to make the `combobox` editable.
131
139
  * @property {PopupPosition} [position] Where to show the dropdown menu.
132
140
  * @property {number} [filterThreshold] Number of items to start showing the filter. Default: `5`.
@@ -283,4 +291,13 @@
283
291
  * @property {() => Promise<void>} convertMarkdown Function to trigger the Lexical converter.
284
292
  */
285
293
 
294
+ /**
295
+ * @typedef {object} SelectedItemDetail
296
+ * @property {HTMLElement} target Element to get the detail from.
297
+ * @property {string} type Data type of the `value`. Typically `string`, `number` or `boolean`.
298
+ * @property {string | undefined} name The `data-name` attribute on the element.
299
+ * @property {string | undefined} label The `data-label` attribute on the element.
300
+ * @property {any} value The `data-value` attribute on the element. Casted to the `valueType`.
301
+ */
302
+
286
303
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sveltia/ui",
3
- "version": "0.26.10",
3
+ "version": "0.27.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "repository": {
@@ -46,33 +46,33 @@
46
46
  "svelte": "^5.0.0"
47
47
  },
48
48
  "devDependencies": {
49
- "@playwright/test": "^1.52.0",
49
+ "@playwright/test": "^1.53.0",
50
50
  "@sveltejs/adapter-auto": "^6.0.1",
51
- "@sveltejs/kit": "^2.21.2",
51
+ "@sveltejs/kit": "^2.21.5",
52
52
  "@sveltejs/package": "^2.3.11",
53
53
  "@sveltejs/vite-plugin-svelte": "5.1.0",
54
- "cspell": "^9.0.2",
54
+ "cspell": "^9.1.1",
55
55
  "eslint": "^8.57.1",
56
56
  "eslint-config-airbnb-base": "^15.0.0",
57
57
  "eslint-config-prettier": "^10.1.5",
58
58
  "eslint-plugin-import": "^2.31.0",
59
- "eslint-plugin-jsdoc": "^50.7.1",
59
+ "eslint-plugin-jsdoc": "^51.0.3",
60
60
  "eslint-plugin-svelte": "^2.46.1",
61
- "postcss": "^8.5.4",
61
+ "postcss": "^8.5.6",
62
62
  "postcss-html": "^1.8.0",
63
63
  "prettier": "^3.5.3",
64
64
  "prettier-plugin-svelte": "^3.4.0",
65
- "sass": "^1.89.1",
65
+ "sass": "^1.89.2",
66
66
  "stylelint": "^16.20.0",
67
67
  "stylelint-config-recommended-scss": "^15.0.1",
68
- "stylelint-scss": "^6.12.0",
69
- "svelte": "5.33.17",
68
+ "stylelint-scss": "^6.12.1",
69
+ "svelte": "5.34.5",
70
70
  "svelte-check": "^4.2.1",
71
71
  "svelte-i18n": "^4.0.1",
72
72
  "svelte-preprocess": "^6.0.3",
73
73
  "tslib": "^2.8.1",
74
74
  "vite": "^6.3.5",
75
- "vitest": "^3.2.2"
75
+ "vitest": "^3.2.4"
76
76
  },
77
77
  "exports": {
78
78
  ".": {