vira 29.9.0 → 30.0.0

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 (50) hide show
  1. package/dist/elements/index.d.ts +1 -6
  2. package/dist/elements/index.js +1 -6
  3. package/dist/elements/pop-up/vira-menu-item.element.d.ts +12 -9
  4. package/dist/elements/pop-up/vira-menu-item.element.js +66 -27
  5. package/dist/elements/pop-up/vira-menu-trigger.element.d.ts +5 -12
  6. package/dist/elements/pop-up/vira-menu-trigger.element.js +13 -38
  7. package/dist/elements/pop-up/vira-menu.element.d.ts +26 -28
  8. package/dist/elements/pop-up/vira-menu.element.js +46 -139
  9. package/dist/elements/pop-up/vira-pop-up-trigger.element.js +2 -2
  10. package/dist/elements/vira-bold-text.element.js +1 -1
  11. package/dist/elements/vira-button.element.js +1 -1
  12. package/dist/elements/vira-card.element.js +1 -1
  13. package/dist/elements/vira-checkbox.element.js +1 -1
  14. package/dist/elements/vira-collapsible-card.element.js +1 -1
  15. package/dist/elements/vira-collapsible-wrapper.element.js +1 -1
  16. package/dist/elements/vira-dropdown.element.d.ts +4 -14
  17. package/dist/elements/vira-dropdown.element.js +43 -27
  18. package/dist/elements/vira-error.element.js +1 -1
  19. package/dist/elements/{form/vira-form.element.d.ts → vira-form.element.d.ts} +1 -1
  20. package/dist/elements/{form/vira-form.element.js → vira-form.element.js} +5 -5
  21. package/dist/elements/vira-icon.element.js +2 -2
  22. package/dist/elements/vira-image.element.js +1 -1
  23. package/dist/elements/vira-input.element.d.ts +1 -1
  24. package/dist/elements/vira-input.element.js +3 -3
  25. package/dist/elements/vira-link.element.js +1 -1
  26. package/dist/elements/vira-modal.element.js +1 -1
  27. package/dist/elements/vira-overflow-switch.element.js +1 -1
  28. package/dist/elements/vira-progress.element.js +1 -1
  29. package/dist/elements/vira-select.element.d.ts +1 -14
  30. package/dist/elements/vira-select.element.js +1 -1
  31. package/dist/elements/vira-tag.element.js +1 -1
  32. package/dist/styles/form-variants.d.ts +5 -1
  33. package/dist/styles/form-variants.js +5 -1
  34. package/dist/util/index.d.ts +5 -0
  35. package/dist/util/index.js +5 -0
  36. package/dist/util/pop-up-helpers.d.ts +53 -0
  37. package/dist/{elements/pop-up → util}/pop-up-helpers.js +26 -23
  38. package/dist/{elements/form → util}/vira-form-fields.d.ts +2 -2
  39. package/dist/util/vira-select-option.d.ts +15 -0
  40. package/package.json +1 -1
  41. package/dist/elements/pop-up/pop-up-helpers.d.ts +0 -33
  42. package/dist/elements/pop-up/pop-up-menu-item.d.ts +0 -31
  43. package/dist/elements/pop-up/vira-pop-up-menu.element.d.ts +0 -35
  44. package/dist/elements/pop-up/vira-pop-up-menu.element.js +0 -79
  45. /package/dist/{elements → util}/define-vira-element.d.ts +0 -0
  46. /package/dist/{elements → util}/define-vira-element.js +0 -0
  47. /package/dist/{elements → util}/shared-text-input-logic.d.ts +0 -0
  48. /package/dist/{elements → util}/shared-text-input-logic.js +0 -0
  49. /package/dist/{elements/form → util}/vira-form-fields.js +0 -0
  50. /package/dist/{elements/pop-up/pop-up-menu-item.js → util/vira-select-option.js} +0 -0
@@ -1,12 +1,6 @@
1
- export * from './define-vira-element.js';
2
- export * from './form/vira-form-fields.js';
3
- export * from './form/vira-form.element.js';
4
- export * from './pop-up/pop-up-helpers.js';
5
- export * from './pop-up/pop-up-menu-item.js';
6
1
  export * from './pop-up/vira-menu-item.element.js';
7
2
  export * from './pop-up/vira-menu-trigger.element.js';
8
3
  export * from './pop-up/vira-menu.element.js';
9
- export * from './pop-up/vira-pop-up-menu.element.js';
10
4
  export * from './pop-up/vira-pop-up-trigger.element.js';
