@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.
Files changed (86) hide show
  1. package/Button.svelte +79 -24
  2. package/Button.svelte.d.ts +1 -0
  3. package/Checkbox.svelte +44 -19
  4. package/Checkbox.svelte.d.ts +1 -0
  5. package/ColorPicker.constants.d.ts +1 -0
  6. package/ColorPicker.constants.js +1 -0
  7. package/ColorPicker.svelte +226 -0
  8. package/ColorPicker.svelte.d.ts +22 -0
  9. package/ColorPicker.types.d.ts +4 -0
  10. package/ColorPicker.types.js +1 -0
  11. package/Dialog.svelte +10 -10
  12. package/Dropdown.svelte +88 -47
  13. package/Dropdown.svelte.d.ts +4 -0
  14. package/Field.svelte +34 -46
  15. package/HexColorSliders.svelte +150 -0
  16. package/HexColorSliders.svelte.d.ts +22 -0
  17. package/HslColorSliders.svelte +187 -0
  18. package/HslColorSliders.svelte.d.ts +22 -0
  19. package/Input.svelte +49 -21
  20. package/Input.svelte.d.ts +2 -1
  21. package/Label.svelte +3 -3
  22. package/Link.svelte +63 -17
  23. package/Link.svelte.d.ts +1 -0
  24. package/List.svelte +31 -30
  25. package/List.svelte.d.ts +1 -0
  26. package/List.types.d.ts +4 -3
  27. package/ListItem.svelte +29 -10
  28. package/ListItem.svelte.d.ts +1 -1
  29. package/Menu.svelte +92 -121
  30. package/Menu.svelte.d.ts +8 -2
  31. package/MenuBar.svelte +77 -32
  32. package/MenuBar.types.d.ts +2 -2
  33. package/MenuButton.svelte +48 -28
  34. package/MenuItem.constants.d.ts +1 -0
  35. package/MenuItem.constants.js +1 -0
  36. package/MenuItem.svelte +202 -139
  37. package/MenuItem.svelte.d.ts +7 -3
  38. package/MenuItem.types.d.ts +14 -5
  39. package/MenuItem.utils.d.ts +2 -0
  40. package/MenuItem.utils.js +16 -0
  41. package/MenuItemDisplay.svelte +9 -2
  42. package/MenuItemDisplay.svelte.d.ts +1 -0
  43. package/MenuSeparator.svelte +3 -3
  44. package/Popover.svelte +68 -64
  45. package/Popover.svelte.d.ts +4 -2
  46. package/Progress.svelte +14 -14
  47. package/Radio.svelte +42 -16
  48. package/Radio.svelte.d.ts +1 -0
  49. package/RgbColorSliders.svelte +161 -0
  50. package/RgbColorSliders.svelte.d.ts +22 -0
  51. package/Select.svelte +50 -32
  52. package/Slider.svelte +108 -118
  53. package/Slider.svelte.d.ts +1 -0
  54. package/Switch.svelte +97 -34
  55. package/Switch.svelte.d.ts +1 -0
  56. package/Tab.svelte +53 -30
  57. package/TabList.svelte +23 -28
  58. package/TabList.svelte.d.ts +1 -0
  59. package/TabList.types.d.ts +1 -1
  60. package/TextArea.svelte +45 -20
  61. package/TextArea.svelte.d.ts +3 -2
  62. package/Tooltip.svelte +12 -11
  63. package/Tree.svelte +37 -35
  64. package/Tree.svelte.d.ts +2 -0
  65. package/Tree.types.d.ts +1 -0
  66. package/TreeChevron.svelte +1 -1
  67. package/TreeItem.svelte +47 -10
  68. package/TreeItem.svelte.d.ts +2 -0
  69. package/TreeItemDisplay.svelte +26 -8
  70. package/TreeItemDisplay.svelte.d.ts +2 -0
  71. package/actions/clickOutside.js +1 -1
  72. package/actions/trapKeyboardFocus.d.ts +3 -0
  73. package/actions/trapKeyboardFocus.js +52 -0
  74. package/floating-ui.types.d.ts +2 -0
  75. package/index.d.ts +10 -5
  76. package/index.js +8 -3
  77. package/package.json +12 -1
  78. package/stores/prefersReducedMotion.d.ts +1 -0
  79. package/stores/prefersReducedMotion.js +10 -0
  80. package/stores/usingKeyboard.d.ts +1 -0
  81. package/stores/usingKeyboard.js +13 -0
  82. package/theme/applyTheme.js +3 -2
  83. package/theme/colors.d.ts +1 -0
  84. package/theme/colors.js +28 -13
  85. package/theme/darkTheme.js +130 -87
  86. package/theme/lightTheme.js +107 -87
