vira 31.16.0 → 31.16.1

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.
@@ -3,7 +3,6 @@ import { type FullSpaRoute, type GenericTreePaths, type SpaRouter } from 'spa-ro
3
3
  import { type ViraIconSvg } from '../icons/icon-svg.js';
4
4
  import { ViraColorVariant } from '../styles/form-variants.js';
5
5
  import { ViraThemeColorName } from '../styles/vira-color-theme-object.js';
6
- import { type HorizontalAnchor, type PopUpOffset } from './pop-up/vira-pop-up-trigger.element.js';
7
6
  /**
8
7
  * Controls which edge of the tab the selection indicator bar appears on.
9
8
  *
@@ -46,7 +45,7 @@ export type ViraTab = {
46
45
  */
47
46
  export declare const ViraTabs: import("element-vir").DeclarativeElementDefinition<"vira-tabs", {
48
47
  tabs: ReadonlyArray<Readonly<ViraTab>>;
49
- router: Pick<SpaRouter<any, any, any>, "createRouteUrl" | "setRouteOnDirectNavigation">;
48
+ router: Pick<SpaRouter<any, any, any>, "createRouteUrl" | "setRouteOnDirectNavigation" | "setRoute">;
50
49
  currentRoute: Readonly<FullSpaRoute>;
51
50
  } & PartialWithUndefined<{
52
51
  /**
@@ -69,22 +68,18 @@ export declare const ViraTabs: import("element-vir").DeclarativeElementDefinitio
69
68
  * @default ViraTabsIconLayout.Vertical
70
69
  */
71
70
  iconLayout: ViraTabsIconLayout;
72
- /**
73
- * Horizontal anchor for the dropdown menu. Only used when tabs overflow into a dropdown.
74
- *
75
- * @default HorizontalAnchor.Left
76
- */
77
- menuHorizontalAnchor: HorizontalAnchor;
78
- /** Whether the dropdown trigger is disabled. Only used when tabs overflow into a dropdown. */
79
- menuIsDisabled: boolean;
80
- /** Offset for the dropdown pop-up. Only used when tabs overflow into a dropdown. */
81
- menuPopUpOffset: Readonly<PopUpOffset>;
82
71
  /** When true, tabs and their container expand to fill all available horizontal space. */
83
72
  shouldFillWidth: boolean;
84
73
  }>, {
85
74
  isOverflowing: boolean;
86
75
  /** A callback to remove all internal observers. */
87
76
  cleanupObserver: undefined | (() => void);
77
+ /**
78
+ * Captured at the moment the overflow select is opened (mousedown or keydown on the
79
+ * select). Once the native picker opens, the OS owns keyboard input, so modifier state
80
+ * must be captured before that.
81
+ */
82
+ modifierKeyHeld: boolean;
88
83
  }, {
89
84
  /** Fires when a tab is clicked with the corresponding tab entry. */
90
85
  tabSelect: import("element-vir").DefineEvent<Readonly<ViraTab>>;
@@ -10,12 +10,9 @@ import { noNativeFormStyles, noUserSelect, viraDisabledStyles, viraTheme } from
10
10
  import { viraThemeByKeys, ViraThemeColorName } from '../styles/vira-color-theme-object.js';
11
11
  import { defineViraElement } from '../util/define-vira-element.js';
12
12
  import { createOverflowObserver } from '../util/overflow-observer.js';
13
- import { renderMenuItemEntries } from '../util/pop-up-helpers.js';
14
- import { ViraMenuTrigger } from './pop-up/vira-menu-trigger.element.js';
15
- import { ViraMenuCornerStyle } from './pop-up/vira-menu.element.js';
16
- import { ViraButton } from './vira-button.element.js';
17
13
  import { ViraIcon } from './vira-icon.element.js';
18
14
  import { ViraLink } from './vira-link.element.js';
15
+ import { ViraSelect } from './vira-select.element.js';
19
16
  /**
20
17
  * Controls which edge of the tab the selection indicator bar appears on.
21
18
  *
@@ -56,6 +53,12 @@ export const ViraTabs = defineViraElement()({
56
53
  isOverflowing: false,
57
54
  /** A callback to remove all internal observers. */
58
55
  cleanupObserver: undefined,
56
+ /**
57
+ * Captured at the moment the overflow select is opened (mousedown or keydown on the
58
+ * select). Once the native picker opens, the OS owns keyboard input, so modifier state
59
+ * must be captured before that.
60
+ */
61
+ modifierKeyHeld: false,
59
62
  };
60
63
  },