11
5
  export * from './vira-bold-text.element.js';
12
6
  export * from './vira-button.element.js';
@@ -16,6 +10,7 @@ export * from './vira-collapsible-card.element.js';
16
10
  export * from './vira-collapsible-wrapper.element.js';
17
11
  export * from './vira-dropdown.element.js';
18
12
  export * from './vira-error.element.js';
13
+ export * from './vira-form.element.js';
19
14
  export * from './vira-icon.element.js';
20
15
  export * from './vira-image.element.js';
21
16
  export * from './vira-input.element.js';
@@ -1,12 +1,6 @@
1
- export * from './define-vira-element.js';
2
- export * from './form/vira-form-fields.js';
3
- export * from './form/vira-form.element.js';
4
- export * from './pop-up/pop-up-helpers.js';
5
- export * from './pop-up/pop-up-menu-item.js';
6
1
  export * from './pop-up/vira-menu-item.element.js';
7
2
  export * from './pop-up/vira-menu-trigger.element.js';
8
3
  export * from './pop-up/vira-menu.element.js';
9
- export * from './pop-up/vira-pop-up-menu.element.js';
10
4
  export * from './pop-up/vira-pop-up-trigger.element.js';
11
5
  export * from './vira-bold-text.element.js';
12
6
  export * from './vira-button.element.js';
@@ -16,6 +10,7 @@ export * from './vira-collapsible-card.element.js';
16
10
  export * from './vira-collapsible-wrapper.element.js';
17
11
  export * from './vira-dropdown.element.js';
18
12
  export * from './vira-error.element.js';
13
+ export * from './vira-form.element.js';
19
14
  export * from './vira-icon.element.js';
20
15
  export * from './vira-image.element.js';
21
16
  export * from './vira-input.element.js';
@@ -1,19 +1,22 @@
1
1
  import { type PartialWithUndefined } from '@augment-vir/common';
2
- import { type MenuItem } from './pop-up-menu-item.js';
2
+ import { type ViraIconSvg } from '../../icons/icon-svg.js';
3
3
  /**
4
4
  * An element for an individual menu item.
5
5
  *
6
6
  * @category PopUp
7
7
  * @category Elements
8
8
  */
9
- export declare const ViraMenuItem: import("element-vir").DeclarativeElementDefinition<"vira-menu-item", {
9
+ export declare const ViraMenuItem: import("element-vir").DeclarativeElementDefinition<"vira-menu-item", PartialWithUndefined<{
10
10
  selected: boolean;
11
- } & PartialWithUndefined<{
11
+ disabled: boolean;
12
12
  /**
13
- * The text to show in the menu item. If this is not provided, it is expected that you will
14
- * instead utilize this element's `<slot>`.
13
+ * Set this to `true` to disable the default `ViraMenuItem` hover and active styles so you
14
+ * can apply your own.
15
15
  */
16
- label: MenuItem["label"];
17
- /** If `true`, does not render the selected check icon. */
18
- hideCheckIcon: boolean;
19
- }>, {}, {}, "vira-menu-item-selected", "vira-menu-item-", readonly [], readonly []>;
16
+ disablePointerStyles: boolean;
17
+ /**
18
+ * If provided, this will override the checkmark icon. If this is provided, the icon will
19
+ * _always_ be shown, even if `selected` is set to `false`.
20
+ */
21
+ iconOverride: ViraIconSvg;
22
+ }>, {}, {}, "vira-menu-item-selected" | "vira-menu-item-disabled" | "vira-menu-item-enabled" | "vira-menu-item-default-icon" | "vira-menu-item-default-styles", "vira-menu-item-", readonly [], readonly []>;
@@ -1,7 +1,8 @@
1
1
  import { css, html } from 'element-vir';
2
2
  import { Check24Icon } from '../../icons/icon-svgs/check-24.icon.js';
3
+ import { viraFormCssVars } from '../../styles/form-styles.js';
3
4
  import { noUserSelect } from '../../styles/index.js';
4
- import { defineViraElement } from '../define-vira-element.js';
5
+ import { defineViraElement } from '../../util/define-vira-element.js';
5
6
  import { ViraIcon } from '../vira-icon.element.js';
