@sveltia/ui 0.7.4 → 0.8.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 (118) hide show
  1. package/package/components/alert/alert.svelte +4 -4
  2. package/package/components/alert/alert.svelte.d.ts +2 -2
  3. package/package/components/button/button.svelte +13 -3
  4. package/package/components/button/button.svelte.d.ts +11 -4
  5. package/package/components/button/select-button-group.svelte +12 -8
  6. package/package/components/button/select-button.svelte +5 -4
  7. package/package/components/button/select-button.svelte.d.ts +2 -0
  8. package/package/components/calendar/calendar.svelte +20 -14
  9. package/package/components/checkbox/checkbox-group.svelte +6 -5
  10. package/package/components/checkbox/checkbox.svelte +16 -9
  11. package/package/components/checkbox/checkbox.svelte.d.ts +2 -2
  12. package/package/components/dialog/alert-dialog.svelte +50 -0
  13. package/package/components/dialog/alert-dialog.svelte.d.ts +55 -0
  14. package/package/components/dialog/confirmation-dialog.svelte +55 -0
  15. package/package/components/dialog/confirmation-dialog.svelte.d.ts +57 -0
  16. package/package/components/dialog/dialog.svelte +164 -220
  17. package/package/components/dialog/dialog.svelte.d.ts +20 -12
  18. package/package/components/dialog/prompt-dialog.svelte +78 -0
  19. package/package/components/dialog/prompt-dialog.svelte.d.ts +72 -0
  20. package/package/components/disclosure/disclosure.svelte +3 -3
  21. package/package/components/divider/divider.svelte +1 -1
  22. package/package/components/divider/spacer.svelte +1 -12
  23. package/package/components/divider/spacer.svelte.d.ts +0 -2
  24. package/package/components/drawer/drawer.svelte +118 -208
  25. package/package/components/drawer/drawer.svelte.d.ts +12 -8
  26. package/package/components/grid/grid-body.svelte +51 -0
  27. package/package/components/grid/grid-body.svelte.d.ts +36 -0
  28. package/package/components/grid/grid-cell.svelte +22 -0
  29. package/package/components/grid/grid-cell.svelte.d.ts +34 -0
  30. package/package/components/grid/grid-col-header.svelte +22 -0
  31. package/package/components/grid/grid-col-header.svelte.d.ts +34 -0
  32. package/package/components/grid/grid-foot.svelte +27 -0
  33. package/package/components/grid/grid-foot.svelte.d.ts +34 -0
  34. package/package/components/grid/grid-head.svelte +27 -0
  35. package/package/components/grid/grid-head.svelte.d.ts +34 -0
  36. package/package/components/grid/grid-row-header.svelte +23 -0
  37. package/package/components/grid/grid-row-header.svelte.d.ts +34 -0
  38. package/package/components/grid/grid-row.svelte +37 -0
  39. package/package/components/grid/grid-row.svelte.d.ts +44 -0
  40. package/package/components/grid/grid.svelte +52 -0
  41. package/package/components/grid/grid.svelte.d.ts +42 -0
  42. package/package/components/icon/icon.svelte +6 -7
  43. package/package/components/icon/icon.svelte.d.ts +0 -2
  44. package/package/components/listbox/listbox.svelte +6 -6
  45. package/package/components/listbox/option-group.svelte +6 -5
  46. package/package/components/listbox/option.svelte +7 -28
  47. package/package/components/listbox/option.svelte.d.ts +2 -0
  48. package/package/components/menu/menu-button.svelte +26 -16
  49. package/package/components/menu/menu-button.svelte.d.ts +2 -2
  50. package/package/components/menu/menu-item-checkbox.svelte +5 -4
  51. package/package/components/menu/menu-item-checkbox.svelte.d.ts +2 -0
  52. package/package/components/menu/menu-item-group.svelte +4 -3
  53. package/package/components/menu/menu-item-radio.svelte +5 -4
  54. package/package/components/menu/menu-item-radio.svelte.d.ts +2 -0
  55. package/package/components/menu/menu-item.svelte +7 -5
  56. package/package/components/menu/menu-item.svelte.d.ts +4 -2
  57. package/package/components/menu/menu.svelte +1 -1
  58. package/package/components/radio/radio-group.svelte +8 -8
  59. package/package/components/radio/radio-group.svelte.d.ts +2 -2
  60. package/package/components/radio/radio.svelte +5 -2
  61. package/package/components/radio/radio.svelte.d.ts +2 -0
  62. package/package/components/select/combobox.svelte +55 -35
  63. package/package/components/select/combobox.svelte.d.ts +3 -2
  64. package/package/components/select/select.svelte +10 -9
  65. package/package/components/select/select.svelte.d.ts +4 -3
  66. package/package/components/slider/slider.svelte +15 -7
  67. package/package/components/switch/switch.svelte +9 -6
  68. package/package/components/switch/switch.svelte.d.ts +2 -2
  69. package/package/components/table/table-body.svelte +31 -3
  70. package/package/components/table/table-body.svelte.d.ts +2 -0
  71. package/package/components/table/table-cell.svelte +3 -4
  72. package/package/components/table/table-cell.svelte.d.ts +1 -1
  73. package/package/components/table/table-col-header.svelte +1 -2
  74. package/package/components/table/table-foot.svelte +7 -3
  75. package/package/components/table/table-head.svelte +7 -3
  76. package/package/components/table/table-row-header.svelte +1 -2
  77. package/package/components/table/table-row.svelte +1 -14
  78. package/package/components/table/table-row.svelte.d.ts +0 -8
  79. package/package/components/table/table.svelte +5 -17
  80. package/package/components/table/table.svelte.d.ts +1 -7
  81. package/package/components/tabs/tab-list.svelte +7 -5
  82. package/package/components/tabs/tab-panel.svelte +1 -1
  83. package/package/components/tabs/tab.svelte +2 -1
  84. package/package/components/tabs/tab.svelte.d.ts +2 -0
  85. package/package/components/text-field/markdown-editor.svelte +36 -9
  86. package/package/components/text-field/markdown-editor.svelte.d.ts +2 -0
  87. package/package/components/text-field/number-input.svelte +107 -43
  88. package/package/components/text-field/number-input.svelte.d.ts +2 -0
  89. package/package/components/text-field/password-input.svelte +43 -12
  90. package/package/components/text-field/password-input.svelte.d.ts +2 -0
  91. package/package/components/text-field/search-bar.svelte +43 -13
  92. package/package/components/text-field/search-bar.svelte.d.ts +5 -0
  93. package/package/components/text-field/text-area.svelte +26 -6
  94. package/package/components/text-field/text-area.svelte.d.ts +2 -0
  95. package/package/components/text-field/text-input.svelte +37 -7
  96. package/package/components/text-field/text-input.svelte.d.ts +14 -4
  97. package/package/components/toast/toast.svelte +6 -16
  98. package/package/components/toast/toast.svelte.d.ts +2 -2
  99. package/package/components/toolbar/toolbar.svelte +3 -4
  100. package/package/components/util/app-shell.svelte +34 -29
  101. package/package/components/util/group.svelte +2 -2
  102. package/package/components/util/modal.svelte +220 -0
  103. package/package/components/util/modal.svelte.d.ts +83 -0
  104. package/package/components/util/popup.svelte +80 -121
  105. package/package/components/util/popup.svelte.d.ts +22 -13
  106. package/package/components/util/portal.svelte +1 -1
  107. package/package/index.d.ts +12 -0
  108. package/package/index.js +12 -0
  109. package/package/locales/en.d.ts +1 -0
  110. package/package/locales/en.js +1 -0
  111. package/package/locales/ja.d.ts +1 -0
  112. package/package/locales/ja.js +1 -0
  113. package/package/services/group.js +67 -13
  114. package/package/services/popup.d.ts +5 -1
  115. package/package/services/popup.js +22 -19
  116. package/package/styles/core.scss +13 -26
  117. package/package/styles/variables.scss +14 -2
  118. package/package.json +107 -11
