@geoffcox/sterling-svelte 2.0.1 → 2.0.3

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 (71) hide show
  1. package/README.md +1 -1
  2. package/dist/Button.svelte +18 -14
  3. package/dist/Button.svelte.d.ts +0 -1
  4. package/dist/Callout.svelte +162 -96
  5. package/dist/Callout.svelte.d.ts +1 -2
  6. package/dist/Checkbox.svelte +34 -15
  7. package/dist/Checkbox.svelte.d.ts +0 -1
  8. package/dist/Dialog.svelte +121 -71
  9. package/dist/Dialog.svelte.d.ts +1 -1
  10. package/dist/Dropdown.svelte +106 -56
  11. package/dist/Dropdown.svelte.d.ts +8 -3
  12. package/dist/Input.svelte +54 -29
  13. package/dist/Input.svelte.d.ts +1 -2
  14. package/dist/Label.svelte +99 -55
  15. package/dist/Label.svelte.d.ts +4 -4
  16. package/dist/Link.svelte +20 -14
  17. package/dist/Link.svelte.d.ts +0 -1
  18. package/dist/List.svelte +181 -126
  19. package/dist/List.svelte.d.ts +0 -1
  20. package/dist/ListItem.svelte +36 -21
  21. package/dist/ListItem.svelte.d.ts +0 -1
  22. package/dist/Menu.svelte +67 -45
  23. package/dist/Menu.svelte.d.ts +0 -1
  24. package/dist/MenuBar.svelte +96 -65
  25. package/dist/MenuBar.svelte.d.ts +0 -1
  26. package/dist/MenuButton.svelte +102 -62
  27. package/dist/MenuButton.svelte.d.ts +1 -1
  28. package/dist/MenuItem.svelte +332 -243
  29. package/dist/MenuItem.svelte.d.ts +3 -3
  30. package/dist/MenuSeparator.svelte +7 -7
  31. package/dist/MenuSeparator.svelte.d.ts +0 -1
  32. package/dist/Pagination.svelte +267 -0
  33. package/dist/Pagination.svelte.d.ts +4 -0
  34. package/dist/Pagination.types.d.ts +24 -0
  35. package/dist/Pagination.types.js +1 -0
  36. package/dist/Popover.svelte +114 -60
  37. package/dist/Popover.svelte.d.ts +1 -2
  38. package/dist/Portal.types.d.ts +1 -4
  39. package/dist/Progress.svelte +40 -15
  40. package/dist/Progress.svelte.d.ts +0 -1
  41. package/dist/Radio.svelte +37 -25
  42. package/dist/Radio.svelte.d.ts +0 -1
  43. package/dist/Select.svelte +191 -125
  44. package/dist/Select.svelte.d.ts +8 -2
  45. package/dist/Slider.svelte +120 -71
  46. package/dist/Slider.svelte.d.ts +0 -1
  47. package/dist/Switch.svelte +51 -20
  48. package/dist/Switch.svelte.d.ts +1 -1
  49. package/dist/Tab.svelte +39 -24
  50. package/dist/Tab.svelte.d.ts +0 -1
  51. package/dist/TabList.svelte +176 -125
  52. package/dist/TabList.svelte.d.ts +0 -1
  53. package/dist/TextArea.svelte +83 -41
  54. package/dist/TextArea.svelte.d.ts +2 -3
  55. package/dist/Tooltip.svelte +68 -36
  56. package/dist/Tree.svelte +52 -24
  57. package/dist/Tree.svelte.d.ts +0 -1
  58. package/dist/TreeChevron.svelte +24 -12
  59. package/dist/TreeChevron.svelte.d.ts +0 -1
  60. package/dist/TreeItem.svelte +292 -225
  61. package/dist/TreeItem.svelte.d.ts +1 -1
  62. package/dist/actions/extraClass.d.ts +1 -0
  63. package/dist/actions/extraClass.js +1 -0
  64. package/dist/idGenerator.d.ts +1 -0
  65. package/dist/idGenerator.js +1 -0
  66. package/dist/index.d.ts +3 -2
  67. package/dist/index.js +3 -2
  68. package/dist/mediaQueries/prefersColorSchemeDark.d.ts +0 -1
  69. package/dist/mediaQueries/prefersReducedMotion.d.ts +0 -1
  70. package/dist/mediaQueries/usingKeyboard.d.ts +0 -1
  71. package/package.json +21 -22