6
7
  /**
7
8
  * An element for an individual menu item.
@@ -12,7 +13,11 @@ import { ViraIcon } from '../vira-icon.element.js';
12
13
  export const ViraMenuItem = defineViraElement()({
13
14
  tagName: 'vira-menu-item',
14
15
  hostClasses: {
15
- 'vira-menu-item-selected': ({ inputs }) => !inputs.hideCheckIcon && inputs.selected,
16
+ 'vira-menu-item-selected': ({ inputs }) => !!inputs.selected || !!inputs.iconOverride,
17
+ 'vira-menu-item-disabled': ({ inputs }) => !!inputs.disabled,
18
+ 'vira-menu-item-enabled': ({ inputs }) => !inputs.disabled,
19
+ 'vira-menu-item-default-icon': ({ inputs }) => !inputs.iconOverride,
20
+ 'vira-menu-item-default-styles': ({ inputs }) => !inputs.disablePointerStyles,
16
21
  },
17
22
  styles: ({ hostClasses }) => css `
18
23
  :host {
@@ -20,44 +25,78 @@ export const ViraMenuItem = defineViraElement()({
20
25
  ${noUserSelect};
21
26
  box-sizing: border-box;
22
27
  max-width: 100%;
28
+ gap: 1px;
23
29
  overflow: hidden;
24
- }
25
-
26
- .item {
27
- pointer-events: none;
28
- min-height: 24px;
29
- display: flex;
30
- max-width: 100%;
30
+ padding: 8px 3px;
31
+ padding-right: 16px;
31
32
  align-items: center;
32
- padding: 8px;
33
- padding-right: 24px;
34
- padding-left: 0;
35
33
  text-align: left;
36
- box-sizing: border-box;
34
+ }
35
+
36
+ ${hostClasses['vira-menu-item-disabled'].selector}${hostClasses['vira-menu-item-default-styles'].selector} {
37
+ cursor: not-allowed;
38
+
39
+ & .slot-wrapper,
40
+ & ${ViraIcon} {
41
+ opacity: 0.3;
42
+ pointer-events: none;
43
+ }
44
+ }
45
+
46
+ ${hostClasses['vira-menu-item-enabled'].selector}${hostClasses['vira-menu-item-default-styles'].selector} {
47
+ cursor: pointer;
48
+
49
+ &:host(:focus) {
50
+ background-color: ${viraFormCssVars['vira-form-selection-hover-color'].value};
51
+ outline: none;
52
+ }
53
+
54
+ &:host(:active) {
55
+ background-color: ${viraFormCssVars['vira-form-selection-active-color'].value};
56
+ outline: none;
57
+ }
58
+ }
59
+
60
+ ${hostClasses['vira-menu-item-default-icon'].selector} {
61
+ ${ViraIcon} {
62
+ visibility: hidden;
63
+ }
37
64
  }
38
65
 
39
66
  ${hostClasses['vira-menu-item-selected'].selector} ${ViraIcon} {
40
- opacity: 1;
41
67
  visibility: visible;
42
68
  }
43
69
 
44
- /*
45
- The check icon looks centered when it has a border.
46
- However, it does not have a border here.
47
- */
48
- ${ViraIcon} {
49
- opacity: 0;
50
- margin-top: -4px;
51
- margin-right: -2px;
52
- margin-left: 2px;
53
- visibility: hidden;
70
+ .slot-wrapper {
71
+ overflow: hidden;
72
+ text-overflow: ellipsis;
73
+ white-space: nowrap;
74
+ min-width: 0;
54
75
  }
55
76
  `,
77
+ init({ host, inputs }) {
78
+ host.setAttribute('role', 'menuitem');
79
+ host.setAttribute('tabindex', inputs.disabled ? '-1' : '0');
80
+ host.setAttribute('aria-selected', String(!!inputs.selected));
81
+ host.setAttribute('aria-disabled', String(!!inputs.disabled));
82
+ host.onmouseenter = () => {
83
+ if (!inputs.disabled) {
84
+ host.focus();
85
+ }
86
+ };
87
+ host.onmouseleave = () => {
88
+ if (!inputs.disabled) {
89
+ host.blur();
90
+ }
91
+ };
92
+ },
56
93
  render({ inputs }) {
57
94
  return html `
58
- <div class="item">
59
- <${ViraIcon.assign({ icon: Check24Icon })}></${ViraIcon}>
60
- <slot>${inputs.label}</slot>
95
+ <${ViraIcon.assign({
96
+ icon: inputs.iconOverride || Check24Icon,
97
+ })}></${ViraIcon}>
98
+ <div class="slot-wrapper">
99
+ <slot>&nbsp;</slot>
61
100
  </div>
62
101
  `;
63
102
  },
@@ -1,8 +1,7 @@
1
1
  import { type PartialWithUndefined } from '@augment-vir/common';
2
2
  import { type NavController } from 'device-navigation';
3
3
  import { type PopUpManager, type ShowPopUpResult } from '../../util/pop-up-manager.js';
4
- import { type MenuItem } from './pop-up-menu-item.js';
5
- import { type PopUpMenuCornerStyle } from './vira-pop-up-menu.element.js';
4
+ import { type ViraMenuCornerStyle } from './vira-menu.element.js';
6
5
  import { type PopUpOffset, type PopUpTriggerPosition } from './vira-pop-up-trigger.element.js';
7
6
  /**
8
7
  * Test ids for {@link ViraMenuTrigger}.
@@ -18,18 +17,12 @@ export declare const viraMenuTriggerTestIds: {
18
17
  * @category PopUp
19
18
  * @category Elements
20
19
  */
21
- export declare const ViraMenuTrigger: import("element-vir").DeclarativeElementDefinition<"vira-menu-trigger", {
22
- items: ReadonlyArray<Readonly<MenuItem>>;
23
- } & PartialWithUndefined<{
24
- /** The selected item ids from the given `items` object. */
25
- selected: ReadonlyArray<PropertyKey>;
20
+ export declare const ViraMenuTrigger: import("element-vir").DeclarativeElementDefinition<"vira-menu-trigger", PartialWithUndefined<{
26
21
  isDisabled: boolean;
27
- isMultiSelect: boolean;
28
22
  z_debug_forceOpenState: boolean;
29
23
  popUpOffset: PopUpOffset;
30
- /** Hide menu item check mark icons. */
31
- hideCheckIcons: boolean;
32
- menuCornerStyle: PopUpMenuCornerStyle;
24
+ keepOpenAfterInteraction: boolean;
25
+ menuCornerStyle: ViraMenuCornerStyle;
33
26
  } & PopUpTriggerPosition>, {
34
27
  navController: undefined | NavController;
35
28
  popUpManager: undefined | PopUpManager;
@@ -38,4 +31,4 @@ export declare const ViraMenuTrigger: import("element-vir").DeclarativeElementDe
38
31
  }, {
39
32
  itemActivate: import("element-vir").DefineEvent<PropertyKey[]>;
40
33
  openChange: import("element-vir").DefineEvent<ShowPopUpResult | undefined>;
41
- }, "vira-menu-trigger-", "vira-menu-trigger-", readonly [], readonly []>;
34
+ }, "vira-menu-trigger-", "vira-menu-trigger-", readonly ["trigger"], readonly []>;
@@ -1,8 +1,6 @@
1
- import { classMap, css, defineElementEvent, html, listen, nothing, testId } from 'element-vir';
2
- import { defineViraElement } from '../define-vira-element.js';
3
- import { updateSelectedItems } from './pop-up-helpers.js';
4
- import { ViraMenu } from './vira-menu.element.js';
5
- import { PopUpMenuDirection, ViraPopUpMenu, } from './vira-pop-up-menu.element.js';
1
+ import { classMap, css, defineElementEvent, html, listen, nothing } from 'element-vir';
2
+ import { defineViraElement } from '../../util/define-vira-element.js';
3
+ import { ViraMenu, ViraMenuPopUpDirection } from './vira-menu.element.js';
6
4
  import { HorizontalAnchor, ViraPopUpTrigger, } from './vira-pop-up-trigger.element.js';
7
5
  /**
8
6
  * Test ids for {@link ViraMenuTrigger}.
@@ -20,6 +18,9 @@ export const viraMenuTriggerTestIds = {
20
18
  */
21
19
  export const ViraMenuTrigger = defineViraElement()({
22
20
  tagName: 'vira-menu-trigger',
21
+ slotNames: [
22
+ 'trigger',
23
+ ],
23
24
  styles: css `
24
25
  :host {
25
26
  display: inline-flex;
@@ -48,13 +49,10 @@ export const ViraMenuTrigger = defineViraElement()({
48
49
  showPopUpResult: undefined,
49
50
  };
50
51
  },
51
- render({ inputs, state, updateState, dispatch, events }) {
52
+ render({ inputs, state, updateState, dispatch, events, slotNames }) {
52
53
  return html `
53
54
  <${ViraPopUpTrigger.assign({
54
55
  ...inputs,
55
- keepOpenAfterInteraction: true,
56
- popUpOffset: inputs.popUpOffset,
57
- horizontalAnchor: inputs.horizontalAnchor || HorizontalAnchor.Left,
58
56
  })}
59
57
  class=${classMap({
60
58
  open: !!state.showPopUpResult,
@@ -72,30 +70,15 @@ export const ViraMenuTrigger = defineViraElement()({
72
70
  updateState({
73
71
  showPopUpResult: event.detail,
74
72
  });
75
- })}
76
- ${listen(ViraPopUpTrigger.events.navSelect, (event) => {
77
- const itemIndex = event.detail.x;
78
- const item = inputs.items[itemIndex];
79
- if (!item) {
80
- throw new Error(`Found no dropdown option at index '${itemIndex}'`);
81
- }
82
- dispatch(new events.itemActivate(updateSelectedItems(item, inputs.selected, inputs.isMultiSelect)));
83
- if (!inputs.isMultiSelect) {
84
- /**
85
- * Defer pop up removal to prevent race conditions with element-internal
86
- * click handlers.
87
- */
88
- globalThis.setTimeout(() => state.popUpManager?.removePopUp());
89
- }
90
73
  })}
91
74
  >
92
- <slot slot=${ViraPopUpTrigger.slotNames.trigger}></slot>
75
+ <slot name=${slotNames.trigger} slot=${ViraPopUpTrigger.slotNames.trigger}></slot>
93
76
  ${state.navController && state.showPopUpResult
94
77
  ? html `
95
- <${ViraPopUpMenu.assign({
78
+ <${ViraMenu.assign({
96
79
  direction: state.showPopUpResult.popDown
97
- ? PopUpMenuDirection.Downwards
98
- : PopUpMenuDirection.Upwards,
80
+ ? ViraMenuPopUpDirection.Downwards
81
+ : ViraMenuPopUpDirection.Upwards,
99
82
  cornerStyle: inputs.menuCornerStyle,
100
83
  })}
101
84
  slot=${ViraPopUpTrigger.slotNames.popUp}
@@ -103,16 +86,8 @@ export const ViraMenuTrigger = defineViraElement()({
103
86
  'full-width-menu': inputs.horizontalAnchor === HorizontalAnchor.Both,
104
87
  })}
105
88
  >
106
- <${ViraMenu.assign({
107
- items: inputs.items,
108
- selected: inputs.selected,
109
- navController: state.navController,
110
- isMultiSelect: !!inputs.isMultiSelect,
111
- hideCheckIcons: inputs.hideCheckIcons,
112
- })}
113
- ${testId(viraMenuTriggerTestIds.menu)}
114
- ></${ViraMenu}>
115
- </${ViraPopUpMenu}>
89
+ <slot></slot>
90
+ </${ViraMenu}>
116
91
  `
117
92
  : nothing}
118
93
  </${ViraPopUpTrigger}>
@@ -1,38 +1,36 @@
1
1
  import { type PartialWithUndefined } from '@augment-vir/common';
2
- import { NavController } from 'device-navigation';
3
- import { type MenuItem } from './pop-up-menu-item.js';
4
2
  /**
5
- * Test ids for {@link ViraMenu}.
3
+ * Possible corner styles for {@link ViraMenu}.
6
4
  *
7
5
  * @category Internal
8
6
  */
9
- export declare const viraMenuTestIds: {
10
- item: string;
11
- };
7
+ export declare enum ViraMenuCornerStyle {
8
+ /** Rounding of corners depends on the open direction of the menu. */
9
+ Directional = "directional",
10
+ /** All of the menus corners should be rounded. */
11
+ AllRounded = "all-rounded",
12
+ /** None of the menus corners should be rounded. */
13
+ AllSquare = "all-square"
14
+ }
12
15
  /**
13
- * A wrapper for menu items. This can be used for dropdown items or menu bar dropdowns. To detect
14
- * when items are selected or unselected, pass in a `NavController` instance and hook into its
15
- * events.
16
+ * Menu pop-up directions available for {@link ViraMenu}.
17
+ *
18
+ * @category Internal
19
+ */
20
+ export declare enum ViraMenuPopUpDirection {
21
+ Downwards = "downwards",
22
+ Upwards = "upwards"
23
+ }
24
+ /**
25
+ * A simple default style wrapper for pop-up menus. Consider using `createMenuItemTemplates` to help
26
+ * rendering many menu items.
16
27
  *
17
28
  * @category PopUp
18
29
  * @category Elements
19
30
  */
20
- export declare const ViraMenu: import("element-vir").DeclarativeElementDefinition<"vira-menu", {
21
- /**
22
- * The parent nav controller for this menu. If none is provided, an internal nav controller
23
- * is created (which means it can't be hooked into by external elements).
24
- *
25
- * It is recommended to not leave this `undefined`.
26
- */
27
- navController: NavController | undefined;
28
- /** All menu items to show to the user. */
29
- items: ReadonlyArray<Readonly<MenuItem>>;
30
- } & PartialWithUndefined<{
31
- /** The ids of the currently selected menu items. */
32
- selected: ReadonlyArray<PropertyKey>;
33
- isMultiSelect: boolean;
34
- /** Hide menu item check mark icons. */
35
- hideCheckIcons: boolean;
36
- }>, {
37
- internalNavController: NavController;
38
- }, {}, "vira-menu-multiselect", "vira-menu-", readonly [], readonly []>;
31
+ export declare const ViraMenu: import("element-vir").DeclarativeElementDefinition<"vira-menu", PartialWithUndefined<{
32
+ /** @default PopUpMenuDirection.Downwards */
33
+ direction: ViraMenuPopUpDirection;
34
+ /** @default PopUpMenuCornerStyle.Directional */
35
+ cornerStyle: ViraMenuCornerStyle;
36
+ }>, {}, {}, "vira-menu-open-upwards" | "vira-menu-rounded" | "vira-menu-square", "vira-menu-", readonly [], readonly []>;
@@ -1,175 +1,82 @@
1
- import { check } from '@augment-vir/assert';
2
- import { nav, navAttribute, NavController, NavValue } from 'device-navigation';
3
- import { classMap, css, html, ifDefined, testId } from 'element-vir';
1
+ import { css, html } from 'element-vir';
4
2
  import { viraFormCssVars } from '../../styles/form-styles.js';
5
- import { noNativeFormStyles, viraDisabledStyles } from '../../styles/index.js';
6
- import { defineViraElement } from '../define-vira-element.js';
7
- import { ViraLink } from '../vira-link.element.js';
8
- import { assertUniqueIdProps } from './pop-up-helpers.js';
9
- import { ViraMenuItem } from './vira-menu-item.element.js';
3
+ import { viraShadows } from '../../styles/shadows.js';
4
+ import { defineViraElement } from '../../util/define-vira-element.js';
10
5
  /**
11
- * Test ids for {@link ViraMenu}.
6
+ * Possible corner styles for {@link ViraMenu}.
12
7
  *
13
8
  * @category Internal
14
9
  */
15
- export const viraMenuTestIds = {
16
- item: 'menu-item',
17
- };
10
+ export var ViraMenuCornerStyle;
11
+ (function (ViraMenuCornerStyle) {
12
+ /** Rounding of corners depends on the open direction of the menu. */
13
+ ViraMenuCornerStyle["Directional"] = "directional";
14
+ /** All of the menus corners should be rounded. */
15
+ ViraMenuCornerStyle["AllRounded"] = "all-rounded";
16
+ /** None of the menus corners should be rounded. */
17
+ ViraMenuCornerStyle["AllSquare"] = "all-square";
18
+ })(ViraMenuCornerStyle || (ViraMenuCornerStyle = {}));
18
19
  /**
19
- * A wrapper for menu items. This can be used for dropdown items or menu bar dropdowns. To detect
20
- * when items are selected or unselected, pass in a `NavController` instance and hook into its
21
- * events.
20
+ * Menu pop-up directions available for {@link ViraMenu}.
21
+ *
22
+ * @category Internal
23
+ */
24
+ export var ViraMenuPopUpDirection;
25
+ (function (ViraMenuPopUpDirection) {
26
+ ViraMenuPopUpDirection["Downwards"] = "downwards";
27
+ ViraMenuPopUpDirection["Upwards"] = "upwards";
28
+ })(ViraMenuPopUpDirection || (ViraMenuPopUpDirection = {}));
29
+ /**
30
+ * A simple default style wrapper for pop-up menus. Consider using `createMenuItemTemplates` to help
31
+ * rendering many menu items.
22
32
  *
23
33
  * @category PopUp
24
34
  * @category Elements
25
35
  */
26
36
  export const ViraMenu = defineViraElement()({
27
37
  tagName: 'vira-menu',
28
- state({ inputs, host }) {
29
- return {
30
- internalNavController: inputs.navController || new NavController(host),
31
- };
32
- },
33
38
  hostClasses: {
34
- 'vira-menu-multiselect': ({ inputs }) => !!inputs.isMultiSelect,
39
+ 'vira-menu-open-upwards': ({ inputs }) => inputs.direction === ViraMenuPopUpDirection.Upwards,
40
+ 'vira-menu-rounded': ({ inputs }) => inputs.cornerStyle === ViraMenuCornerStyle.AllRounded,
41
+ 'vira-menu-square': ({ inputs }) => inputs.cornerStyle === ViraMenuCornerStyle.AllSquare,
35
42
  },
36
43
  styles: ({ hostClasses }) => css `
37
44
  :host {
38
45
  display: flex;
39
46
  flex-direction: column;
40
-
41
- width: 100%;
42
47
  max-width: 100%;
43
48
  max-height: 100%;
44
49
  overflow-y: auto;
45
- overscroll-behavior: contain;
46
- z-index: 100;
50
+ z-index: 99;
47
51
  box-sizing: border-box;
52
+ overscroll-behavior: contain;
53
+ border-radius: ${viraFormCssVars['vira-form-radius'].value};
54
+ border-top-left-radius: 0;
55
+ border-top-right-radius: 0;
48
56
  background-color: ${viraFormCssVars['vira-form-background-color'].value};
57
+ border: 1px solid ${viraFormCssVars['vira-form-border-color'].value};
49
58
  color: ${viraFormCssVars['vira-form-foreground-color'].value};
59
+ ${viraShadows.menuShadow}
50
60
  }
51
61
 
52
- .menu-item {
53
- ${noNativeFormStyles};
54
- will-change: background-color;
55
- background-color: inherit;
56
- outline: none;
57
-
58
- &.default-pointer-styles {
59
- cursor: pointer;
60
- }
61
- &.no-default-pointer-styles {
62
- cursor: auto !important;
63
- }
62
+ ${hostClasses['vira-menu-open-upwards'].selector} {
63
+ ${viraShadows.menuShadowReversed}
64
+ border-radius: ${viraFormCssVars['vira-form-radius'].value};
65
+ border-bottom-left-radius: 0;
66
+ border-bottom-right-radius: 0;
64
67
  }
65
68
 
66
- ${navAttribute.css({
67
- baseSelector: '.menu-item.default-pointer-styles:not(.disabled):not(.selected)',
68
- navValue: NavValue.Focused,
69
- })}, .menu-item.default-pointer-styles:not(.disabled):not(.selected):hover {
70
- background-color: ${viraFormCssVars['vira-form-selection-hover-color'].value};
71
- outline: none;
72
- }
73
- ${navAttribute.css({
74
- baseSelector: '.menu-item.default-pointer-styles:not(.disabled):not(.selected)',
75
- navValue: NavValue.Active,
76
- })}, .menu-item.default-pointer-styles:not(.disabled):not(.selected):active {
77
- background-color: ${viraFormCssVars['vira-form-selection-active-color'].value};
78
- outline: none;
79
- }
80
-
81
- ${hostClasses['vira-menu-multiselect'].selector} {
82
- &
83
- ${navAttribute.css({
84
- baseSelector: '.menu-item:not(.disabled)',
85
- navValue: NavValue.Focused,
86
- })},
87
- .menu-item:not(.disabled):hover {
88
- background-color: ${viraFormCssVars['vira-form-selection-hover-color'].value};
89
- outline: none;
90
- }
91
-
92
- &
93
- ${navAttribute.css({
94
- baseSelector: '.menu-item:not(.disabled)',
95
- navValue: NavValue.Active,
96
- })},
97
- .menu-item:not(.disabled):active {
98
- background-color: ${viraFormCssVars['vira-form-selection-active-color'].value};
99
- outline: none;
100
- }
69
+ ${hostClasses['vira-menu-square'].selector} {
70
+ border-radius: 0;
101
71
  }
102
72
 
103
- ${ViraMenuItem} {
104
- pointer-events: none;
105
- }
106
-
107
- .menu-item.disabled {
108
- ${viraDisabledStyles};
109
- pointer-events: auto;
73
+ ${hostClasses['vira-menu-rounded'].selector} {
74
+ border-radius: ${viraFormCssVars['vira-form-radius'].value};
110
75
  }
111
76
  `,
112
- cleanup({ inputs, state }) {
113
- if (!inputs.navController) {
114
- state.internalNavController.destroy();
115
- }
116
- },
117
- render({ inputs, state }) {
118
- assertUniqueIdProps(inputs.items);
119
- const itemTemplates = inputs.items.map((item) => {
120
- const selected = !!inputs.selected?.includes(item.id);
121
- const innerTemplate = check.isString(item.label)
122
- ? html `
123
- <${ViraMenuItem.assign({
124
- label: item.label,
125
- selected,
126
- hideCheckIcon: inputs.hideCheckIcons,
127
- })}></${ViraMenuItem}>
128
- `
129
- : item.label;
130
- const disabled = item.disabled || (!inputs.isMultiSelect && selected);
131
- if (item.route) {
132
- return html `
133
- <${ViraLink.assign({
134
- route: item.route,
135
- disableLinkStyles: true,
136
- })}
137
- class="menu-item ${classMap({
138
- disabled: !!item.disabled,
139
- selected,
140
- 'default-pointer-styles': !item.disableDefaultPointerStyles,
141
- 'no-default-pointer-styles': !!item.disableDefaultPointerStyles,
142
- })}"
143
- ${testId(viraMenuTestIds.item)}
144
- title=${ifDefined(item.titleText || undefined)}
145
- role="option"
146
- ${nav(state.internalNavController, { disabled })}
147
- >
148
- ${innerTemplate}
149
- </${ViraLink}>
150
- `;
151
- }
152
- else {
153
- return html `
154
- <button
155
- class="menu-item ${classMap({
156
- disabled: !!item.disabled,
157
- selected,
158
- 'default-pointer-styles': !item.disableDefaultPointerStyles,
159
- 'no-default-pointer-styles': !!item.disableDefaultPointerStyles,
160
- })}"
161
- ${testId(viraMenuTestIds.item)}
162
- title=${ifDefined(item.titleText || undefined)}
163
- role="option"
164
- ${nav(state.internalNavController, { disabled })}
165
- >
166
- ${innerTemplate}
167
- </button>
168
- `;
169
- }
170
- });
77
+ render() {
171
78
  return html `
172
- ${itemTemplates}
79
+ <slot>&nbsp;</slot>
173
80
  `;
174
81
  },
175
82
  });
@@ -4,9 +4,9 @@ import { NavController } from 'device-navigation';
4
4
  import { classMap, css, defineElementEvent, html, listen, renderIf } from 'element-vir';
5
5
  import { createFocusStyles } from '../../styles/focus.js';
6
6
  import { noNativeFormStyles, noUserSelect, viraDisabledStyles } from '../../styles/index.js';
7
+ import { defineViraElement } from '../../util/define-vira-element.js';
8
+ import { triggerPopUpState } from '../../util/pop-up-helpers.js';
7
9
  import { HidePopUpEvent, isInputLikeElement, NavSelectEvent, PopUpManager, } from '../../util/pop-up-manager.js';
8
- import { defineViraElement } from '../define-vira-element.js';
9
- import { triggerPopUpState } from './pop-up-helpers.js';
10
10
  /**
11
11
  * Anchor options for pop-ups.
12
12
  *
@@ -1,5 +1,5 @@
1
1
  import { css, html } from 'element-vir';
2
- import { defineViraElement } from './define-vira-element.js';
2
+ import { defineViraElement } from '../util/define-vira-element.js';
3
3
  /**
4
4
  * Use this element to reserve space for bolded text, even if it isn't bold yet.
5
5
  *
@@ -5,7 +5,7 @@ import { createFocusStyles } from '../styles/focus.js';
5
5
  import { viraFormCssVars } from '../styles/form-styles.js';
6
6
  import { noUserSelect } from '../styles/index.js';
7
7
  import { noNativeFormStyles } from '../styles/native-styles.js';
8
- import { defineViraElement } from './define-vira-element.js';
8
+ import { defineViraElement } from '../util/define-vira-element.js';
9
9
  import { ViraIcon } from './vira-icon.element.js';
10
10
  /**
11
11
  * Button styles available for {@link ViraButton}.
@@ -1,6 +1,6 @@
1
1
  import { css, html } from 'element-vir';
2
2
  import { viraFormCssVars } from '../styles/form-styles.js';
3
- import { defineViraElement } from './define-vira-element.js';
3
+ import { defineViraElement } from '../util/define-vira-element.js';
4
4
  /**
5
5
  * State options for {@link ViraCard}.
6
6
  *