@geoffcox/sterling-svelte 0.0.25 → 0.0.27
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.
- package/Button.svelte +79 -24
- package/Button.svelte.d.ts +1 -0
- package/Checkbox.svelte +44 -19
- package/Checkbox.svelte.d.ts +1 -0
- package/ColorPicker.constants.d.ts +1 -0
- package/ColorPicker.constants.js +1 -0
- package/ColorPicker.svelte +226 -0
- package/ColorPicker.svelte.d.ts +22 -0
- package/ColorPicker.types.d.ts +4 -0
- package/ColorPicker.types.js +1 -0
- package/Dialog.svelte +10 -10
- package/Dropdown.svelte +88 -47
- package/Dropdown.svelte.d.ts +4 -0
- package/Field.svelte +34 -46
- package/HexColorSliders.svelte +150 -0
- package/HexColorSliders.svelte.d.ts +22 -0
- package/HslColorSliders.svelte +187 -0
- package/HslColorSliders.svelte.d.ts +22 -0
- package/Input.svelte +49 -21
- package/Input.svelte.d.ts +2 -1
- package/Label.svelte +3 -3
- package/Link.svelte +63 -17
- package/Link.svelte.d.ts +1 -0
- package/List.svelte +31 -30
- package/List.svelte.d.ts +1 -0
- package/List.types.d.ts +4 -3
- package/ListItem.svelte +29 -10
- package/ListItem.svelte.d.ts +1 -1
- package/Menu.svelte +92 -121
- package/Menu.svelte.d.ts +8 -2
- package/MenuBar.svelte +77 -32
- package/MenuBar.types.d.ts +2 -2
- package/MenuButton.svelte +48 -28
- package/MenuItem.constants.d.ts +1 -0
- package/MenuItem.constants.js +1 -0
- package/MenuItem.svelte +202 -139
- package/MenuItem.svelte.d.ts +7 -3
- package/MenuItem.types.d.ts +14 -5
- package/MenuItem.utils.d.ts +2 -0
- package/MenuItem.utils.js +16 -0
- package/MenuItemDisplay.svelte +9 -2
- package/MenuItemDisplay.svelte.d.ts +1 -0
- package/MenuSeparator.svelte +3 -3
- package/Popover.svelte +68 -64
- package/Popover.svelte.d.ts +4 -2
- package/Progress.svelte +14 -14
- package/Radio.svelte +42 -16
- package/Radio.svelte.d.ts +1 -0
- package/RgbColorSliders.svelte +161 -0
- package/RgbColorSliders.svelte.d.ts +22 -0
- package/Select.svelte +50 -32
- package/Slider.svelte +108 -118
- package/Slider.svelte.d.ts +1 -0
- package/Switch.svelte +97 -34
- package/Switch.svelte.d.ts +1 -0
- package/Tab.svelte +53 -30
- package/TabList.svelte +23 -28
- package/TabList.svelte.d.ts +1 -0
- package/TabList.types.d.ts +1 -1
- package/TextArea.svelte +45 -20
- package/TextArea.svelte.d.ts +3 -2
- package/Tooltip.svelte +12 -11
- package/Tree.svelte +37 -35
- package/Tree.svelte.d.ts +2 -0
- package/Tree.types.d.ts +1 -0
- package/TreeChevron.svelte +1 -1
- package/TreeItem.svelte +47 -10
- package/TreeItem.svelte.d.ts +2 -0
- package/TreeItemDisplay.svelte +26 -8
- package/TreeItemDisplay.svelte.d.ts +2 -0
- package/actions/clickOutside.js +1 -1
- package/actions/trapKeyboardFocus.d.ts +3 -0
- package/actions/trapKeyboardFocus.js +52 -0
- package/floating-ui.types.d.ts +2 -0
- package/index.d.ts +10 -5
- package/index.js +8 -3
- package/package.json +12 -1
- package/stores/prefersReducedMotion.d.ts +1 -0
- package/stores/prefersReducedMotion.js +10 -0
- package/stores/usingKeyboard.d.ts +1 -0
- package/stores/usingKeyboard.js +13 -0
- package/theme/applyTheme.js +3 -2
- package/theme/colors.d.ts +1 -0
- package/theme/colors.js +28 -13
- package/theme/darkTheme.js +130 -87
- package/theme/lightTheme.js +107 -87
package/MenuItem.svelte
CHANGED
|
@@ -1,50 +1,61 @@
|
|
|
1
|
-
<script>import {
|
|
2
|
-
|
|
1
|
+
<script>import {
|
|
2
|
+
getContext,
|
|
3
|
+
afterUpdate,
|
|
4
|
+
createEventDispatcher,
|
|
5
|
+
onMount,
|
|
6
|
+
setContext,
|
|
7
|
+
tick
|
|
8
|
+
} from "svelte";
|
|
3
9
|
import { writable } from "svelte/store";
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
import MenuItemDisplay from "./MenuItemDisplay.svelte";
|
|
10
|
+
import { idGenerator } from "./idGenerator";
|
|
11
|
+
import Menu from "./Menu.svelte";
|
|
7
12
|
import { MENU_BAR_CONTEXT_KEY } from "./MenuBar.constants";
|
|
8
13
|
import { MENU_ITEM_CONTEXT_KEY } from "./MenuItem.constants";
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
focusNextChild,
|
|
14
|
-
focusPreviousChild
|
|
15
|
-
} from "./MenuItem.utils";
|
|
16
|
-
import { idGenerator } from "./idGenerator";
|
|
14
|
+
import { isElementEnabledMenuItem } from "./MenuItem.utils";
|
|
15
|
+
import MenuItemDisplay from "./MenuItemDisplay.svelte";
|
|
16
|
+
import Popover from "./Popover.svelte";
|
|
17
|
+
import { usingKeyboard } from "./stores/usingKeyboard";
|
|
17
18
|
export let checked = false;
|
|
19
|
+
export let colorful = false;
|
|
18
20
|
export let composed = false;
|
|
19
21
|
export let disabled = false;
|
|
20
|
-
export let open = false;
|
|
21
22
|
export let value;
|
|
22
23
|
export let role = "menuitem";
|
|
23
24
|
export let text = void 0;
|
|
24
25
|
const {
|
|
26
|
+
isMenuBarItem,
|
|
27
|
+
openValues = writable([]),
|
|
25
28
|
rootValue = value,
|
|
26
29
|
depth = 0,
|
|
27
|
-
|
|
28
|
-
unregister = void 0,
|
|
29
|
-
closeMenu = void 0,
|
|
30
|
-
focusPrevious = void 0,
|
|
31
|
-
focusNext = void 0,
|
|
30
|
+
closeContainingMenu = void 0,
|
|
32
31
|
onOpen = void 0,
|
|
33
32
|
onClose = void 0,
|
|
34
33
|
onSelect = void 0
|
|
35
34
|
} = getContext(MENU_ITEM_CONTEXT_KEY) || {};
|
|
36
|
-
const {
|
|
35
|
+
const { openPreviousMenuBarItem = void 0, openNextMenuBarItem = void 0 } = getContext(MENU_BAR_CONTEXT_KEY) || {};
|
|
37
36
|
const instanceId = idGenerator.nextId("MenuItem");
|
|
38
37
|
$:
|
|
39
38
|
displayId = `${value}-display-${instanceId}`;
|
|
39
|
+
$:
|
|
40
|
+
open = $openValues.includes(value);
|
|
40
41
|
$:
|
|
41
42
|
menuId = `${value}-menu-${instanceId}`;
|
|
42
43
|
let menuItemRef;
|
|
44
|
+
let menuRef;
|
|
43
45
|
const children = writable([]);
|
|
44
46
|
let mounted = false;
|
|
45
47
|
let prevOpen = open;
|
|
46
48
|
$:
|
|
47
49
|
hasChildren = $$slots.default;
|
|
50
|
+
export const blur = () => {
|
|
51
|
+
menuItemRef?.blur();
|
|
52
|
+
};
|
|
53
|
+
export const click = () => {
|
|
54
|
+
menuItemRef?.click();
|
|
55
|
+
};
|
|
56
|
+
export const focus = (options) => {
|
|
57
|
+
menuItemRef?.focus(options);
|
|
58
|
+
};
|
|
48
59
|
const dispatch = createEventDispatcher();
|
|
49
60
|
const raiseClose = (value2) => {
|
|
50
61
|
dispatch("close", { value: value2 });
|
|
@@ -64,157 +75,176 @@ const raiseSelect = (value2) => {
|
|
|
64
75
|
dispatch("select", { value: value2 });
|
|
65
76
|
onSelect?.(value2);
|
|
66
77
|
};
|
|
67
|
-
|
|
68
|
-
let
|
|
69
|
-
|
|
70
|
-
|
|
78
|
+
const focusPreviousMenuItem = () => {
|
|
79
|
+
let candidate = menuItemRef?.previousElementSibling || menuItemRef?.parentElement?.lastElementChild;
|
|
80
|
+
while (candidate && !isElementEnabledMenuItem(candidate)) {
|
|
81
|
+
candidate = candidate.previousElementSibling || menuItemRef?.parentElement?.lastElementChild;
|
|
82
|
+
if (candidate === menuItemRef) {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
candidate?.focus();
|
|
87
|
+
return !!candidate;
|
|
71
88
|
};
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
89
|
+
const focusNextMenuItem = () => {
|
|
90
|
+
let candidate = menuItemRef?.nextElementSibling || menuItemRef?.parentElement?.firstElementChild;
|
|
91
|
+
while (candidate && !isElementEnabledMenuItem(candidate)) {
|
|
92
|
+
candidate = candidate.nextElementSibling || menuItemRef?.parentElement?.firstElementChild;
|
|
93
|
+
if (candidate === menuItemRef) {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
75
96
|
}
|
|
97
|
+
candidate?.focus();
|
|
98
|
+
return !!candidate;
|
|
76
99
|
};
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
100
|
+
const openMenu = () => {
|
|
101
|
+
if (!$openValues.includes(value)) {
|
|
102
|
+
openValues.set([...$openValues.slice(0, depth), value]);
|
|
103
|
+
}
|
|
81
104
|
};
|
|
82
|
-
|
|
83
|
-
|
|
105
|
+
const closeMenu = async () => {
|
|
106
|
+
const index = $openValues.indexOf(value);
|
|
107
|
+
if (index !== -1) {
|
|
108
|
+
openValues.set([...$openValues.slice(0, index)]);
|
|
109
|
+
await tick();
|
|
110
|
+
menuItemRef?.focus();
|
|
111
|
+
}
|
|
84
112
|
};
|
|
85
|
-
|
|
86
|
-
|
|
113
|
+
const closeAllMenus = () => {
|
|
114
|
+
openValues.set([]);
|
|
87
115
|
};
|
|
88
116
|
onMount(() => {
|
|
89
117
|
mounted = true;
|
|
90
|
-
keyborg.subscribe(keyborgHandler);
|
|
91
|
-
const menuItemSelf = {
|
|
92
|
-
value,
|
|
93
|
-
open: () => {
|
|
94
|
-
open = true;
|
|
95
|
-
},
|
|
96
|
-
close: () => {
|
|
97
|
-
open = false;
|
|
98
|
-
},
|
|
99
|
-
focus: () => {
|
|
100
|
-
menuItemRef?.focus();
|
|
101
|
-
}
|
|
102
|
-
};
|
|
103
|
-
register?.(menuItemSelf);
|
|
104
|
-
return () => {
|
|
105
|
-
keyborg.unsubscribe(keyborgHandler);
|
|
106
|
-
unregister?.(menuItemSelf);
|
|
107
|
-
};
|
|
108
118
|
});
|
|
109
119
|
afterUpdate(() => {
|
|
110
120
|
prevOpen = open;
|
|
111
121
|
});
|
|
112
|
-
const onKeyDown = (event) => {
|
|
122
|
+
const onKeyDown = async (event) => {
|
|
113
123
|
if (!disabled && !event.altKey && !event.ctrlKey && !event.shiftKey) {
|
|
114
124
|
switch (event.key) {
|
|
115
125
|
case "ArrowDown":
|
|
116
|
-
if (
|
|
117
|
-
|
|
118
|
-
setTimeout(() =>
|
|
126
|
+
if (isMenuBarItem && hasChildren) {
|
|
127
|
+
openMenu();
|
|
128
|
+
setTimeout(async () => {
|
|
129
|
+
await tick();
|
|
130
|
+
menuRef?.focusFirstMenuItem();
|
|
131
|
+
}, 10);
|
|
119
132
|
event.preventDefault();
|
|
133
|
+
event.stopPropagation();
|
|
120
134
|
return false;
|
|
121
|
-
}
|
|
122
|
-
|
|
135
|
+
}
|
|
136
|
+
if (!isMenuBarItem) {
|
|
137
|
+
focusNextMenuItem();
|
|
123
138
|
event.preventDefault();
|
|
139
|
+
event.stopPropagation();
|
|
124
140
|
return false;
|
|
125
141
|
}
|
|
126
142
|
break;
|
|
127
143
|
case "ArrowLeft":
|
|
128
|
-
if (
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
144
|
+
if (isMenuBarItem) {
|
|
145
|
+
focusPreviousMenuItem();
|
|
146
|
+
event.preventDefault();
|
|
147
|
+
event.stopPropagation();
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
if (depth > 1) {
|
|
151
|
+
closeContainingMenu?.();
|
|
152
|
+
event.preventDefault();
|
|
153
|
+
event.stopPropagation();
|
|
154
|
+
return false;
|
|
134
155
|
}
|
|
156
|
+
openPreviousMenuBarItem?.();
|
|
135
157
|
event.preventDefault();
|
|
158
|
+
event.stopPropagation();
|
|
136
159
|
return false;
|
|
137
160
|
case "ArrowRight":
|
|
138
|
-
if (
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
closeMenu?.(true);
|
|
144
|
-
openNextMenu?.(rootValue);
|
|
161
|
+
if (isMenuBarItem) {
|
|
162
|
+
focusNextMenuItem();
|
|
163
|
+
event.preventDefault();
|
|
164
|
+
event.stopPropagation();
|
|
165
|
+
return false;
|
|
145
166
|
}
|
|
146
|
-
|
|
147
|
-
|
|
167
|
+
if (hasChildren) {
|
|
168
|
+
openMenu();
|
|
169
|
+
setTimeout(async () => {
|
|
170
|
+
await tick();
|
|
171
|
+
menuRef?.focusFirstMenuItem();
|
|
172
|
+
}, 10);
|
|
173
|
+
event.preventDefault();
|
|
174
|
+
event.stopPropagation();
|
|
175
|
+
return false;
|
|
176
|
+
}
|
|
177
|
+
if (openNextMenuBarItem) {
|
|
178
|
+
openNextMenuBarItem();
|
|
179
|
+
event.preventDefault();
|
|
180
|
+
event.stopPropagation();
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
break;
|
|
148
184
|
case "ArrowUp":
|
|
149
|
-
if (
|
|
150
|
-
|
|
151
|
-
setTimeout(() =>
|
|
185
|
+
if (isMenuBarItem && hasChildren) {
|
|
186
|
+
openMenu();
|
|
187
|
+
setTimeout(async () => {
|
|
188
|
+
await tick();
|
|
189
|
+
menuRef?.focusLastMenuItem();
|
|
190
|
+
}, 10);
|
|
152
191
|
event.preventDefault();
|
|
192
|
+
event.stopPropagation();
|
|
153
193
|
return false;
|
|
154
|
-
}
|
|
155
|
-
|
|
194
|
+
}
|
|
195
|
+
if (!isMenuBarItem) {
|
|
196
|
+
focusPreviousMenuItem();
|
|
156
197
|
event.preventDefault();
|
|
198
|
+
event.stopPropagation();
|
|
157
199
|
return false;
|
|
158
200
|
}
|
|
201
|
+
break;
|
|
159
202
|
case "Escape":
|
|
160
203
|
open = false;
|
|
161
|
-
|
|
204
|
+
closeAllMenus();
|
|
162
205
|
event.preventDefault();
|
|
206
|
+
event.stopPropagation();
|
|
163
207
|
return false;
|
|
164
208
|
}
|
|
165
209
|
}
|
|
166
210
|
};
|
|
167
211
|
const onMouseEnter = (event) => {
|
|
168
|
-
|
|
169
|
-
menuItemRef?.focus();
|
|
170
|
-
}, 10);
|
|
212
|
+
menuItemRef?.focus();
|
|
171
213
|
};
|
|
172
|
-
const
|
|
214
|
+
const onClick = (event) => {
|
|
173
215
|
if (!disabled) {
|
|
174
216
|
if (hasChildren) {
|
|
175
|
-
|
|
217
|
+
if (!$openValues.includes(value)) {
|
|
218
|
+
openMenu();
|
|
219
|
+
if ($usingKeyboard) {
|
|
220
|
+
setTimeout(async () => {
|
|
221
|
+
await tick();
|
|
222
|
+
menuRef?.focusFirstMenuItem();
|
|
223
|
+
}, 10);
|
|
224
|
+
}
|
|
225
|
+
} else {
|
|
226
|
+
closeMenu();
|
|
227
|
+
}
|
|
176
228
|
event.preventDefault();
|
|
177
229
|
event.stopPropagation();
|
|
178
230
|
return false;
|
|
179
231
|
} else {
|
|
180
232
|
raiseSelect(value);
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
const onClickOutside = (event) => {
|
|
186
|
-
const {
|
|
187
|
-
detail: { mouseEvent }
|
|
188
|
-
} = event;
|
|
189
|
-
let element = mouseEvent.target;
|
|
190
|
-
while (element) {
|
|
191
|
-
if (element.getAttribute("data-root-value") === rootValue) {
|
|
192
|
-
return;
|
|
233
|
+
closeAllMenus();
|
|
234
|
+
event.preventDefault();
|
|
235
|
+
event.stopPropagation();
|
|
236
|
+
return false;
|
|
193
237
|
}
|
|
194
|
-
element = element.parentElement;
|
|
195
238
|
}
|
|
196
|
-
closeMenu?.(true);
|
|
197
239
|
};
|
|
198
240
|
setContext(MENU_ITEM_CONTEXT_KEY, {
|
|
241
|
+
isMenuBarItem: false,
|
|
242
|
+
openValues,
|
|
199
243
|
rootValue,
|
|
200
244
|
depth: depth + 1,
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
},
|
|
204
|
-
unregister: (menuItem) => {
|
|
205
|
-
children.set($children.filter((x) => x.value !== menuItem.value));
|
|
206
|
-
},
|
|
207
|
-
closeMenu: (recursive) => {
|
|
208
|
-
open = false;
|
|
209
|
-
if (recursive) {
|
|
210
|
-
closeMenu?.(recursive);
|
|
211
|
-
}
|
|
212
|
-
if (!recursive || depth === 0) {
|
|
213
|
-
menuItemRef?.focus();
|
|
214
|
-
}
|
|
245
|
+
closeContainingMenu: () => {
|
|
246
|
+
closeMenu();
|
|
215
247
|
},
|
|
216
|
-
focusPrevious: (currentValue) => focusPreviousChild($children, currentValue),
|
|
217
|
-
focusNext: (currentValue) => focusNextChild($children, currentValue),
|
|
218
248
|
onOpen: raiseOpen,
|
|
219
249
|
onClose: raiseClose,
|
|
220
250
|
onSelect: raiseSelect
|
|
@@ -229,15 +259,15 @@ setContext(MENU_ITEM_CONTEXT_KEY, {
|
|
|
229
259
|
aria-owns={menuId}
|
|
230
260
|
bind:this={menuItemRef}
|
|
231
261
|
class="sterling-menu-item"
|
|
262
|
+
class:colorful
|
|
232
263
|
class:composed
|
|
233
|
-
class:disabled
|
|
234
264
|
class:using-keyboard={usingKeyboard}
|
|
235
265
|
data-value={value}
|
|
236
266
|
data-root-value={rootValue}
|
|
267
|
+
{disabled}
|
|
237
268
|
{role}
|
|
238
269
|
tabindex={0}
|
|
239
270
|
type="button"
|
|
240
|
-
use:clickOutside
|
|
241
271
|
on:blur
|
|
242
272
|
on:click
|
|
243
273
|
on:dblclick
|
|
@@ -268,27 +298,40 @@ setContext(MENU_ITEM_CONTEXT_KEY, {
|
|
|
268
298
|
on:pointerover
|
|
269
299
|
on:pointerout
|
|
270
300
|
on:pointerup
|
|
271
|
-
on:wheel
|
|
272
|
-
on:click={
|
|
273
|
-
on:click_outside={onClickOutside}
|
|
301
|
+
on:wheel|passive
|
|
302
|
+
on:click={onClick}
|
|
274
303
|
on:keydown={onKeyDown}
|
|
275
304
|
on:mouseenter={onMouseEnter}
|
|
276
305
|
{...$$restProps}
|
|
277
306
|
>
|
|
278
307
|
<div class="item" id={displayId}>
|
|
279
|
-
<slot
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
308
|
+
<slot
|
|
309
|
+
name="item"
|
|
310
|
+
{checked}
|
|
311
|
+
{depth}
|
|
312
|
+
{disabled}
|
|
313
|
+
{hasChildren}
|
|
314
|
+
{isMenuBarItem}
|
|
315
|
+
{open}
|
|
316
|
+
{role}
|
|
317
|
+
{text}
|
|
318
|
+
{value}
|
|
319
|
+
>
|
|
320
|
+
<MenuItemDisplay {checked} {disabled} {hasChildren} {isMenuBarItem} menuItemRole={role}
|
|
321
|
+
>{text}</MenuItemDisplay
|
|
285
322
|
>
|
|
286
323
|
</slot>
|
|
287
324
|
</div>
|
|
288
325
|
{#if menuItemRef && open && hasChildren}
|
|
289
|
-
<
|
|
290
|
-
|
|
291
|
-
|
|
326
|
+
<Popover
|
|
327
|
+
reference={menuItemRef}
|
|
328
|
+
placement={isMenuBarItem ? 'bottom-start' : 'right-start'}
|
|
329
|
+
{open}
|
|
330
|
+
>
|
|
331
|
+
<Menu bind:this={menuRef} id={menuId}>
|
|
332
|
+
<slot {depth} {disabled} />
|
|
333
|
+
</Menu>
|
|
334
|
+
</Popover>
|
|
292
335
|
{/if}
|
|
293
336
|
</button>
|
|
294
337
|
|
|
@@ -296,11 +339,11 @@ setContext(MENU_ITEM_CONTEXT_KEY, {
|
|
|
296
339
|
.sterling-menu-item {
|
|
297
340
|
background-color: transparent;
|
|
298
341
|
border-color: transparent;
|
|
299
|
-
border-radius: var(--stsv-
|
|
342
|
+
border-radius: var(--stsv-button__border-radius);
|
|
300
343
|
border-style: none;
|
|
301
344
|
border-width: 0;
|
|
302
345
|
box-sizing: border-box;
|
|
303
|
-
color: var(--stsv-
|
|
346
|
+
color: var(--stsv-common__color);
|
|
304
347
|
cursor: pointer;
|
|
305
348
|
font: inherit;
|
|
306
349
|
margin: 0;
|
|
@@ -316,8 +359,8 @@ setContext(MENU_ITEM_CONTEXT_KEY, {
|
|
|
316
359
|
}
|
|
317
360
|
|
|
318
361
|
.sterling-menu-item:hover {
|
|
319
|
-
background-color: var(--stsv-
|
|
320
|
-
color: var(--stsv-
|
|
362
|
+
background-color: var(--stsv-button__background-color--hover);
|
|
363
|
+
color: var(--stsv-button__color--hover);
|
|
321
364
|
}
|
|
322
365
|
|
|
323
366
|
.sterling-menu-item:focus {
|
|
@@ -325,15 +368,35 @@ setContext(MENU_ITEM_CONTEXT_KEY, {
|
|
|
325
368
|
}
|
|
326
369
|
|
|
327
370
|
.sterling-menu-item.using-keyboard:focus {
|
|
328
|
-
border-color: var(--stsv-
|
|
329
|
-
outline-color: var(--stsv-
|
|
330
|
-
outline-offset: var(--stsv-
|
|
331
|
-
outline-style: var(--stsv-
|
|
332
|
-
outline-width: var(--stsv-
|
|
371
|
+
border-color: var(--stsv-button__border-color--focus);
|
|
372
|
+
outline-color: var(--stsv-common__outline-color);
|
|
373
|
+
outline-offset: var(--stsv-common__outline-offset);
|
|
374
|
+
outline-style: var(--stsv-common__outline-style);
|
|
375
|
+
outline-width: var(--stsv-common__outline-width);
|
|
333
376
|
}
|
|
334
377
|
|
|
335
378
|
.sterling-menu-item:focus {
|
|
336
|
-
background-color: var(--stsv-
|
|
379
|
+
background-color: var(--stsv-input__background-color--selected);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/** ----- colorful ----- */
|
|
383
|
+
|
|
384
|
+
.sterling-menu-item.colorful {
|
|
385
|
+
color: var(--stsv-common--colorful__color);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
.sterling-menu-item.colorful:hover {
|
|
389
|
+
background-color: var(--stsv-button--colorful__background-color--hover);
|
|
390
|
+
color: var(--stsv-button--colorful__color--hover);
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
.sterling-menu-item.colorful.using-keyboard:focus {
|
|
394
|
+
border-color: var(--stsv-button--colorful__border-color--focus);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
.sterling-menu-item.colorful:focus {
|
|
398
|
+
background-color: var(--stsv-button--colorful__background-color--focus);
|
|
399
|
+
color: var(--stsv-button--colorful__color--focus);
|
|
337
400
|
}
|
|
338
401
|
|
|
339
402
|
.sterling-menu-item.composed,
|
package/MenuItem.svelte.d.ts
CHANGED
|
@@ -3,14 +3,14 @@ declare const __propDef: {
|
|
|
3
3
|
props: {
|
|
4
4
|
[x: string]: any;
|
|
5
5
|
checked?: boolean | undefined;
|
|
6
|
+
colorful?: boolean | undefined;
|
|
6
7
|
composed?: boolean | undefined;
|
|
7
8
|
disabled?: boolean | undefined;
|
|
8
|
-
open?: boolean | undefined;
|
|
9
9
|
value: string;
|
|
10
10
|
role?: "menuitem" | "menuitemcheckbox" | "menuitemradio" | undefined;
|
|
11
11
|
text?: string | undefined;
|
|
12
|
-
click?: (() => void) | undefined;
|
|
13
12
|
blur?: (() => void) | undefined;
|
|
13
|
+
click?: (() => void) | undefined;
|
|
14
14
|
focus?: ((options?: FocusOptions) => void) | undefined;
|
|
15
15
|
};
|
|
16
16
|
events: {
|
|
@@ -45,6 +45,9 @@ declare const __propDef: {
|
|
|
45
45
|
pointerout: PointerEvent;
|
|
46
46
|
pointerup: PointerEvent;
|
|
47
47
|
wheel: WheelEvent;
|
|
48
|
+
close: CustomEvent<any>;
|
|
49
|
+
open: CustomEvent<any>;
|
|
50
|
+
select: CustomEvent<any>;
|
|
48
51
|
} & {
|
|
49
52
|
[evt: string]: CustomEvent<any>;
|
|
50
53
|
};
|
|
@@ -54,6 +57,7 @@ declare const __propDef: {
|
|
|
54
57
|
depth: number;
|
|
55
58
|
disabled: boolean;
|
|
56
59
|
hasChildren: boolean;
|
|
60
|
+
isMenuBarItem: boolean | undefined;
|
|
57
61
|
open: boolean;
|
|
58
62
|
role: "menuitem" | "menuitemcheckbox" | "menuitemradio";
|
|
59
63
|
text: string | undefined;
|
|
@@ -69,8 +73,8 @@ export type MenuItemProps = typeof __propDef.props;
|
|
|
69
73
|
export type MenuItemEvents = typeof __propDef.events;
|
|
70
74
|
export type MenuItemSlots = typeof __propDef.slots;
|
|
71
75
|
export default class MenuItem extends SvelteComponentTyped<MenuItemProps, MenuItemEvents, MenuItemSlots> {
|
|
72
|
-
get click(): () => void;
|
|
73
76
|
get blur(): () => void;
|
|
77
|
+
get click(): () => void;
|
|
74
78
|
get focus(): (options?: FocusOptions | undefined) => void;
|
|
75
79
|
}
|
|
76
80
|
export {};
|
package/MenuItem.types.d.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import type { Writable } from 'svelte/store';
|
|
2
|
+
import type { MENU_ITEM_ROLES } from './MenuItem.constants';
|
|
3
|
+
type MenuItemRoleTuple = typeof MENU_ITEM_ROLES;
|
|
4
|
+
export type MenuItemRole = MenuItemRoleTuple[number];
|
|
1
5
|
export type MenuItemRegistration = {
|
|
2
6
|
value: string;
|
|
3
7
|
open: () => void;
|
|
@@ -5,14 +9,19 @@ export type MenuItemRegistration = {
|
|
|
5
9
|
focus: () => void;
|
|
6
10
|
};
|
|
7
11
|
export type MenuItemContext = {
|
|
12
|
+
/**
|
|
13
|
+
* If the menu item is a top-elvel item in a menu bar
|
|
14
|
+
*/
|
|
15
|
+
isMenuBarItem?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* The menu item values for the chain of open menus.
|
|
18
|
+
*/
|
|
19
|
+
openValues: Writable<string[]>;
|
|
8
20
|
rootValue?: string;
|
|
9
21
|
depth?: number;
|
|
10
|
-
|
|
11
|
-
unregister?: (menuItem: MenuItemRegistration) => void;
|
|
12
|
-
focusPrevious?: (currentValue: string) => void;
|
|
13
|
-
focusNext?: (currentValue: string) => void;
|
|
14
|
-
closeMenu?: (recursive?: boolean) => void;
|
|
22
|
+
closeContainingMenu?: () => void;
|
|
15
23
|
onOpen?: (value: string) => void;
|
|
16
24
|
onClose?: (value: string) => void;
|
|
17
25
|
onSelect?: (value: string) => void;
|
|
18
26
|
};
|
|
27
|
+
export {};
|
package/MenuItem.utils.d.ts
CHANGED
|
@@ -3,3 +3,5 @@ export declare const focusPreviousChild: (children: MenuItemRegistration[], curr
|
|
|
3
3
|
export declare const focusNextChild: (children: MenuItemRegistration[], currentValue: string) => void;
|
|
4
4
|
export declare const focusFirstChild: (children: MenuItemRegistration[]) => void;
|
|
5
5
|
export declare const focusLastChild: (children: MenuItemRegistration[]) => void;
|
|
6
|
+
export declare const isElementMenuItem: (candidate: Element | null | undefined) => boolean;
|
|
7
|
+
export declare const isElementEnabledMenuItem: (candidate: Element | null | undefined) => boolean;
|
package/MenuItem.utils.js
CHANGED
|
@@ -18,3 +18,19 @@ export const focusFirstChild = (children) => {
|
|
|
18
18
|
export const focusLastChild = (children) => {
|
|
19
19
|
children?.[children.length - 1]?.focus();
|
|
20
20
|
};
|
|
21
|
+
export const isElementMenuItem = (candidate) => {
|
|
22
|
+
if (!candidate)
|
|
23
|
+
return false;
|
|
24
|
+
const dataValue = candidate?.getAttribute('data-value');
|
|
25
|
+
const role = candidate?.getAttribute('role');
|
|
26
|
+
return ((role === 'menuitem' || role === 'menuitemcheckbox' || role === 'menuitemradio') &&
|
|
27
|
+
dataValue !== null &&
|
|
28
|
+
dataValue !== undefined);
|
|
29
|
+
};
|
|
30
|
+
export const isElementEnabledMenuItem = (candidate) => {
|
|
31
|
+
if (!isElementMenuItem(candidate)) {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
const disabled = candidate?.getAttribute('disabled');
|
|
35
|
+
return disabled === null || disabled === 'false';
|
|
36
|
+
};
|
package/MenuItemDisplay.svelte
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script>export let checked = false;
|
|
2
2
|
export let disabled = false;
|
|
3
3
|
export let hasChildren = false;
|
|
4
|
+
export let isMenuBarItem = false;
|
|
4
5
|
export let menuItemRole = "menuitem";
|
|
5
6
|
</script>
|
|
6
7
|
|
|
@@ -19,7 +20,7 @@ export let menuItemRole = "menuitem";
|
|
|
19
20
|
<slot name="shortcut" />
|
|
20
21
|
</div>
|
|
21
22
|
{:else}
|
|
22
|
-
<div class="chevron" class:has-children={hasChildren} />
|
|
23
|
+
<div class="chevron" class:has-children={!isMenuBarItem && hasChildren} />
|
|
23
24
|
{/if}
|
|
24
25
|
</div>
|
|
25
26
|
|
|
@@ -102,7 +103,13 @@ export let menuItemRole = "menuitem";
|
|
|
102
103
|
}
|
|
103
104
|
|
|
104
105
|
.sterling-menu-item-display::after {
|
|
105
|
-
background:
|
|
106
|
+
background: repeating-linear-gradient(
|
|
107
|
+
45deg,
|
|
108
|
+
var(--stsv-common__background-color1--disabled),
|
|
109
|
+
var(--stsv-common__background-color1--disabled) 3px,
|
|
110
|
+
var(--stsv-common__background-color2--disabled) 3px,
|
|
111
|
+
var(--stsv-common__background-color2--disabled) 6px
|
|
112
|
+
);
|
|
106
113
|
bottom: 0;
|
|
107
114
|
content: '';
|
|
108
115
|
left: 0;
|
package/MenuSeparator.svelte
CHANGED
|
@@ -35,14 +35,14 @@ A styled line to visually separate menu items in a menu.
|
|
|
35
35
|
on:pointerover
|
|
36
36
|
on:pointerout
|
|
37
37
|
on:pointerup
|
|
38
|
-
on:wheel
|
|
38
|
+
on:wheel|passive
|
|
39
39
|
{...$$restProps}
|
|
40
40
|
/>
|
|
41
41
|
|
|
42
42
|
<style>
|
|
43
43
|
.sterling-menu-item-separator {
|
|
44
|
-
height: var(--stsv-
|
|
45
|
-
background-color: var(--stsv-
|
|
44
|
+
height: var(--stsv-common__border-width);
|
|
45
|
+
background-color: var(--stsv-common__border-color);
|
|
46
46
|
margin: 0.1em 0;
|
|
47
47
|
}
|
|
48
48
|
</style>
|