@geoffcox/sterling-svelte 0.0.3 → 0.0.5

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.
@@ -0,0 +1,313 @@
1
+ <script>import { createEventDispatcher } from "svelte";
2
+ export let disabled = false;
3
+ export let items = [];
4
+ export let horizontal = false;
5
+ export let selectedIndex = -1;
6
+ export let selectedItem = void 0;
7
+ $: {
8
+ selectedItem = items[selectedIndex];
9
+ }
10
+ let listRef;
11
+ let itemRefs = {};
12
+ let focusVisible = false;
13
+ const dispatch = createEventDispatcher();
14
+ const raiseItemSelected = (index) => {
15
+ dispatch("itemSelected", { index, item: items[index] });
16
+ };
17
+ export const focusSelectedItem = () => {
18
+ listRef.focus();
19
+ const selectedRef = itemRefs[selectedIndex];
20
+ selectedRef?.focus();
21
+ selectedRef?.scrollIntoView({ behavior: "smooth", block: "nearest", inline: "nearest" });
22
+ };
23
+ $:
24
+ canSelectPreviousItem = items.length > 0 && selectedIndex !== 0;
25
+ $:
26
+ canSelectNextItem = items.length > 0 && selectedIndex !== items.length - 1;
27
+ export const selectPreviousItem = () => {
28
+ if (canSelectPreviousItem) {
29
+ selectedIndex = Math.max(0, selectedIndex - 1);
30
+ }
31
+ };
32
+ export const selectNextItem = () => {
33
+ if (canSelectNextItem) {
34
+ selectedIndex = Math.min(items.length - 1, selectedIndex + 1);
35
+ }
36
+ };
37
+ $: {
38
+ raiseItemSelected(selectedIndex);
39
+ }
40
+ $: {
41
+ const selectedRef = itemRefs[selectedIndex];
42
+ selectedRef?.scrollIntoView({ behavior: "smooth", block: "nearest", inline: "nearest" });
43
+ }
44
+ const onItemClick = (index) => {
45
+ if (!disabled) {
46
+ selectedIndex = index;
47
+ }
48
+ };
49
+ const onArrowSelectPrevious = (event) => {
50
+ event.preventDefault();
51
+ event.stopPropagation();
52
+ selectPreviousItem();
53
+ };
54
+ const onArrowSelectNext = (event) => {
55
+ event.preventDefault();
56
+ event.stopPropagation();
57
+ selectNextItem();
58
+ };
59
+ const onKeydown = (event) => {
60
+ if (!disabled && !event.ctrlKey && !event.shiftKey && !event.altKey && !event.metaKey) {
61
+ switch (event.key) {
62
+ case "ArrowLeft":
63
+ if (horizontal) {
64
+ onArrowSelectPrevious(event);
65
+ }
66
+ break;
67
+ case "ArrowRight":
68
+ if (horizontal) {
69
+ onArrowSelectNext(event);
70
+ }
71
+ break;
72
+ case "ArrowUp":
73
+ if (!horizontal) {
74
+ onArrowSelectPrevious(event);
75
+ }
76
+ break;
77
+ case "ArrowDown":
78
+ if (!horizontal) {
79
+ onArrowSelectNext(event);
80
+ }
81
+ break;
82
+ default:
83
+ break;
84
+ }
85
+ }
86
+ };
87
+ </script>
88
+
89
+ <!--
90
+ @component
91
+ A list of items where a single item can be selected.
92
+ -->
93
+ {#if $$slots.label}
94
+ <!-- svelte-ignore a11y-label-has-associated-control -->
95
+ <label class="sterling-list-label" class:horizontal class:disabled>
96
+ <div class="label-content">
97
+ <slot name="label" />
98
+ </div>
99
+ <div
100
+ bind:this={listRef}
101
+ class="sterling-list labeled"
102
+ class:disabled
103
+ class:focus-visible={focusVisible}
104
+ class:horizontal
105
+ role="listbox"
106
+ tabindex={!disabled ? 0 : undefined}
107
+ on:blur
108
+ on:click
109
+ on:copy
110
+ on:cut
111
+ on:dblclick
112
+ on:focus
113
+ on:focusin
114
+ on:focusout
115
+ on:keydown={onKeydown}
116
+ on:keydown
117
+ on:keypress
118
+ on:keyup
119
+ on:mousedown
120
+ on:mouseenter
121
+ on:mouseleave
122
+ on:mousemove
123
+ on:mouseover
124
+ on:mouseout
125
+ on:mouseup
126
+ on:scroll
127
+ on:wheel
128
+ on:paste
129
+ {...$$restProps}
130
+ >
131
+ {#each items as item, index (item)}
132
+ {@const selected = selectedIndex === index}
133
+ <!-- svelte-ignore a11y-click-events-have-key-events -->
134
+ <div
135
+ bind:this={itemRefs[index]}
136
+ aria-selected={disabled ? undefined : selected}
137
+ class="list-item"
138
+ class:selected
139
+ class:disabled
140
+ data-index={index + 1}
141
+ role="option"
142
+ on:click={() => onItemClick(index)}
143
+ >
144
+ <slot {disabled} {index} {item} {selected}>
145
+ {item}
146
+ </slot>
147
+ </div>
148
+ {/each}
149
+ </div>
150
+ </label>
151
+ {:else}
152
+ <div
153
+ bind:this={listRef}
154
+ class="sterling-list"
155
+ class:disabled
156
+ class:focus-visible={focusVisible}
157
+ class:horizontal
158
+ role="listbox"
159
+ tabindex={!disabled ? 0 : undefined}
160
+ on:blur
161
+ on:click
162
+ on:copy
163
+ on:cut
164
+ on:dblclick
165
+ on:focus
166
+ on:focusin
167
+ on:focusout
168
+ on:keydown={onKeydown}
169
+ on:keydown
170
+ on:keypress
171
+ on:keyup
172
+ on:mousedown
173
+ on:mouseenter
174
+ on:mouseleave
175
+ on:mousemove
176
+ on:mouseover
177
+ on:mouseout
178
+ on:mouseup
179
+ on:scroll
180
+ on:wheel
181
+ on:paste
182
+ {...$$restProps}
183
+ >
184
+ {#each items as item, index (item)}
185
+ {@const selected = selectedIndex === index}
186
+ <!-- svelte-ignore a11y-click-events-have-key-events -->
187
+ <div
188
+ bind:this={itemRefs[index]}
189
+ aria-selected={disabled ? undefined : selected}
190
+ class="list-item"
191
+ class:selected
192
+ class:disabled
193
+ data-index={index + 1}
194
+ role="option"
195
+ on:click={() => onItemClick(index)}
196
+ >
197
+ <slot {disabled} {index} {item} {selected}>
198
+ {item}
199
+ </slot>
200
+ </div>
201
+ {/each}
202
+ </div>
203
+ {/if}
204
+
205
+ <style>
206
+ .sterling-list-label,
207
+ .sterling-list {
208
+ background-color: var(--Common__background-color);
209
+ border-color: var(--Common__border-color);
210
+ border-radius: var(--Common__border-radius);
211
+ border-style: var(--Common__border-style);
212
+ border-width: var(--Common__border-width);
213
+ box-sizing: border-box;
214
+ color: var(--Common__color);
215
+ display: flex;
216
+ flex-direction: column;
217
+ flex-wrap: nowrap;
218
+ height: 100%;
219
+ margin: 0;
220
+ padding: 0;
221
+ transition: background-color 250ms, color 250ms, border-color 250ms;
222
+ }
223
+
224
+ .sterling-list-label.horizontal,
225
+ .sterling-list.horizontal {
226
+ height: unset;
227
+ width: 100%;
228
+ }
229
+
230
+ .sterling-list {
231
+ overflow-x: hidden;
232
+ overflow-y: scroll;
233
+ position: relative;
234
+ }
235
+
236
+ .sterling-list.horizontal {
237
+ flex-direction: row;
238
+ overflow-x: scroll;
239
+ overflow-y: hidden;
240
+ }
241
+
242
+ .sterling-list-label:hover,
243
+ .sterling-list:hover {
244
+ border-color: var(--Common__border-color--hover);
245
+ color: var(--Common__color--hover);
246
+ }
247
+
248
+ .sterling-list-label:focus-visible,
249
+ .sterling-list-label.focus-visible,
250
+ .sterling-list:focus-visible,
251
+ .sterling-list.focus-visible {
252
+ border-color: var(--Common__border-color--focus);
253
+ color: var(--Common__color--focus);
254
+ outline-color: var(--Common__outline-color);
255
+ outline-offset: var(--Common__outline-offset);
256
+ outline-style: var(--Common__outline-style);
257
+ outline-width: var(--Common__outline-width);
258
+ }
259
+
260
+ .sterling-list-label.disabled,
261
+ .sterling-list.disabled {
262
+ background-color: var(--Common__background-color--disabled);
263
+ border-color: var(---Common__border-color--disabled);
264
+ color: var(--Common__color--disabled);
265
+ cursor: not-allowed;
266
+ }
267
+
268
+ .sterling-list.labeled,
269
+ .sterling-list.labeled:hover,
270
+ .sterling-list.labeled:focus-visible,
271
+ .sterling-list.labeled.focus-visible,
272
+ .sterling-list.labeled:disabled {
273
+ background-color: transparent;
274
+ border: none;
275
+ outline: none;
276
+ }
277
+ .label {
278
+ display: flex;
279
+ flex-direction: column;
280
+ box-sizing: border-box;
281
+ }
282
+
283
+ .label-content {
284
+ font-size: 0.7em;
285
+ margin: 0.5em 0.7em;
286
+ color: var(--Display__color--subtle);
287
+ }
288
+
289
+ .list-item {
290
+ box-sizing: border-box;
291
+ color: var(--Input__color);
292
+ margin: 0;
293
+ padding: 0.5em;
294
+ outline: none;
295
+ text-overflow: ellipsis;
296
+ transition: background-color 150ms, color 150ms;
297
+ white-space: nowrap;
298
+ }
299
+
300
+ .list-item:hover {
301
+ background-color: var(--Button__background-color--hover);
302
+ color: var(--Button__color--hover);
303
+ }
304
+
305
+ .list-item.selected {
306
+ background-color: var(--Input__background-color--selected);
307
+ color: var(--Input__color--selected);
308
+ }
309
+
310
+ .list-item.disabled {
311
+ color: var(--Input__color--disabled);
312
+ }
313
+ </style>
@@ -0,0 +1,59 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ declare const __propDef: {
3
+ props: {
4
+ [x: string]: any;
5
+ disabled?: boolean | undefined;
6
+ items?: any[] | undefined;
7
+ horizontal?: boolean | undefined;
8
+ selectedIndex?: number | undefined;
9
+ selectedItem?: any;
10
+ focusSelectedItem?: (() => void) | undefined;
11
+ selectPreviousItem?: (() => void) | undefined;
12
+ selectNextItem?: (() => void) | undefined;
13
+ };
14
+ events: {
15
+ blur: FocusEvent;
16
+ click: MouseEvent;
17
+ copy: ClipboardEvent;
18
+ cut: ClipboardEvent;
19
+ dblclick: MouseEvent;
20
+ focus: FocusEvent;
21
+ focusin: FocusEvent;
22
+ focusout: FocusEvent;
23
+ keydown: KeyboardEvent;
24
+ keypress: KeyboardEvent;
25
+ keyup: KeyboardEvent;
26
+ mousedown: MouseEvent;
27
+ mouseenter: MouseEvent;
28
+ mouseleave: MouseEvent;
29
+ mousemove: MouseEvent;
30
+ mouseover: MouseEvent;
31
+ mouseout: MouseEvent;
32
+ mouseup: MouseEvent;
33
+ scroll: Event;
34
+ wheel: WheelEvent;
35
+ paste: ClipboardEvent;
36
+ itemSelected: CustomEvent<any>;
37
+ } & {
38
+ [evt: string]: CustomEvent<any>;
39
+ };
40
+ slots: {
41
+ label: {};
42
+ default: {
43
+ disabled: boolean;
44
+ index: any;
45
+ item: any;
46
+ selected: any;
47
+ };
48
+ };
49
+ };
50
+ export type ListProps = typeof __propDef.props;
51
+ export type ListEvents = typeof __propDef.events;
52
+ export type ListSlots = typeof __propDef.slots;
53
+ /** A list of items where a single item can be selected. */
54
+ export default class List extends SvelteComponentTyped<ListProps, ListEvents, ListSlots> {
55
+ get focusSelectedItem(): () => void;
56
+ get selectPreviousItem(): () => void;
57
+ get selectNextItem(): () => void;
58
+ }
59
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geoffcox/sterling-svelte",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
4
4
  "devDependencies": {
5
5
  "@fontsource/fira-mono": "^4.5.10",
6
6
  "@fontsource/overpass": "^4.5.10",
@@ -24,15 +24,13 @@ export const darkTheme = {
24
24
  '--Common__background-color--disabled': neutrals.neutral45,
25
25
  '--Common__border-color--disabled': neutrals.neutral92,
26
26
  '--Common__color--disabled': neutrals.neutral92,
27
- // ----- BaseLayer ---- //
28
- '--BaseLayer__background-color': neutrals.neutral15,
29
- '--BaseLayer__color': neutrals.neutral100,
30
- '--BaseLayer__background-color--1': neutrals.neutral30,
31
- '--BaseLayer__color--1': neutrals.neutral100,
32
- '--BaseLayer__background-color--2': neutrals.neutral45,
33
- '--BaseLayer__color--2': neutrals.neutral100,
34
- '--BaseLayer__background-color--3': neutrals.neutral60,
35
- '--BaseLayer__color--3': neutrals.neutral100,
27
+ // ----- Layer ---- //
28
+ '--Layer__background-color--1': neutrals.neutral30,
29
+ '--Layer__color--1': neutrals.neutral100,
30
+ '--Layer__background-color--2': neutrals.neutral45,
31
+ '--Layer__color--2': neutrals.neutral100,
32
+ '--Layer__background-color--3': neutrals.neutral60,
33
+ '--Layer__color--3': neutrals.neutral100,
36
34
  // ----- Button ----- //
37
35
  '--Button__background-color': neutrals.neutral45,
38
36
  '--Button__border-color': neutrals.neutral92,
@@ -80,7 +78,7 @@ export const darkTheme = {
80
78
  '--Input__border-color--disabled': neutrals.neutral85,
81
79
  '--Input__color--disabled': neutrals.neutral85,
82
80
  // ----- Display ----- //
83
- '--Display__background-color': neutrals.neutral60,
81
+ '--Display__background-color': neutrals.neutral30,
84
82
  '--Display__border-color': neutrals.neutral92,
85
83
  '--Display__color': neutrals.neutral100,
86
84
  '--Display__color--subtle': neutrals.neutral96,
@@ -24,15 +24,13 @@ export const lightTheme = {
24
24
  '--Common__background-color--disabled': neutrals.neutral96,
25
25
  '--Common__border-color--disabled': neutrals.neutral60,
26
26
  '--Common__color--disabled': neutrals.neutral60,
27
- // ----- BaseLayer ---- //
28
- '--BaseLayer__background-color': neutrals.neutral100,
29
- '--BaseLayer__color': neutrals.neutral15,
30
- '--BaseLayer__background-color--1': neutrals.neutral98,
31
- '--BaseLayer__color--1': neutrals.neutral15,
32
- '--BaseLayer__background-color--2': neutrals.neutral96,
33
- '--BaseLayer__color--2': neutrals.neutral15,
34
- '--BaseLayer__background-color--3': neutrals.neutral92,
35
- '--BaseLayer__color--3': neutrals.neutral15,
27
+ // ----- Layer ---- //
28
+ '--Layer__background-color--1': neutrals.neutral98,
29
+ '--Layer__color--1': neutrals.neutral15,
30
+ '--Layer__background-color--2': neutrals.neutral96,
31
+ '--Layer__color--2': neutrals.neutral15,
32
+ '--Layer__background-color--3': neutrals.neutral92,
33
+ '--Layer__color--3': neutrals.neutral15,
36
34
  // ----- Button ----- //
37
35
  '--Button__background-color': neutrals.neutral96,
38
36
  '--Button__border-color': neutrals.neutral60,