@ixfx/components 0.5.17 → 0.5.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/bundle/index.d.ts +71 -8
  2. package/bundle/index.d.ts.map +1 -1
  3. package/bundle/index.js +563 -116
  4. package/bundle/index.js.map +1 -1
  5. package/bundle/style.css +4 -2
  6. package/dist/ac-text.d.ts +1 -1
  7. package/dist/button.d.ts +1 -1
  8. package/dist/button.d.ts.map +1 -1
  9. package/dist/{colour-picker-DbypcEp6.js → colour-picker-37NyVenk.js} +2 -2
  10. package/dist/{colour-picker-DbypcEp6.js.map → colour-picker-37NyVenk.js.map} +1 -1
  11. package/dist/colour-picker.d.ts +1 -1
  12. package/dist/colour-picker.js +1 -1
  13. package/dist/{crumb-navigation-DFqTzElw.js → crumb-navigation-BrB0r14u.js} +169 -98
  14. package/dist/crumb-navigation-BrB0r14u.js.map +1 -0
  15. package/dist/crumbs.d.ts +3 -1
  16. package/dist/crumbs.d.ts.map +1 -1
  17. package/dist/crumbs.js +1 -1
  18. package/dist/{defaults-DcE8RQJc.js → defaults-BkWCPJFL.js} +7 -1
  19. package/dist/{defaults-DcE8RQJc.js.map → defaults-BkWCPJFL.js.map} +1 -1
  20. package/dist/{icon-DpA9x2Ve.d.ts → icon-BUwP1CZ1.d.ts} +2 -2
  21. package/dist/icon-BUwP1CZ1.d.ts.map +1 -0
  22. package/dist/icons.d.ts +2 -2
  23. package/dist/icons.js +1 -1
  24. package/dist/{index-D_ftz_IT.d.ts → index-BKAlRgbq.d.ts} +2 -2
  25. package/dist/{index-D_ftz_IT.d.ts.map → index-BKAlRgbq.d.ts.map} +1 -1
  26. package/dist/{index-CoqtMSd9.d.ts → index-BUB5SICW.d.ts} +2 -2
  27. package/dist/{index-CoqtMSd9.d.ts.map → index-BUB5SICW.d.ts.map} +1 -1
  28. package/dist/{index-DfEkTGvT.d.ts → index-DkhBGHgF.d.ts} +3 -3
  29. package/dist/{index-DfEkTGvT.d.ts.map → index-DkhBGHgF.d.ts.map} +1 -1
  30. package/dist/{index-BtGFYfaK.d.ts → index-RqMh1i-O.d.ts} +2 -2
  31. package/dist/{index-BtGFYfaK.d.ts.map → index-RqMh1i-O.d.ts.map} +1 -1
  32. package/dist/index.d.ts +55 -9
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/index.js +288 -10
  35. package/dist/index.js.map +1 -1
  36. package/dist/{labelled-input-base-DiTme1JO.d.ts → labelled-input-base-Dp_9KP0G.d.ts} +2 -2
  37. package/dist/{labelled-input-base-DiTme1JO.d.ts.map → labelled-input-base-Dp_9KP0G.d.ts.map} +1 -1
  38. package/dist/labelled-radial-input.d.ts +2 -2
  39. package/dist/labelled-radial-input.d.ts.map +1 -1
  40. package/dist/labelled-range-input.d.ts +1 -1
  41. package/dist/{menu-B8gE2MSo.js → menu-CdwSe_XN.js} +2 -2
  42. package/dist/{menu-B8gE2MSo.js.map → menu-CdwSe_XN.js.map} +1 -1
  43. package/dist/{menu-item-DSyf9f_L.d.ts → menu-item-BG5w7fi4.d.ts} +4 -2
  44. package/dist/menu-item-BG5w7fi4.d.ts.map +1 -0
  45. package/dist/{menu-item-BYRvfyXK.js → menu-item-CrmUwIoJ.js} +7 -2
  46. package/dist/menu-item-CrmUwIoJ.js.map +1 -0
  47. package/dist/menu.d.ts +2 -2
  48. package/dist/menu.js +2 -2
  49. package/dist/panel.d.ts +1 -1
  50. package/dist/split-layout.d.ts +7 -1
  51. package/dist/split-layout.d.ts.map +1 -1
  52. package/dist/split-layout.js +84 -14
  53. package/dist/split-layout.js.map +1 -1
  54. package/dist/style.css +4 -2
  55. package/dist/{tab-list-ih-0I0NE.d.ts → tab-list-Beuh2nom.d.ts} +10 -3
  56. package/dist/tab-list-Beuh2nom.d.ts.map +1 -0
  57. package/dist/{tab-list-6W5CgXix.js → tab-list-mAoD6L0e.js} +20 -2
  58. package/dist/tab-list-mAoD6L0e.js.map +1 -0
  59. package/dist/tabs.d.ts +1 -1
  60. package/dist/tabs.js +1 -1
  61. package/docs-user/README.md +1 -0
  62. package/docs-user/crumbs.md +4 -0
  63. package/docs-user/select-horiz.md +114 -0
  64. package/docs-user/split-layout.md +29 -7
  65. package/package.json +3 -1
  66. package/dist/crumb-navigation-DFqTzElw.js.map +0 -1
  67. package/dist/icon-DpA9x2Ve.d.ts.map +0 -1
  68. package/dist/menu-item-BYRvfyXK.js.map +0 -1
  69. package/dist/menu-item-DSyf9f_L.d.ts.map +0 -1
  70. package/dist/tab-list-6W5CgXix.js.map +0 -1
  71. package/dist/tab-list-ih-0I0NE.d.ts.map +0 -1
package/bundle/index.js CHANGED
@@ -2979,6 +2979,11 @@ const ICON_WARNING = `<svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="
2979
2979
  * fill="currentColor" so it inherits CSS color.
2980
2980
  */
2981
2981
  const ICON_CHEVRON_RIGHT = `<svg viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z"/></svg>`;
