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