vira 25.7.2 → 25.8.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 (29) hide show
  1. package/dist/elements/index.d.ts +8 -3
  2. package/dist/elements/index.js +8 -3
  3. package/dist/elements/pop-up/pop-up-helpers.d.ts +30 -0
  4. package/dist/elements/pop-up/pop-up-helpers.js +58 -0
  5. package/dist/elements/pop-up/pop-up-menu-item.d.ts +24 -0
  6. package/dist/elements/pop-up/pop-up-menu-item.js +1 -0
  7. package/dist/elements/pop-up/vira-menu-item.element.d.ts +15 -0
  8. package/dist/elements/{dropdown/vira-dropdown-item.element.js → pop-up/vira-menu-item.element.js} +9 -22
  9. package/dist/elements/pop-up/vira-menu-trigger.element.d.ts +37 -0
  10. package/dist/elements/pop-up/vira-menu-trigger.element.js +107 -0
  11. package/dist/elements/pop-up/vira-menu.element.d.ts +36 -0
  12. package/dist/elements/pop-up/vira-menu.element.js +129 -0
  13. package/dist/elements/pop-up/vira-pop-up-menu.element.d.ts +10 -0
  14. package/dist/elements/pop-up/vira-pop-up-menu.element.js +48 -0
  15. package/dist/elements/pop-up/vira-pop-up-trigger.element.d.ts +44 -0
  16. package/dist/elements/pop-up/vira-pop-up-trigger.element.js +235 -0
  17. package/dist/elements/vira-bold-text.element.js +3 -2
  18. package/dist/elements/{dropdown/vira-dropdown.element.d.ts → vira-dropdown.element.d.ts} +12 -9
  19. package/dist/elements/vira-dropdown.element.js +185 -0
  20. package/dist/styles/focus.d.ts +0 -1
  21. package/dist/util/pop-up-manager.d.ts +1 -1
  22. package/dist/util/pop-up-manager.js +20 -9
  23. package/package.json +11 -10
  24. package/dist/elements/dropdown/dropdown-helpers.d.ts +0 -45
  25. package/dist/elements/dropdown/dropdown-helpers.js +0 -78
  26. package/dist/elements/dropdown/vira-dropdown-item.element.d.ts +0 -27
  27. package/dist/elements/dropdown/vira-dropdown-options.element.d.ts +0 -29
  28. package/dist/elements/dropdown/vira-dropdown-options.element.js +0 -116
  29. package/dist/elements/dropdown/vira-dropdown.element.js +0 -324
@@ -1,10 +1,15 @@
1
1
  export * from './define-vira-element.js';
2
- export * from './dropdown/vira-dropdown-item.element.js';
3
- export * from './dropdown/vira-dropdown-options.element.js';
4
- export * from './dropdown/vira-dropdown.element.js';
2
+ export * from './pop-up/pop-up-helpers.js';
3
+ export * from './pop-up/pop-up-menu-item.js';
4
+ export * from './pop-up/vira-menu-item.element.js';
5
+ export * from './pop-up/vira-menu-trigger.element.js';
6
+ export * from './pop-up/vira-menu.element.js';
7
+ export * from './pop-up/vira-pop-up-menu.element.js';
8
+ export * from './pop-up/vira-pop-up-trigger.element.js';
5
9
  export * from './vira-bold-text.element.js';
6
10
  export * from './vira-button.element.js';
7
11
  export * from './vira-collapsible-wrapper.element.js';
12
+ export * from './vira-dropdown.element.js';
8
13
  export * from './vira-icon.element.js';
9
14
  export * from './vira-image.element.js';
10
15
  export * from './vira-input.element.js';
@@ -1,10 +1,15 @@
1
1
  export * from './define-vira-element.js';
2
- export * from './dropdown/vira-dropdown-item.element.js';
3
- export * from './dropdown/vira-dropdown-options.element.js';
4
- export * from './dropdown/vira-dropdown.element.js';
2
+ export * from './pop-up/pop-up-helpers.js';
3
+ export * from './pop-up/pop-up-menu-item.js';
4
+ export * from './pop-up/vira-menu-item.element.js';
5
+ export * from './pop-up/vira-menu-trigger.element.js';
6
+ export * from './pop-up/vira-menu.element.js';
7
+ export * from './pop-up/vira-pop-up-menu.element.js';
8
+ export * from './pop-up/vira-pop-up-trigger.element.js';
5
9
  export * from './vira-bold-text.element.js';