@@ -1,31 +1,62 @@
1
1
  <svelte:options runes={true} />
2
2
 
3
- <script lang="ts">import { idGenerator } from './idGenerator';
4
- import { usingKeyboard } from './mediaQueries/usingKeyboard';
5
- let { checked = $bindable(false), class: _class, disabled, id, offLabel, onLabel, vertical, ...rest } = $props();
6
- const inputId = id || idGenerator.nextId('Switch');
7
- let inputRef;
8
- let switchWidth = $state(0);
9
- let switchHeight = $state(0);
10
- let thumbWidth = $state(0);
11
- let thumbHeight = $state(0);
12
- let switchSize = $derived(vertical ? switchHeight : switchWidth);
13
- let thumbSize = $derived(vertical ? thumbHeight : thumbWidth);
14
- let ratio = $derived(vertical ? (checked ? 0 : 1) : checked ? 1 : 0);
15
- let valueOffset = $derived((switchSize - thumbSize) * ratio);
16
- export const blur = () => {
3
+ <script lang="ts">
4
+ import type { Snippet } from 'svelte';
5
+ import type { HTMLInputAttributes } from 'svelte/elements';
6
+ import { usingKeyboard } from './mediaQueries/usingKeyboard';
7
+
8
+ const uuid = $props.id();
9
+
10
+ type LabelSnippet = Snippet<
11
+ [{ checked: boolean | null | undefined; disabled: boolean | null | undefined; inputId: string }]
12
+ >;
13
+
14
+ type Props = HTMLInputAttributes & {
15
+ offLabel?: string | LabelSnippet;
16
+ onLabel?: string | LabelSnippet;
17
+ vertical?: boolean | null | undefined;
18
+ };
19
+
20
+ let {
21
+ checked = $bindable(false),
22
+ class: _class,
23
+ disabled,
24
+ id,
25
+ offLabel,
26
+ onLabel,
27
+ vertical,
28
+ ...rest
29
+ }: Props = $props();
30
+
31
+ const inputId = id || `Switch-${uuid}`;
32
+
33
+ let inputRef: HTMLInputElement;
34
+
35
+ let switchWidth: number = $state(0);
36
+ let switchHeight: number = $state(0);
37
+ let thumbWidth: number = $state(0);
38
+ let thumbHeight: number = $state(0);
39
+
40
+ let switchSize = $derived(vertical ? switchHeight : switchWidth);
41
+ let thumbSize = $derived(vertical ? thumbHeight : thumbWidth);
42
+ let ratio = $derived(vertical ? (checked ? 0 : 1) : checked ? 1 : 0);
43
+ let valueOffset = $derived((switchSize - thumbSize) * ratio);
44
+
45
+ export const blur = () => {
17
46
  inputRef?.blur();
18
- };
19
- export const click = () => {
47
+ };
48
+
49
+ export const click = () => {
20
50
  inputRef?.click();
21
- };
22
- export const focus = (options) => {
51
+ };
52
+
53
+ export const focus = (options?: FocusOptions) => {
23
54
  inputRef?.focus(options);
24
- };
55
+ };
25
56
  </script>
26
57
 
27
58
  <div
28
- class={`sterling-switch ${_class}`}
59
+ class={['sterling-switch', _class]}
29
60
  class:checked
30
61
  class:disabled
31
62
  class:vertical
@@ -1,5 +1,5 @@
1
- import type { HTMLInputAttributes } from 'svelte/elements';
2
1
  import type { Snippet } from 'svelte';