@@ -9,11 +9,7 @@
9
9
  export default class TableRow extends SvelteComponent<{
10
10
  [x: string]: any;
11
11
  class?: string;
12
- selected?: boolean;
13
12
  }, {
14
- click: MouseEvent;
15
- select: Event;
16
- } & {
17
13
  [evt: string]: CustomEvent<any>;
18
14
  }, {
19
15
  default: {};
@@ -27,12 +23,8 @@ declare const __propDef: {
27
23
  props: {
28
24
  [x: string]: any;
29
25
  class?: string;
30
- selected?: boolean;
31
26
  };
32
27
  events: {
33
- click: MouseEvent;
34
- select: Event;
35
- } & {
36
28
  [evt: string]: CustomEvent<any>;
37
29
  };
38
30
  slots: {
@@ -2,37 +2,25 @@
2
2
  @component
3
3
  The equivalent of the HTML `<table>` element.
4
4
  @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/table
5
- @see https://w3c.github.io/aria/#grid
5
+ @see https://w3c.github.io/aria/#table
6
6
  -->
7
7
  <script>
8
- import { activateGroup } from '../../services/group';
9
-
10
8
  /**
11
- * CSS class name on the button.
9
+ * The `class` attribute on the wrapper element.
12
10
  * @type {string}
13
11
  */
14
12
  let className = '';
15
-
16
13
  export { className as class };
17
-
18
- /** @type {HTMLElement?} */
19
- export let element = undefined;
20
14
  </script>
21
15
 
22
- <div
23
- role="grid"
24
- class="sui table {className}"
25
- {...$$restProps}
26
- bind:this={element}
27
- use:activateGroup
28
- on:change
29
- >
16
+ <div role="table" class="sui table {className}" {...$$restProps}>
30
17
  <slot />
31
18
  </div>
32
19
 
33
20
  <style>.table {
34
21
  display: table;
35
- width: 100%;
22
+ margin: var(--sui-focus-ring-width);
23
+ width: calc(100% - var(--sui-focus-ring-width) * 2);
36
24
  }
37
25
  .table:global(.data) {
38
26
  border-collapse: collapse;
@@ -4,15 +4,12 @@
4
4
  /**
5
5
  * The equivalent of the HTML `<table>` element.
6
6
  * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/table
7
- * @see https://w3c.github.io/aria/#grid
7
+ * @see https://w3c.github.io/aria/#table
8
8
  */
9
9
  export default class Table extends SvelteComponent<{
10
10
  [x: string]: any;
11
11
  class?: string;
12
- element?: HTMLElement;
13
12
  }, {
14
- change: Event;
15
- } & {
16
13
  [evt: string]: CustomEvent<any>;
17
14
  }, {
18
15
  default: {};
@@ -26,11 +23,8 @@ declare const __propDef: {
26
23
  props: {
27
24
  [x: string]: any;
28
25
  class?: string;
29
- element?: HTMLElement | null;
30
26
  };
31
27
  events: {
32
- change: Event;
33
- } & {
34
28
  [evt: string]: CustomEvent<any>;
35
29
  };
36
30
  slots: {
@@ -36,8 +36,8 @@
36
36
  </script>
37
37
 
38
38
  <div
39
- class="sui tab-list {className}"
40
39
  role="tablist"
40
+ class="sui tab-list {className}"
41
41
  hidden={hidden || undefined}
42
42
  aria-hidden={hidden}
43
43
  aria-disabled={disabled}
@@ -47,7 +47,7 @@
47
47
  use:activateGroup
48
48
  on:change
49
49
  >
50
- <div class="inner" inert={disabled}>
50
+ <div role="none" class="inner" inert={disabled}>
51
51
  <slot />
52
52
  </div>
53
53
  </div>
@@ -55,11 +55,12 @@
55
55
  <style>.tab-list {
56
56
  display: flex;
57
57
  align-items: center;
58
+ margin: var(--sui-focus-ring-width);
58
59
  border-color: var(--sui-control-border-color);
59
60
  }
60
61
  .tab-list[aria-orientation=horizontal] {
61
- gap: 16px;
62
- margin: 0 0 32px;
62
+ gap: 8px;
63
+ margin-bottom: 32px;
63
64
  border-width: 0 0 1px;
64
65
  padding: 0 16px;
65
66
  }
@@ -69,7 +70,7 @@
69
70
  .tab-list[aria-orientation=vertical] {
70
71
  gap: 8px;
71
72
  flex-direction: column;
72
- margin: 0 32px 0 0;
73
+ margin-right: 32px;
73
74
  border-width: 0 1px 0 0;
74
75
  padding: 8px 0;
75
76
  width: 240px;
@@ -81,6 +82,7 @@
81
82
  .tab-list :global(button) {
82
83
  justify-content: flex-start;
83
84
  border-color: transparent;
85
+ margin: 0 !important;
84
86
  padding: 0;
85
87
  border-radius: 0;
86
88
  height: var(--sui-tab-medium-height);
@@ -13,7 +13,7 @@
13
13
  export { className as class };
14
14
  </script>
15
15
 
16
- <div class="sui tabpanel {className}" role="tabpanel" {...$$restProps}>
16
+ <div role="tabpanel" class="sui tabpanel {className}" {...$$restProps}>
17
17
  <slot />
18
18
  </div>
19
19
 
@@ -31,13 +31,14 @@
31
31
  </script>
32
32
 
33
33
  <Button
34
- class="sui tab {className}"
35
34
  role="tab"
35
+ class="sui tab {className}"
36
36
  {hidden}
37
37
  {disabled}
38
38
  aria-selected={selected}
39
39
  {...$$restProps}
40
40
  on:select
41
+ on:change
41
42
  >
42
43
  <slot name="start-icon" slot="start-icon" />
43
44
  <slot />
@@ -14,6 +14,7 @@ export default class Tab extends SvelteComponent<{
14
14
  selected?: boolean;
15
15
  }, {
16
16
  select: Event;
17
+ change: Event;
17
18
  } & {
18
19
  [evt: string]: CustomEvent<any>;
19
20
  }, {
@@ -40,6 +41,7 @@ declare const __propDef: {
40
41
  };
41
42
  events: {
42
43
  select: Event;
44
+ change: Event;
43
45
  } & {
44
46
  [evt: string]: CustomEvent<any>;
45
47
  };
@@ -4,12 +4,18 @@
4
4
  -->
5
5
  <script>
6
6
  import { _ } from 'svelte-i18n';
7
+ import { getRandomId } from '../../services/util';
7
8
  import Button from '../button/button.svelte';
8
9
  import Divider from '../divider/divider.svelte';
9
10
  import Icon from '../icon/icon.svelte';
10
11
  import Toolbar from '../toolbar/toolbar.svelte';
11
12
  import TextArea from './text-area.svelte';
12
13
 
14
+ /**
15
+ * Make the text input container flexible.
16
+ * @type {boolean}
17
+ */
18
+ export let flex = false;
13
19
  /**
14
20
  * Whether to hide the widget. An alias of the `aria-hidden` attribute.
15
21
  * @type {boolean | undefined}
@@ -26,12 +32,12 @@
26
32
  */
27
33
  export let readonly = false;
28
34
  /**
29
- * Whether to disable the widget. An alias of the `aria-required` attribute.
35
+ * Whether to mark the widget required. An alias of the `aria-required` attribute.
30
36
  * @type {boolean}
31
37
  */
32
38
  export let required = false;
33
39
  /**
34
- * Whether to disable the widget. An alias of the `aria-invalid` attribute.
40
+ * Whether to mark the widget invalid. An alias of the `aria-invalid` attribute.
35
41
  * @type {boolean}
36
42
  */
37
43
  export let invalid = false;
@@ -41,6 +47,8 @@
41
47
  */
42
48
  export let value = undefined;
43
49
 
50
+ const id = getRandomId('editor');
51
+
44
52
  const defaultButtons = [
45
53
  { name: 'bold', label: $_('_sui.markdown_editor.bold'), icon: 'format_bold' },
46
54
  { name: 'italic', label: $_('_sui.markdown_editor.italic'), icon: 'format_italic' },
@@ -72,25 +80,39 @@
72
80
  ];
73
81
  </script>
74
82
 
75
- <div class="wrapper" class:disabled hidden={hidden || undefined} {...$$restProps}>
76
- <div class="inner" inert={disabled}>
77
- <Toolbar aria-label={$_('_sui.markdown_editor.markdown_editor')}>
83
+ <div role="none" class="wrapper" hidden={hidden || undefined} {...$$restProps}>
84
+ <div role="none" class="inner">
85
+ <Toolbar
86
+ disabled={disabled || readonly}
87
+ aria-label={$_('_sui.markdown_editor.markdown_editor')}
88
+ >
78
89
  {#each defaultButtons as { label, icon, separator }}
79
90
  {#if separator}
80
91
  <Divider />
81
92
  {:else}
82
- <Button iconic {disabled}>
83
- <Icon slot="start-icon" name={icon} {label} />
93
+ <Button iconic aria-label={label} aria-controls={id}>
94
+ <Icon slot="start-icon" name={icon} />
84
95
  </Button>
85
96
  {/if}
86
97
  {/each}
87
98
  </Toolbar>
88
- <TextArea autoResize={true} bind:value {hidden} {disabled} {readonly} {required} {invalid} />
99
+ <TextArea
100
+ {id}
101
+ autoResize={true}
102
+ bind:value
103
+ {flex}
104
+ {hidden}
105
+ {disabled}
106
+ {readonly}
107
+ {required}
108
+ {invalid}
109
+ />
89
110
  </div>
90
111
  </div>
91
112
 
92
113
  <style>.wrapper {
93
- display: contents;
114
+ margin: var(--sui-focus-ring-width);
115
+ width: calc(100% - var(--sui-focus-ring-width) * 2);
94
116
  }
95
117
  .wrapper :global([role="toolbar"]) {
96
118
  display: flex;
@@ -101,6 +123,7 @@
101
123
  }
102
124
  .wrapper :global([role="toolbar"]) :global(button) {
103
125
  flex: none;
126
+ margin: 0 !important;
104
127
  }
105
128
  .wrapper :global([role="toolbar"]) + :global(div) {
106
129
  width: 100%;
@@ -111,4 +134,8 @@
111
134
 
112
135
  .inner {
113
136
  display: contents;
137
+ }
138
+ .inner :global(.text-area) {
139
+ margin: 0 !important;
140
+ width: 100% !important;
114
141
  }</style>
@@ -10,6 +10,7 @@ export default class MarkdownEditor extends SvelteComponent<{
10
10
  value?: string;
11
11
  hidden?: boolean;
12
12
  readonly?: boolean;
13
+ flex?: boolean;
13
14
  }, {
14
15
  [evt: string]: CustomEvent<any>;
15
16
  }, {}> {
@@ -27,6 +28,7 @@ declare const __propDef: {
27
28
  value?: string | undefined;
28
29
  hidden?: boolean | undefined;
29
30
  readonly?: boolean;
31
+ flex?: boolean;
30
32
  };
31
33
  events: {
32
34
  [evt: string]: CustomEvent<any>;
@@ -6,6 +6,7 @@
6
6
  -->
7
7
  <script>
8
8
  import { _ } from 'svelte-i18n';
9
+ import { getRandomId } from '../../services/util';
9
10
  import Button from '../button/button.svelte';
10
11
  import Icon from '../icon/icon.svelte';
11
12
  import TextInput from './text-input.svelte';
@@ -16,6 +17,11 @@
16
17
  */
17
18
  let className = '';
18
19
  export { className as class };
20
+ /**
21
+ * Make the text input container flexible.
22
+ * @type {boolean}
23
+ */
24
+ export let flex = false;
19
25
  /**
20
26
  * Whether to hide the widget. An alias of the `aria-hidden` attribute.
21
27
  * @type {boolean | undefined}
@@ -32,12 +38,12 @@
32
38
  */
33
39
  export let readonly = false;
34
40
  /**
35
- * Whether to disable the widget. An alias of the `aria-required` attribute.
41
+ * Whether to mark the widget required. An alias of the `aria-required` attribute.
36
42
  * @type {boolean}
37
43
  */
38
44
  export let required = false;
39
45
  /**
40
- * Whether to disable the widget. An alias of the `aria-invalid` attribute.
46
+ * Whether to mark the widget invalid. An alias of the `aria-invalid` attribute.
41
47
  * @type {boolean}
42
48
  */
43
49
  export let invalid = false;
@@ -61,14 +67,20 @@
61
67
  */
62
68
  export let step = 1;
63
69
 
70
+ const id = getRandomId('input');
71
+ let edited = false;
72
+
64
73
  $: maximumFractionDigits = String(step).split('.')[1]?.length || 0;
65
74
  $: isMin = typeof min === 'number' && Number(value || 0) <= min;
66
75
  $: isMax = typeof max === 'number' && Number(value || 0) >= max;
67
76
 
68
77
  $: invalid =
69
- (value !== undefined && Number.isNaN(Number(value))) ||
70
- (typeof min === 'number' && Number(value || 0) < min) ||
71
- (typeof max === 'number' && Number(value || 0) > max);
78
+ (required && edited && (value === undefined || value === '')) ||
79
+ (value !== undefined &&
80
+ value !== '' &&
81
+ (Number.isNaN(Number(value)) ||
82
+ (typeof min === 'number' && Number(value || 0) < min) ||
83
+ (typeof max === 'number' && Number(value || 0) > max)));
72
84
 
73
85
  let component;
74
86
 
@@ -95,11 +107,44 @@
95
107
  };
96
108
  </script>
97
109
 
98
- <div class="sui number-input {className}" class:disabled hidden={hidden || undefined}>
110
+ <div
111
+ role="none"
112
+ class="sui number-input {className}"
113
+ class:flex
114
+ class:disabled
115
+ class:readonly
116
+ hidden={hidden || undefined}
117
+ >
118
+ <div role="none" class="buttons">
119
+ <Button
120
+ iconic
121
+ disabled={disabled || readonly || Number.isNaN(Number(value)) || isMax}
122
+ aria-label={$_('_sui.number_input.increase')}
123
+ aria-controls={id}
124
+ on:click={() => {
125
+ increase();
126
+ }}
127
+ >
128
+ <Icon slot="start-icon" name="expand_less" />
129
+ </Button>
130
+ <Button
131
+ iconic
132
+ disabled={disabled || readonly || Number.isNaN(Number(value)) || isMin}
133
+ aria-label={$_('_sui.number_input.decrease')}
134
+ aria-controls={id}
135
+ on:click={() => {
136
+ decrease();
137
+ }}
138
+ >
139
+ <Icon slot="start-icon" name="expand_more" />
140
+ </Button>
141
+ </div>
99
142
  <TextInput
100
- bind:this={component}
101
- bind:value
102
143
  role="spinbutton"
144
+ {id}
145
+ bind:value
146
+ spellcheck="false"
147
+ {flex}
103
148
  {hidden}
104
149
  {disabled}
105
150
  {readonly}
@@ -108,7 +153,9 @@
108
153
  aria-valuenow={Number(value || 0)}
109
154
  aria-valuemin={min}
110
155
  aria-valuemax={max}
156
+ inputmode={maximumFractionDigits > 0 ? 'decimal' : 'numeric'}
111
157
  {...$$restProps}
158
+ bind:this={component}
112
159
  on:keydown={(event) => {
113
160
  const { key, ctrlKey, metaKey, altKey, shiftKey } = event;
114
161
  const hasModifier = shiftKey || altKey || ctrlKey || metaKey;
@@ -122,58 +169,75 @@
122
169
  event.preventDefault();
123
170
  increase();
124
171
  }
172
+
173
+ if (!edited) {
174
+ edited = true;
175
+ }
125
176
  }}
126
177
  on:keypress
127
178
  on:input
128
179
  />
129
- <Button
130
- iconic
131
- disabled={disabled || Number.isNaN(Number(value)) || isMin}
132
- on:click={() => {
133
- decrease();
134
- }}
135
- >
136
- <Icon slot="start-icon" name="arrow_downward" label={$_('_sui.number_input.decrease')} />
137
- </Button>
138
- <Button
139
- iconic
140
- disabled={disabled || Number.isNaN(Number(value)) || isMax}
141
- on:click={() => {
142
- increase();
143
- }}
144
- >
145
- <Icon slot="start-icon" name={'arrow_upward'} label={$_('_sui.number_input.increase')} />
146
- </Button>
147
180
  </div>
148
181
 
149
182
  <style>.number-input {
150
- width: 100%;
151
183
  display: inline-flex;
152
184
  align-items: center;
185
+ margin: var(--sui-focus-ring-width);
186
+ min-width: var(--sui-textbox-singleline-min-width);
153
187
  }
154
- .number-input :global(input) {
188
+ .number-input.flex {
189
+ width: -moz-available;
190
+ width: -webkit-fill-available;
191
+ width: stretch;
192
+ min-width: 0;
193
+ }
194
+ .number-input :global(:not(:first-child) input) {
195
+ border-top-left-radius: 0;
196
+ border-bottom-left-radius: 0;
197
+ }
198
+ .number-input :global(:not(:last-child) input) {
155
199
  border-top-right-radius: 0;
156
200
  border-bottom-right-radius: 0;
157
201
  }
158
- .number-input :global(button) {
202
+ .number-input:not(.disabled) :global(button[aria-disabled="true"]) {
203
+ filter: grayscale(0) opacity(1);
204
+ }
205
+ .number-input:not(.disabled) :global(button[aria-disabled="true"]) :global(*) {
206
+ filter: grayscale(1) opacity(0.35);
207
+ }
208
+ .number-input :global(.text-input) {
209
+ flex: auto;
210
+ margin: 0 !important;
211
+ width: 0;
212
+ min-width: 0 !important;
213
+ }
214
+
215
+ .buttons {
216
+ display: flex;
217
+ flex-direction: column;
218
+ width: 24px;
219
+ height: var(--sui-textbox-height);
220
+ }
221
+ .buttons :global(button) {
159
222
  flex: none;
223
+ margin: 0 !important;
160
224
  border-width: 1px;
161
225
  border-color: var(--sui-textbox-border-color);
162
- width: var(--sui-textbox-height);
163
- }
164
- .number-input :global(button):first-of-type {
165
- border-radius: 0;
166
- border-width: 1px 0;
167
- }
168
- .number-input :global(button):last-of-type {
169
- border-radius: 0 4px 4px 0;
226
+ width: 100%;
227
+ height: 50%;
170
228
  }
171
- .number-input :global(button) :global(.icon) {
172
- font-size: var(--sui-font-size-xx-large);
229
+ .buttons :global(button):first-of-type {
230
+ border-top-right-radius: 0;
231
+ border-bottom-right-radius: 0;
232
+ border-bottom-left-radius: 0;
233
+ border-width: 1px 0 0 1px;
173
234
  }
174
- .number-input:not(.disabled) :global(button[aria-disabled="true"]) {
175
- filter: grayscale(0) opacity(1);
235
+ .buttons :global(button):last-of-type {
236
+ border-top-left-radius: 0;
237
+ border-top-right-radius: 0;
238
+ border-bottom-right-radius: 0;
239
+ border-width: 0 0 1px 1px;
176
240
  }
177
- .number-input:not(.disabled) :global(button[aria-disabled="true"]) :global(*) {
178
- filter: grayscale(1) opacity(0.35);
241
+ .buttons :global(button) :global(.icon) {
242
+ font-size: 20px;
179
243
  }</style>
@@ -18,6 +18,7 @@ export default class NumberInput extends SvelteComponent<{
18
18
  value?: string;
19
19
  hidden?: boolean;
20
20
  readonly?: boolean;
21
+ flex?: boolean;
21
22
  }, {
22
23
  keypress: KeyboardEvent;
23
24
  input: Event;
@@ -42,6 +43,7 @@ declare const __propDef: {
42
43
  value?: string | undefined;
43
44
  hidden?: boolean | undefined;
44
45
  readonly?: boolean;
46
+ flex?: boolean;
45
47
  };
46
48
  events: {
47
49
  keypress: KeyboardEvent;
@@ -7,6 +7,7 @@
7
7
  -->
8
8
  <script>
9
9
  import { _ } from 'svelte-i18n';
10
+ import { getRandomId } from '../../services/util';
10
11
  import Button from '../button/button.svelte';
11
12
  import Icon from '../icon/icon.svelte';
12
13
  import TextInput from './text-input.svelte';
@@ -17,6 +18,11 @@
17
18
  */
18
19
  let className = '';
19
20
  export { className as class };
21
+ /**
22
+ * Make the text input container flexible.
23
+ * @type {boolean}
24
+ */
25
+ export let flex = false;
20
26
  /**
21
27
  * Whether to hide the widget. An alias of the `aria-hidden` attribute.
22
28
  * @type {boolean | undefined}
@@ -33,12 +39,12 @@
33
39
  */
34
40
  export let readonly = false;
35
41
  /**
36
- * Whether to disable the widget. An alias of the `aria-required` attribute.
42
+ * Whether to mark the widget required. An alias of the `aria-required` attribute.
37
43
  * @type {boolean}
38
44
  */
39
45
  export let required = false;
40
46
  /**
41
- * Whether to disable the widget. An alias of the `aria-invalid` attribute.
47
+ * Whether to mark the widget invalid. An alias of the `aria-invalid` attribute.
42
48
  * @type {boolean}
43
49
  */
44
50
  export let invalid = false;
@@ -48,6 +54,8 @@
48
54
  */
49
55
  export let value = undefined;
50
56
 
57
+ const id = getRandomId('input');
58
+
51
59
  /**
52
60
  * @type {TextInput}
53
61
  */
@@ -61,41 +69,64 @@
61
69
  }
62
70
  </script>
63
71
 
64
- <div class="sui password-input {className}" class:disabled hidden={hidden || undefined}>
72
+ <div
73
+ role="none"
74
+ class="sui password-input {className}"
75
+ class:flex
76
+ class:disabled
77
+ class:readonly
78
+ hidden={hidden || undefined}
79
+ >
65
80
  <TextInput
66
- bind:this={inputComponent}
81
+ {id}
67
82
  bind:value
68
83
  type="password"
84
+ spellcheck="false"
85
+ {flex}
69
86
  {hidden}
70
87
  {disabled}
71
88
  {readonly}
72
89
  {required}
73
90
  {invalid}
74
91
  {...$$restProps}
92
+ bind:this={inputComponent}
75
93
  on:input
76
94
  on:keypress
77
95
  on:change
78
96
  />
79
97
  <Button
80
98
  iconic
81
- {disabled}
99
+ disabled={disabled || readonly}
82
100
  pressed={passwordVisible}
101
+ aria-label={$_(
102
+ passwordVisible ? '_sui.password_input.hide_password' : '_sui.password_input.show_password',
103
+ )}
104
+ aria-controls={id}
83
105
  on:click={() => {
84
106
  passwordVisible = !passwordVisible;
85
107
  }}
86
108
  >
87
- <Icon
88
- slot="start-icon"
89
- name={passwordVisible ? 'visibility_off' : 'visibility'}
90
- label={$_('_sui.password_input.show_password')}
91
- />
109
+ <Icon slot="start-icon" name={passwordVisible ? 'visibility_off' : 'visibility'} />
92
110
  </Button>
93
111
  </div>
94
112
 
95
113
  <style>.password-input {
96
- width: 100%;
97
114
  display: inline-flex;
98
115
  align-items: center;
116
+ margin: var(--sui-focus-ring-width);
117
+ min-width: var(--sui-textbox-singleline-min-width);
118
+ }
119
+ .password-input.flex {
120
+ width: -moz-available;
121
+ width: -webkit-fill-available;
122
+ width: stretch;
123
+ min-width: 0;
124
+ }
125
+ .password-input :global(.text-input) {
126
+ flex: auto;
127
+ margin: 0 !important;
128
+ width: 0;
129
+ min-width: 0 !important;
99
130
  }
100
131
  .password-input :global(input) {
101
132
  border-top-right-radius: 0;
@@ -103,7 +134,7 @@
103
134
  }
104
135
  .password-input :global(button) {
105
136
  flex: none;
106
- margin-left: -1px;
137
+ margin: 0 0 0 -1px;
107
138
  border-width: 1px;
108
139
  border-color: var(--sui-textbox-border-color);
109
140
  width: var(--sui-textbox-height);
@@ -16,6 +16,7 @@ export default class PasswordInput extends SvelteComponent<{
16
16
  value?: string;
17
17
  hidden?: boolean;
18
18
  readonly?: boolean;
19
+ flex?: boolean;
19
20
  }, {
20
21
  input: Event;
21
22
  keypress: KeyboardEvent;
@@ -38,6 +39,7 @@ declare const __propDef: {
38
39
  value?: string | undefined;
39
40
  hidden?: boolean | undefined;
40
41
  readonly?: boolean;
42
+ flex?: boolean;
41
43
  };
42
44
  events: {
43
45
  input: Event;