@sveltia/ui 0.12.3 → 0.13.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.
@@ -46,6 +46,7 @@
46
46
  .checkbox-group.horizontal {
47
47
  gap: 8px;
48
48
  align-items: center;
49
+ flex-wrap: wrap;
49
50
  }
50
51
  .checkbox-group.vertical {
51
52
  gap: 4px;
@@ -79,6 +79,7 @@
79
79
  .radio-group.horizontal {
80
80
  gap: 8px;
81
81
  align-items: center;
82
+ flex-wrap: wrap;
82
83
  }
83
84
  .radio-group.vertical {
84
85
  gap: 4px;
@@ -0,0 +1,137 @@
1
+ <script>
2
+ import { createEventDispatcher } from 'svelte';
3
+ import { _ } from 'svelte-i18n';
4
+ import Button from '../button/button.svelte';
5
+ import Icon from '../icon/icon.svelte';
6
+ import Option from '../listbox/option.svelte';
7
+ import Select from './select.svelte';
8
+
9
+ /**
10
+ * The `class` attribute on the wrapper element.
11
+ * @type {string}
12
+ */
13
+ let className = '';
14
+ export { className as class };
15
+ /**
16
+ * Whether to hide the widget. An alias of the `aria-hidden` attribute.
17
+ * @type {boolean | undefined}
18
+ */
19
+ export let hidden = undefined;
20
+ /**
21
+ * Whether to disable the widget. An alias of the `aria-disabled` attribute.
22
+ * @type {boolean}
23
+ */
24
+ export let disabled = false;
25
+ /**
26
+ * Whether to make the widget read-only. An alias of the `aria-readonly` attribute.
27
+ * @type {boolean}
28
+ */
29
+ export let readonly = false;
30
+ /**
31
+ * Whether to mark the widget required. An alias of the `aria-required` attribute.
32
+ * @type {boolean}
33
+ */
34
+ export let required = false;
35
+ /**
36
+ * Whether to mark the widget invalid. An alias of the `aria-invalid` attribute.
37
+ * @type {boolean}
38
+ */
39
+ export let invalid = false;
40
+ /**
41
+ * Available options.
42
+ * @type {{ label: string, value: string, searchValue?: string }[]}
43
+ */
44
+ export let options;
45
+ /**
46
+ * Selected option values.
47
+ * @type {string[]}
48
+ */
49
+ export let values = [];
50
+ /**
51
+ * Maximum number of selectable options.
52
+ * @type {number | undefined}
53
+ */
54
+ export let max = undefined;
55
+
56
+ /**
57
+ * @type {string | undefined}
58
+ */
59
+ let selectedValue = undefined;
60
+
61
+ const dispatch = createEventDispatcher();
62
+ </script>
63
+
64
+ <div
65
+ role="none"
66
+ class="sui select-tags {className}"
67
+ class:disabled={disabled || readonly}
68
+ hidden={hidden || undefined}
69
+ >
70
+ {#each values as value}
71
+ {@const option = options.find((o) => o.value === value)}
72
+ {#if option}
73
+ <span role="none">
74
+ {option.label}
75
+ <Button
76
+ iconic
77
+ size="small"
78
+ disabled={disabled || readonly}
79
+ aria-label={$_('remove_x', { values: { name: option.label } })}
80
+ on:click={() => {
81
+ values = values.filter((v) => v !== value);
82
+ dispatch('RemoveValue', { value });
83
+ }}
84
+ >
85
+ <Icon slot="start-icon" name="close" />
86
+ </Button>
87
+ </span>
88
+ {/if}
89
+ {/each}
90
+ {#if (typeof max !== 'number' || values.length < max) && values.length < options.length}
91
+ <Select
92
+ disabled={disabled || readonly}
93
+ {readonly}
94
+ {required}
95
+ {invalid}
96
+ {...$$restProps}
97
+ bind:value={selectedValue}
98
+ on:change={() => {
99
+ if (selectedValue) {
100
+ values = [...values, selectedValue];
101
+ dispatch('AddValue', { value: selectedValue });
102
+ // Reset the combobox
103
+ selectedValue = undefined;
104
+ }
105
+ }}
106
+ >
107
+ {#each options as { label, value, searchValue } (value)}
108
+ {#if !values.includes(value)}
109
+ <Option {label} {value} {searchValue} />
110
+ {/if}
111
+ {/each}
112
+ </Select>
113
+ {/if}
114
+ </div>
115
+
116
+ <style>.select-tags {
117
+ display: flex;
118
+ flex-wrap: wrap;
119
+ align-items: center;
120
+ }
121
+ .select-tags.disabled {
122
+ pointer-events: none;
123
+ }
124
+ .select-tags.disabled > * {
125
+ opacity: 0.5;
126
+ }
127
+ .select-tags span {
128
+ display: inline-flex;
129
+ align-items: center;
130
+ margin: var(--sui-focus-ring-width);
131
+ padding: 0 0 0 8px;
132
+ border-radius: var(--sui-control-medium-border-radius);
133
+ background-color: var(--sui-secondary-background-color);
134
+ }
135
+ .select-tags span :global(.icon) {
136
+ font-size: var(--sui-font-size-large);
137
+ }</style>
@@ -0,0 +1,55 @@
1
+ /** @typedef {typeof __propDef.props} SelectTagsProps */
2
+ /** @typedef {typeof __propDef.events} SelectTagsEvents */
3
+ /** @typedef {typeof __propDef.slots} SelectTagsSlots */
4
+ export default class SelectTags extends SvelteComponent<{
5
+ [x: string]: any;
6
+ options: {
7
+ label: string;
8
+ value: string;
9
+ searchValue?: string | undefined;
10
+ }[];
11
+ class?: string | undefined;
12
+ invalid?: boolean | undefined;
13
+ disabled?: boolean | undefined;
14
+ hidden?: boolean | undefined;
15
+ readonly?: boolean | undefined;
16
+ values?: string[] | undefined;
17
+ required?: boolean | undefined;
18
+ max?: number | undefined;
19
+ }, {
20
+ RemoveValue: CustomEvent<any>;
21
+ AddValue: CustomEvent<any>;
22
+ } & {
23
+ [evt: string]: CustomEvent<any>;
24
+ }, {}> {
25
+ }
26
+ export type SelectTagsProps = typeof __propDef.props;
27
+ export type SelectTagsEvents = typeof __propDef.events;
28
+ export type SelectTagsSlots = typeof __propDef.slots;
29
+ import { SvelteComponent } from "svelte";
30
+ declare const __propDef: {
31
+ props: {
32
+ [x: string]: any;
33
+ options: {
34
+ label: string;
35
+ value: string;
36
+ searchValue?: string;
37
+ }[];
38
+ class?: string | undefined;
39
+ invalid?: boolean | undefined;
40
+ disabled?: boolean | undefined;
41
+ hidden?: boolean | undefined;
42
+ readonly?: boolean | undefined;
43
+ values?: string[] | undefined;
44
+ required?: boolean | undefined;
45
+ max?: number | undefined;
46
+ };
47
+ events: {
48
+ RemoveValue: CustomEvent<any>;
49
+ AddValue: CustomEvent<any>;
50
+ } & {
51
+ [evt: string]: CustomEvent<any>;
52
+ };
53
+ slots: {};
54
+ };
55
+ export {};
@@ -18,8 +18,8 @@ export default class Slider extends SvelteComponent<{
18
18
  hidden?: boolean | undefined;
19
19
  readonly?: boolean | undefined;
20
20
  values?: [number, number] | undefined;
21
- min?: number | undefined;
22
21
  max?: number | undefined;
22
+ min?: number | undefined;
23
23
  sliderLabel?: string | undefined;
24
24
  sliderLabels?: [string, string] | undefined;
25
25
  step?: number | undefined;
@@ -44,8 +44,8 @@ declare const __propDef: {
44
44
  hidden?: boolean | undefined;
45
45
  readonly?: boolean | undefined;
46
46
  values?: [number, number] | undefined;
47
- min?: number | undefined;
48
47
  max?: number | undefined;
48
+ min?: number | undefined;
49
49
  sliderLabel?: string | undefined;
50
50
  sliderLabels?: [string, string] | undefined;
51
51
  step?: number | undefined;
@@ -1,6 +1,11 @@
1
1
  <script>
2
2
  import { getContext, onMount } from 'svelte';
3
3
 
4
+ /**
5
+ * Whether to hide the widget. An alias of the `aria-hidden` attribute.
6
+ * @type {boolean | undefined}
7
+ */
8
+ export let hidden = undefined;
4
9
  /**
5
10
  * Whether to disable the widget. An alias of the `aria-disabled` attribute.
6
11
  * @type {boolean}
@@ -11,6 +16,16 @@
11
16
  * @type {boolean}
12
17
  */
13
18
  export let readonly = false;
19
+ /**
20
+ * Whether to mark the widget required. An alias of the `aria-required` attribute.
21
+ * @type {boolean}
22
+ */
23
+ export let required = false;
24
+ /**
25
+ * Whether to mark the widget invalid. An alias of the `aria-invalid` attribute.
26
+ * @type {boolean}
27
+ */
28
+ export let invalid = false;
14
29
  /**
15
30
  * Input value.
16
31
  * @type {string | undefined}
@@ -21,14 +36,8 @@
21
36
  * Text editor state.
22
37
  * @type {TextEditorState}
23
38
  */
24
- const {
25
- editor,
26
- editorId,
27
- selectionBlockType,
28
- selectionInlineTypes,
29
- useRichText,
30
- hasConverterError,
31
- } = getContext('state');
39
+ const { editor, editorId, selectionBlockType, selectionInlineTypes, hasConverterError } =
40
+ getContext('state');
32
41
 
33
42
  /**
34
43
  * Reference to the Lexical editor root element.
@@ -86,19 +95,22 @@
86
95
  <div
87
96
  role="textbox"
88
97
  aria-multiline="true"
98
+ aria-hidden={hidden}
89
99
  aria-disabled={disabled}
90
100
  aria-readonly={readonly}
101
+ aria-required={required}
102
+ aria-invalid={invalid}
91
103
  class="lexical-root"
92
104
  id="{$editorId}-lexical-root"
93
105
  contenteditable={editable}
106
+ {hidden}
94
107
  bind:this={lexicalRoot}
95
- hidden={!$useRichText}
96
108
  ></div>
97
109
 
98
110
  <style>.lexical-root {
99
111
  border: 1px solid var(--sui-textbox-border-color);
100
112
  border-radius: 0 0 var(--sui-textbox-border-radius) var(--sui-textbox-border-radius) !important;
101
- padding: 16px;
113
+ padding: var(--sui-textbox-multiline-padding);
102
114
  min-height: 8em;
103
115
  color: var(--sui-textbox-foreground-color);
104
116
  background-color: var(--sui-textbox-background-color);
@@ -109,6 +121,9 @@
109
121
  .lexical-root:focus-visible {
110
122
  outline: 0;
111
123
  }
124
+ .lexical-root[aria-invalid=true] {
125
+ border-color: var(--sui-error-foreground-color);
126
+ }
112
127
  .lexical-root > :global(:first-child) {
113
128
  margin-top: 0;
114
129
  }
@@ -2,9 +2,12 @@
2
2
  /** @typedef {typeof __propDef.events} LexicalRootEvents */
3
3
  /** @typedef {typeof __propDef.slots} LexicalRootSlots */
4
4
  export default class LexicalRoot extends SvelteComponent<{
5
+ invalid?: boolean | undefined;
5
6
  disabled?: boolean | undefined;
6
7
  value?: string | undefined;
8
+ hidden?: boolean | undefined;
7
9
  readonly?: boolean | undefined;
10
+ required?: boolean | undefined;
8
11
  }, {
9
12
  [evt: string]: CustomEvent<any>;
10
13
  }, {}> {
@@ -15,9 +18,12 @@ export type LexicalRootSlots = typeof __propDef.slots;
15
18
  import { SvelteComponent } from "svelte";
16
19
  declare const __propDef: {
17
20
  props: {
21
+ invalid?: boolean | undefined;
18
22
  disabled?: boolean | undefined;
19
23
  value?: string | undefined;
24
+ hidden?: boolean | undefined;
20
25
  readonly?: boolean | undefined;
26
+ required?: boolean | undefined;
21
27
  };
22
28
  events: {
23
29
  [evt: string]: CustomEvent<any>;
@@ -121,7 +121,14 @@
121
121
 
122
122
  <div role="none" class="sui text-editor" hidden={hidden || undefined} {...$$restProps}>
123
123
  <EditorToolbar {disabled} {readonly} />
124
- <LexicalRoot {disabled} {readonly} bind:value />
124
+ <LexicalRoot
125
+ bind:value
126
+ hidden={!$useRichText || hidden}
127
+ {disabled}
128
+ {readonly}
129
+ {required}
130
+ {invalid}
131
+ />
125
132
  <TextArea
126
133
  autoResize={true}
127
134
  bind:value
@@ -16,8 +16,8 @@ export default class NumberInput extends SvelteComponent<{
16
16
  readonly?: boolean | undefined;
17
17
  flex?: boolean | undefined;
18
18
  required?: boolean | undefined;
19
- min?: number | undefined;
20
19
  max?: number | undefined;
20
+ min?: number | undefined;
21
21
  step?: number | undefined;
22
22
  }, {
23
23
  keydown: KeyboardEvent;
@@ -51,8 +51,8 @@ declare const __propDef: {
51
51
  readonly?: boolean | undefined;
52
52
  flex?: boolean | undefined;
53
53
  required?: boolean | undefined;
54
- min?: number | undefined;
55
54
  max?: number | undefined;
55
+ min?: number | undefined;
56
56
  step?: number | undefined;
57
57
  };
58
58
  events: {
@@ -163,7 +163,7 @@
163
163
  height: var(--sui-button-medium-height);
164
164
  }
165
165
  .search-bar :global(.label) {
166
- --sui-textbox-padding: 0 36px;
166
+ --sui-textbox-singleline-padding: 0 36px;
167
167
  }
168
168
  .search-bar :global(.text-input) {
169
169
  flex: auto;
@@ -113,7 +113,7 @@ textarea,
113
113
  border-width: var(--sui-textbox-border-width, 1px);
114
114
  border-color: var(--sui-textbox-border-color);
115
115
  border-radius: var(--sui-textbox-border-radius);
116
- padding: 8px;
116
+ padding: var(--sui-textbox-multiline-padding);
117
117
  width: 100%;
118
118
  min-height: 8em;
119
119
  color: var(--sui-textbox-foreground-color);
@@ -153,7 +153,7 @@ input {
153
153
  border-width: var(--sui-textbox-border-width, 1px);
154
154
  border-color: var(--sui-textbox-border-color);
155
155
  border-radius: var(--sui-textbox-border-radius);
156
- padding: var(--sui-textbox-padding, 0 8px);
156
+ padding: var(--sui-textbox-singleline-padding);
157
157
  min-width: 0;
158
158
  height: var(--sui-textbox-height);
159
159
  color: var(--sui-textbox-foreground-color);
@@ -200,7 +200,7 @@ input ~ :global(button) :global(.icon) {
200
200
 
201
201
  .label {
202
202
  position: absolute;
203
- inset: var(--sui-textbox-padding, 0 8px);
203
+ inset: var(--sui-textbox-singleline-padding);
204
204
  z-index: 2;
205
205
  display: flex;
206
206
  align-items: center;
@@ -224,8 +224,10 @@
224
224
  --sui-textbox-background-color: hsl(var(--sui-background-color-1-hsl));
225
225
  --sui-textbox-font-family: var(--sui-font-family-default);
226
226
  --sui-textbox-font-size: var(--sui-font-size-default);
227
+ --sui-textbox-singleline-padding: 0 8px;
227
228
  --sui-textbox-singleline-min-width: 240px;
228
229
  --sui-textbox-singleline-line-height: var(--sui-line-height-compact);
230
+ --sui-textbox-multiline-padding: 12px;
229
231
  --sui-textbox-multiline-min-width: 480px;
230
232
  --sui-textbox-multiline-line-height: var(--sui-line-height-comfortable);
231
233
  --sui-tab-height: var(--sui-control-medium-height);
@@ -493,6 +495,11 @@
493
495
  line-height: var(--sui-line-height-comfortable);
494
496
  }
495
497
 
498
+ :global(ul),
499
+ :global(ol) {
500
+ padding-left: 2em;
501
+ }
502
+
496
503
  :global(code),
497
504
  :global(pre) {
498
505
  border-radius: 4px;
@@ -40,6 +40,7 @@ export { default as Menu } from "./components/menu/menu.svelte";
40
40
  export { default as RadioGroup } from "./components/radio/radio-group.svelte";
41
41
  export { default as Radio } from "./components/radio/radio.svelte";
42
42
  export { default as Combobox } from "./components/select/combobox.svelte";
43
+ export { default as SelectTags } from "./components/select/select-tags.svelte";
43
44
  export { default as Select } from "./components/select/select.svelte";
44
45
  export { default as Slider } from "./components/slider/slider.svelte";
45
46
  export { default as Switch } from "./components/switch/switch.svelte";
package/package/index.js CHANGED
@@ -72,6 +72,7 @@ export { default as Menu } from './components/menu/menu.svelte';
72
72
  export { default as RadioGroup } from './components/radio/radio-group.svelte';
73
73
  export { default as Radio } from './components/radio/radio.svelte';
74
74
  export { default as Combobox } from './components/select/combobox.svelte';
75
+ export { default as SelectTags } from './components/select/select-tags.svelte';
75
76
  export { default as Select } from './components/select/select.svelte';
76
77
  export { default as Slider } from './components/slider/slider.svelte';
77
78
  export { default as Switch } from './components/switch/switch.svelte';
@@ -102,6 +102,11 @@ li {
102
102
  line-height: var(--sui-line-height-comfortable);
103
103
  }
104
104
 
105
+ ul,
106
+ ol {
107
+ padding-left: 2em;
108
+ }
109
+
105
110
  code,
106
111
  pre {
107
112
  border-radius: 4px;
@@ -219,8 +219,10 @@
219
219
  --sui-textbox-background-color: hsl(var(--sui-background-color-1-hsl));
220
220
  --sui-textbox-font-family: var(--sui-font-family-default);
221
221
  --sui-textbox-font-size: var(--sui-font-size-default);
222
+ --sui-textbox-singleline-padding: 0 8px;
222
223
  --sui-textbox-singleline-min-width: 240px;
223
224
  --sui-textbox-singleline-line-height: var(--sui-line-height-compact);
225
+ --sui-textbox-multiline-padding: 12px;
224
226
  --sui-textbox-multiline-min-width: 480px;
225
227
  --sui-textbox-multiline-line-height: var(--sui-line-height-comfortable);
226
228
  // Tab
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sveltia/ui",
3
- "version": "0.12.3",
3
+ "version": "0.13.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -257,6 +257,11 @@
257
257
  "svelte": "./package/components/select/combobox.svelte",
258
258
  "default": "./package/components/select/combobox.svelte"
259
259
  },
260
+ "./components/select/select-tags.svelte": {
261
+ "types": "./package/components/select/select-tags.svelte.d.ts",
262
+ "svelte": "./package/components/select/select-tags.svelte",
263
+ "default": "./package/components/select/select-tags.svelte"
264
+ },
260
265
  "./components/select/select.svelte": {
261
266
  "types": "./package/components/select/select.svelte.d.ts",
262
267
  "svelte": "./package/components/select/select.svelte",
@@ -554,6 +559,9 @@
554
559
  "components/select/combobox.svelte": [
555
560
  "./package/components/select/combobox.svelte.d.ts"
556
561
  ],
562
+ "components/select/select-tags.svelte": [
563
+ "./package/components/select/select-tags.svelte.d.ts"
564
+ ],
557
565
  "components/select/select.svelte": [
558
566
  "./package/components/select/select.svelte.d.ts"
559
567
  ],