@limetech/lime-elements 40.6.1 → 40.6.2

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 (74) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/cjs/{component-CFk7Dfoi.js → component-Cz24PdGy.js} +3 -3
  3. package/dist/cjs/{component-BrNWuGdj.js → component-DNiVfYHV.js} +1 -1
  4. package/dist/cjs/{component-y8swlNNR.js → component-GW2n79GH.js} +1 -1
  5. package/dist/cjs/{component-UyqdiWGc.js → component-xiw46M1b.js} +1 -1
  6. package/dist/cjs/{isArrayLikeObject-BhSkOTkw.js → isArrayLikeObject-U2Ddbw4n.js} +0 -17
  7. package/dist/cjs/{keycodes-k-EdzcMX.js → keycodes-BQ_AERli.js} +4 -0
  8. package/dist/cjs/limel-breadcrumbs_6.cjs.entry.js +6 -6
  9. package/dist/cjs/limel-chip-set.cjs.entry.js +5 -5
  10. package/dist/cjs/limel-chip_2.cjs.entry.js +1 -1
  11. package/dist/cjs/limel-date-picker.cjs.entry.js +4 -4
  12. package/dist/cjs/limel-dialog.cjs.entry.js +2 -2
  13. package/dist/cjs/limel-form.cjs.entry.js +18 -2
  14. package/dist/cjs/limel-helper-line_3.cjs.entry.js +2 -2
  15. package/dist/cjs/limel-pagination-jump.cjs.entry.js +1 -1
  16. package/dist/cjs/limel-picker.cjs.entry.js +1 -1
  17. package/dist/cjs/limel-popover_2.cjs.entry.js +1 -1
  18. package/dist/cjs/limel-select.cjs.entry.js +3 -3
  19. package/dist/cjs/limel-tab-bar.cjs.entry.js +202 -1972
  20. package/dist/cjs/limel-text-editor-link-menu.cjs.entry.js +1 -1
  21. package/dist/cjs/{ponyfill-BgIFyUG5.js → ponyfill-CHp7Zocr.js} +0 -1
  22. package/dist/collection/components/tab-bar/tab-bar.js +61 -46
  23. package/dist/collection/util/keyboard-navigation.js +144 -0
  24. package/dist/collection/util/keycodes.js +2 -0
  25. package/dist/esm/{component-wGVqvUmL.js → component-CVihTrav.js} +3 -3
  26. package/dist/esm/{component-7QB0OUSF.js → component-CrjPGt1I.js} +1 -1
  27. package/dist/esm/{component-D4qgwaTf.js → component-CyFeUQ0l.js} +1 -1
  28. package/dist/esm/{component-B2Vy44Z3.js → component-kP1jCDLp.js} +1 -1
  29. package/dist/esm/{isArrayLikeObject-tmUOLOWr.js → isArrayLikeObject-CJB8HbtH.js} +1 -17
  30. package/dist/esm/{keycodes-C4_9qUMP.js → keycodes-DQ5DmW_Y.js} +3 -1
  31. package/dist/esm/limel-breadcrumbs_6.entry.js +6 -6
  32. package/dist/esm/limel-chip-set.entry.js +5 -5
  33. package/dist/esm/limel-chip_2.entry.js +1 -1
  34. package/dist/esm/limel-date-picker.entry.js +4 -4
  35. package/dist/esm/limel-dialog.entry.js +2 -2
  36. package/dist/esm/limel-form.entry.js +17 -1
  37. package/dist/esm/limel-helper-line_3.entry.js +2 -2
  38. package/dist/esm/limel-pagination-jump.entry.js +1 -1
  39. package/dist/esm/limel-picker.entry.js +1 -1
  40. package/dist/esm/limel-popover_2.entry.js +1 -1
  41. package/dist/esm/limel-select.entry.js +3 -3
  42. package/dist/esm/limel-tab-bar.entry.js +202 -1972
  43. package/dist/esm/limel-text-editor-link-menu.entry.js +1 -1
  44. package/dist/esm/{ponyfill-ChRGk668.js → ponyfill-6YuZiAPi.js} +1 -1
  45. package/dist/lime-elements/lime-elements.esm.js +1 -1
  46. package/dist/lime-elements/{p-6adc7c88.entry.js → p-02a06cf7.entry.js} +1 -1
  47. package/dist/lime-elements/{p-80153f45.entry.js → p-0ece667e.entry.js} +1 -1
  48. package/dist/lime-elements/p-107654bb.entry.js +13 -0
  49. package/dist/lime-elements/{p-440a0b43.entry.js → p-120ca628.entry.js} +1 -1
  50. package/dist/lime-elements/{p-BwJGg-WI.js → p-1CgnIGyd.js} +4 -4
  51. package/dist/lime-elements/{p-5386c629.entry.js → p-45461ec5.entry.js} +1 -1
  52. package/dist/lime-elements/{p-8988b7e1.entry.js → p-5e448070.entry.js} +1 -1
  53. package/dist/lime-elements/{p-ChRGk668.js → p-6YuZiAPi.js} +3 -3
  54. package/dist/lime-elements/{p-159603cf.entry.js → p-74060535.entry.js} +3 -3
  55. package/dist/lime-elements/{p-b6c0dc91.entry.js → p-7fa85785.entry.js} +2 -2
  56. package/dist/lime-elements/p-958396b5.entry.js +1 -0
  57. package/dist/lime-elements/{p-92669910.entry.js → p-970e0810.entry.js} +1 -1
  58. package/dist/lime-elements/p-9e084e7c.entry.js +1 -0
  59. package/dist/lime-elements/{p-BN1-aIOw.js → p-BZXGwiAr.js} +1 -1
  60. package/dist/lime-elements/{p-DZkKQUDM.js → p-C1FFnUvf.js} +3 -3
  61. package/dist/lime-elements/{p-C9yTLqR8.js → p-CmtleG1y.js} +1 -1
  62. package/dist/lime-elements/{p-C4_9qUMP.js → p-DQ5DmW_Y.js} +1 -1
  63. package/dist/lime-elements/{p-31f314e6.entry.js → p-a42f8c2d.entry.js} +1 -1
  64. package/dist/lime-elements/{p-f04e2897.entry.js → p-d1b7cc55.entry.js} +1 -1
  65. package/dist/lime-elements/p-pk5KIdKH.js +1 -0
  66. package/dist/types/components/tab-bar/tab-bar.d.ts +11 -6
  67. package/dist/types/components.d.ts +4 -0
  68. package/dist/types/util/keyboard-navigation.d.ts +105 -0
  69. package/dist/types/util/keycodes.d.ts +2 -0
  70. package/package.json +1 -1
  71. package/dist/lime-elements/p-31226737.entry.js +0 -13
  72. package/dist/lime-elements/p-4dfd1962.entry.js +0 -67
  73. package/dist/lime-elements/p-DWMfAkOE.js +0 -1
  74. package/dist/lime-elements/p-ab8021b9.entry.js +0 -1