package/MenuItem.svelte CHANGED
@@ -1,50 +1,61 @@
1
- <script>import { createKeyborg } from "keyborg";
2
- import { getContext, onMount, setContext } from "svelte";
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 { clickOutside } from "./actions/clickOutside";
5
- import { afterUpdate, createEventDispatcher } from "svelte/internal";
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 Menu from "./Menu.svelte";
10
- import {
11
- focusFirstChild,
12
- focusLastChild,
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
- register = void 0,
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 { openPreviousMenu = void 0, openNextMenu = void 0 } = getContext(MENU_BAR_CONTEXT_KEY) || {};
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
- let keyborg = createKeyborg(window);
68
- let usingKeyboard = keyborg.isNavigatingWithKeyboard();
69
- const keyborgHandler = (value2) => {
70
- usingKeyboard = value2;
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 autoFocusFirstChild = (open2, insideMenu) => {
73
- if (open2 && insideMenu) {
74
- setTimeout(() => focusFirstChild($children), 10);
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
- autoFocusFirstChild(open, depth > 0);
79
- export const click = () => {
80
- menuItemRef?.click();
100
+ const openMenu = () => {
101
+ if (!$openValues.includes(value)) {
102
+ openValues.set([...$openValues.slice(0, depth), value]);
103
+ }
81
104
  };
82
- export const blur = () => {
83
- menuItemRef?.blur();
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
- export const focus = (options) => {
86
- menuItemRef?.focus(options);
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 (depth === 0 && hasChildren) {
117
- open = true;
118
- setTimeout(() => focusFirstChild($children), 10);
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
- } else if (depth > 0) {
122
- focusNext?.(value);
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 (depth < 2) {
129
- open = false;
130
- closeMenu?.(true);
131
- openPreviousMenu?.(rootValue);
132
- } else {
133
- closeMenu?.();
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 (depth > 0 && hasChildren) {
139
- open = true;
140
- setTimeout(focusFirstChild, 10);
141
- } else {
142
- open = false;
143
- closeMenu?.(true);
144
- openNextMenu?.(rootValue);
161
+ if (isMenuBarItem) {
162
+ focusNextMenuItem();
163
+ event.preventDefault();
164
+ event.stopPropagation();
165
+ return false;
145
166
  }
146
- event.preventDefault();
147
- return false;
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 (depth === 0 && hasChildren) {
150
- open = true;
151
- setTimeout(() => focusLastChild($children), 10);
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
- } else if (depth > 0) {
155
- focusPrevious?.(value);
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
- closeMenu?.(true);
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
- setTimeout(() => {
169
- menuItemRef?.focus();
170
- }, 10);
212
+ menuItemRef?.focus();
171
213
  };
172
- const onMenuItemClick = (event) => {
214
+ const onClick = (event) => {
173
215
  if (!disabled) {
174
216
  if (hasChildren) {
175
- open = !open;
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
- closeMenu?.(true);
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
- register: (menuItem) => {
202
- children.set([...$children, menuItem]);
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={onMenuItemClick}
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 name="item" {checked} {depth} {disabled} {hasChildren} {open} {role} {text} {value}>
280
- <MenuItemDisplay
281
- {checked}
282
- {disabled}
283
- hasChildren={depth > 0 && hasChildren}
284
- menuItemRole={role}>{text}</MenuItemDisplay
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
- <Menu id={menuId} {open} reference={menuItemRef}>
290
- <slot {depth} {disabled} />
291
- </Menu>
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-Button__border-radius);
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-Common__color);
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-Button__background-color--hover);
320
- color: var(--stsv-Button__color--hover);
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-Button__border-color--focus);
329
- outline-color: var(--stsv-Common__outline-color);
330
- outline-offset: var(--stsv-Common__outline-offset);
331
- outline-style: var(--stsv-Common__outline-style);
332
- outline-width: var(--stsv-Common__outline-width);
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-Input__background-color--selected);
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,
@@ -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 {};
@@ -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
- register?: (menuItem: MenuItemRegistration) => void;
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 {};
@@ -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
+ };
@@ -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: var(--stsv-Disabled__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;
@@ -4,6 +4,7 @@ declare const __propDef: {
4
4
  checked?: boolean | undefined;
5
5
  disabled?: boolean | undefined;
6
6
  hasChildren?: boolean | undefined;
7
+ isMenuBarItem?: boolean | undefined;
7
8
  menuItemRole?: "menuitem" | "menuitemcheckbox" | "menuitemradio" | undefined;
8
9
  };
9
10
  events: {
@@ -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-Common__border-width);
45
- background-color: var(--stsv-Common__border-color);
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>