2982
+ /**
2983
+ * Folder with up arrow. Angled line style for navigating up one level.
2984
+ * fill="currentColor" so it inherits CSS color.
2985
+ */
2986
+ const ICON_FOLDER_UP = `<svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M12 4L4 12h5v8h6v-8h5L12 4z"/></svg>`;
2982
2987
  function registerDefaults() {
2983
2988
  registerIcon(`chevron-down`, ICON_CHEVRON_DOWN);
2984
2989
  registerIcon(`chevron-right`, ICON_CHEVRON_RIGHT);
@@ -2986,6 +2991,7 @@ function registerDefaults() {
2986
2991
  registerIcon(`check`, ICON_CHECK);
2987
2992
  registerIcon(`close`, ICON_CLOSE);
2988
2993
  registerIcon(`error`, ICON_ERROR);
2994
+ registerIcon(`folder-up`, ICON_FOLDER_UP);
2989
2995
  registerIcon(`info`, ICON_INFO);
2990
2996
  registerIcon(`warning`, ICON_WARNING);
2991
2997
  }
@@ -3843,6 +3849,7 @@ let MenuTrigger = class MenuTrigger extends i {
3843
3849
  this.mode = `trigger`;
3844
3850
  this.label = `⋮`;
3845
3851
  this.placement = `bottom-start`;
3852
+ this.tabStop = true;
3846
3853
  this._isOpen = false;
3847
3854
  this._hasMenu = false;
3848
3855
  this._hasTriggerSlot = false;
@@ -4105,7 +4112,7 @@ let MenuTrigger = class MenuTrigger extends i {
4105
4112
  @click=${this._handleTriggerClick}
4106
4113
  @contextmenu=${this._handleContextMenu}
4107
4114
  >
4108
- ${showButton ? b`<button class="trigger-btn" part="base">${this.label}</button>` : null}
4115
+ ${showButton ? b`<button class="trigger-btn" part="base" tabindex=${this.tabStop ? `0` : `-1`}>${this.label}</button>` : null}
4109
4116
  <slot name="trigger" @slotchange=${this._handleTriggerSlotChange}></slot>
4110
4117
  </div>
4111
4118
  <div
@@ -4123,6 +4130,10 @@ __decorate([property({ type: String })], MenuTrigger.prototype, "label", void 0)
4123
4130
  __decorate([property({ attribute: false })], MenuTrigger.prototype, "registry", void 0);
4124
4131
  __decorate([property({ attribute: false })], MenuTrigger.prototype, "keyboardManager", void 0);
4125
4132
  __decorate([property({ type: String })], MenuTrigger.prototype, "placement", void 0);
4133
+ __decorate([property({
4134
+ type: Boolean,
4135
+ attribute: `tab-stop`
4136
+ })], MenuTrigger.prototype, "tabStop", void 0);
4126
4137
  __decorate([state()], MenuTrigger.prototype, "_isOpen", void 0);
4127
4138
  __decorate([state()], MenuTrigger.prototype, "_hasMenu", void 0);
4128
4139
  __decorate([state()], MenuTrigger.prototype, "_hasTriggerSlot", void 0);
@@ -7100,6 +7111,8 @@ let CrumbNavigationElement = class CrumbNavigationElement extends i {
7100
7111
  this.leadingCaret = false;
7101
7112
  this.caretEmbedded = true;
7102
7113
  this.hideRoot = false;
7114
+ this.padEnding = false;
7115
+ this.withUp = false;
7103
7116
  this.#previousSelectionKey = ``;
7104
7117
  this.#menuOpenedByKeyboard = false;
7105
7118
  this.#currentOpenTrigger = null;
@@ -7137,7 +7150,7 @@ let CrumbNavigationElement = class CrumbNavigationElement extends i {
7137
7150
  const r = this.root;
7138
7151
  const sel = this.selectedNode;
7139
7152
  if (!r || !sel) break;
7140
- const totalItems = (this.#findPath(r, sel) ?? [r]).length + (this.#hasChildOptions() ? 1 : 0);
7153
+ const totalItems = this.#getTickledItems().length;
7141
7154
  const currentTickled = this.tickled.tickledId ?? -1;
7142
7155
  if (e.key === `ArrowLeft`) {
7143
7156
  if (currentTickled > 0) this.tickled.handleKeyboardNavigation(`previous`);
@@ -7150,13 +7163,13 @@ let CrumbNavigationElement = class CrumbNavigationElement extends i {
7150
7163
  const r = this.root;
7151
7164
  const sel = this.selectedNode;
7152
7165
  if (!r || !sel) return;
7153
- const totalItems = (this.#findPath(r, sel) ?? [r]).length + (this.#hasChildOptions() ? 1 : 0);
7166
+ const totalItems = this.#getTickledItems().length;
7154
7167
  const currentTickled = this.tickled.tickledId ?? -1;
7155
7168
  switch (e.key) {
7156
7169
  case `ArrowRight`:
7157
7170
  e.preventDefault();
7158
7171
  if (currentTickled < totalItems - 1) this.tickled.handleKeyboardNavigation(`next`);
7159
- else if (currentTickled === totalItems - 1) this.#shiftFocusToNarrowedText();
7172
+ else if (currentTickled === totalItems - 1 && this.#canFocusSuggestions()) this.#shiftFocusToNarrowedText();
7160
7173
  break;
7161
7174
  case `ArrowLeft`:
7162
7175
  e.preventDefault();
@@ -7176,8 +7189,9 @@ let CrumbNavigationElement = class CrumbNavigationElement extends i {
7176
7189
  }
7177
7190
  break;
7178
7191
  case `Enter`:
7192
+ case ` `:
7179
7193
  e.preventDefault();
7180
- this.#handleEnter();
7194
+ this.#activateTickled();
7181
7195
  break;
7182
7196
  case `Escape`:
7183
7197
  e.preventDefault();
@@ -7185,16 +7199,12 @@ let CrumbNavigationElement = class CrumbNavigationElement extends i {
7185
7199
  this.tickled.clearTickled();
7186
7200
  this.blur();
7187
7201
  break;
7188
- case `Tab`: if (e.shiftKey) {
7189
- e.preventDefault();
7190
- this.#shiftFocusToPath();
7191
- } else if (currentTickled === totalItems - 1) {
7192
- e.preventDefault();
7193
- this._menuOpen = false;
7194
- this._focusOnNarrowedText = true;
7195
- const narrowedText = this.shadowRoot?.querySelector(`ixfx-narrowed-text`);
7196
- if (narrowedText) narrowedText.focus();
7197
- }
7202
+ case `Tab`:
7203
+ if (e.shiftKey) break;
7204
+ if (currentTickled === totalItems - 1 && this.#canFocusSuggestions()) {
7205
+ e.preventDefault();
7206
+ this.#shiftFocusToNarrowedText();
7207
+ }
7198
7208
  }
7199
7209
  };
7200
7210
  this.#onNarrowedTextBlur = () => {
@@ -7246,7 +7256,7 @@ let CrumbNavigationElement = class CrumbNavigationElement extends i {
7246
7256
  enabled: true
7247
7257
  });
7248
7258
  });
7249
- if (this.#hasChildOptions()) items.push({
7259
+ if (this.#canFocusSuggestions()) items.push({
7250
7260
  id: pathNodes.length,
7251
7261
  enabled: true
7252
7262
  });
@@ -7282,8 +7292,8 @@ let CrumbNavigationElement = class CrumbNavigationElement extends i {
7282
7292
  if (!r || !sel) return;
7283
7293
  const pathNodes = this.#findPath(r, sel) ?? [r];
7284
7294
  let el = null;
7285
- if (index < pathNodes.length) el = this.shadowRoot?.querySelectorAll(`.crumb-segment`)[index] ?? null;
7286
- else if (index === pathNodes.length) el = this.shadowRoot?.querySelector(`#child-options-trigger`) ?? null;
7295
+ if (this.caretEmbedded && this.#canFocusSuggestions() && index === pathNodes.length) el = this.shadowRoot?.querySelector(`ixfx-narrowed-text`) ?? null;
7296
+ else el = this.shadowRoot?.querySelectorAll(`.crumb-segment`)[index] ?? null;
7287
7297
  el?.scrollIntoView({
7288
7298
  inline: `nearest`,
7289
7299
  block: `nearest`,
@@ -7296,6 +7306,10 @@ let CrumbNavigationElement = class CrumbNavigationElement extends i {
7296
7306
  const isPending = this.#pendingNode === s;
7297
7307
  return (s.children ?? []).length > 0 || isPending;
7298
7308
  }
7309
+ /** True when the suggestions (narrowed-text) sub-part is renderable and focusable. */
7310
+ #canFocusSuggestions() {
7311
+ return this.showSuggestions && this.#hasChildOptions();
7312
+ }
7299
7313
  #onFocus;
7300
7314
  #onBlur;
7301
7315
  #getHostContainer() {
@@ -7308,26 +7322,18 @@ let CrumbNavigationElement = class CrumbNavigationElement extends i {
7308
7322
  const r = this.root;
7309
7323
  const sel = this.selectedNode;
7310
7324
  if (!r || !sel) return;
7311
- if (currentTickled < (this.#findPath(r, sel) ?? [r]).length - 1) {
7312
- const trigger = (this.shadowRoot?.querySelectorAll(`.crumb-segment`))?.[currentTickled]?.querySelector(`.caret ixfx-menu-trigger`);
7313
- if (trigger) {
7314
- this.#menuOpenedByKeyboard = true;
7315
- this.#currentOpenTrigger = trigger;
7316
- document.addEventListener(`keydown`, this.#onMenuKeyNav, { capture: true });
7317
- trigger.openMenu();
7318
- this.#propagateInputModeToMenu();
7319
- return;
7320
- }
7325
+ const pathNodes = this.#findPath(r, sel) ?? [r];
7326
+ if (this.caretEmbedded && this.#canFocusSuggestions() && currentTickled === pathNodes.length) {
7327
+ this.#shiftFocusToNarrowedText();
7328
+ return;
7321
7329
  }
7322
- if (this.#hasChildOptions()) {
7323
- const trigger = this.shadowRoot?.querySelector(`#child-options-trigger`);
7324
- if (trigger) {
7325
- this.#menuOpenedByKeyboard = true;
7326
- this.#currentOpenTrigger = trigger;
7327
- document.addEventListener(`keydown`, this.#onMenuKeyNav, { capture: true });
7328
- trigger.openMenu();
7329
- this.#propagateInputModeToMenu();
7330
- }
7330
+ const trigger = (this.shadowRoot?.querySelectorAll(`.crumb-segment`))?.[currentTickled]?.querySelector(`.caret ixfx-menu-trigger`);
7331
+ if (trigger) {
7332
+ this.#menuOpenedByKeyboard = true;
7333
+ this.#currentOpenTrigger = trigger;
7334
+ document.addEventListener(`keydown`, this.#onMenuKeyNav, { capture: true });
7335
+ trigger.openMenu();
7336
+ this.#propagateInputModeToMenu();
7331
7337
  }
7332
7338
  }
7333
7339
  #propagateInputModeToMenu() {
@@ -7340,40 +7346,24 @@ let CrumbNavigationElement = class CrumbNavigationElement extends i {
7340
7346
  #onMenuTriggerClose;
7341
7347
  #onMenuKeyNav;
7342
7348
  #onKeyDown;
7343
- #handleEnter() {
7349
+ /** Activates the currently tickled item, as if it had been clicked. */
7350
+ #activateTickled() {
7351
+ const currentTickled = this.tickled.tickledId;
7352
+ if (currentTickled === void 0) return;
7344
7353
  const r = this.root;
7345
7354
  const sel = this.selectedNode;
7346
7355
  if (!r || !sel) return;
7347
7356
  const pathNodes = this.#findPath(r, sel) ?? [r];
7348
- const hasChildOptions = this.#hasChildOptions();
7349
- const currentTickled = this.tickled.tickledId ?? -1;
7350
- if (currentTickled < pathNodes.length) {
7351
- const node = pathNodes[currentTickled];
7352
- this.#setSelected(node);
7353
- this._menuOpen = false;
7354
- this.dispatchEvent(new CustomEvent(`item-click`, {
7355
- detail: {
7356
- node,
7357
- depth: currentTickled
7358
- },
7359
- bubbles: true,
7360
- composed: true
7361
- }));
7362
- } else if (hasChildOptions && currentTickled === pathNodes.length) {
7363
- this._menuOpen = true;
7364
- this.#menuOpenedByKeyboard = true;
7365
- const trigger = this.shadowRoot?.querySelector(`#child-options-trigger`);
7366
- if (trigger) {
7367
- this.#currentOpenTrigger = trigger;
7368
- document.addEventListener(`keydown`, this.#onMenuKeyNav, { capture: true });
7369
- trigger.openMenu();
7370
- this.#propagateInputModeToMenu();
7371
- }
7357
+ if (this.caretEmbedded && this.#canFocusSuggestions() && currentTickled === pathNodes.length) {
7358
+ this.#shiftFocusToNarrowedText();
7359
+ return;
7372
7360
  }
7361
+ (this.shadowRoot?.querySelector(`.crumb-segment[data-segment-id="${currentTickled}"]`))?.click();
7373
7362
  }
7374
7363
  #shiftFocusToNarrowedText() {
7375
7364
  const narrowedText = this.shadowRoot?.querySelector(`ixfx-narrowed-text`);
7376
7365
  if (narrowedText) {
7366
+ this._menuOpen = false;
7377
7367
  this._focusOnNarrowedText = true;
7378
7368
  narrowedText.focus();
7379
7369
  }
@@ -7501,6 +7491,24 @@ let CrumbNavigationElement = class CrumbNavigationElement extends i {
7501
7491
  inline: `start`
7502
7492
  });
7503
7493
  }
7494
+ #updateTrailingWidth() {
7495
+ if (!this.padEnding || !this.shadowRoot) return;
7496
+ const hostContainer = this.shadowRoot.querySelector(`.host-container`);
7497
+ const trailing = this.shadowRoot.querySelector(`.trailing`);
7498
+ if (!hostContainer || !trailing) return;
7499
+ const segments = this.shadowRoot.querySelectorAll(`.crumb-segment`);
7500
+ const lastSegment = segments[segments.length - 1];
7501
+ if (!lastSegment) return;
7502
+ const containerWidth = hostContainer.getBoundingClientRect().width;
7503
+ const itemWidth = lastSegment.getBoundingClientRect().width;
7504
+ if (itemWidth < containerWidth) {
7505
+ trailing.style.width = `${containerWidth - itemWidth - 5}px`;
7506
+ requestAnimationFrame(() => {
7507
+ if (hostContainer.scrollWidth <= hostContainer.clientWidth) hostContainer.style.setProperty(`--scroll-fade-x-start`, `0px`, `important`);
7508
+ else hostContainer.style.removeProperty(`--scroll-fade-x-start`);
7509
+ });
7510
+ } else trailing.style.width = ``;
7511
+ }
7504
7512
  #setSelected(node) {
7505
7513
  const previous = this.selectedNode;
7506
7514
  if (previous) this.#previousSelectionKey = previous.item?.key ?? ``;
@@ -7508,11 +7516,14 @@ let CrumbNavigationElement = class CrumbNavigationElement extends i {
7508
7516
  const previousSet = previous ? /* @__PURE__ */ new Set([previous]) : /* @__PURE__ */ new Set();
7509
7517
  this.selectedNode = node;
7510
7518
  this._selectedNodes = /* @__PURE__ */ new Set([node]);
7511
- if (this.leadingCaret && this.root) {
7519
+ if (this.root) {
7512
7520
  const path = this.#findPath(this.root, node);
7513
7521
  if (path) {
7514
7522
  const depth = this.hideRoot && path.length > 1 ? path.length - 2 : path.length - 1;
7515
7523
  requestAnimationFrame(() => {
7524
+ this.#updateTrailingWidth();
7525
+ const hostContainer = this.#getHostContainer();
7526
+ if (hostContainer) hostContainer.scrollLeft = 0;
7516
7527
  this.#scrollSegmentIntoView(depth);
7517
7528
  });
7518
7529
  }
@@ -7529,7 +7540,7 @@ let CrumbNavigationElement = class CrumbNavigationElement extends i {
7529
7540
  #onLabelClick(node, depth) {
7530
7541
  this._openIdx = -1;
7531
7542
  this.#setSelected(node);
7532
- if (this.leadingCaret) this.#scrollSegmentIntoView(depth);
7543
+ this.#scrollSegmentIntoView(depth);
7533
7544
  this.dispatchEvent(new CustomEvent(`item-click`, {
7534
7545
  detail: {
7535
7546
  node,
@@ -7643,6 +7654,15 @@ let CrumbNavigationElement = class CrumbNavigationElement extends i {
7643
7654
  composed: true
7644
7655
  }));
7645
7656
  }
7657
+ #onUpClick() {
7658
+ const r = this.root;
7659
+ const sel = this.selectedNode;
7660
+ if (!r || !sel) return;
7661
+ const path = this.#findPath(r, sel);
7662
+ if (!path || path.length <= 1) return;
7663
+ const parent = path[path.length - 2];
7664
+ this.#setSelected(parent);
7665
+ }
7646
7666
  /** Navigate to a node by key path. Returns false if any key is not found in already-loaded children. */
7647
7667
  navigateTo(keys) {
7648
7668
  if (!this.root?.children) return false;
@@ -7690,6 +7710,9 @@ let CrumbNavigationElement = class CrumbNavigationElement extends i {
7690
7710
  let pathNodes = this.#findPath(r, sel) ?? [r];
7691
7711
  if (this.hideRoot && pathNodes.length > 1) pathNodes = pathNodes.slice(1);
7692
7712
  this.#hasChildOptions();
7713
+ const isAtRoot = (() => {
7714
+ return (this.#findPath(r, sel) ?? [r]).length <= 1;
7715
+ })();
7693
7716
  const parts = [];
7694
7717
  let segmentId = 0;
7695
7718
  pathNodes.forEach((node, i) => {
@@ -7720,7 +7743,7 @@ let CrumbNavigationElement = class CrumbNavigationElement extends i {
7720
7743
  ${showLeadingCaret ? b`
7721
7744
  <span class="caret ${isOpen ? `open` : ``} ${isPending ? `pending` : ``}">
7722
7745
  ${isPending ? b`<span class="loading-spinner"></span>` : b`
7723
- <ixfx-menu-trigger mode="trigger" label="›" @menu-command=${(e) => this.#onSegmentMenuCommand(e, node, i)}>
7746
+ <ixfx-menu-trigger mode="trigger" label="›" .tabStop=${false} @menu-command=${(e) => this.#onSegmentMenuCommand(e, node, i)}>
7724
7747
  <ixfx-menu-container slot="menu">
7725
7748
  ${siblingMenuItems}
7726
7749
  </ixfx-menu-container>
@@ -7732,7 +7755,7 @@ let CrumbNavigationElement = class CrumbNavigationElement extends i {
7732
7755
  ${showTrailingCaret ? b`
7733
7756
  <span class="caret ${isOpen ? `open` : ``} ${isPending ? `pending` : ``}">
7734
7757
  ${isPending ? b`<span class="loading-spinner"></span>` : b`
7735
- <ixfx-menu-trigger mode="trigger" label="›" placement="right-start" @menu-command=${(e) => this.#onSegmentMenuCommand(e, node, i)}>
7758
+ <ixfx-menu-trigger mode="trigger" label="›" .tabStop=${false} placement="right-start" @menu-command=${(e) => this.#onSegmentMenuCommand(e, node, i)}>
7736
7759
  <ixfx-menu-container slot="menu">
7737
7760
  ${childMenuItems}
7738
7761
  </ixfx-menu-container>
@@ -7754,7 +7777,7 @@ let CrumbNavigationElement = class CrumbNavigationElement extends i {
7754
7777
  >
7755
7778
  <span class="caret ${isOpen ? `open` : ``} ${isPending ? `pending` : ``}">
7756
7779
  ${isPending ? b`<span class="loading-spinner"></span>` : b`
7757
- <ixfx-menu-trigger mode="trigger" label="›" placement="right-start" @menu-command=${(e) => this.#onSegmentMenuCommand(e, node, i)}>
7780
+ <ixfx-menu-trigger mode="trigger" label="›" .tabStop=${false} placement="right-start" @menu-command=${(e) => this.#onSegmentMenuCommand(e, node, i)}>
7758
7781
  <ixfx-menu-container slot="menu">
7759
7782
  ${siblingMenuItems}
7760
7783
  </ixfx-menu-container>
@@ -7789,7 +7812,7 @@ let CrumbNavigationElement = class CrumbNavigationElement extends i {
7789
7812
  >
7790
7813
  <span class="caret ${isOpen ? `open` : ``} ${isPending ? `pending` : ``}">
7791
7814
  ${isPending ? b`<span class="loading-spinner"></span>` : b`
7792
- <ixfx-menu-trigger mode="trigger" label="›" @menu-command=${(e) => this.#onSegmentMenuCommand(e, node, i)}>
7815
+ <ixfx-menu-trigger mode="trigger" label="›" .tabStop=${false} @menu-command=${(e) => this.#onSegmentMenuCommand(e, node, i)}>
7793
7816
  <ixfx-menu-container slot="menu">
7794
7817
  ${childMenuItems}
7795
7818
  </ixfx-menu-container>
@@ -7803,18 +7826,29 @@ let CrumbNavigationElement = class CrumbNavigationElement extends i {
7803
7826
  }
7804
7827
  });
7805
7828
  return b`
7806
- <div
7807
- class="host-container scroll-fade-x"
7808
- tabindex="0"
7809
- @focus=${this.#onFocus}
7810
- @blur=${this.#onBlur}
7811
- @keydown=${this.#onKeyDown}
7812
- @click=${this.#onHostClick}
7813
- @menu-trigger-close=${this.#onMenuTriggerClose}
7814
- @mouseout=${(e) => this.tickled.handlePointerLeave(e)}
7815
- >
7816
- <div class="parts"
7817
- @mouseover=${(e) => {
7829
+ <div class="crumb-wrapper">
7830
+ ${this.withUp ? b`
7831
+ <button
7832
+ class="up-button"
7833
+ ?disabled=${isAtRoot}
7834
+ aria-label="Go up one level"
7835
+ @click=${this.#onUpClick}
7836
+ >
7837
+ <ixfx-icon name="folder-up"></ixfx-icon>
7838
+ </button>
7839
+ ` : A}
7840
+ <div
7841
+ class="host-container scroll-fade-x"
7842
+ tabindex="0"
7843
+ @focus=${this.#onFocus}
7844
+ @blur=${this.#onBlur}
7845
+ @keydown=${this.#onKeyDown}
7846
+ @click=${this.#onHostClick}
7847
+ @menu-trigger-close=${this.#onMenuTriggerClose}
7848
+ @mouseout=${(e) => this.tickled.handlePointerLeave(e)}
7849
+ >
7850
+ <div class="parts"
7851
+ @mouseover=${(e) => {
7818
7852
  if (this.#isWheelScrolling) return;
7819
7853
  const target = e.target;
7820
7854
  if (!(target instanceof HTMLElement)) return;
@@ -7835,8 +7869,9 @@ let CrumbNavigationElement = class CrumbNavigationElement extends i {
7835
7869
  composed: true
7836
7870
  }));
7837
7871
  }}
7838
- >${parts}<div class="trailing"></div></div>
7839
- ${this.showSuggestions ? this.#renderChildOptions() : A}
7872
+ >${parts}${this.padEnding ? b`<div class="trailing"></div>` : A}</div>
7873
+ ${this.showSuggestions ? this.#renderChildOptions() : A}
7874
+ </div>
7840
7875
  </div>
7841
7876
  `;
7842
7877
  }
@@ -7897,7 +7932,7 @@ let CrumbNavigationElement = class CrumbNavigationElement extends i {
7897
7932
  --crumb-item-text-tickled: var(--item-text-tickled);
7898
7933
  --crumb-item-border: var(--item-border);
7899
7934
  --crumb-item-border-tickled: var(--item-border-tickled);
7900
- --crumb-item-padding: var(--item-padding, var(--space-xs));
7935
+ --crumb-item-padding: var(--space-s, 2px);
7901
7936
  --crumb-item-border-radius: var(--item-border-radius);
7902
7937
  --crumb-item-gap: var(--item-gap, var(--space-xs));
7903
7938
  --crumb-separator: var(--surface-muted-text);
@@ -7906,24 +7941,65 @@ let CrumbNavigationElement = class CrumbNavigationElement extends i {
7906
7941
  width: 100%;
7907
7942
  }
7908
7943
 
7909
- :host(.focused) {
7910
- outline: none;
7911
- }
7912
-
7913
- :host(:focus-within) .host-container {
7944
+ /* Outline goes on :host, not .host-container: .host-container carries the
7945
+ * scroll-fade mask-image, and CSS masks clip everything painted outside
7946
+ * the masked box - including an outline, which paints outside the border edge. */
7947
+ :host(:focus-within) {
7914
7948
  outline: 2px solid var(--accent);
7915
7949
  outline-offset: 2px;
7916
7950
  }
7917
7951
 
7952
+ .crumb-wrapper {
7953
+ display: flex;
7954
+ align-items: center;
7955
+ gap: var(--crumb-item-gap);
7956
+ width: 100%;
7957
+ }
7958
+
7959
+ .up-button {
7960
+ display: inline-flex;
7961
+ align-items: center;
7962
+ justify-content: center;
7963
+ flex-shrink: 0;
7964
+ background: var(--crumb-item-bg);
7965
+ border: var(--crumb-item-border);
7966
+ border-radius: var(--crumb-item-border-radius);
7967
+ padding: var(--crumb-item-padding);
7968
+ cursor: pointer;
7969
+ color: inherit;
7970
+ }
7971
+
7972
+ .up-button:disabled {
7973
+ opacity: 0.5;
7974
+ cursor: not-allowed;
7975
+ }
7976
+
7977
+ .up-button:hover:not(:disabled) {
7978
+ background: var(--crumb-item-bg-tickled);
7979
+ border-color: var(--crumb-item-border-tickled);
7980
+ }
7981
+
7982
+ .up-button ixfx-icon {
7983
+ width: 1em;
7984
+ height: 1em;
7985
+ pointer-events: none;
7986
+ }
7987
+
7918
7988
  /* Edge fade (shows/hides based on scroll position) comes from the
7919
7989
  * shared .scroll-fade-x class - see ../styles/scroll-fade.ts */
7920
7990
  .host-container {
7921
7991
  display: flex;
7922
- width: 100%;
7992
+ flex: 1;
7993
+ min-width: 0;
7923
7994
  outline: none;
7924
7995
  overflow: scroll;
7925
7996
  scroll-snap-type: x mandatory;
7926
7997
  scrollbar-width: none;
7998
+ overscroll-behavior: none;
7999
+ }
8000
+
8001
+ .host-container::-webkit-scrollbar {
8002
+ display: none;
7927
8003
  }
7928
8004
 
7929
8005
  .parts {
@@ -7932,9 +8008,7 @@ let CrumbNavigationElement = class CrumbNavigationElement extends i {
7932
8008
  }
7933
8009
 
7934
8010
  .trailing {
7935
- flex: 1;
7936
- min-width: 1em;
7937
- cursor: pointer;
8011
+ flex-shrink: 0;
7938
8012
  }
7939
8013
 
7940
8014
  .crumb-segment {
@@ -7944,6 +8018,7 @@ let CrumbNavigationElement = class CrumbNavigationElement extends i {
7944
8018
  background: var(--crumb-item-bg);
7945
8019
  border: var(--crumb-item-border);
7946
8020
  border-radius: var(--crumb-item-border-radius);
8021
+ padding:0;
7947
8022
  }
7948
8023
 
7949
8024
  .crumb-segment.leading-caret {
@@ -7972,6 +8047,7 @@ let CrumbNavigationElement = class CrumbNavigationElement extends i {
7972
8047
  }
7973
8048
 
7974
8049
  .label {
8050
+ padding: var(--crumb-item-padding);
7975
8051
  cursor: pointer;
7976
8052
  white-space: nowrap;
7977
8053
  color: inherit;
@@ -7992,15 +8068,12 @@ let CrumbNavigationElement = class CrumbNavigationElement extends i {
7992
8068
  }
7993
8069
 
7994
8070
  .crumb-segment ixfx-menu-trigger {
7995
- --ixfx-button-padding: var(--space-xs) 8px;
8071
+ --ixfx-button-padding: var(--space-s, 2px);
7996
8072
  }
7997
8073
 
7998
8074
  .caret {
7999
8075
  position: relative;
8000
8076
  cursor: pointer;
8001
- padding: var(--crumb-item-padding);
8002
- margin-left: var(--crumb-item-gap);
8003
- margin-right: var(--crumb-item-gap);
8004
8077
  color: var(--crumb-separator);
8005
8078
  display: inline-flex;
8006
8079
  align-items: center;
@@ -8027,7 +8100,6 @@ let CrumbNavigationElement = class CrumbNavigationElement extends i {
8027
8100
  background: none;
8028
8101
  border: none;
8029
8102
  color: inherit;
8030
- padding: 0;
8031
8103
  cursor: pointer;
8032
8104
  font-size: inherit;
8033
8105
  line-height: 1;
@@ -8152,6 +8224,16 @@ __decorate([property({
8152
8224
  reflect: true,
8153
8225
  attribute: `hide-root`
8154
8226
  })], CrumbNavigationElement.prototype, "hideRoot", void 0);
8227
+ __decorate([property({
8228
+ type: Boolean,
8229
+ reflect: true,
8230
+ attribute: `pad-ending`
8231
+ })], CrumbNavigationElement.prototype, "padEnding", void 0);
8232
+ __decorate([property({
8233
+ type: Boolean,
8234
+ reflect: true,
8235
+ attribute: `with-up`
8236
+ })], CrumbNavigationElement.prototype, "withUp", void 0);
8155
8237
  CrumbNavigationElement = __decorate([safeCustomElement(`ixfx-crumb-navigation`)], CrumbNavigationElement);
8156
8238
  //#endregion
8157
8239
  //#region src/crumbs/crumb-path-controller.ts
@@ -21661,6 +21743,258 @@ __decorate([property({ type: Number })], RangeElement.prototype, "value", null);
21661
21743
  __decorate([property({ type: Number })], RangeElement.prototype, "step", void 0);
21662
21744
  RangeElement = __decorate([safeCustomElement(`ixfx-range`)], RangeElement);
21663
21745
  //#endregion
21746
+ //#region src/select-horiz/select-horiz.ts
21747
+ let SelectHorizElement = class SelectHorizElement extends WheelNudgeMixin(i) {
21748
+ constructor(..._args) {
21749
+ super(..._args);
21750
+ this._selectedIndex = -1;
21751
+ this._slottedItems = [];
21752
+ this.tickled = new TickledController(this, {
21753
+ getItems: () => this._slottedItems.map((_, i) => ({
21754
+ id: i,
21755
+ enabled: true
21756
+ })),
21757
+ onStateChange: () => this._syncTickled()
21758
+ });
21759
+ this._onSlotChange = () => {
21760
+ this._slottedItems = Array.from(this.shadowRoot?.querySelector(`slot`)?.assignedElements() ?? []);
21761
+ const declaredIndex = this._slottedItems.findIndex((item) => item.hasAttribute(`selected`));
21762
+ let resolvedIndex = declaredIndex >= 0 ? declaredIndex : this._selectedIndex;
21763
+ if (resolvedIndex >= this._slottedItems.length) resolvedIndex = this._slottedItems.length - 1;
21764
+ if (resolvedIndex < 0 && this._slottedItems.length > 0) resolvedIndex = 0;
21765
+ this.selectedIndex = resolvedIndex;
21766
+ };
21767
+ this._syncTickled = () => {
21768
+ this._slottedItems.forEach((item, i) => {
21769
+ const isTickled = this.tickled.isTickled(i);
21770
+ item.classList.toggle(`tickled`, isTickled);
21771
+ item.tabIndex = isTickled && this.tickled.inputMode === `keyboard` ? 0 : -1;
21772
+ });
21773
+ };
21774
+ this._findSlottedItem = (target) => {
21775
+ let el = target instanceof Element ? target : null;
21776
+ while (el) {
21777
+ if (this._slottedItems.includes(el)) return el;
21778
+ el = el.parentElement;
21779
+ }
21780
+ };
21781
+ this._handlePointerOver = (e) => {
21782
+ const item = this._findSlottedItem(e.target);
21783
+ if (item) this.tickled.handlePointerEnter(this._slottedItems.indexOf(item));
21784
+ };
21785
+ this._handleKeyDown = (e) => {
21786
+ if (e.key === `ArrowLeft`) {
21787
+ e.preventDefault();
21788
+ this.tickled.handleKeyboardNavigation(`previous`);
21789
+ this._applyTickledSelection();
21790
+ } else if (e.key === `ArrowRight`) {
21791
+ e.preventDefault();
21792
+ this.tickled.handleKeyboardNavigation(`next`);
21793
+ this._applyTickledSelection();
21794
+ } else if (e.key === `Home`) {
21795
+ e.preventDefault();
21796
+ this.tickled.handleKeyboardNavigation(`first`);
21797
+ this._applyTickledSelection();
21798
+ } else if (e.key === `End`) {
21799
+ e.preventDefault();
21800
+ this.tickled.handleKeyboardNavigation(`last`);
21801
+ this._applyTickledSelection();
21802
+ }
21803
+ };
21804
+ this._applyTickledSelection = () => {
21805
+ const id = this.tickled.tickledId;
21806
+ if (id !== void 0 && id !== this._selectedIndex) this.selectedIndex = id;
21807
+ };
21808
+ this._wheelCooldown = false;
21809
+ this._handleClick = (e) => {
21810
+ e.currentTarget.focus();
21811
+ const item = this._findSlottedItem(e.target);
21812
+ const index = item ? this._slottedItems.indexOf(item) : -1;
21813
+ if (index >= 0 && index !== this._selectedIndex) this.selectedIndex = index;
21814
+ };
21815
+ this._updateSelectedAttribute = () => {
21816
+ this._slottedItems.forEach((item, i) => {
21817
+ if (i === this._selectedIndex) item.setAttribute(`selected`, ``);
21818
+ else item.removeAttribute(`selected`);
21819
+ });
21820
+ };
21821
+ this._scrollSelectedIntoView = () => {
21822
+ const item = this._slottedItems[this._selectedIndex];
21823
+ if (item) item.scrollIntoView({
21824
+ inline: `center`,
21825
+ behavior: `smooth`
21826
+ });
21827
+ };
21828
+ this._emitChange = () => {
21829
+ this.dispatchEvent(new CustomEvent(`change`, {
21830
+ detail: {
21831
+ selectedIndex: this._selectedIndex,
21832
+ selectedItem: this.selectedItem,
21833
+ selectedValue: this.selectedValue
21834
+ },
21835
+ bubbles: true,
21836
+ composed: true
21837
+ }));
21838
+ };
21839
+ }
21840
+ static {
21841
+ this.styles = [
21842
+ themeFallbacks,
21843
+ tickledStyles,
21844
+ tickledItemStyles,
21845
+ scrollFadeStyles(`x`),
21846
+ i$3`
21847
+ :host {
21848
+ --select-horiz-item-width: 80%;
21849
+ --select-horiz-gap: var(--space-s);
21850
+ --select-horiz-bg: var(--surface-3);
21851
+ --select-horiz-border: var(--border);
21852
+ --select-horiz-radius: var(--radius-l);
21853
+ display: flex;
21854
+ width: 100%;
21855
+ background: var(--select-horiz-bg);
21856
+ border: var(--select-horiz-border);
21857
+ border-radius: var(--select-horiz-radius);
21858
+ }
21859
+
21860
+ /* Edge fade (the scroll-fade-x class, see ../styles/scroll-fade.ts) must sit on
21861
+ * the element that actually scrolls - its mask is sized to this element's own
21862
+ * box, and content overflowing a *different*, non-scrolling ancestor gets the
21863
+ * mask tiled across it instead of fading correctly. */
21864
+ .items {
21865
+ display: flex;
21866
+ align-items: center;
21867
+ gap: var(--select-horiz-gap);
21868
+ padding: var(--space-xs) var(--scroll-fade-width, 30px);
21869
+ width: 100%;
21870
+ min-height: 48px;
21871
+ overflow-x: scroll;
21872
+ overflow-y: hidden;
21873
+ scrollbar-width: none;
21874
+ scroll-snap-type: x mandatory;
21875
+ -webkit-overflow-scrolling: touch;
21876
+ cursor: grab;
21877
+
21878
+ box-sizing: border-box;
21879
+ }
21880
+
21881
+ .items:focus-within {
21882
+ cursor: default;
21883
+ }
21884
+
21885
+ .spacer {
21886
+ flex: 0 0 var(--select-horiz-spacer-width, 10%);
21887
+ pointer-events: none;
21888
+ user-select: none;
21889
+ }
21890
+
21891
+ ::slotted(*) {
21892
+ flex: 0 0 var(--select-horiz-item-width);
21893
+ scroll-snap-align: center;
21894
+ user-select: none;
21895
+ min-height: 100%;
21896
+ box-sizing: border-box;
21897
+ transition: opacity var(--transition), background var(--transition), border-color var(--transition), color var(--transition);
21898
+ background: var(--item-bg);
21899
+ border: var(--item-border);
21900
+ border-radius: var(--item-border-radius);
21901
+ padding: var(--item-padding);
21902
+ display: grid;
21903
+ align-content: center;
21904
+ justify-content: center;
21905
+ }
21906
+
21907
+ ::slotted(.tickled) {
21908
+ background: var(--item-bg-tickled);
21909
+ border-color: var(--item-border-tickled);
21910
+ color: var(--item-text-tickled);
21911
+ }
21912
+
21913
+ ::slotted([selected]) {
21914
+ background: var(--item-bg-selected);
21915
+ border-color: var(--item-border-selected);
21916
+ color: var(--item-text-selected);
21917
+ }
21918
+
21919
+ ::slotted([selected].tickled) {
21920
+ background: var(--item-bg-selected-tickled);
21921
+ outline: 2px dashed var(--surface-3);
21922
+ outline-offset: -2px;
21923
+ }
21924
+
21925
+ ::-webkit-scrollbar {
21926
+ display: none;
21927
+ }
21928
+ `
21929
+ ];
21930
+ }
21931
+ get selectedIndex() {
21932
+ return this._selectedIndex;
21933
+ }
21934
+ set selectedIndex(value) {
21935
+ const oldValue = this._selectedIndex;
21936
+ if (value < -1 || this._slottedItems.length > 0 && value >= this._slottedItems.length) return;
21937
+ this._selectedIndex = value;
21938
+ this._updateSelectedAttribute();
21939
+ this._scrollSelectedIntoView();
21940
+ this.tickled.setTickled(value === -1 ? void 0 : value);
21941
+ if (oldValue !== value) this._emitChange();
21942
+ }
21943
+ get selectedValue() {
21944
+ return this._slottedItems[this._selectedIndex]?.getAttribute(`value`) ?? null;
21945
+ }
21946
+ set selectedValue(value) {
21947
+ if (value === null) return;
21948
+ const index = this._slottedItems.findIndex((item) => item.getAttribute(`value`) === value);
21949
+ if (index >= 0) this.selectedIndex = index;
21950
+ }
21951
+ get selectedItem() {
21952
+ return this._slottedItems[this._selectedIndex] ?? null;
21953
+ }
21954
+ get items() {
21955
+ return this._slottedItems;
21956
+ }
21957
+ render() {
21958
+ return b`
21959
+ <div
21960
+ class="items scroll-fade-x"
21961
+ tabindex="0"
21962
+ data-input-mode=${this.tickled.inputMode}
21963
+ @pointerover=${this._handlePointerOver}
21964
+ @pointerleave=${(e) => this.tickled.handlePointerLeave(e)}
21965
+ @keydown=${this._handleKeyDown}
21966
+ @click=${this._handleClick}
21967
+ >
21968
+ <div class="spacer"></div>
21969
+ <slot @slotchange=${this._onSlotChange}></slot>
21970
+ <div class="spacer"></div>
21971
+ </div>
21972
+ `;
21973
+ }
21974
+ willUpdate(changed) {
21975
+ super.willUpdate(changed);
21976
+ this.setAttribute(`data-input-mode`, this.tickled.inputMode);
21977
+ }
21978
+ _applyWheelDelta(direction, _event) {
21979
+ if (this._wheelCooldown) return;
21980
+ this._wheelCooldown = true;
21981
+ this.tickled.handleKeyboardNavigation(direction === 1 ? `next` : `previous`);
21982
+ this._applyTickledSelection();
21983
+ setTimeout(() => {
21984
+ this._wheelCooldown = false;
21985
+ }, 250);
21986
+ }
21987
+ };
21988
+ __decorate([state()], SelectHorizElement.prototype, "_selectedIndex", void 0);
21989
+ __decorate([state()], SelectHorizElement.prototype, "_slottedItems", void 0);
21990
+ __decorate([property({
21991
+ type: Number,
21992
+ reflect: true,
21993
+ attribute: `selected-index`
21994
+ })], SelectHorizElement.prototype, "selectedIndex", null);
21995
+ __decorate([property({ type: String })], SelectHorizElement.prototype, "selectedValue", null);
21996
+ SelectHorizElement = __decorate([safeCustomElement(`ixfx-select-horiz`)], SelectHorizElement);
21997
+ //#endregion
21664
21998
  //#region src/selecthorizontal.ts
21665
21999
  let SelectHorizontalElement = class SelectHorizontalElement extends i {
21666
22000
  constructor(..._args) {
@@ -23967,7 +24301,7 @@ let SplitLayoutElement = class SplitLayoutElement extends i {
23967
24301
  if (nestedSplit) {
23968
24302
  this.#nestedSplitInitialSizeA = nestedSplit.sizeA;
23969
24303
  const nestedBounds = nestedSplit.getBoundingClientRect();
23970
- const nestedHandle = nestedSplit.shadowRoot?.querySelector(`.resize-handle`);
24304
+ const nestedHandle = nestedSplit.shadowRoot?.querySelector(`.split-bar`);
23971
24305
  if (nestedHandle) {
23972
24306
  this.#nestedSplitBounds = nestedBounds;
23973
24307
  this.#nestedHandleBounds = nestedHandle.getBoundingClientRect();
@@ -24036,6 +24370,11 @@ let SplitLayoutElement = class SplitLayoutElement extends i {
24036
24370
  event.preventDefault();
24037
24371
  };
24038
24372
  }
24373
+ get showGrabHandle() {
24374
+ const size = getComputedStyle(this).getPropertyValue(`--handle-size`).trim();
24375
+ const num = Number.parseFloat(size);
24376
+ return !Number.isNaN(num) && num > 3;
24377
+ }
24039
24378
  #elementBounds;
24040
24379
  #startSizeA;
24041
24380
  #startSizeB;
@@ -24256,17 +24595,30 @@ let SplitLayoutElement = class SplitLayoutElement extends i {
24256
24595
  <div id="zone">
24257
24596
  <slot style=${sizeA} name="a"></slot>
24258
24597
  ${this._hasCorner ? b`<div class="corner-zone" @pointerdown=${this.#onCornerResizeDown}></div>` : ``}
24259
- <div @pointerdown=${this.#onResizeHandleDown} class="resize-handle"></div>
24260
- <slot style=${sizeB} name="b"></slot>
24598
+ <div @pointerdown=${this.#onResizeHandleDown} class="split-bar">
24599
+ ${this.showGrabHandle ? b`
24600
+ <div class="grab-handle">
24601
+ <span class="dot"></span>
24602
+ <span class="dot"></span>
24603
+ <span class="dot"></span>
24604
+ </div>
24605
+ ` : ``}
24606
+ </div>
24607
+ <slot style=${sizeB} name="b"></slot>
24261
24608
  </div>`;
24262
24609
  }
24263
24610
  static {
24264
24611
  this.styles = [themeFallbacks, i$3`
24265
24612
  :host {
24266
24613
  --handle-size: 2px;
24267
- --handle-colour: var(--surface-5);
24614
+ --handle-colour: transparent;
24268
24615
  --handle-hover-colour: var(--surface-6);
24269
24616
  --handle-active-colour: var(--accent);
24617
+ --handle-bg: var(--handle-colour);
24618
+ --handle-grab-colour: var(--border-subtle-color);
24619
+ --handle-grab-dot-size: 3px;
24620
+ --handle-grab-size: 16px;
24621
+ --handle-grab-thickness: 8px;
24270
24622
 
24271
24623
  display: block;
24272
24624
  box-sizing: border-box;
@@ -24284,29 +24636,80 @@ let SplitLayoutElement = class SplitLayoutElement extends i {
24284
24636
  slot {
24285
24637
  display: block;
24286
24638
  overflow: hidden;
24639
+ border: var(--border-subtle);
24640
+ border-radius: var(--radius-m);
24287
24641
  }
24288
24642
  :slotted(*) {
24289
24643
  width: 100%;
24290
24644
  height: 100%;
24291
24645
  }
24292
24646
 
24293
- .resize-handle {
24647
+ .split-bar {
24648
+ position: relative;
24294
24649
  background-color: var(--handle-colour);
24650
+ transition: background-color 0.3s ease 0s;
24295
24651
  width: var(--handle-size);
24296
24652
  height: 100%;
24297
24653
  cursor: ew-resize;
24298
24654
  flex-shrink: 0;
24655
+ border-radius: var(--radius-m);
24656
+
24657
+ }
24658
+
24659
+ @keyframes handle-hover {
24660
+ from { background-color: var(--handle-colour); }
24661
+ to { background-color: var(--handle-hover-colour); }
24662
+ }
24663
+
24664
+ .grab-handle {
24665
+ position: absolute;
24666
+ top: 50%;
24667
+ left: 50%;
24668
+ transform: translate(-50%, -50%);
24669
+ display: flex;
24670
+ align-items: center;
24671
+ justify-content: center;
24672
+ gap: var(--handle-grab-dot-size);
24673
+ background: var(--handle-bg);
24674
+ border-radius: var(--radius-s);
24675
+ }
24676
+
24677
+ .grab-handle .dot {
24678
+ width: var(--handle-grab-dot-size);
24679
+ height: var(--handle-grab-dot-size);
24680
+ border-radius: 50%;
24681
+ background: var(--handle-grab-colour);
24682
+ flex-shrink: 0;
24683
+ }
24684
+
24685
+ :host([layout="vertical"]) .grab-handle {
24686
+ flex-direction: column;
24687
+ width: var(--handle-grab-thickness);
24688
+ height: var(--handle-grab-size);
24689
+ }
24690
+
24691
+ :host([layout="horizontal"]) .grab-handle {
24692
+ flex-direction: row;
24693
+ width: var(--handle-grab-size);
24694
+ height: var(--handle-grab-thickness);
24695
+ }
24696
+
24697
+ #zone.user-resizing .grab-handle {
24698
+ display: none;
24299
24699
  }
24300
24700
  #zone.user-resizing {
24301
24701
  slot {
24302
24702
  opacity: 0.5;
24303
24703
  }
24304
- .resize-handle {
24704
+ .split-bar {
24305
24705
  background-color: var(--handle-active-colour);
24706
+ transition: none;
24707
+ animation: none !important;
24306
24708
  }
24307
24709
  }
24308
- .resize-handle:hover {
24309
- background-color: var(--handle-hover-colour);
24710
+
24711
+ #zone:not(.user-resizing) .split-bar:hover {
24712
+ animation: handle-hover 0.001s ease-out 0.7s both;
24310
24713
  }
24311
24714
 
24312
24715
  .corner-zone {
@@ -24325,17 +24728,18 @@ let SplitLayoutElement = class SplitLayoutElement extends i {
24325
24728
  #zone {
24326
24729
  flex-direction: column;
24327
24730
  }
24328
- .resize-handle {
24329
- background-color: silver;
24731
+ .split-bar {
24732
+ position: relative;
24733
+ background-color: var(--handle-colour);
24734
+ transition: background-color 0.3s ease 0s;
24330
24735
  height: var(--handle-size);
24331
24736
  width: 100%;
24332
24737
  cursor: ns-resize;
24333
24738
  }
24334
- .resize-handle:hover {
24335
- background-color: var(--handle-hover-colour);
24336
- }
24337
- #zone.user-resizing .resize-handle {
24739
+ #zone.user-resizing .split-bar {
24338
24740
  background-color: var(--handle-active-colour);
24741
+ transition: none;
24742
+ animation: none !important;
24339
24743
  }
24340
24744
  }
24341
24745
 
@@ -24591,11 +24995,16 @@ let TabListItemElement = class TabListItemElement extends i {
24591
24995
  constructor(..._args) {
24592
24996
  super(..._args);
24593
24997
  this.closeable = false;
24998
+ this.hideLabels = false;
24594
24999
  this.iconName = void 0;
24595
25000
  this.description = void 0;
24596
25001
  this.commandActive = void 0;
24597
25002
  this.registry = void 0;
24598
25003
  this._compact = false;
25004
+ this._hasToolbarContent = false;
25005
+ this._onToolbarSlotChange = () => {
25006
+ this._updateToolbarContent();
25007
+ };
24599
25008
  }
24600
25009
  connectedCallback() {
24601
25010
  super.connectedCallback();
@@ -24603,6 +25012,7 @@ let TabListItemElement = class TabListItemElement extends i {
24603
25012
  this._compact = entry.contentRect.width < 64;
24604
25013
  });
24605
25014
  this._resizeObserver.observe(this);
25015
+ (this.shadowRoot?.querySelector(`slot[name="toolbar"]`))?.addEventListener(`slotchange`, this._onToolbarSlotChange);
24606
25016
  }
24607
25017
  disconnectedCallback() {
24608
25018
  super.disconnectedCallback();
@@ -24610,6 +25020,7 @@ let TabListItemElement = class TabListItemElement extends i {
24610
25020
  this._resizeObserver = void 0;
24611
25021
  this._commandCleanup?.();
24612
25022
  this._commandCleanup = void 0;
25023
+ (this.shadowRoot?.querySelector(`slot[name="toolbar"]`))?.removeEventListener(`slotchange`, this._onToolbarSlotChange);
24613
25024
  }
24614
25025
  updated(changed) {
24615
25026
  super.updated(changed);
@@ -24632,12 +25043,21 @@ let TabListItemElement = class TabListItemElement extends i {
24632
25043
  if (id === this.commandActive) this.click();
24633
25044
  });
24634
25045
  }
25046
+ _updateToolbarContent() {
25047
+ const slot = this.shadowRoot?.querySelector(`slot[name="toolbar"]`);
25048
+ this._hasToolbarContent = (slot?.assignedElements().length ?? 0) > 0;
25049
+ }
25050
+ firstUpdated() {
25051
+ this._updateToolbarContent();
25052
+ }
24635
25053
  render() {
24636
- const showLabel = !this._compact || !this.iconName;
25054
+ const showLabel = !this.hideLabels || !this.iconName;
25055
+ const hasActions = this.closeable || this._hasToolbarContent;
24637
25056
  return b`
24638
25057
  <div>
24639
25058
  ${this.iconName ? b`<ixfx-icon name="${this.iconName}"></ixfx-icon>` : A}
24640
25059
  ${showLabel ? b`<span class="label"><slot></slot></span>` : A}
25060
+ ${hasActions ? b`
24641
25061
  <div class="actions">
24642
25062
  <div class="toolbar"><slot name="toolbar"></slot></div>
24643
25063
  ${this.closeable ? b`
@@ -24651,6 +25071,7 @@ let TabListItemElement = class TabListItemElement extends i {
24651
25071
  </button>
24652
25072
  ` : A}
24653
25073
  </div>
25074
+ ` : A}
24654
25075
  </div>
24655
25076
  `;
24656
25077
  }
@@ -24677,17 +25098,19 @@ let TabListItemElement = class TabListItemElement extends i {
24677
25098
  min-width: 0;
24678
25099
  user-select: none;
24679
25100
  box-sizing: border-box;
25101
+ height:fit-content;
24680
25102
  }
24681
25103
 
24682
25104
  :host > div {
24683
25105
  display: flex;
24684
25106
  align-items: center;
24685
- gap: var(--space-s, 4px);
24686
- padding: var(--tab-padding) calc(2 * var(--tab-padding));
25107
+ padding: var(--tab-padding) calc(2 * var(--tab-padding-horizontal, var(--tab-padding)));
24687
25108
  min-width: 0;
24688
25109
  width: 100%;
24689
25110
  font-weight: 500;
24690
25111
  border: var(--selected-tab-border-width) solid transparent;
25112
+ gap: var(--space-s);
25113
+
24691
25114
  }
24692
25115
 
24693
25116
  :host([selected]) > div {
@@ -24698,6 +25121,7 @@ let TabListItemElement = class TabListItemElement extends i {
24698
25121
  border-right-color: var(--indicator-color-right, transparent);
24699
25122
  background: var(--selected-background);
24700
25123
  font-weight: var(--selected-tab-weight);
25124
+ border-radius:var(--radius-m);
24701
25125
  }
24702
25126
 
24703
25127
  .label {
@@ -24772,6 +25196,10 @@ let TabListItemElement = class TabListItemElement extends i {
24772
25196
  }
24773
25197
  };
24774
25198
  __decorate([property({ type: Boolean })], TabListItemElement.prototype, "closeable", void 0);
25199
+ __decorate([property({
25200
+ type: Boolean,
25201
+ attribute: `hide-labels`
25202
+ })], TabListItemElement.prototype, "hideLabels", void 0);
24775
25203
  __decorate([property({
24776
25204
  type: String,
24777
25205
  attribute: `icon-name`
@@ -24783,6 +25211,7 @@ __decorate([property({
24783
25211
  })], TabListItemElement.prototype, "commandActive", void 0);
24784
25212
  __decorate([property({ attribute: false })], TabListItemElement.prototype, "registry", void 0);
24785
25213
  __decorate([state()], TabListItemElement.prototype, "_compact", void 0);
25214
+ __decorate([state()], TabListItemElement.prototype, "_hasToolbarContent", void 0);
24786
25215
  TabListItemElement = __decorate([safeCustomElement(`ixfx-tab-list-item`)], TabListItemElement);
24787
25216
  //#endregion
24788
25217
  //#region src/tabs/tab-panel.ts
@@ -25201,6 +25630,7 @@ let TabListElement = class TabListElement extends i {
25201
25630
  this.orientation = `horizontal`;
25202
25631
  this.flip = false;
25203
25632
  this.scrollable = false;
25633
+ this.hideLabels = false;
25204
25634
  this.dragMode = `off`;
25205
25635
  this.#items = [];
25206
25636
  this.#dragState = null;
@@ -25209,6 +25639,7 @@ let TabListElement = class TabListElement extends i {
25209
25639
  this.updateComplete.then(() => {
25210
25640
  this.#items = (this.shadowRoot?.querySelector(`slot`))?.assignedElements({ flatten: true }) ?? [];
25211
25641
  this.#syncIndicatorColors();
25642
+ this.#syncHideLabels();
25212
25643
  });
25213
25644
  };
25214
25645
  this.#onKeyUp = (event) => {
@@ -25350,13 +25781,21 @@ let TabListElement = class TabListElement extends i {
25350
25781
  #onSlotChange;
25351
25782
  firstUpdated() {
25352
25783
  this.updateComplete.then(() => {
25353
- if (this.#items.length > 0) this.#syncIndicatorColors();
25784
+ if (this.#items.length > 0) {
25785
+ this.#syncIndicatorColors();
25786
+ this.#syncHideLabels();
25787
+ }
25354
25788
  });
25355
25789
  }
25356
25790
  updated(changedProperties) {
25357
25791
  super.updated(changedProperties);
25358
25792
  this.classList.toggle(`scrollable`, this.scrollable);
25359
25793
  if (changedProperties.has(`dragMode`)) this.toggleAttribute(`drag-mode`, this.dragMode !== `off`);
25794
+ if (changedProperties.has(`hideLabels`)) this.#syncHideLabels();
25795
+ }
25796
+ #syncHideLabels() {
25797
+ for (const item of this.#items) if (this.hideLabels) item.setAttribute(`hide-labels`, ``);
25798
+ else item.removeAttribute(`hide-labels`);
25360
25799
  }
25361
25800
  #syncIndicatorColors() {
25362
25801
  for (const item of this.#items) {
@@ -25611,6 +26050,10 @@ let TabListElement = class TabListElement extends i {
25611
26050
  :host(.scrollable) {
25612
26051
  max-height: var(--scroll-max-height);
25613
26052
  }
26053
+ :host([hide-labels]) {
26054
+ display: inline-flex;
26055
+ width: auto;
26056
+ }
25614
26057
  text {
25615
26058
  user-select:none;
25616
26059
  }
@@ -25694,6 +26137,10 @@ let TabListElement = class TabListElement extends i {
25694
26137
  __decorate([property({ type: String })], TabListElement.prototype, "orientation", void 0);
25695
26138
  __decorate([property({ type: Boolean })], TabListElement.prototype, "flip", void 0);
25696
26139
  __decorate([property({ type: Boolean })], TabListElement.prototype, "scrollable", void 0);
26140
+ __decorate([property({
26141
+ type: Boolean,
26142
+ attribute: `hide-labels`
26143
+ })], TabListElement.prototype, "hideLabels", void 0);
25697
26144
  __decorate([property({
25698
26145
  type: String,
25699
26146
  attribute: `drag-mode`
@@ -28401,6 +28848,6 @@ function init() {
28401
28848
  console.log(`Init`);
28402
28849
  }
28403
28850
  //#endregion
28404
- export { AcTextElement, AcTokenElement, ButtonElement, Checkbox, ColourPicker, ColourPickerPopup, CrumbNavigationElement, CrumbPathController, CrumbPathElement, DataController, DataDisplayComponent, EditableLabel, EditableNumber, FormElement, FormGroupElement, FormPartElement, GroupedItemListerElement, ICON_CARET_RIGHT, ICON_CHECK, ICON_CHEVRON_DOWN, ICON_CLOSE, IncrSearchTreeController as IncrSearchMillerController, IncrSearchTreeController, IxfxHexEditorElement, IxfxIconElement, IxfxTimelineElement, LabelledRadialInput, LabelledRangeInput, LedElement, menu_exports as Menu, MillerBaseElement, MillerListElement, MillerTreeController, NarrowedTextElement, NotificationManager, NotificationPillElement, PanelElement, PanelGroupElement, PlotDataSeries, PlotHistogram, PlotMultiAxis, PlotSingleAxis, PlotXyAxis, PolarPad, RadialInputElement, RadioGroup, RangeElement, RangeInput, RangeMultiElement, SelectHorizontalElement, SliderInputElement, SnackbarElement, SnapContainer, SplitButton, SplitLayoutElement, SwipeElement, TabController, TabListElement, TabListItemElement, TabPanelElement, TabPanelsElement, TimelineController, TimelineTrackTabElement, TooltipElement, TransitoryLabelElement, TreeBaseElement, TreeController, TreeDataModel, TreeListElement, VerticalListElement, XyPad, applyAgeModification, applyHighlights, attachTimelineInteractions, buildHighlightTargets, clearHighlights, collectDataResult, computeColour, createAcCompletionProvider, createElementIncrSearch, createFuzzySearch, createIncrSearch, createPillRenderer, createTreeListAdapter, createVerticalListAdapter, getIcon, hasIcon, iconBus, init, monitorIndeterminate, parseColourScaleAttr, readBaseColour, registerIcon, resolveCssVars, resolveGrid, svgToDataUri, timelineStyles };
28851
+ export { AcTextElement, AcTokenElement, ButtonElement, Checkbox, ColourPicker, ColourPickerPopup, CrumbNavigationElement, CrumbPathController, CrumbPathElement, DataController, DataDisplayComponent, EditableLabel, EditableNumber, FormElement, FormGroupElement, FormPartElement, GroupedItemListerElement, ICON_CARET_RIGHT, ICON_CHECK, ICON_CHEVRON_DOWN, ICON_CLOSE, IncrSearchTreeController as IncrSearchMillerController, IncrSearchTreeController, IxfxHexEditorElement, IxfxIconElement, IxfxTimelineElement, LabelledRadialInput, LabelledRangeInput, LedElement, menu_exports as Menu, MillerBaseElement, MillerListElement, MillerTreeController, NarrowedTextElement, NotificationManager, NotificationPillElement, PanelElement, PanelGroupElement, PlotDataSeries, PlotHistogram, PlotMultiAxis, PlotSingleAxis, PlotXyAxis, PolarPad, RadialInputElement, RadioGroup, RangeElement, RangeInput, RangeMultiElement, SelectHorizElement, SelectHorizontalElement, SliderInputElement, SnackbarElement, SnapContainer, SplitButton, SplitLayoutElement, SwipeElement, TabController, TabListElement, TabListItemElement, TabPanelElement, TabPanelsElement, TimelineController, TimelineTrackTabElement, TooltipElement, TransitoryLabelElement, TreeBaseElement, TreeController, TreeDataModel, TreeListElement, VerticalListElement, XyPad, applyAgeModification, applyHighlights, attachTimelineInteractions, buildHighlightTargets, clearHighlights, collectDataResult, computeColour, createAcCompletionProvider, createElementIncrSearch, createFuzzySearch, createIncrSearch, createPillRenderer, createTreeListAdapter, createVerticalListAdapter, getIcon, hasIcon, iconBus, init, monitorIndeterminate, parseColourScaleAttr, readBaseColour, registerIcon, resolveCssVars, resolveGrid, svgToDataUri, timelineStyles };
28405
28852
 
28406
28853
  //# sourceMappingURL=index.js.map