6
10
  export * from './vira-button.element.js';
7
11
  export * from './vira-collapsible-wrapper.element.js';
12
+ export * from './vira-dropdown.element.js';
8
13
  export * from './vira-icon.element.js';
9
14
  export * from './vira-image.element.js';
10
15
  export * from './vira-input.element.js';
@@ -0,0 +1,30 @@
1
+ import { type PopUpManager, type ShowPopUpResult } from '../../util/pop-up-manager.js';
2
+ import { type MenuItem } from './pop-up-menu-item.js';
3
+ /**
4
+ * Verifies that all items have unique ids.
5
+ *
6
+ * @category Internal
7
+ */
8
+ export declare function assertUniqueIdProps(items: ReadonlyArray<Readonly<{
9
+ id: PropertyKey;
10
+ }>>): void;
11
+ /**
12
+ * Creates a new array of selections based on the current selection and new selection id. This
13
+ * behaves differently when multi select is enabled, hence this function.
14
+ *
15
+ * @category Internal
16
+ */
17
+ export declare function updateSelectedItems(
18
+ /** The item that should be newly toggled. */
19
+ newItem: Readonly<MenuItem>, currentSelection?: ReadonlyArray<PropertyKey>, isMultiSelect?: boolean): PropertyKey[];
20
+ /**
21
+ * Handles toggling pop up state for `ViraDropdown`.
22
+ *
23
+ * @category Internal
24
+ */
25
+ export declare function triggerPopUpState({ open, callback, popUpManager, host, }: {
26
+ open: boolean;
27
+ popUpManager: PopUpManager;
28
+ host: HTMLElement;
29
+ callback?: ((showPopUpResult: ShowPopUpResult | undefined) => void) | undefined;
30
+ }): void;
@@ -0,0 +1,58 @@
1
+ import { joinWithFinalConjunction } from '@augment-vir/common';
2
+ /**
3
+ * Verifies that all items have unique ids.
4
+ *
5
+ * @category Internal
6
+ */
7
+ export function assertUniqueIdProps(items) {
8
+ const usedIds = new Set();
9
+ const duplicateIds = [];
10
+ items.forEach((option) => {
11
+ if (usedIds.has(option.id)) {
12
+ duplicateIds.push(option.id);
13
+ }
14
+ else {
15
+ usedIds.add(option.id);
16
+ }
17
+ });
18
+ if (duplicateIds.length) {
19
+ throw new Error(`Duplicate option ids were given: ${joinWithFinalConjunction(duplicateIds)}`);
20
+ }
21
+ }
22
+ /**
23
+ * Creates a new array of selections based on the current selection and new selection id. This
24
+ * behaves differently when multi select is enabled, hence this function.
25
+ *
26
+ * @category Internal
27
+ */
28
+ export function updateSelectedItems(
29
+ /** The item that should be newly toggled. */
30
+ newItem, currentSelection = [], isMultiSelect = false) {
31
+ if (isMultiSelect) {
32
+ return currentSelection.includes(newItem.id)
33
+ ? currentSelection.filter((entry) => entry !== newItem.id)
34
+ : [
35
+ ...currentSelection,
36
+ newItem.id,
37
+ ];
38
+ }
39
+ else {
40
+ /** In single select, only the toggled item is allowed. */
41
+ return [newItem.id];
42
+ }
43
+ }
44
+ /**
45
+ * Handles toggling pop up state for `ViraDropdown`.
46
+ *
47
+ * @category Internal
48
+ */
49
+ export function triggerPopUpState({ open, callback, popUpManager, host, }) {
50
+ if (open) {
51
+ const showPopUpResult = popUpManager.showPopUp(host);
52
+ callback?.(showPopUpResult);
53
+ }
54
+ else {
55
+ popUpManager.removePopUp();
56
+ callback?.(undefined);
57
+ }
58
+ }
@@ -0,0 +1,24 @@
1
+ import { type PartialWithUndefined } from '@augment-vir/common';
2
+ import { type HTMLTemplateResult } from 'element-vir';
3
+ /**
4
+ * An individual menu item consumed partially by `ViraMenuItem` and used by `ViraMenu`.
5
+ *
6
+ * @category Internal
7
+ */
8
+ export type MenuItem = {
9
+ /** Each `id` must be unique across all items in a single menu. */
10
+ id: PropertyKey;
11
+ /** The user-facing label for this menu item. */
12
+ label: string;
13
+ } & PartialWithUndefined<{
14
+ disabled: boolean;
15
+ /** Text assigned to the `title` HTML attribute that'll show on long hover. */
16
+ titleText: string;
17
+ /**
18
+ * An optional custom template for this menu item. This will replace the menu item text and icon
19
+ * content, but will still be styled correctly if used within `ViraMenu`. Feel free to use
20
+ * `ViraMenuItem` as the template with a custom `<slot>` to keep the selected checkmark
21
+ * functionality.
22
+ */
23
+ template: HTMLTemplateResult;
24
+ }>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,15 @@
1
+ import { type MenuItem } from './pop-up-menu-item.js';
2
+ /**
3
+ * An element for an individual menu item.
4
+ *
5
+ * @category PopUp
6
+ * @category Elements
7
+ */
8
+ export declare const ViraMenuItem: import("element-vir").DeclarativeElementDefinition<"vira-menu-item", Readonly<{
9
+ /**
10
+ * The text to show in the menu item. If this is not provided, it is expected that you will
11
+ * instead utilize this element's `<slot>`.
12
+ */
13
+ label?: MenuItem["label"] | undefined;
14
+ selected: boolean;
15
+ }>, {}, {}, "vira-menu-item-selected", "vira-menu-item-", readonly []>;
@@ -1,19 +1,18 @@
1
1
  import { css, html } from 'element-vir';
