@sveltia/ui 0.10.8 → 0.11.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.
@@ -153,6 +153,7 @@
153
153
  on:change={(/** @type {CustomEvent} */ event) => {
154
154
  dispatch('change', event.detail);
155
155
  }}
156
+ on:toggle
156
157
  >
157
158
  <slot name="start-icon" />
158
159
  {#if variant === 'link'}
@@ -41,6 +41,7 @@ export default class Button extends SvelteComponent<{
41
41
  keypress: KeyboardEvent;
42
42
  focus: FocusEvent;
43
43
  blur: FocusEvent;
44
+ toggle: Event;
44
45
  select: CustomEvent<any>;
45
46
  change: CustomEvent<any>;
46
47
  } & {
@@ -150,6 +151,7 @@ declare const __propDef: {
150
151
  keypress: KeyboardEvent;
151
152
  focus: FocusEvent;
152
153
  blur: FocusEvent;
154
+ toggle: Event;
153
155
  select: CustomEvent<any>;
154
156
  change: CustomEvent<any>;
155
157
  } & {
@@ -150,7 +150,6 @@
150
150
  position: absolute;
151
151
  display: flex;
152
152
  flex-direction: column;
153
- overflow: hidden;
154
153
  max-width: 100dvw;
155
154
  max-height: 100dvh;
156
155
  background-color: var(--sui-secondary-background-color-translucent);
@@ -46,6 +46,16 @@
46
46
  * @type {boolean}
47
47
  */
48
48
  export let multiple = false;
49
+ /**
50
+ * Search terms to be used to filter the items.
51
+ * @type {string}
52
+ */
53
+ export let searchTerms = '';
54
+
55
+ /**
56
+ * @type {boolean}
57
+ */
58
+ let filtered = false;
49
59
 
50
60
  const dispatch = createEventDispatcher();
51
61
  </script>
@@ -53,6 +63,7 @@
53
63
  <div
54
64
  role="listbox"
55
65
  class="sui listbox {className}"
66
+ class:filtered
56
67
  tabindex={disabled ? -1 : 0}
57
68
  hidden={hidden || undefined}
58
69
  aria-hidden={hidden}
@@ -62,11 +73,15 @@
62
73
  aria-invalid={invalid}
63
74
  aria-multiselectable={multiple}
64
75
  {...$$restProps}
65
- use:activateGroup
76
+ use:activateGroup={{ searchTerms }}
66
77
  on:click
67
78
  on:change={(/** @type {CustomEvent} */ event) => {
68
79
  dispatch('change', event.detail);
69
80
  }}
81
+ on:filter
82
+ on:filter={(/** @type {CustomEvent} */ { detail: { matched, total } }) => {
83
+ filtered = matched !== total;
84
+ }}
70
85
  >
71
86
  <div role="none" class="inner" inert={disabled}>
72
87
  <slot />
@@ -113,6 +128,12 @@
113
128
  [role=listbox]:global(.tabs) :global(.option button[aria-selected="true"]) {
114
129
  border-color: var(--sui-primary-accent-color-light);
115
130
  }
131
+ [role=listbox].in-combobox:focus-visible {
132
+ outline-color: transparent;
133
+ }
134
+ [role=listbox].filtered :global([role="separator"]) {
135
+ display: none;
136
+ }
116
137
 
117
138
  .inner {
118
139
  display: contents;
@@ -16,8 +16,10 @@ export default class Listbox extends SvelteComponent<{
16
16
  required?: boolean | undefined;
17
17
  hidden?: boolean | undefined;
18
18
  readonly?: boolean | undefined;
19
+ searchTerms?: string | undefined;
19
20
  }, {
20
21
  click: MouseEvent;
22
+ filter: Event | KeyboardEvent | UIEvent | ErrorEvent | AnimationEvent | MouseEvent | InputEvent | FocusEvent | CompositionEvent | ClipboardEvent | DragEvent | FormDataEvent | PointerEvent | ProgressEvent<EventTarget> | SecurityPolicyViolationEvent | SubmitEvent | TouchEvent | TransitionEvent | WheelEvent;
21
23
  change: CustomEvent<any>;
22
24
  } & {
23
25
  [evt: string]: CustomEvent<any>;
@@ -39,9 +41,11 @@ declare const __propDef: {
39
41
  required?: boolean | undefined;
40
42
  hidden?: boolean | undefined;
41
43
  readonly?: boolean | undefined;
44
+ searchTerms?: string | undefined;
42
45
  };
43
46
  events: {
44
47
  click: MouseEvent;
48
+ filter: Event | KeyboardEvent | UIEvent | ErrorEvent | AnimationEvent | MouseEvent | InputEvent | FocusEvent | CompositionEvent | ClipboardEvent | DragEvent | FormDataEvent | PointerEvent | ProgressEvent<EventTarget> | SecurityPolicyViolationEvent | SubmitEvent | TouchEvent | TransitionEvent | WheelEvent;
45
49
  change: CustomEvent<any>;
46
50
  } & {
47
51
  [evt: string]: CustomEvent<any>;
@@ -31,14 +31,19 @@
31
31
  export let disabled = false;
32
32
  /**
33
33
  * Text label displayed on the item.
34
- * @type {string | undefined}
34
+ * @type {string}
35
35
  */
36
- export let label = '';
36
+ export let label;
37
37
  /**
38
38
  * The `value` attribute on the `<button>` element.
39
- * @type {string | undefined}
39
+ * @type {string}
40
+ */
41
+ export let value = label;
42
+ /**
43
+ * The value to be searched.
44
+ * @type {string}
40
45
  */
41
- export let value = undefined;
46
+ export let searchValue = label;
42
47
  </script>
43
48
 
44
49
  <div role="none" class="sui option {className}" hidden={hidden || undefined}>
@@ -51,6 +56,8 @@
51
56
  {hidden}
52
57
  {disabled}
53
58
  data-type={typeof value}
59
+ data-label={label}
60
+ data-search-value={searchValue}
54
61
  {...$$restProps}
55
62
  on:click
56
63
  on:dblclick
@@ -65,6 +72,10 @@
65
72
  on:change={(event) => {
66
73
  selected = event.detail.selected;
67
74
  }}
75
+ on:toggle={(event) => {
76
+ hidden = /** @type {CustomEvent} */ (event).detail.hidden;
77
+ selected = false;
78
+ }}
68
79
  >
69
80
  {#if selected}
70
81
  <slot name="check-icon">
@@ -8,12 +8,13 @@
8
8
  */
9
9
  export default class Option extends SvelteComponent<{
10
10
  [x: string]: any;
11
+ label: string;
11
12
  class?: string | undefined;
12
13
  disabled?: boolean | undefined;
13
- label?: string | undefined;
14
14
  value?: string | undefined;
15
15
  hidden?: boolean | undefined;
16
16
  selected?: boolean | undefined;
17
+ searchValue?: string | undefined;
17
18
  }, {
18
19
  click: MouseEvent;
19
20
  dblclick: MouseEvent;
@@ -45,12 +46,13 @@ import { SvelteComponent } from "svelte";
45
46
  declare const __propDef: {
46
47
  props: {
47
48
  [x: string]: any;
49
+ label: string;
48
50
  class?: string | undefined;
49
51
  disabled?: boolean | undefined;
50
- label?: string | undefined;
51
52
  value?: string | undefined;
52
53
  hidden?: boolean | undefined;
53
54
  selected?: boolean | undefined;
55
+ searchValue?: string | undefined;
54
56
  };
55
57
  events: {
56
58
  click: MouseEvent;
@@ -13,6 +13,7 @@
13
13
  import Button from '../button/button.svelte';
14
14
  import Icon from '../icon/icon.svelte';
15
15
  import Listbox from '../listbox/listbox.svelte';
16
+ import SearchBar from '../text-field/search-bar.svelte';
16
17
  import TextInput from '../text-field/text-input.svelte';
17
18
  import Popup from '../util/popup.svelte';
18
19
 
@@ -74,6 +75,12 @@
74
75
  let isPopupOpen = writable(false);
75
76
  /** @type {string} */
76
77
  let label = '';
78
+ /** @type {boolean} */
79
+ let showFilter = false;
80
+ /** @type {string} */
81
+ let searchTerms = '';
82
+ /** @type {boolean} */
83
+ let hasMatchingOptions = true;
77
84
 
78
85
  /**
79
86
  * Update the {@link label} and selected option when the {@link value} is changed.
@@ -86,7 +93,7 @@
86
93
  );
87
94
 
88
95
  if (target) {
89
- label = target.querySelector('.label')?.textContent || target.textContent || target.value;
96
+ label = target.dataset.label || target.textContent || target.value;
90
97
 
91
98
  if (selected !== target) {
92
99
  selected?.setAttribute('aria-selected', 'false');
@@ -200,16 +207,49 @@
200
207
  touchOptimized={true}
201
208
  bind:open={isPopupOpen}
202
209
  bind:this={popupComponent}
210
+ on:open={() => {
211
+ showFilter = (popupComponent?.content?.querySelectorAll('[role="option"]')?.length ?? 0) > 5;
212
+ searchTerms = '';
213
+ }}
203
214
  >
204
- <Listbox
205
- on:click={(event) => {
206
- if (/** @type {HTMLElement} */ (event.target).matches('[role="option"]')) {
207
- onSelect(/** @type {HTMLButtonElement} */ (event.target));
208
- }
209
- }}
210
- >
211
- <slot />
212
- </Listbox>
215
+ <div role="none" class="combobox-inner">
216
+ {#if showFilter}
217
+ <SearchBar
218
+ flex
219
+ aria-label={$_('_sui.combobox.filter_options')}
220
+ aria-controls="{id}-listbox"
221
+ bind:value={searchTerms}
222
+ on:keydown={(event) => {
223
+ if (['ArrowUp', 'ArrowDown', 'Enter'].includes(event.key)) {
224
+ event.preventDefault();
225
+ popupComponent?.content
226
+ ?.querySelector('.sui.listbox')
227
+ ?.dispatchEvent(new KeyboardEvent('keydown', event));
228
+ }
229
+ }}
230
+ />
231
+ {/if}
232
+ <Listbox
233
+ id="{id}-listbox"
234
+ class="in-combobox"
235
+ {searchTerms}
236
+ on:click={(event) => {
237
+ if (/** @type {HTMLElement} */ (event.target).matches('[role="option"]')) {
238
+ onSelect(/** @type {HTMLButtonElement} */ (event.target));
239
+ }
240
+ }}
241
+ on:filter={(event) => {
242
+ hasMatchingOptions = !!(/** @type {CustomEvent} */ (event).detail.matched);
243
+ }}
244
+ >
245
+ <slot />
246
+ </Listbox>
247
+ {#if !hasMatchingOptions}
248
+ <div role="alert" class="no-options">
249
+ {$_('_sui.combobox.no_matching_options')}
250
+ </div>
251
+ {/if}
252
+ </div>
213
253
  </Popup>
214
254
 
215
255
  <style>.combobox {
@@ -297,4 +337,25 @@
297
337
  .combobox + :global([role="listbox"]:not(.open)) {
298
338
  opacity: 0;
299
339
  pointer-events: none;
340
+ }
341
+
342
+ .combobox-inner {
343
+ display: flex;
344
+ flex-direction: column;
345
+ overflow: hidden;
346
+ }
347
+ .combobox-inner :global(.sui.search-bar) {
348
+ flex: none;
349
+ }
350
+ .combobox-inner :global(.sui.listbox) {
351
+ flex: auto;
352
+ overflow-y: auto;
353
+ }
354
+ .combobox-inner .no-options {
355
+ flex: none;
356
+ display: flex;
357
+ align-items: center;
358
+ padding: var(--sui-option-padding);
359
+ height: var(--sui-option-height);
360
+ color: var(--sui-tertiary-foreground-color);
300
361
  }</style>
@@ -268,10 +268,10 @@
268
268
  --sui-background-color-2-hsl: var(--sui-base-hue) 5% 98%;
269
269
  --sui-background-color-3-hsl: var(--sui-base-hue) 5% 96%;
270
270
  --sui-background-color-4-hsl: var(--sui-base-hue) 5% 94%;
271
- --sui-background-color-5-hsl: var(--sui-base-hue) 5% 74%;
272
- --sui-border-color-1-hsl: var(--sui-base-hue) 5% 50%;
273
- --sui-border-color-2-hsl: var(--sui-base-hue) 5% 74%;
274
- --sui-border-color-3-hsl: var(--sui-base-hue) 5% 70%;
271
+ --sui-background-color-5-hsl: var(--sui-base-hue) 5% 84%;
272
+ --sui-border-color-1-hsl: var(--sui-base-hue) 5% 65%;
273
+ --sui-border-color-2-hsl: var(--sui-base-hue) 5% 84%;
274
+ --sui-border-color-3-hsl: var(--sui-base-hue) 5% 88%;
275
275
  --sui-shadow-color: var(--sui-base-hue) 10% 0%;
276
276
  --sui-primary-accent-color-text: hsl(var(--sui-base-hue) 80% 40%);
277
277
  --sui-primary-accent-color-light: hsl(var(--sui-base-hue) 80% 45%);
@@ -303,7 +303,7 @@
303
303
  --sui-background-color-3-hsl: var(--sui-base-hue) 10% 14%;
304
304
  --sui-background-color-4-hsl: var(--sui-base-hue) 10% 16%;
305
305
  --sui-background-color-5-hsl: var(--sui-base-hue) 10% 26%;
306
- --sui-border-color-1-hsl: var(--sui-base-hue) 10% 50%;
306
+ --sui-border-color-1-hsl: var(--sui-base-hue) 10% 45%;
307
307
  --sui-border-color-2-hsl: var(--sui-base-hue) 10% 26%;
308
308
  --sui-border-color-3-hsl: var(--sui-base-hue) 10% 22%;
309
309
  --sui-shadow-color: var(--sui-base-hue) 10% 0%;
@@ -337,10 +337,10 @@
337
337
  --sui-background-color-2-hsl: var(--sui-base-hue) 5% 98%;
338
338
  --sui-background-color-3-hsl: var(--sui-base-hue) 5% 96%;
339
339
  --sui-background-color-4-hsl: var(--sui-base-hue) 5% 94%;
340
- --sui-background-color-5-hsl: var(--sui-base-hue) 5% 74%;
341
- --sui-border-color-1-hsl: var(--sui-base-hue) 5% 50%;
342
- --sui-border-color-2-hsl: var(--sui-base-hue) 5% 74%;
343
- --sui-border-color-3-hsl: var(--sui-base-hue) 5% 70%;
340
+ --sui-background-color-5-hsl: var(--sui-base-hue) 5% 84%;
341
+ --sui-border-color-1-hsl: var(--sui-base-hue) 5% 65%;
342
+ --sui-border-color-2-hsl: var(--sui-base-hue) 5% 84%;
343
+ --sui-border-color-3-hsl: var(--sui-base-hue) 5% 88%;
344
344
  --sui-shadow-color: var(--sui-base-hue) 10% 0%;
345
345
  --sui-primary-accent-color-text: hsl(var(--sui-base-hue) 80% 40%);
346
346
  --sui-primary-accent-color-light: hsl(var(--sui-base-hue) 80% 45%);
@@ -374,7 +374,7 @@
374
374
  --sui-background-color-3-hsl: var(--sui-base-hue) 10% 14%;
375
375
  --sui-background-color-4-hsl: var(--sui-base-hue) 10% 16%;
376
376
  --sui-background-color-5-hsl: var(--sui-base-hue) 10% 26%;
377
- --sui-border-color-1-hsl: var(--sui-base-hue) 10% 50%;
377
+ --sui-border-color-1-hsl: var(--sui-base-hue) 10% 45%;
378
378
  --sui-border-color-2-hsl: var(--sui-base-hue) 10% 26%;
379
379
  --sui-border-color-3-hsl: var(--sui-base-hue) 10% 22%;
380
380
  --sui-shadow-color: var(--sui-base-hue) 10% 0%;
@@ -221,7 +221,7 @@ dialog.backdrop {
221
221
  background-color: var(--sui-popup-backdrop-color);
222
222
  }
223
223
  dialog.open {
224
- transition-duration: 200ms;
224
+ transition-duration: 50ms;
225
225
  opacity: 1;
226
226
  }
227
227
  dialog:not(.open) {
@@ -203,7 +203,7 @@
203
203
  padding: 8px 4px !important;
204
204
  }
205
205
  :global(dialog.open) .content {
206
- transition-duration: 150ms;
206
+ transition-duration: 50ms;
207
207
  opacity: 1;
208
208
  transform: translateY(2px);
209
209
  }
@@ -21,6 +21,8 @@ export namespace strings {
21
21
  }
22
22
  namespace combobox {
23
23
  const select_an_option: string;
24
+ const filter_options: string;
25
+ const no_matching_options: string;
24
26
  }
25
27
  namespace number_input {
26
28
  const decrease: string;
@@ -21,6 +21,8 @@ export const strings = {
21
21
  },
22
22
  combobox: {
23
23
  select_an_option: 'Select an option…',
24
+ filter_options: 'Filter Options',
25
+ no_matching_options: 'No matching options found',
24
26
  },
25
27
  number_input: {
26
28
  decrease: 'Decrease',
@@ -21,6 +21,8 @@ export namespace strings {
21
21
  }
22
22
  namespace combobox {
23
23
  const select_an_option: string;
24
+ const filter_options: string;
25
+ const no_matching_options: string;
24
26
  }
25
27
  namespace number_input {
26
28
  const decrease: string;
@@ -21,6 +21,8 @@ export const strings = {
21
21
  },
22
22
  combobox: {
23
23
  select_an_option: 'オプションを選択…',
24
+ filter_options: 'オプションを絞り込み',
25
+ no_matching_options: '一致するオプションは見つかりませんでした',
24
26
  },
25
27
  number_input: {
26
28
  decrease: '減らす',
@@ -1 +1 @@
1
- export function activateGroup(parent: HTMLElement): void;
1
+ export function activateGroup(parent: HTMLElement, _params?: object | undefined): import('svelte/action').ActionReturn;
@@ -75,7 +75,18 @@ class Group {
75
75
  this.childSelectedProp = childSelectedAttr.replace('aria-', '');
76
76
  this.focusChild = focusChild;
77
77
 
78
- const { allMembers, selected: defaultSelected } = this;
78
+ // Wait a bit before the relevant components, including the `aria-controls` target are mounted
79
+ (async () => {
80
+ await sleep(100);
81
+ this.activate();
82
+ })();
83
+ }
84
+
85
+ /**
86
+ * Activate the members.
87
+ */
88
+ activate() {
89
+ const { parent, allMembers, selected: defaultSelected } = this;
79
90
 
80
91
  allMembers.forEach((element, index) => {
81
92
  // Select the first one if no member has the `selected` attribute
@@ -340,9 +351,10 @@ class Group {
340
351
  const target = /** @type {HTMLElement} */ (event.target);
341
352
  const { allMembers, activeMembers } = this;
342
353
 
354
+ /** @type {HTMLElement | undefined} */
343
355
  const currentTarget = (() => {
344
356
  if (!this.focusChild) {
345
- return activeMembers.find((member) => member.matches('.focused')) ?? activeMembers[0];
357
+ return activeMembers.find((member) => member.matches('.focused'));
346
358
  }
347
359
 
348
360
  if (target.matches(this.selector)) {
@@ -352,22 +364,20 @@ class Group {
352
364
  return undefined;
353
365
  })();
354
366
 
355
- if (!currentTarget) {
356
- return;
357
- }
358
-
359
367
  if (['Enter', ' ', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(key)) {
360
368
  event.preventDefault();
361
369
  }
362
370
 
363
371
  if (key === 'Enter') {
364
- currentTarget.click(); // Also close the popup if needed
372
+ currentTarget?.click(); // Also close the popup if needed
365
373
 
366
374
  return;
367
375
  }
368
376
 
369
377
  if (key === ' ') {
370
- this.selectTarget(event, currentTarget);
378
+ if (currentTarget) {
379
+ this.selectTarget(event, currentTarget);
380
+ }
371
381
 
372
382
  return;
373
383
  }
@@ -376,9 +386,9 @@ class Group {
376
386
  let newTarget;
377
387
 
378
388
  if (this.grid) {
379
- const colCount = Math.floor(this.parent.clientWidth / currentTarget.clientWidth);
389
+ const colCount = Math.floor(this.parent.clientWidth / activeMembers[0].clientWidth);
380
390
 
381
- index = allMembers.indexOf(currentTarget);
391
+ index = currentTarget ? allMembers.indexOf(currentTarget) : -1;
382
392
 
383
393
  if (key === 'ArrowUp' && index > 0) {
384
394
  newTarget = allMembers[index - colCount];
@@ -400,7 +410,7 @@ class Group {
400
410
  newTarget = undefined;
401
411
  }
402
412
  } else {
403
- index = activeMembers.indexOf(currentTarget);
413
+ index = currentTarget ? activeMembers.indexOf(currentTarget) : -1;
404
414
 
405
415
  if (key === (this.orientation === 'horizontal' ? 'ArrowLeft' : 'ArrowUp')) {
406
416
  if (index > 0) {
@@ -431,17 +441,56 @@ class Group {
431
441
  this.selectTarget(event, newTarget);
432
442
  }
433
443
  }
444
+
445
+ /**
446
+ * Called whenever the params are updated. Filter the items based on the search terms.
447
+ * @param {{ searchTerms: string }} params - Updated params.
448
+ */
449
+ onUpdate({ searchTerms }) {
450
+ const terms = searchTerms.trim().toLocaleLowerCase();
451
+ const _terms = terms ? terms.split(/\s+/) : [];
452
+
453
+ const matched = this.allMembers
454
+ .map((member) => {
455
+ const searchValue =
456
+ (
457
+ member.dataset.searchValue ??
458
+ member.dataset.label ??
459
+ member.querySelector('.label')?.textContent ??
460
+ member.textContent
461
+ )?.toLocaleLowerCase() ?? '';
462
+
463
+ const hidden = !_terms.every((term) => searchValue.includes(term));
464
+
465
+ member.dispatchEvent(new CustomEvent('toggle', { detail: { hidden } }));
466
+
467
+ return hidden;
468
+ })
469
+ .filter((hidden) => !hidden).length;
470
+
471
+ this.parent.dispatchEvent(
472
+ new CustomEvent('filter', { detail: { matched, total: this.allMembers.length } }),
473
+ );
474
+ }
434
475
  }
435
476
 
436
477
  /**
437
478
  * Activate a new group.
438
479
  * @param {HTMLElement} parent - Parent element.
480
+ * @param {object} [_params] - Action params.
481
+ * @returns {import('svelte/action').ActionReturn} Action.
439
482
  */
440
- export const activateGroup = (parent) => {
441
- (async () => {
442
- // Wait a bit before the relevant components, including the `aria-controls` target are mounted
443
- await sleep(100);
444
-
445
- return new Group(parent);
446
- })();
483
+ // eslint-disable-next-line no-unused-vars
484
+ export const activateGroup = (parent, _params) => {
485
+ const group = new Group(parent);
486
+
487
+ return {
488
+ /**
489
+ * Called whenever the params are updated.
490
+ * @param {any} params - Updated params.
491
+ */
492
+ update(params) {
493
+ group.onUpdate(params);
494
+ },
495
+ };
447
496
  };
@@ -9,10 +9,10 @@
9
9
  --sui-background-color-2-hsl: var(--sui-base-hue) 5% 98%; // primary
10
10
  --sui-background-color-3-hsl: var(--sui-base-hue) 5% 96%; // secondary
11
11
  --sui-background-color-4-hsl: var(--sui-base-hue) 5% 94%; // tertiary/disabled
12
- --sui-background-color-5-hsl: var(--sui-base-hue) 5% 74%; // highlight
13
- --sui-border-color-1-hsl: var(--sui-base-hue) 5% 50%; // control
14
- --sui-border-color-2-hsl: var(--sui-base-hue) 5% 74%; // primary
15
- --sui-border-color-3-hsl: var(--sui-base-hue) 5% 70%; // secondary
12
+ --sui-background-color-5-hsl: var(--sui-base-hue) 5% 84%; // highlight
13
+ --sui-border-color-1-hsl: var(--sui-base-hue) 5% 65%; // control
14
+ --sui-border-color-2-hsl: var(--sui-base-hue) 5% 84%; // primary
15
+ --sui-border-color-3-hsl: var(--sui-base-hue) 5% 88%; // secondary
16
16
  --sui-shadow-color: var(--sui-base-hue) 10% 0%;
17
17
  // Accents
18
18
  --sui-primary-accent-color-text: hsl(var(--sui-base-hue) 80% 40%);
@@ -46,7 +46,7 @@
46
46
  --sui-background-color-3-hsl: var(--sui-base-hue) 10% 14%; // secondary
47
47
  --sui-background-color-4-hsl: var(--sui-base-hue) 10% 16%; // tertiary/disabled
48
48
  --sui-background-color-5-hsl: var(--sui-base-hue) 10% 26%; // highlight
49
- --sui-border-color-1-hsl: var(--sui-base-hue) 10% 50%; // control
49
+ --sui-border-color-1-hsl: var(--sui-base-hue) 10% 45%; // control
50
50
  --sui-border-color-2-hsl: var(--sui-base-hue) 10% 26%; // primary
51
51
  --sui-border-color-3-hsl: var(--sui-base-hue) 10% 22%; // secondary
52
52
  --sui-shadow-color: var(--sui-base-hue) 10% 0%;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sveltia/ui",
3
- "version": "0.10.8",
3
+ "version": "0.11.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -26,32 +26,32 @@
26
26
  "svelte": "^4.2.12"
27
27
  },
28
28
  "devDependencies": {
29
- "@playwright/test": "^1.42.1",
29
+ "@playwright/test": "^1.43.0",
30
30
  "@sveltejs/adapter-auto": "^3.2.0",
31
31
  "@sveltejs/kit": "^2.5.5",
32
- "@sveltejs/package": "^2.3.0",
32
+ "@sveltejs/package": "^2.3.1",
33
33
  "@sveltejs/vite-plugin-svelte": "^3.0.2",
34
34
  "cspell": "^8.6.1",
35
35
  "eslint": "^8.57.0",
36
36
  "eslint-config-airbnb-base": "^15.0.0",
37
37
  "eslint-config-prettier": "^9.1.0",
38
38
  "eslint-plugin-import": "^2.29.1",
39
- "eslint-plugin-jsdoc": "^48.2.2",
39
+ "eslint-plugin-jsdoc": "^48.2.3",
40
40
  "eslint-plugin-svelte": "^2.35.1",
41
41
  "npm-run-all": "^4.1.5",
42
42
  "postcss": "^8.4.38",
43
43
  "postcss-html": "^1.6.0",
44
44
  "prettier": "^3.2.5",
45
45
  "prettier-plugin-svelte": "^3.2.2",
46
- "sass": "^1.72.0",
46
+ "sass": "^1.74.1",
47
47
  "stylelint": "^16.3.1",
48
48
  "stylelint-config-recommended-scss": "^14.0.0",
49
49
  "stylelint-scss": "^6.2.1",
50
- "svelte-check": "^3.6.8",
50
+ "svelte-check": "^3.6.9",
51
51
  "svelte-i18n": "^4.0.0",
52
52
  "svelte-preprocess": "^5.1.3",
53
53
  "tslib": "^2.6.2",
54
- "vite": "^5.2.7",
54
+ "vite": "^5.2.8",
55
55
  "vitest": "^1.4.0"
56
56
  },
57
57
  "exports": {