@@ -2,7 +2,7 @@
2
2
 
3
3
  var index = require('./index-BlsqxTB1.js');
4
4
  var translations = require('./translations-CNTWud2a.js');
5
- var keycodes = require('./keycodes-k-EdzcMX.js');
5
+ var keycodes = require('./keycodes-BQ_AERli.js');
6
6
  require('./language-v-MMS6ym.js');
7
7
 
8
8
  const editorLinkMenuCss = () => `:host(limel-text-editor-link-menu){animation:fade 0.2s ease forwards;animation-delay:0.1s;opacity:0;display:flex;flex-direction:column;gap:0.5rem;padding:0.5rem;max-width:calc(100vw - 2rem);border-radius:0.5rem;background-color:var(--lime-elevated-surface-background-color);box-shadow:var(--shadow-depth-16)}.actions{display:flex;justify-content:end;gap:0.5rem}@keyframes fade{0%{scale:0.86;opacity:0}100%{scale:1;opacity:1}}`;
@@ -328,7 +328,6 @@ function estimateScrollWidth(element) {
328
328
  exports.MDCComponent = MDCComponent;
329
329
  exports.MDCFoundation = MDCFoundation;
330
330
  exports.__extends = __extends;
331
- exports.__read = __read;
332
331
  exports.__values = __values;
333
332
  exports.closest = closest;
334
333
  exports.estimateScrollWidth = estimateScrollWidth;
@@ -1,18 +1,12 @@
1
1
  import { h, } from "@stencil/core";
2
- import { MDCTabBar } from "@material/tab-bar";
3
- import { strings } from "@material/tab-bar/constants";
4
- import { isEqual, difference, noop } from "lodash-es";
2
+ import { MDCRipple } from "@material/ripple";
3
+ import { isEqual, difference } from "lodash-es";
5
4
  import { setActiveTab } from "./tabs";
6
5
  import { getIconColor, getIconName } from "../icon/get-icon-props";
7
- const { TAB_ACTIVATED_EVENT } = strings;
8
- // MDC wants to scroll the tabs into view itself, and finds what to scroll by
9
- // looking for the `mdc-tab-scroller` class. Scrolling is up to `limel-scroller`.
10
- const tabScrollerForMdc = {
11
- scrollTo: noop,
12
- incrementScroll: noop,
13
- getScrollPosition: () => 0,
14
- getScrollContentWidth: () => 0,
15
- destroy: noop,
6
+ import { findNavigationTarget, findTabStop, isNavigationKey, NO_NAVIGATION_TARGET, } from "../../util/keyboard-navigation";
7
+ const NAVIGATION = {
8
+ orientation: 'horizontal',
9
+ wrap: true,
16
10
  };
17
11
  /**
18
12
  * Tabs are great to organize information hierarchically in the interface and divide it into distinct categories. Using tabs, you can create groups of content that are related and at the same level in the hierarchy.
@@ -23,6 +17,7 @@ const tabScrollerForMdc = {
23
17
  * An exception for using tab bars in a high level of hierarchy is their usage in modals. This is because modals are perceived as a separate place and not a part of the current context. Therefore you can use tab bars in a modal to group and organize its content.
24
18
  * A tab bar can contain an unlimited number of tabs. However, depending on the device width and width of the tabs, the number of tabs that are visible at the same time will vary. When there is limited horizontal space, the component shows a left-arrow and/or right-arrow button, which scrolls and reveals the additional tabs. The tab bar can also be swiped left and right on a touch-device.
25
19
  * The arrows are only a shortcut for people who use a mouse or a touch screen. Screen readers do not announce them, and the Tab key skips them. People who use a keyboard or a screen reader move between the tabs, and the tab bar keeps the selected tab in view.
20
+ * The left and right arrow keys move to the previous and the next tab, and select it. Home and End move to the first and the last tab. Moving past the last tab continues at the first one, and the other way around. The Tab key moves on to what comes after the tab bar, and moving back with Shift and Tab lands on the selected tab, or on the first tab when none is selected.
26
21
  * :::tip Other things to consider
27
22
  * Never divide the content of a tab using a nested tab bar.
28
23
  * Never place two tab bars within the same screen.
@@ -41,41 +36,34 @@ export class TabBar {
41
36
  * List of tabs to display
42
37
  */
43
38
  this.tabs = [];
44
- this.setupMdc = false;
39
+ this.ripples = new Map();
45
40
  this.hasLoaded = false;
46
- this.handleTabActivated = this.handleTabActivated.bind(this);
47
- this.renderTab = this.renderTab.bind(this);
41
+ this.handleKeyDown = this.handleKeyDown.bind(this);
48
42
  }
49
43
  async connectedCallback() {
50
- this.setup();
51
44
  // Connecting after the first render means that the bar was moved, which
52
45
  // resets how far it is scrolled.
53
46
  if (!this.hasLoaded) {
54
47
  return;
55
48
  }
49
+ this.updateRipples();
56
50
  this.revealedTabId = undefined;
57
51
  await this.revealActiveTab('auto');
58
52
  }
59
53
  componentDidLoad() {
60
54
  this.hasLoaded = true;
61
- this.setup();
62
55
  this.triggerIconColorWarning();
63
56
  }
64
57
  async componentDidRender() {
58
+ this.updateRipples();
65
59
  await this.revealActiveTab(this.hasLoaded ? undefined : 'auto');
66
60
  }
67
- componentDidUpdate() {
68
- if (!this.setupMdc) {
69
- return;
70
- }
71
- this.setup();
72
- this.setupMdc = false;
73
- }
74
61
  disconnectedCallback() {
75
- this.tearDown();
62
+ this.destroyRipples();
76
63
  }
77
64
  render() {
78
- return (h("div", { key: '343865b4ddac8aa25042cb91916ad411366b4602', class: "mdc-tab-bar", role: "tablist" }, h("limel-scroller", { key: '7329ad9bb97c09afc79c3770d27db9fbb16093f3', class: "mdc-tab-scroller" }, this.tabs.map(this.renderTab))));
65
+ const tabStop = findTabStop(this.tabs, this.tabs.findIndex((tab) => tab.active), NAVIGATION);
66
+ return (h("div", { key: '7ab809d50e3605613f027a1782d54511e734de93', class: "mdc-tab-bar", role: "tablist", onKeyDown: this.handleKeyDown }, h("limel-scroller", { key: 'd6ac2c90e6da77a239292ac0e90288c3e70b62f8' }, this.tabs.map((tab, index) => this.renderTab(tab, index, index === tabStop)))));
79
67
  }
80
68
  tabsChanged(newTabs = [], oldTabs = []) {
81
69
  const newIds = newTabs.map((tab) => tab.id);
@@ -83,26 +71,37 @@ export class TabBar {
83
71
  if (isEqual(newIds, oldIds)) {
84
72
  return;
85
73
  }
86
- this.setupMdc = true;
87
74
  this.revealedTabId = undefined;
88
- this.tearDown();
89
75
  }
90
- setup() {
91
- const element = this.host.shadowRoot.querySelector('.mdc-tab-bar');
92
- if (!element) {
93
- return;
76
+ getTabElements() {
77
+ return [
78
+ ...this.host.shadowRoot.querySelectorAll('button[role="tab"]'),
79
+ ];
80
+ }
81
+ /**
82
+ * Gives every tab MDC's ripple, which is the feedback when a tab is
83
+ * pressed. Tabs that are gone lose theirs.
84
+ */
85
+ updateRipples() {
86
+ const tabs = this.getTabElements();
87
+ for (const [tab, ripple] of this.ripples) {
88
+ if (tabs.includes(tab)) {
89
+ continue;
90
+ }
91
+ ripple.destroy();
92
+ this.ripples.delete(tab);
93
+ }
94
+ for (const tab of tabs) {
95
+ if (!this.ripples.has(tab)) {
96
+ this.ripples.set(tab, new MDCRipple(tab));
97
+ }
94
98
  }
95
- this.mdcTabBar = new MDCTabBar(element, undefined, undefined, () => tabScrollerForMdc);
96
- this.mdcTabBar.focusOnActivate = true;
97
- this.mdcTabBar.useAutomaticActivation = true;
98
- this.mdcTabBar.listen(TAB_ACTIVATED_EVENT, this.handleTabActivated);
99
99
  }
100
- tearDown() {
101
- if (!this.mdcTabBar) {
102
- return;
100
+ destroyRipples() {
101
+ for (const ripple of this.ripples.values()) {
102
+ ripple.destroy();
103
103
  }
104
- this.mdcTabBar.unlisten(TAB_ACTIVATED_EVENT, this.handleTabActivated);
105
- this.mdcTabBar.destroy();
104
+ this.ripples.clear();
106
105
  }
107
106
  /**
108
107
  * A tab that is activated by the user has focus, and the scroller reveals
@@ -121,7 +120,7 @@ export class TabBar {
121
120
  return;
122
121
  }
123
122
  this.revealedTabId = this.tabs[index].id;
124
- const element = this.host.shadowRoot.querySelectorAll('button[role="tab"]')[index];
123
+ const element = this.getTabElements()[index];
125
124
  const scroller = this.host.shadowRoot.querySelector('limel-scroller');
126
125
  if (!element || !scroller || element.matches(':focus')) {
127
126
  return;
@@ -129,8 +128,24 @@ export class TabBar {
129
128
  await scroller.componentOnReady();
130
129
  await scroller.reveal(element, behavior);
131
130
  }
132
- handleTabActivated(event) {
133
- const index = event.detail.index;
131
+ handleKeyDown(event) {
132
+ if (!isNavigationKey(event, NAVIGATION)) {
133
+ return;
134
+ }
135
+ event.preventDefault();
136
+ const current = this.getTabElements().indexOf(event.target);
137
+ this.activateTab(findNavigationTarget(this.tabs, event.key, current, NAVIGATION));
138
+ }
139
+ activateTab(index) {
140
+ if (index === NO_NAVIGATION_TARGET) {
141
+ return;
142
+ }
143
+ // Not every browser focuses a button that is clicked, and a key can
144
+ // lead to the selected tab from another tab that has focus.
145
+ this.getTabElements()[index].focus();
146
+ if (index === this.tabs.findIndex((tab) => tab.active)) {
147
+ return;
148
+ }
134
149
  const newTabs = setActiveTab(this.tabs, index);
135
150
  const changedTabs = difference(newTabs, this.tabs).sort(this.sortByInactive);
136
151
  for (const tab of changedTabs) {
@@ -153,11 +168,11 @@ export class TabBar {
153
168
  }
154
169
  return (h("limel-icon", { class: "mdc-tab__icon", name: name, style: style, size: "small", "aria-hidden": "true" }));
155
170
  }
156
- renderTab(tab) {
171
+ renderTab(tab, index, isTabStop) {
157
172
  return (h("button", { class: {
158
173
  'mdc-tab': true,
159
174
  'mdc-tab--active': !!tab.active,
160
- }, role: "tab", "aria-selected": tab.active ? 'true' : 'false', tabindex: tab.active ? 0 : -1 }, h("span", { class: "mdc-tab__content" }, this.renderIcon(tab), h("span", { class: "mdc-tab__text-label" }, tab.text), tab.badge ? h("limel-badge", { label: tab.badge }) : ''), h("span", { class: {
175
+ }, role: "tab", "aria-selected": tab.active ? 'true' : 'false', tabindex: isTabStop ? 0 : -1, onClick: () => this.activateTab(index) }, h("span", { class: "mdc-tab__content" }, this.renderIcon(tab), h("span", { class: "mdc-tab__text-label" }, tab.text), tab.badge ? h("limel-badge", { label: tab.badge }) : ''), h("span", { class: {
161
176
  'mdc-tab-indicator': true,
162
177
  'mdc-tab-indicator--active': !!tab.active,
163
178
  } }, h("span", { class: "mdc-tab-indicator__content mdc-tab-indicator__content--underline" })), h("span", { class: "mdc-tab__ripple" })));
@@ -0,0 +1,144 @@
1
+ import { ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT, ARROW_UP, END, HOME, } from "./keycodes";
2
+ /**
3
+ * Returned when there is no item to move to.
4
+ */
5
+ export const NO_NAVIGATION_TARGET = -1;
6
+ const MOVES = {
7
+ horizontal: new Map([
8
+ [ARROW_LEFT, 'previous'],
9
+ [ARROW_RIGHT, 'next'],
10
+ [HOME, 'first'],
11
+ [END, 'last'],
12
+ ]),
13
+ vertical: new Map([
14
+ [ARROW_UP, 'previous'],
15
+ [ARROW_DOWN, 'next'],
16
+ [HOME, 'first'],
17
+ [END, 'last'],
18
+ ]),
19
+ };
20
+ /**
21
+ * Whether a keyboard event is one that moves between the items: an arrow key
22
+ * that goes along the orientation, or Home or End.
23
+ *
24
+ * A key that is pressed with Alt, Ctrl or Cmd is not, since the browser puts
25
+ * those to its own use, such as going back with Alt and the left arrow. Shift
26
+ * is allowed.
27
+ *
28
+ * When this returns `true`, the component should prevent the default action
29
+ * of the event, so that the page does not scroll. Also when there turns out to
30
+ * be nowhere to move to.
31
+ *
32
+ * @param event - the keyboard event to inspect
33
+ * @param options - the same options that are used to move between the items.
34
+ * Only the orientation matters here.
35
+ * @returns `true` when the event is for moving between the items
36
+ */
37
+ export function isNavigationKey(event, options) {
38
+ if (event.altKey || event.ctrlKey || event.metaKey) {
39
+ return false;
40
+ }
41
+ return MOVES[options.orientation].has(event.key);
42
+ }
43
+ /**
44
+ * Find the item that a key press moves to.
45
+ *
46
+ * - The arrow keys that go along the orientation move to the next and the
47
+ * previous item. At the ends they stop, or continue at the other end when
48
+ * `options.wrap` is set.
49
+ * - Home and End move to the first and the last item.
50
+ * - Items that cannot be moved to are skipped.
51
+ * - Without a current item, moving forward starts at the first item, and
52
+ * moving back at the last one.
53
+ *
54
+ * @param items - the items, in the order that they are laid out in. Only their
55
+ * number matters, unless `options.isDisabled` is given.
56
+ * @param key - the `key` of the keyboard event
57
+ * @param currentIndex - the index of the item to move from, usually the one
58
+ * that has focus. Anything outside `items` is treated as "no current item".
59
+ * @param options - which keys move, and how
60
+ * @returns the index of the item to move to. That is `currentIndex` itself
61
+ * when there is nowhere to go from there, since the end is reached and it does
62
+ * not wrap, or since it is the only item that can be moved to. It is
63
+ * `NO_NAVIGATION_TARGET` when the key does not move in this orientation, and
64
+ * when none of the items can be moved to.
65
+ */
66
+ export function findNavigationTarget(items, key, currentIndex, options) {
67
+ const move = MOVES[options.orientation].get(key);
68
+ const count = items.length;
69
+ const canMoveTo = createReachableTest(items, options);
70
+ const first = findReachable(count, 0, 1, false, canMoveTo);
71
+ if (!move || first === NO_NAVIGATION_TARGET) {
72
+ return NO_NAVIGATION_TARGET;
73
+ }
74
+ if (move === 'first') {
75
+ return first;
76
+ }
77
+ const last = findReachable(count, count - 1, -1, false, canMoveTo);
78
+ if (move === 'last') {
79
+ return last;
80
+ }
81
+ if (!isWithin(currentIndex, count)) {
82
+ return move === 'next' ? first : last;
83
+ }
84
+ const step = move === 'next' ? 1 : -1;
85
+ const target = findReachable(count, currentIndex + step, step, Boolean(options.wrap), canMoveTo);
86
+ return target === NO_NAVIGATION_TARGET ? currentIndex : target;
87
+ }
88
+ /**
89
+ * Find the item that should be in the tab order, which is the one that Tab
90
+ * lands on when it enters the group. The rest of the items are left out of the
91
+ * tab order, and are reached with the arrow keys.
92
+ *
93
+ * That is the preferred item, if it can be moved to. Otherwise the first item
94
+ * that can.
95
+ *
96
+ * @param items - the items, in the order that they are laid out in. Only their
97
+ * number matters, unless `options.isDisabled` is given.
98
+ * @param preferredIndex - the index of the item that should be in the tab
99
+ * order if possible. For a group with a selection that is the selected item,
100
+ * and otherwise the item that last had focus, which the component has to keep
101
+ * track of. Anything outside `items` means that there is no preference.
102
+ * @param options - the same options that are used to move between the items
103
+ * @returns the index of the item to put in the tab order, or
104
+ * `NO_NAVIGATION_TARGET` when none of the items can be moved to
105
+ */
106
+ export function findTabStop(items, preferredIndex, options) {
107
+ const count = items.length;
108
+ const canMoveTo = createReachableTest(items, options);
109
+ if (isWithin(preferredIndex, count) && canMoveTo(preferredIndex)) {
110
+ return preferredIndex;
111
+ }
112
+ return findReachable(count, 0, 1, false, canMoveTo);
113
+ }
114
+ function isWithin(index, count) {
115
+ return index >= 0 && index < count;
116
+ }
117
+ function createReachableTest(items, options) {
118
+ return (index) => { var _a; return !((_a = options === null || options === void 0 ? void 0 : options.isDisabled) === null || _a === void 0 ? void 0 : _a.call(options, items[index])); };
119
+ }
120
+ /**
121
+ * Look for an item that can be moved to, one item at a time.
122
+ *
123
+ * @param count - the number of items
124
+ * @param start - the index to start looking at
125
+ * @param step - the direction to look in, `1` for forward and `-1` for back
126
+ * @param wrap - whether to continue at the other end, instead of giving up at
127
+ * the end of the items. Every item is looked at once at most.
128
+ * @param canMoveTo - tells whether the item at an index can be moved to
129
+ * @returns the index of the first item that can be moved to, or
130
+ * `NO_NAVIGATION_TARGET` when there is none
131
+ */
132
+ function findReachable(count, start, step, wrap, canMoveTo) {
133
+ for (let distance = 0; distance < count; distance += 1) {
134
+ const position = start + step * distance;
135
+ if (!wrap && !isWithin(position, count)) {
136
+ break;
137
+ }
138
+ const index = ((position % count) + count) % count;
139
+ if (canMoveTo(index)) {
140
+ return index;
141
+ }
142
+ }
143
+ return NO_NAVIGATION_TARGET;
144
+ }
@@ -13,3 +13,5 @@ export const ARROW_UP = 'ArrowUp';
13
13
  export const ARROW_DOWN = 'ArrowDown';
14
14
  export const ARROW_LEFT = 'ArrowLeft';
15
15
  export const ARROW_RIGHT = 'ArrowRight';
16
+ export const HOME = 'Home';
17
+ export const END = 'End';
@@ -1,6 +1,6 @@
1
- import { _ as __extends, a as __assign, M as MDCFoundation, c as MDCComponent, b as __values, m as matches } from './ponyfill-ChRGk668.js';
2
- import { a as applyPassive, M as MDCRipple, b as MDCRippleFoundation } from './component-7QB0OUSF.js';
3
- import { a as MDCFloatingLabelFoundation, M as MDCFloatingLabel } from './component-D4qgwaTf.js';
1
+ import { _ as __extends, a as __assign, M as MDCFoundation, c as MDCComponent, b as __values, m as matches } from './ponyfill-6YuZiAPi.js';
2
+ import { a as applyPassive, M as MDCRipple, b as MDCRippleFoundation } from './component-CrjPGt1I.js';
3
+ import { a as MDCFloatingLabelFoundation, M as MDCFloatingLabel } from './component-CyFeUQ0l.js';
4
4
 
5
5
  /**
6
6
  * @license
@@ -1,4 +1,4 @@
1
- import { _ as __extends, a as __assign, b as __values, M as MDCFoundation, m as matches, c as MDCComponent } from './ponyfill-ChRGk668.js';
1
+ import { _ as __extends, a as __assign, b as __values, M as MDCFoundation, m as matches, c as MDCComponent } from './ponyfill-6YuZiAPi.js';
2
2
 
3
3
  /**
4
4
  * @license
@@ -1,4 +1,4 @@
1
- import { _ as __extends, a as __assign, M as MDCFoundation, c as MDCComponent, e as estimateScrollWidth } from './ponyfill-ChRGk668.js';
1
+ import { _ as __extends, a as __assign, M as MDCFoundation, c as MDCComponent, e as estimateScrollWidth } from './ponyfill-6YuZiAPi.js';
2
2
 
3
3
  /**
4
4
  * @license
@@ -1,4 +1,4 @@
1
- import { _ as __extends, a as __assign, M as MDCFoundation, m as matches, d as closest, c as MDCComponent } from './ponyfill-ChRGk668.js';
1
+ import { _ as __extends, a as __assign, M as MDCFoundation, m as matches, d as closest, c as MDCComponent } from './ponyfill-6YuZiAPi.js';
2
2
 
3
3
  /**
4
4
  * @license
@@ -27,22 +27,6 @@ function apply(func, thisArg, args) {
27
27
  return func.apply(thisArg, args);
28
28
  }
29
29
 
30
- /**
31
- * This method returns `undefined`.
32
- *
33
- * @static
34
- * @memberOf _
35
- * @since 2.3.0
36
- * @category Util
37
- * @example
38
- *
39
- * _.times(2, _.noop);
40
- * // => [undefined, undefined]
41
- */
42
- function noop() {
43
- // No operation performed.
44
- }
45
-
46
30
  /** Used to detect hot functions by number of calls within a span of milliseconds. */
47
31
  var HOT_COUNT = 800,
48
32
  HOT_SPAN = 16;
@@ -334,4 +318,4 @@ function isArrayLikeObject(value) {
334
318
  return isObjectLike(value) && isArrayLike(value);
335
319
  }
336
320
 
337
- export { arrayIncludes as a, baseRest as b, baseFlatten as c, isArrayLikeObject as i, noop as n };
321
+ export { arrayIncludes as a, baseRest as b, baseFlatten as c, isArrayLikeObject as i };
@@ -13,5 +13,7 @@ const ARROW_UP = 'ArrowUp';
13
13
  const ARROW_DOWN = 'ArrowDown';
14
14
  const ARROW_LEFT = 'ArrowLeft';
15
15
  const ARROW_RIGHT = 'ArrowRight';
16
+ const HOME = 'Home';
17
+ const END = 'End';
16
18
 
17
- export { ARROW_UP as A, BACKSPACE as B, DELETE as D, ESCAPE as E, SPACEBAR as S, TAB as T, ENTER as a, ARROW_DOWN as b, ARROW_LEFT as c, ARROW_RIGHT as d, SPACE as e };
19
+ export { ARROW_UP as A, BACKSPACE as B, DELETE as D, ESCAPE as E, HOME as H, SPACEBAR as S, TAB as T, ENTER as a, ARROW_DOWN as b, END as c, ARROW_LEFT as d, ARROW_RIGHT as e, SPACE as f };
@@ -2,23 +2,23 @@ import { r as registerInstance, c as createEvent, h, a as getElement, H as Host
2
2
  import { m as makeEnterClickable, r as removeEnterClickable } from './make-enter-clickable-CIf8aGSd.js';
3
3
  import { c as createRandomString } from './random-string-BrjD-ITe.js';
4
4
  import { g as getIconName, b as getIconColor } from './get-icon-props-CgNJbSP4.js';
5
- import { T as TAB, A as ARROW_UP, b as ARROW_DOWN, E as ESCAPE, a as ENTER, e as SPACE, c as ARROW_LEFT, d as ARROW_RIGHT } from './keycodes-C4_9qUMP.js';
5
+ import { T as TAB, A as ARROW_UP, b as ARROW_DOWN, E as ESCAPE, a as ENTER, f as SPACE, d as ARROW_LEFT, e as ARROW_RIGHT } from './keycodes-DQ5DmW_Y.js';
6
6
  import { b as getHref, a as getTarget, g as getRel } from './link-helper-5KsJICvh.js';
7
7
  import { g as globalConfig } from './config-Dnt5w_Bp.js';
8
8
  import { d as debounce } from './debounce-B67JMchz.js';
9
- import { M as MDCTextField } from './component-wGVqvUmL.js';
9
+ import { M as MDCTextField } from './component-CVihTrav.js';
10
10
  import { f as focusTriggerElement, z as zipObject } from './focus-trigger-element-BOFcjLq3.js';
11
11
  import { h as hotkeyFromKeyboardEvent, t as tokenizeHotkeyString, n as normalizeHotkeyString } from './hotkeys-DjmlD0Mw.js';
12
12
  import { i as isFunction } from './isFunction-9zQTeQI8.js';
13
- import { _ as __extends, a as __assign, b as __values, M as MDCFoundation, c as MDCComponent, d as closest } from './ponyfill-ChRGk668.js';
14
- import { c as cssClasses$2, n as numbers$2, M as MDCListFoundation, a as MDCList } from './component-B2Vy44Z3.js';
15
- import { M as MDCRipple } from './component-7QB0OUSF.js';
13
+ import { _ as __extends, a as __assign, b as __values, M as MDCFoundation, c as MDCComponent, d as closest } from './ponyfill-6YuZiAPi.js';
14
+ import { c as cssClasses$2, n as numbers$2, M as MDCListFoundation, a as MDCList } from './component-kP1jCDLp.js';
15
+ import { M as MDCRipple } from './component-CrjPGt1I.js';
16
16
  import { i as isDescendant } from './dom-B9Ofc5RB.js';
17
17
  import './isObject-BJQylLSL.js';
18
18
  import './toNumber-D6JYpQI9.js';
19
19
  import './isSymbol-ClAke5ga.js';
20
20
  import './isObjectLike-oiMYqRQ0.js';
21
- import './component-D4qgwaTf.js';
21
+ import './component-CyFeUQ0l.js';
22
22
  import './_assignValue-CEFvyZxO.js';
23
23
  import './_defineProperty-C69Btzid.js';
24
24
  import './_getNative-COawFdVX.js';
@@ -1,10 +1,10 @@
1
1
  import { r as registerInstance, c as createEvent, h, H as Host, a as getElement } from './index-BU9IJqli.js';
2
- import { c as ARROW_LEFT, d as ARROW_RIGHT, a as ENTER, D as DELETE, B as BACKSPACE, E as ESCAPE } from './keycodes-C4_9qUMP.js';
2
+ import { d as ARROW_LEFT, e as ARROW_RIGHT, a as ENTER, D as DELETE, B as BACKSPACE, E as ESCAPE } from './keycodes-DQ5DmW_Y.js';
3
3
  import { t as translations } from './translations-Y4i8PVc9.js';
4
4
  import { a as getTarget, b as getHref } from './link-helper-5KsJICvh.js';
5
5
  import { c as createRandomString } from './random-string-BrjD-ITe.js';
6
6
  import { i as isEqual } from './isEqual-CE83yS8T.js';
7
- import { M as MDCTextField } from './component-wGVqvUmL.js';
7
+ import { M as MDCTextField } from './component-CVihTrav.js';
8
8
  import './language-ChagAaNf.js';
9
9
  import './_baseIsEqual-CyF4P8uM.js';
10
10
  import './eq-CZ30nDJE.js';
@@ -16,9 +16,9 @@ import './isFunction-9zQTeQI8.js';
16
16
  import './_getNative-COawFdVX.js';
17
17
  import './isArray-B8VKuhvH.js';
18
18
  import './_isIndex-B--C3qwe.js';
19
- import './ponyfill-ChRGk668.js';
20
- import './component-7QB0OUSF.js';
21
- import './component-D4qgwaTf.js';
19
+ import './ponyfill-6YuZiAPi.js';
20
+ import './component-CrjPGt1I.js';
21
+ import './component-CyFeUQ0l.js';
22
22
 
23
23
  /**
24
24
  * Key handler for the input field.
@@ -4,7 +4,7 @@ import { g as getRel } from './link-helper-5KsJICvh.js';
4
4
  import { g as getIconName } from './get-icon-props-CgNJbSP4.js';
5
5
  import { m as makeEnterClickable, r as removeEnterClickable } from './make-enter-clickable-CIf8aGSd.js';
6
6
  import { t as translations } from './translations-Y4i8PVc9.js';
7
- import { D as DELETE, B as BACKSPACE } from './keycodes-C4_9qUMP.js';
7
+ import { D as DELETE, B as BACKSPACE } from './keycodes-DQ5DmW_Y.js';
8
8
  import { i as isEmpty } from './isEmpty-BGVZ12Ea.js';
9
9
  import './language-ChagAaNf.js';
10
10
  import './_getTag-BiAaLWvH.js';
@@ -4,11 +4,11 @@ import { i as isIOSDevice, a as isAndroidDevice } from './device-B-tmXAXV.js';
4
4
  import './sv-DpsDSi7k.js';
5
5
  import { m as moment } from './moment-_DadZLWp.js';
6
6
  import { g as getPrimarySubtag } from './language-ChagAaNf.js';
7
- import { M as MDCTextField } from './component-wGVqvUmL.js';
7
+ import { M as MDCTextField } from './component-CVihTrav.js';
8
8
  import './_commonjsHelpers-B85MJLTf.js';
9
- import './ponyfill-ChRGk668.js';
10
- import './component-7QB0OUSF.js';
11
- import './component-D4qgwaTf.js';
9
+ import './ponyfill-6YuZiAPi.js';
10
+ import './component-CrjPGt1I.js';
11
+ import './component-CyFeUQ0l.js';
12
12
 
13
13
  class DateFormatter {
14
14
  constructor(language = 'en') {
@@ -1,8 +1,8 @@
1
1
  import { r as registerInstance, c as createEvent, h, a as getElement } from './index-BU9IJqli.js';
2
2
  import { d as dispatchResizeEvent } from './dispatch-resize-event-z_E3sq3p.js';
3
3
  import { c as createRandomString } from './random-string-BrjD-ITe.js';
4
- import { _ as __extends, a as __assign, M as MDCFoundation, b as __values, c as MDCComponent, d as closest, m as matches } from './ponyfill-ChRGk668.js';
5
- import { M as MDCRipple } from './component-7QB0OUSF.js';
4
+ import { _ as __extends, a as __assign, M as MDCFoundation, b as __values, c as MDCComponent, d as closest, m as matches } from './ponyfill-6YuZiAPi.js';
5
+ import { M as MDCRipple } from './component-CrjPGt1I.js';
6
6
  import { i as isEqual } from './isEqual-CE83yS8T.js';
7
7
  import './_baseIsEqual-CyF4P8uM.js';
8
8
  import './eq-CZ30nDJE.js';
@@ -7,7 +7,7 @@ import { b as baseGetTag } from './isObject-BJQylLSL.js';
7
7
  import { g as getPrototype } from './_getPrototype-B0kMNv1F.js';
8
8
  import { i as isObjectLike } from './isObjectLike-oiMYqRQ0.js';
9
9
  import { b as baseSet, n as negate } from './_baseSet-Cw2IE6ZF.js';
10
- import { n as noop$1, a as arrayIncludes, b as baseRest, c as baseFlatten, i as isArrayLikeObject } from './isArrayLikeObject-tmUOLOWr.js';
10
+ import { a as arrayIncludes, b as baseRest, c as baseFlatten, i as isArrayLikeObject } from './isArrayLikeObject-CJB8HbtH.js';
11
11
  import { s as setToArray, S as SetCache, c as cacheHas } from './_baseIsEqual-CyF4P8uM.js';
12
12
  import { S as Set$1 } from './_getTag-BiAaLWvH.js';
13
13
  import { m as moment } from './moment-_DadZLWp.js';
@@ -25,6 +25,22 @@ import './_defineProperty-C69Btzid.js';
25
25
  import './_getNative-COawFdVX.js';
26
26
  import './eq-CZ30nDJE.js';
27
27
 
28
+ /**
29
+ * This method returns `undefined`.
30
+ *
31
+ * @static
32
+ * @memberOf _
33
+ * @since 2.3.0
34
+ * @category Util
35
+ * @example
36
+ *
37
+ * _.times(2, _.noop);
38
+ * // => [undefined, undefined]
39
+ */
40
+ function noop$1() {
41
+ // No operation performed.
42
+ }
43
+
28
44
  /** `Object#toString` result references. */
29
45
  var objectTag = '[object Object]';
30
46
 
@@ -1,6 +1,6 @@
1
1
  import { r as registerInstance, h, H as Host, c as createEvent, a as getElement } from './index-BU9IJqli.js';
2
- import { a as MDCList, s as strings } from './component-B2Vy44Z3.js';
3
- import './ponyfill-ChRGk668.js';
2
+ import { a as MDCList, s as strings } from './component-kP1jCDLp.js';
3
+ import './ponyfill-6YuZiAPi.js';
4
4
 
5
5
  const helperLineCss = () => `:host(limel-helper-line){transition:opacity 0.2s ease;box-sizing:border-box;display:grid;min-width:0;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-size:0.6875rem;line-height:normal;color:rgb(var(--contrast-1200))}div{display:flex;justify-content:space-between;gap:0.75rem;overflow:hidden;padding:0 1rem}:host(limel-helper-line.invalid){--limel-h-l-grid-template-rows-transition-speed:0.46s;--limel-h-l-grid-template-rows:1fr}:host(limel-helper-line.invalid) .helper-text{color:var(--limel-theme-error-color)}.counter{flex-shrink:0;margin-left:auto}.helper-text,.counter{padding-top:0.125rem}:host(limel-helper-line){transition:grid-template-rows var(--limel-h-l-grid-template-rows-transition-speed, 0.46s) cubic-bezier(1, 0.09, 0, 0.89);grid-template-rows:var(--limel-h-l-grid-template-rows, 1fr)}:host(limel-helper-line.hide){--limel-h-l-grid-template-rows-transition-speed:0.3s;--limel-h-l-grid-template-rows:0fr}`;
6
6
 
@@ -1,6 +1,6 @@
1
1
  import { r as registerInstance, c as createEvent, h, H as Host } from './index-BU9IJqli.js';
2
2
  import { t as translations } from './translations-Y4i8PVc9.js';
3
- import { a as ENTER } from './keycodes-C4_9qUMP.js';
3
+ import { a as ENTER } from './keycodes-DQ5DmW_Y.js';
4
4
  import { p as pageFromInput } from './pagination.util-CSC2LJ7P.js';
5
5
  import './language-ChagAaNf.js';
6
6
 
@@ -1,7 +1,7 @@
1
1
  import { r as registerInstance, c as createEvent, h, a as getElement } from './index-BU9IJqli.js';
2
2
  import { t as translations } from './translations-Y4i8PVc9.js';
3
3
  import { i as isDescendant } from './dom-B9Ofc5RB.js';
4
- import { E as ESCAPE, T as TAB, a as ENTER, A as ARROW_UP, b as ARROW_DOWN } from './keycodes-C4_9qUMP.js';
4
+ import { E as ESCAPE, T as TAB, a as ENTER, A as ARROW_UP, b as ARROW_DOWN } from './keycodes-DQ5DmW_Y.js';
5
5
  import { c as createRandomString } from './random-string-BrjD-ITe.js';
6
6
  import { a as getIconFillColor, g as getIconName } from './get-icon-props-CgNJbSP4.js';
7
7
  import { d as debounce } from './debounce-B67JMchz.js';
@@ -1,6 +1,6 @@
1
1
  import { r as registerInstance, c as createEvent, h, a as getElement } from './index-BU9IJqli.js';
2
2
  import { c as createRandomString } from './random-string-BrjD-ITe.js';
3
- import { E as ESCAPE } from './keycodes-C4_9qUMP.js';
3
+ import { E as ESCAPE } from './keycodes-DQ5DmW_Y.js';
4
4
  import { f as focusTriggerElement, z as zipObject } from './focus-trigger-element-BOFcjLq3.js';
5
5
  import './_assignValue-CEFvyZxO.js';
6
6
  import './_defineProperty-C69Btzid.js';
@@ -1,12 +1,12 @@
1
1
  import { h, r as registerInstance, c as createEvent, a as getElement } from './index-BU9IJqli.js';
2
2
  import { b as isMobileDevice } from './device-B-tmXAXV.js';
3
- import { S as SPACEBAR, a as ENTER } from './keycodes-C4_9qUMP.js';
3
+ import { S as SPACEBAR, a as ENTER } from './keycodes-DQ5DmW_Y.js';
4
4
  import { i as isMultiple } from './multiple-BylwpiM6.js';
5
5
  import { c as createRandomString } from './random-string-BrjD-ITe.js';
6
6
  import { r as renderListComponent } from './render-list-component-J1IzNpbv.js';
7
7
  import { b as getIconColor, g as getIconName } from './get-icon-props-CgNJbSP4.js';
8
- import { M as MDCFloatingLabel } from './component-D4qgwaTf.js';
9
- import { _ as __extends, a as __assign, M as MDCFoundation, c as MDCComponent } from './ponyfill-ChRGk668.js';
8
+ import { M as MDCFloatingLabel } from './component-CyFeUQ0l.js';
9
+ import { _ as __extends, a as __assign, M as MDCFoundation, c as MDCComponent } from './ponyfill-6YuZiAPi.js';
10
10
  import './isArray-B8VKuhvH.js';
11
11
 
12
12
  /**