2
2
  import { Check24Icon } from '../../icons/icon-svgs/check-24.icon.js';
3
- import { viraBorders } from '../../styles/border.js';
4
- import { noUserSelect, viraAnimationDurations } from '../../styles/index.js';
3
+ import { noUserSelect } from '../../styles/index.js';
5
4
  import { defineViraElement } from '../define-vira-element.js';
6
5
  import { ViraIcon } from '../vira-icon.element.js';
7
6
  /**
8
- * An element for an individual item in the ViraDropdown menu.
7
+ * An element for an individual menu item.
9
8
  *
10
- * @category Dropdown
9
+ * @category PopUp
11
10
  * @category Elements
12
11
  */
13
- export const ViraDropdownItem = defineViraElement()({
14
- tagName: 'vira-dropdown-item',
12
+ export const ViraMenuItem = defineViraElement()({
13
+ tagName: 'vira-menu-item',
15
14
  hostClasses: {
16
- 'vira-dropdown-item-selected': ({ inputs }) => inputs.selected,
15
+ 'vira-menu-item-selected': ({ inputs }) => inputs.selected,
17
16
  },
18
17
  styles: ({ hostClasses }) => css `
19
18
  :host {
@@ -21,7 +20,7 @@ export const ViraDropdownItem = defineViraElement()({
21
20
  ${noUserSelect};
22
21
  }
23
22
 
24
- .option {
23
+ .item {
25
24
  pointer-events: none;
26
25
  min-height: 24px;
27
26
  display: flex;
@@ -31,7 +30,7 @@ export const ViraDropdownItem = defineViraElement()({
31
30
  text-align: left;
32
31
  }
33
32
 
34
- ${hostClasses['vira-dropdown-item-selected'].selector} ${ViraIcon} {
33
+ ${hostClasses['vira-menu-item-selected'].selector} ${ViraIcon} {
35
34
  opacity: 1;
36
35
  }
37
36
 
@@ -40,27 +39,15 @@ export const ViraDropdownItem = defineViraElement()({
40
39
  However, it does not have a border here.
41
40
  */
42
41
  ${ViraIcon} {
43
- transition: opacity
44
- ${viraAnimationDurations['vira-interaction-animation-duration'].value};
45
42
  opacity: 0;
46
43
  margin-top: -4px;
47
44
  margin-right: -2px;
48
45
  margin-left: 2px;
49
46
  }
50
-
51
- .dropdown-wrapper:not(.reverse-direction) .option:last-of-type {
52
- border-radius: 0 0 ${viraBorders['vira-form-input-radius'].value}
53
- ${viraBorders['vira-form-input-radius'].value};
54
- }
55
-
56
- .dropdown-wrapper.reverse-direction .option:first-of-type {
57
- border-radius: ${viraBorders['vira-form-input-radius'].value}
58
- ${viraBorders['vira-form-input-radius'].value} 0 0;
59
- }
60
47
  `,
61
48
  render({ inputs }) {
62
49
  return html `
63
- <div class="option">
50
+ <div class="item">
64
51
  <${ViraIcon.assign({ icon: Check24Icon })}></${ViraIcon}>
65
52
  <slot>${inputs.label}</slot>
66
53
  </div>
@@ -0,0 +1,37 @@
1
+ import { type PartialWithUndefined } from '@augment-vir/common';
2
+ import { type NavController } from 'device-navigation';
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 PopUpOffset } from './vira-pop-up-trigger.element.js';
6
+ /**
7
+ * Test ids for {@link ViraMenuTrigger}.
8
+ *
9
+ * @category Internal
10
+ */
11
+ export declare const viraMenuTriggerTestIds: {
12
+ menu: string;
13
+ };
14
+ /**
15
+ * A more specific wrapper of `ViraPopUpTrigger` that always opens a menu.
16
+ *
17
+ * @category PopUp
18
+ * @category Elements
19
+ */
20
+ export declare const ViraMenuTrigger: import("element-vir").DeclarativeElementDefinition<"vira-menu-trigger", {
21
+ items: ReadonlyArray<Readonly<MenuItem>>;
22
+ } & PartialWithUndefined<{
23
+ /** The selected item ids from the given `items` object. */
24
+ selected: ReadonlyArray<PropertyKey>;
25
+ isDisabled: boolean;
26
+ isMultiSelect: boolean;
27
+ z_debug_forceOpenState: boolean;
28
+ popUpOffset: PopUpOffset;
29
+ }>, {
30
+ navController: undefined | NavController;
31
+ popUpManager: undefined | PopUpManager;
32
+ /** `undefined` means the pop up is not currently showing. */
33
+ showPopUpResult: ShowPopUpResult | undefined;
34
+ }, {
35
+ itemActivate: import("element-vir").DefineEvent<PropertyKey[]>;
36
+ openChange: import("element-vir").DefineEvent<ShowPopUpResult | undefined>;
37
+ }, "vira-menu-trigger-", "vira-menu-trigger-", readonly ["trigger"]>;
@@ -0,0 +1,107 @@
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 { ViraPopUpMenu } from './vira-pop-up-menu.element.js';
6
+ import { ViraPopUpTrigger } from './vira-pop-up-trigger.element.js';
7
+ /**
8
+ * Test ids for {@link ViraMenuTrigger}.
9
+ *
10
+ * @category Internal
11
+ */
12
+ export const viraMenuTriggerTestIds = {
13
+ menu: 'menu-trigger-menu',
14
+ };
15
+ /**
16
+ * A more specific wrapper of `ViraPopUpTrigger` that always opens a menu.
17
+ *
18
+ * @category PopUp
19
+ * @category Elements
20
+ */
21
+ export const ViraMenuTrigger = defineViraElement()({
22
+ tagName: 'vira-menu-trigger',
23
+ styles: css `
24
+ :host {
25
+ display: inline-flex;
26
+ box-sizing: border-box;
27
+ vertical-align: middle;
28
+ max-width: 100%;
29
+ }
30
+
31
+ ${ViraPopUpTrigger} {
32
+ width: 100%;
33
+ }
34
+ `,
35
+ events: {
36
+ itemActivate: defineElementEvent(),
37
+ openChange: defineElementEvent(),
38
+ },
39
+ slotNames: ['trigger'],
40
+ state() {
41
+ return {
42
+ navController: undefined,
43
+ popUpManager: undefined,
44
+ /** `undefined` means the pop up is not currently showing. */
45
+ showPopUpResult: undefined,
46
+ };
47
+ },
48
+ render({ inputs, state, updateState, dispatch, events, slotNames }) {
49
+ return html `
50
+ <${ViraPopUpTrigger.assign({
51
+ isDisabled: inputs.isDisabled,
52
+ keepOpenAfterInteraction: true,
53
+ z_debug_forceOpenState: inputs.z_debug_forceOpenState,
54
+ popUpOffset: inputs.popUpOffset,
55
+ })}
56
+ class=${classMap({
57
+ open: !!state.showPopUpResult,
58
+ })}
59
+ ${listen(ViraPopUpTrigger.events.init, (event) => {
60
+ updateState({
61
+ navController: event.detail.navController,
62
+ popUpManager: event.detail.popUpManager,
63
+ });
64
+ })}
65
+ ${listen(ViraPopUpTrigger.events.openChange, (event) => {
66
+ if (!!state.showPopUpResult !== !!event.detail) {
67
+ dispatch(new events.openChange(event.detail));
68
+ }
69
+ updateState({
70
+ showPopUpResult: event.detail,
71
+ });
72
+ })}
73
+ ${listen(ViraPopUpTrigger.events.navSelect, (event) => {
74
+ const itemIndex = event.detail.x;
75
+ const item = inputs.items[itemIndex];
76
+ if (!item) {
77
+ throw new Error(`Found no dropdown option at index '${itemIndex}'`);
78
+ }
79
+ dispatch(new events.itemActivate(updateSelectedItems(item, inputs.selected, inputs.isMultiSelect)));
80
+ if (!inputs.isMultiSelect) {
81
+ state.popUpManager?.removePopUp();
82
+ }
83
+ })}
84
+ >
85
+ <slot slot=${slotNames.trigger} name=${ViraPopUpTrigger.slotNames.trigger}></slot>
86
+ ${state.navController && state.showPopUpResult
87
+ ? html `
88
+ <${ViraPopUpMenu.assign({
89
+ openUpwards: !state.showPopUpResult.popDown,
90
+ })}
91
+ slot=${ViraPopUpTrigger.slotNames.popUp}
92
+ >
93
+ <${ViraMenu.assign({
94
+ items: inputs.items,
95
+ selected: inputs.selected,
96
+ navController: state.navController,
97
+ isMultiSelect: !!inputs.isMultiSelect,
98
+ })}
99
+ ${testId(viraMenuTriggerTestIds.menu)}
100
+ ></${ViraMenu}>
101
+ </${ViraPopUpMenu}>
102
+ `
103
+ : nothing}
104
+ </${ViraPopUpTrigger}>
105
+ `;
106
+ },
107
+ });
@@ -0,0 +1,36 @@
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
+ /**
5
+ * Test ids for {@link ViraMenu}.
6
+ *
7
+ * @category Internal
8
+ */
9
+ export declare const viraMenuTestIds: {
10
+ item: string;
11
+ };
12
+ /**
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
+ *
17
+ * @category PopUp
18
+ * @category Elements
19
+ */
20
+ export declare const ViraMenu: import("element-vir").DeclarativeElementDefinition<"vira-menu", Readonly<{
21
+ /**
22
+ * The parent nav controller for this menu. If none is provided, an internal nav
23
+ * controller 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
+ }>>, {
35
+ internalNavController: NavController;
36
+ }, {}, "vira-menu-multiselect", "vira-menu-", readonly []>;
@@ -0,0 +1,129 @@
1
+ import { nav, navAttribute, NavController, NavValue } from 'device-navigation';
2
+ import { classMap, css, html, ifDefined, testId } from 'element-vir';
3
+ import { viraFormCssVars } from '../../styles/form-themes.js';
4
+ import { noNativeFormStyles, viraDisabledStyles } from '../../styles/index.js';
5
+ import { defineViraElement } from '../define-vira-element.js';
6
+ import { assertUniqueIdProps } from './pop-up-helpers.js';
7
+ import { ViraMenuItem } from './vira-menu-item.element.js';
8
+ /**
9
+ * Test ids for {@link ViraMenu}.
10
+ *
11
+ * @category Internal
12
+ */
13
+ export const viraMenuTestIds = {
14
+ item: 'menu-item',
15
+ };
16
+ /**
17
+ * A wrapper for menu items. This can be used for dropdown items or menu bar dropdowns. To detect
18
+ * when items are selected or unselected, pass in a `NavController` instance and hook into its
19
+ * events.
20
+ *
21
+ * @category PopUp
22
+ * @category Elements
23
+ */
24
+ export const ViraMenu = defineViraElement()({
25
+ tagName: 'vira-menu',
26
+ state({ inputs, host }) {
27
+ return {
28
+ internalNavController: inputs.navController || new NavController(host),
29
+ };
30
+ },
31
+ hostClasses: {
32
+ 'vira-menu-multiselect': ({ inputs }) => !!inputs.isMultiSelect,
33
+ },
34
+ styles: ({ hostClasses }) => css `
35
+ :host {
36
+ display: flex;
37
+ flex-direction: column;
38
+
39
+ width: 100%;
40
+ max-height: 100%;
41
+ overflow-y: auto;
42
+ z-index: 100;
43
+ box-sizing: border-box;
44
+ background-color: ${viraFormCssVars['vira-form-background-color'].value};
45
+ color: ${viraFormCssVars['vira-form-foreground-color'].value};
46
+ }
47
+
48
+ .menu-item {
49
+ ${noNativeFormStyles};
50
+ background-color: white;
51
+ outline: none;
52
+ cursor: pointer;
53
+ }
54
+
55
+ ${navAttribute.css({
56
+ baseSelector: '.menu-item:not(.disabled):not(.selected)',
57
+ navValue: NavValue.Focused,
58
+ })}, ${navAttribute.css({
59
+ baseSelector: '.menu-item:not(.disabled):not(.selected)',
60
+ navValue: NavValue.Active,
61
+ })}, .menu-item:not(.disabled):not(.selected):hover {
62
+ background-color: ${viraFormCssVars['vira-form-selection-hover-background-color']
63
+ .value};
64
+ outline: none;
65
+ }
66
+
67
+ ${hostClasses['vira-menu-multiselect'].selector} {
68
+ &
69
+ ${navAttribute.css({
70
+ baseSelector: '.menu-item:not(.disabled)',
71
+ navValue: NavValue.Focused,
72
+ })},
73
+ ${navAttribute.css({
74
+ baseSelector: '.menu-item:not(.disabled)',
75
+ navValue: NavValue.Active,
76
+ })},
77
+ .menu-item:not(.disabled):hover {
78
+ background-color: ${viraFormCssVars['vira-form-selection-hover-background-color']
79
+ .value};
80
+ outline: none;
81
+ }
82
+ }
83
+
84
+ ${ViraMenuItem} {
85
+ pointer-events: none;
86
+ }
87
+
88
+ .menu-item.disabled {
89
+ ${viraDisabledStyles};
90
+ pointer-events: auto;
91
+ }
92
+ `,
93
+ cleanup({ inputs, state }) {
94
+ if (!inputs.navController) {
95
+ state.internalNavController.destroy();
96
+ }
97
+ },
98
+ render({ inputs, state }) {
99
+ assertUniqueIdProps(inputs.items);
100
+ const itemTemplates = inputs.items.map((item) => {
101
+ const selected = !!inputs.selected?.includes(item.id);
102
+ const innerTemplate = item.template ||
103
+ html `
104
+ <${ViraMenuItem.assign({
105
+ label: item.label,
106
+ selected,
107
+ })}></${ViraMenuItem}>
108
+ `;
109
+ const disabled = item.disabled || (!inputs.isMultiSelect && selected);
110
+ return html `
111
+ <button
112
+ class="menu-item ${classMap({
113
+ disabled: !!item.disabled,
114
+ selected,
115
+ })}"
116
+ ${testId(viraMenuTestIds.item)}
117
+ title=${ifDefined(item.titleText || undefined)}
118
+ role="option"
119
+ ${nav(state.internalNavController, { disabled })}
120
+ >
121
+ ${innerTemplate}
122
+ </button>
123
+ `;
124
+ });
125
+ return html `
126
+ ${itemTemplates}
127
+ `;
128
+ },
129
+ });
@@ -0,0 +1,10 @@
1
+ /**
2
+ * A simple default style wrapper for pop-up menus.
3
+ *
4
+ * @category PopUp
5
+ * @category Elements
6
+ */
7
+ export declare const ViraPopUpMenu: import("element-vir").DeclarativeElementDefinition<"vira-pop-up-menu", {
8
+ /** If true, indicates that the menu is opening upwards and should be styled accordingly. */
9
+ openUpwards?: boolean;
10
+ }, {}, {}, "vira-pop-up-menu-open-upwards", "vira-pop-up-menu-", readonly []>;
@@ -0,0 +1,48 @@
1
+ import { css, html } from 'element-vir';
2
+ import { viraBorders } from '../../styles/border.js';
3
+ import { viraFormCssVars } from '../../styles/form-themes.js';
4
+ import { viraShadows } from '../../styles/shadows.js';
5
+ import { defineViraElement } from '../define-vira-element.js';
6
+ /**
7
+ * A simple default style wrapper for pop-up menus.
8
+ *
9
+ * @category PopUp
10
+ * @category Elements
11
+ */
12
+ export const ViraPopUpMenu = defineViraElement()({
13
+ tagName: 'vira-pop-up-menu',
14
+ hostClasses: {
15
+ 'vira-pop-up-menu-open-upwards': ({ inputs }) => !!inputs.openUpwards,
16
+ },
17
+ styles: ({ hostClasses }) => css `
18
+ :host {
19
+ display: flex;
20
+
21
+ width: 100%;
22
+ max-height: 100%;
23
+ overflow-y: auto;
24
+ z-index: 99;
25
+ box-sizing: border-box;
26
+ border-radius: ${viraBorders['vira-form-input-radius'].value};
27
+ border-top-left-radius: 0;
28
+ border-top-right-radius: 0;
29
+ background-color: ${viraFormCssVars['vira-form-background-color'].value};
30
+ border: 1px solid ${viraFormCssVars['vira-form-border-color'].value};
31
+ color: ${viraFormCssVars['vira-form-foreground-color'].value};
32
+ ${viraShadows.menuShadow}
33
+ }
34
+
35
+ ${hostClasses['vira-pop-up-menu-open-upwards'].selector} {
36
+ border-bottom-left-radius: 0;
37
+ border-bottom-right-radius: 0;
38
+ border-top-left-radius: ${viraBorders['vira-form-input-radius'].value};
39
+ border-top-right-radius: ${viraBorders['vira-form-input-radius'].value};
40
+ ${viraShadows.menuShadowReversed}
41
+ }
42
+ `,
43
+ render() {
44
+ return html `
45
+ <slot></slot>
46
+ `;
47
+ },
48
+ });
@@ -0,0 +1,44 @@
1
+ import { type PartialWithUndefined } from '@augment-vir/common';
2
+ import { NavController, type Coords } from 'device-navigation';
3
+ import { PopUpManager, type ShowPopUpResult } from '../../util/pop-up-manager.js';
4
+ /**
5
+ * Offsets applied to any menu opened by {@link ViraPopUpTrigger}.
6
+ *
7
+ * @category Internal
8
+ */
9
+ export type PopUpOffset = PartialWithUndefined<{
10
+ vertical: number;
11
+ right: number;
12
+ left: number;
13
+ }>;
14
+ /**
15
+ * An element with slots for a pop-up trigger and pop-up contents.
16
+ *
17
+ * @category PopUp
18
+ * @category Elements
19
+ * @see https://electrovir.github.io/element-vir/vira/book/elements/vira-pop-up-trigger
20
+ */
21
+ export declare const ViraPopUpTrigger: import("element-vir").DeclarativeElementDefinition<"vira-pop-up-trigger", PartialWithUndefined<{
22
+ isDisabled: boolean;
23
+ /** For debugging purposes only. Very bad for actual production code use. */
24
+ z_debug_forceOpenState: boolean;
25
+ /** Set to `true` to keep the pop-up open if it is interacted with. */
26
+ keepOpenAfterInteraction: boolean;
27
+ /** All values in px. */
28
+ popUpOffset?: PopUpOffset;
29
+ }>, {
30
+ /** `undefined` means the pop up is not currently showing. */
31
+ showPopUpResult: ShowPopUpResult | undefined;
32
+ popUpManager: PopUpManager;
33
+ }, {
34
+ navSelect: import("element-vir").DefineEvent<Coords>;
35
+ /**
36
+ * - `undefined` indicates that the pop-up just closed.
37
+ * - {@link ShowPopUpResult} indicates that the pop-up just opened.
38
+ */
39
+ openChange: import("element-vir").DefineEvent<ShowPopUpResult | undefined>;
40
+ init: import("element-vir").DefineEvent<{
41
+ navController: NavController;
42
+ popUpManager: PopUpManager;
43
+ }>;
44
+ }, "vira-pop-up-trigger-disabled", "vira-pop-up-trigger-", readonly ["trigger", "popUp"]>;