61
64
  hostClasses: {
@@ -142,6 +145,7 @@ export const ViraTabs = defineViraElement()({
142
145
  return css `
143
146
  :host {
144
147
  display: flex;
148
+ position: relative;
145
149
  box-sizing: border-box;
146
150
  ${noUserSelect};
147
151
  width: 100%;
@@ -292,18 +296,19 @@ export const ViraTabs = defineViraElement()({
292
296
 
293
297
  ${hostClasses['vira-tabs-overflowing'].selector} .tabs-container {
294
298
  visibility: hidden;
299
+ position: absolute;
295
300
  height: 0;
296
301
  }
297
302
 
298
- .overflow-menu {
303
+ ${ViraSelect} {
299
304
  display: none;
300
305
  }
301
306
 
302
- ${hostClasses['vira-tabs-overflowing'].selector} .overflow-menu {
303
- display: flex;
307
+ ${hostClasses['vira-tabs-overflowing'].selector} ${ViraSelect} {
308
+ display: inline-flex;
304
309
  align-items: center;
305
310
  width: fit-content;
306
- padding-left: 8px;
311
+ max-width: 100%;
307
312
  }
308
313
 
309
314
  ${hostClasses['vira-tabs-fill-width'].selector} {
@@ -329,10 +334,6 @@ export const ViraTabs = defineViraElement()({
329
334
  display: flex;
330
335
  padding: 8px 16px;
331
336
  }
332
-
333
- ${ViraMenuTrigger} {
334
- margin: 3px 0;
335
- }
336
337
  `;
337
338
  },
338
339
  cleanup({ state }) {
@@ -392,53 +393,53 @@ export const ViraTabs = defineViraElement()({
392
393
  `;
393
394
  }, check.isTruthy);
394
395
  const selectedTab = inputs.tabs.find((tab) => routeHasPaths(inputs.currentRoute, tab.paths));
395
- const menuItems = renderMenuItemEntries(filterMap(inputs.tabs, (tab) => {
396
+ const selectOptions = filterMap(inputs.tabs, (tab) => {
396
397
  if (tab.isHidden) {
397
398
  return undefined;
398
399
  }
399
- const isSelected = routeHasPaths(inputs.currentRoute, tab.paths);
400
400
  return {
401
- content: html `
402
- <${ViraLink.assign({
403
- route: {
404
- router: inputs.router,
405
- route: {
406
- paths: tab.paths.fullPaths,
407
- },
408
- scrollToTop: true,
409
- },
410
- disableLinkStyles: true,
411
- })}>
412
- ${tab.label}
413
- </${ViraLink}>
414
- `,
415
- selected: isSelected,
401
+ value: tab.paths.fullPaths.join('/'),
402
+ label: tab.label,
416
403
  disabled: tab.isDisabled,
417
- onClick() {
418
- if (!tab.isDisabled) {
419
- dispatch(new events.tabSelect(tab));
420
- }
421
- },
422
404
  };
423
- }, check.isTruthy));
405
+ }, check.isTruthy);
406
+ function captureModifierState(event) {
407
+ updateState({
408
+ modifierKeyHeld: event.ctrlKey || event.metaKey || event.shiftKey,
409
+ });
410
+ }
424
411
  return html `
425
- <${ViraMenuTrigger.assign({
426
- horizontalAnchor: inputs.menuHorizontalAnchor,
427
- isDisabled: inputs.menuIsDisabled,
428
- popUpOffset: inputs.menuPopUpOffset,
429
- menuCornerStyle: ViraMenuCornerStyle.AllRounded,
412
+ <${ViraSelect.assign({
413
+ options: selectOptions,
414
+ value: selectedTab?.paths.fullPaths.join('/'),
430
415
  })}
431
- class="overflow-menu"
432
- >
433
- <${ViraButton.assign({
434
- text: selectedTab?.label || '',
435
- showMenuCaret: true,
436
- color: ViraColorVariant.Neutral,
416
+ ${listen('mousedown', captureModifierState)}
417
+ ${listen('keydown', captureModifierState)}
418
+ ${listen(ViraSelect.events.valueChange, (event) => {
419
+ try {
420
+ const selectedValue = event.detail;
421
+ const tab = inputs.tabs.find((tab) => tab.paths.fullPaths.join('/') === selectedValue);
422
+ if (!tab || tab.isDisabled) {
423
+ return;
424
+ }
425
+ dispatch(new events.tabSelect(tab));
426
+ const route = {
427
+ paths: tab.paths.fullPaths,
428
+ };
429
+ if (state.modifierKeyHeld) {
430
+ globalThis.open(inputs.router.createRouteUrl(route), '_blank', 'noopener,noreferrer');
431
+ }
432
+ else {
433
+ inputs.router.setRoute(route);
434
+ }
435
+ }
436
+ finally {
437
+ updateState({
438
+ modifierKeyHeld: false,
439
+ });
440
+ }
437
441
  })}
438
- slot=${ViraMenuTrigger.slotNames.trigger}
439
- ></${ViraButton}>
440
- ${menuItems}
441
- </${ViraMenuTrigger}>
442
+ ></${ViraSelect}>
442
443
  <ul
443
444
  class="tabs-container"
444
445
  role="tablist"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vira",
3
- "version": "31.16.0",
3
+ "version": "31.16.1",
4
4
  "description": "A simple and highly versatile design system using element-vir.",
5
5
  "keywords": [
6
6
  "design",