2
+ import type { HTMLInputAttributes } from 'svelte/elements';
3
3
  type LabelSnippet = Snippet<[
4
4
  {
5
5
  checked: boolean | null | undefined;
package/dist/Tab.svelte CHANGED
@@ -1,39 +1,54 @@
1
1
  <svelte:options runes={true} />
2
2
 
3
- <script lang="ts">import { getContext } from 'svelte';
4
- import { TAB_LIST_CONTEXT_KEY } from './TabList.constants';
5
- import { usingKeyboard } from './mediaQueries/usingKeyboard';
6
- let { children, class: _class, disabled = false, value, ...rest } = $props();
7
- let tabRef;
8
- const tabListContext = getContext(TAB_LIST_CONTEXT_KEY);
9
- let selected = $state(tabListContext.selectedValue === value);
10
- let _disabled = $derived(tabListContext.disabled || disabled);
11
- // Using $derived would be preferred, but this helps avoid
12
- // updates to every tab when selectedValue changes.
13
- // let selected = $derived(tabContext.selectedValue === value);
14
- $effect(() => {
3
+ <script lang="ts">
4
+ import { getContext } from 'svelte';
5
+ import type { HTMLButtonAttributes } from 'svelte/elements';
6
+ import { TAB_LIST_CONTEXT_KEY } from './TabList.constants';
7
+ import type { TabListContext } from './TabList.types';
8
+ import { usingKeyboard } from './mediaQueries/usingKeyboard';
9
+
10
+ type Props = HTMLButtonAttributes & {
11
+ value: string;
12
+ };
13
+
14
+ let { children, class: _class, disabled = false, value, ...rest }: Props = $props();
15
+
16
+ let tabRef: HTMLButtonElement;
17
+
18
+ const tabListContext = getContext<TabListContext>(TAB_LIST_CONTEXT_KEY);
19
+
20
+ let selected = $state(tabListContext.selectedValue === value);
21
+
22
+ let _disabled = $derived(tabListContext.disabled || disabled);
23
+
24
+ // Using $derived would be preferred, but this helps avoid
25
+ // updates to every tab when selectedValue changes.
26
+ // let selected = $derived(tabContext.selectedValue === value);
27
+ $effect(() => {
15
28
  if (tabListContext.selectedValue === value && !selected) {
16
- selected = true;
17
- }
18
- else if (tabListContext.selectedValue !== value && selected) {
19
- selected = false;
29
+ selected = true;
30
+ } else if (tabListContext.selectedValue !== value && selected) {
31
+ selected = false;
20
32
  }
21
- });
22
- export const click = () => {
33
+ });
34
+
35
+ export const click = () => {
23
36
  tabRef?.click();
24
- };
25
- export const blur = () => {
37
+ };
38
+
39
+ export const blur = () => {
26
40
  tabRef?.blur();
27
- };
28
- export const focus = (options) => {
41
+ };
42
+
43
+ export const focus = (options?: FocusOptions) => {
29
44
  tabRef?.focus(options);
30
- };
45
+ };
31
46
  </script>
32
47
 
33
48
  <button
34
49
  bind:this={tabRef}
35
50
  aria-selected={selected}
36
- class={`sterling-tab ${_class}`}
51
+ class={['sterling-tab', _class]}
37
52
  class:selected
38
53
  class:using-keyboard={$usingKeyboard}
39
54
  class:vertical={tabListContext.vertical}
@@ -1,4 +1,3 @@
1
- /// <reference types="svelte" />
2
1
  import type { HTMLButtonAttributes } from 'svelte/elements';
3
2
  type Props = HTMLButtonAttributes & {
4
3
  value: string;
@@ -1,195 +1,246 @@
1
1
  <svelte:options runes={true} />
2
2
 
3
- <script lang="ts">import { setContext } from 'svelte';
4
- import { TAB_LIST_CONTEXT_KEY } from './TabList.constants';
5
- let { children, class: _class, disabled = false, onSelect, selectedValue = $bindable(), vertical = false, ...rest } = $props();
6
- let tabListRef;
7
- let lastSelectedTabRef;
8
- let tabListContext = {
3
+ <script lang="ts">
4
+ import { setContext } from 'svelte';
5
+ import type { HTMLAttributes, KeyboardEventHandler, MouseEventHandler } from 'svelte/elements';
6
+ import { TAB_LIST_CONTEXT_KEY } from './TabList.constants';
7
+ import type { TabListContext } from './TabList.types';
8
+
9
+ type Props = HTMLAttributes<HTMLDivElement> & {
10
+ disabled?: boolean | null;
11
+ selectedValue?: string;
12
+ vertical?: boolean | null;
13
+ onSelect?: (value?: string) => void;
14
+ };
15
+
16
+ let {
17
+ children,
18
+ class: _class,
19
+ disabled = false,
20
+ onSelect,
21
+ selectedValue = $bindable(),
22
+ vertical = false,
23
+ ...rest
24
+ }: Props = $props();
25
+
26
+ let tabListRef: HTMLDivElement;
27
+ let lastSelectedTabRef: HTMLElement;
28
+
29
+ let tabListContext: TabListContext = {
9
30
  get disabled() {
10
- return disabled;
31
+ return disabled;
11
32
  },
12
33
  set disabled(value) {
13
- disabled = value;
34
+ disabled = value;
14
35
  },
15
36
  get selectedValue() {
16
- return selectedValue;
37
+ return selectedValue;
17
38
  },
18
39
  set selectedValue(value) {
19
- selectedValue = value;
40
+ selectedValue = value;
20
41
  },
21
42
  get vertical() {
22
- return vertical;
43
+ return vertical;
23
44
  },
24
45
  set vertical(value) {
25
- vertical = value;
46
+ vertical = value;
26
47
  }
27
- };
28
- $effect(() => {
48
+ };
49
+
50
+ $effect(() => {
29
51
  tabListContext.disabled = disabled;
30
- });
31
- $effect(() => {
52
+ });
53
+
54
+ $effect(() => {
32
55
  tabListContext.selectedValue = selectedValue;
33
- });
34
- $effect(() => {
56
+ });
57
+
58
+ $effect(() => {
35
59
  tabListContext.vertical = vertical;
36
- });
37
- setContext(TAB_LIST_CONTEXT_KEY, tabListContext);
38
- $effect(() => {
60
+ });
61
+
62
+ setContext<TabListContext>(TAB_LIST_CONTEXT_KEY, tabListContext);
63
+
64
+ $effect(() => {
39
65
  onSelect?.(selectedValue);
40
- });
41
- export const blur = () => {
66
+ });
67
+
68
+ export const blur = () => {
42
69
  tabListRef?.blur();
43
- };
44
- export const focus = (options) => {
70
+ };
71
+
72
+ export const focus = (options?: FocusOptions) => {
45
73
  let selectedItem = getSelectedTabElement();
46
74
  if (selectedValue && selectedItem) {
47
- selectTab(selectedValue, selectedItem);
48
- }
49
- else {
50
- selectFirstTab();
51
- }
52
- };
53
- const isElementTab = (candidate) => {
54
- return (candidate &&
55
- candidate.getAttribute('data-value') !== null &&
56
- candidate.getAttribute('data-value') !== undefined &&
57
- candidate.getAttribute('role') === 'tab');
58
- };
59
- const getSelectedTabElement = () => {
60
- if (isElementTab(lastSelectedTabRef) &&
61
- lastSelectedTabRef?.getAttribute('data-value') === selectedValue &&
62
- lastSelectedTabRef?.closest('[role="tablist"]') === tabListRef) {
63
- return lastSelectedTabRef;
75
+ selectTab(selectedValue, selectedItem as HTMLElement);
76
+ } else {
77
+ selectFirstTab();
64
78
  }
65
- else {
66
- return tabListRef?.querySelector('[data-value][aria-selected=true]');
79
+ };
80
+
81
+ const isElementTab = (candidate: Element) => {
82
+ return (
83
+ candidate &&
84
+ candidate.getAttribute('data-value') !== null &&
85
+ candidate.getAttribute('data-value') !== undefined &&
86
+ candidate.getAttribute('role') === 'tab'
87
+ );
88
+ };
89
+
90
+ const getSelectedTabElement = () => {
91
+ if (
92
+ isElementTab(lastSelectedTabRef) &&
93
+ lastSelectedTabRef?.getAttribute('data-value') === selectedValue &&
94
+ lastSelectedTabRef?.closest('[role="tablist"]') === tabListRef
95
+ ) {
96
+ return lastSelectedTabRef;
97
+ } else {
98
+ return tabListRef?.querySelector('[data-value][aria-selected=true]');
67
99
  }
68
- };
69
- const selectTab = (value, element) => {
100
+ };
101
+
102
+ const selectTab = (value: string, element: HTMLElement) => {
70
103
  selectedValue = value;
71
104
  lastSelectedTabRef = element;
72
105
  element.scrollIntoView({ block: 'nearest', inline: 'nearest' });
73
106
  element.focus();
74
- };
75
- export const selectFirstTab = () => {
76
- let candidate = tabListRef?.firstElementChild;
107
+ };
108
+
109
+ export const selectFirstTab = () => {
110
+ let candidate: Element | undefined | null = tabListRef?.firstElementChild;
77
111
  while (candidate && !isElementTab(candidate)) {
78
- candidate = candidate.nextElementSibling;
112
+ candidate = candidate.nextElementSibling;
79
113
  }
80
114
  let candidateValue = candidate?.getAttribute('data-value');
115
+
81
116
  if (candidateValue && candidate) {
82
- selectTab(candidateValue, candidate);
83
- return true;
117
+ selectTab(candidateValue, candidate as HTMLElement);
118
+ return true;
84
119
  }
120
+
85
121
  return false;
86
- };
87
- export const selectPreviousTab = () => {
122
+ };
123
+
124
+ export const selectPreviousTab = () => {
88
125
  let selectedTab = getSelectedTabElement();
89
126
  let candidate = selectedTab?.previousElementSibling;
90
127
  while (candidate && !isElementTab(candidate)) {
91
- candidate = candidate.previousElementSibling;
128
+ candidate = candidate.previousElementSibling;
92
129
  }
93
130
  let candidateValue = candidate?.getAttribute('data-value');
131
+
94
132
  if (candidateValue && candidate) {
95
- selectTab(candidateValue, candidate);
96
- return true;
133
+ selectTab(candidateValue, candidate as HTMLElement);
134
+ return true;
97
135
  }
136
+
98
137
  return false;
99
- };
100
- export const selectNextTab = () => {
138
+ };
139
+
140
+ export const selectNextTab = () => {
101
141
  let selectedTab = getSelectedTabElement();
102
142
  let candidate = selectedTab?.nextElementSibling;
103
143
  while (candidate && !isElementTab(candidate)) {
104
- candidate = candidate.nextElementSibling;
144
+ candidate = candidate.nextElementSibling;
105
145
  }
106
146
  let candidateValue = candidate?.getAttribute('data-value');
147
+
107
148
  if (candidateValue && candidate) {
108
- selectTab(candidateValue, candidate);
109
- return true;
149
+ selectTab(candidateValue, candidate as HTMLElement);
150
+ return true;
110
151
  }
152
+
111
153
  return false;
112
- };
113
- export const selectLastTab = () => {
114
- let candidate = tabListRef?.lastElementChild;
154
+ };
155
+
156
+ export const selectLastTab = () => {
157
+ let candidate: Element | undefined | null = tabListRef?.lastElementChild;
115
158
  while (candidate && !isElementTab(candidate)) {
116
- candidate = candidate.previousElementSibling;
159
+ candidate = candidate.previousElementSibling;
117
160
  }
118
161
  let candidateValue = candidate?.getAttribute('data-value');
162
+
119
163
  if (candidateValue && candidate) {
120
- selectTab(candidateValue, candidate);
121
- return true;
164
+ selectTab(candidateValue, candidate as HTMLElement);
165
+ return true;
122
166
  }
167
+
123
168
  return false;
124
- };
125
- const onClick = (event) => {
169
+ };
170
+
171
+ const onClick: MouseEventHandler<HTMLDivElement> = (event) => {
126
172
  if (!disabled) {
127
- let candidate = event.target;
128
- let candidateValue = candidate?.getAttribute('data-value');
129
- if (candidateValue === undefined || candidateValue === null) {
130
- candidate = candidate?.closest('[role=tab]');
131
- candidateValue = candidate?.getAttribute('data-value');
132
- }
133
- if (candidateValue && candidate) {
134
- selectTab(candidateValue, candidate);
135
- }
173
+ let candidate: HTMLElement | null | undefined = event.target as HTMLElement;
174
+ let candidateValue: string | null | undefined = candidate?.getAttribute('data-value');
175
+
176
+ if (candidateValue === undefined || candidateValue === null) {
177
+ candidate = candidate?.closest<HTMLElement>('[role=tab]');
178
+ candidateValue = candidate?.getAttribute('data-value');
179
+ }
180
+
181
+ if (candidateValue && candidate) {
182
+ selectTab(candidateValue, candidate);
183
+ }
136
184
  }
185
+
137
186
  rest.onclick?.(event);
138
- };
139
- const onKeydown = (event) => {
187
+ };
188
+
189
+ const onKeydown: KeyboardEventHandler<HTMLDivElement> = (event) => {
140
190
  // if using arrows, only move when there are no modifier keys
141
191
  if (!disabled && !event.ctrlKey && !event.shiftKey && !event.altKey && !event.metaKey) {
142
- switch (event.key) {
143
- case 'Home':
144
- selectFirstTab();
145
- event.preventDefault();
146
- event.stopPropagation();
147
- break;
148
- case 'End':
149
- selectLastTab();
150
- event.preventDefault();
151
- event.stopPropagation();
152
- break;
153
- case 'ArrowLeft':
154
- if (!vertical) {
155
- selectPreviousTab();
156
- }
157
- event.preventDefault();
158
- event.stopPropagation();
159
- break;
160
- case 'ArrowRight':
161
- if (!vertical) {
162
- selectNextTab();
163
- }
164
- event.preventDefault();
165
- event.stopPropagation();
166
- break;
167
- case 'ArrowUp':
168
- if (vertical) {
169
- selectPreviousTab();
170
- }
171
- event.preventDefault();
172
- event.stopPropagation();
173
- break;
174
- case 'ArrowDown':
175
- if (vertical) {
176
- selectNextTab();
177
- }
178
- event.preventDefault();
179
- event.stopPropagation();
180
- break;
181
- default:
182
- break;
183
- }
192
+ switch (event.key) {
193
+ case 'Home':
194
+ selectFirstTab();
195
+ event.preventDefault();
196
+ event.stopPropagation();
197
+ break;
198
+ case 'End':
199
+ selectLastTab();
200
+ event.preventDefault();
201
+ event.stopPropagation();
202
+ break;
203
+ case 'ArrowLeft':
204
+ if (!vertical) {
205
+ selectPreviousTab();
206
+ }
207
+ event.preventDefault();
208
+ event.stopPropagation();
209
+ break;
210
+ case 'ArrowRight':
211
+ if (!vertical) {
212
+ selectNextTab();
213
+ }
214
+ event.preventDefault();
215
+ event.stopPropagation();
216
+ break;
217
+ case 'ArrowUp':
218
+ if (vertical) {
219
+ selectPreviousTab();
220
+ }
221
+ event.preventDefault();
222
+ event.stopPropagation();
223
+ break;
224
+ case 'ArrowDown':
225
+ if (vertical) {
226
+ selectNextTab();
227
+ }
228
+ event.preventDefault();
229
+ event.stopPropagation();
230
+ break;
231
+ default:
232
+ break;
233
+ }
184
234
  }
235
+
185
236
  rest.onkeydown?.(event);
186
- };
237
+ };
187
238
  </script>
188
239
 
189
240
  <div
190
241
  aria-orientation={vertical ? 'vertical' : 'horizontal'}
191
242
  bind:this={tabListRef}
192
- class={`sterling-tab-list ${_class}`}
243
+ class={['sterling-tab-list', _class]}
193
244
  class:disabled
194
245
  class:vertical
195
246
  role="tablist"
@@ -1,4 +1,3 @@
1
- /// <reference types="svelte" />
2
1
  import type { HTMLAttributes } from 'svelte/elements';
3
2
  type Props = HTMLAttributes<HTMLDivElement> & {
4
3
  disabled?: boolean | null;