vira 25.14.0 → 25.15.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.
@@ -1,5 +1,6 @@
1
1
  import { type PartialWithUndefined } from '@augment-vir/common';
2
2
  import { type HTMLTemplateResult } from 'element-vir';
3
+ import { type ViraLinkRoute } from '../vira-link.element.js';
3
4
  /**
4
5
  * An individual menu item consumed partially by `ViraMenuItem` and used by `ViraMenu`.
5
6
  *
@@ -8,17 +9,18 @@ import { type HTMLTemplateResult } from 'element-vir';
8
9
  export type MenuItem = {
9
10
  /** Each `id` must be unique across all items in a single menu. */
10
11
  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
12
  /**
18
- * An optional custom template for this menu item. This will replace the menu item text and icon
13
+ * The user-facing label for this menu item.
14
+ *
15
+ * Optionally, this can be a custom HTML template. This will replace the menu item text and icon
19
16
  * content, but will still be styled correctly if used within `ViraMenu`. Feel free to use
20
17
  * `ViraMenuItem` as the template with a custom `<slot>` to keep the selected checkmark
21
18
  * functionality.
22
19
  */
23
- template: HTMLTemplateResult;
20
+ label: string | HTMLTemplateResult;
21
+ } & PartialWithUndefined<{
22
+ route: ViraLinkRoute;
23
+ disabled: boolean;
24
+ /** Text assigned to the `title` HTML attribute that'll show on long hover. */
25
+ titleText: string;
24
26
  }>;
@@ -77,7 +77,11 @@ export const ViraMenuTrigger = defineViraElement()({
77
77
  }
78
78
  dispatch(new events.itemActivate(updateSelectedItems(item, inputs.selected, inputs.isMultiSelect)));
79
79
  if (!inputs.isMultiSelect) {
80
- state.popUpManager?.removePopUp();
80
+ /**
81
+ * Defer pop up removal to prevent race conditions with element-internal
82
+ * click handlers.
83
+ */
84
+ globalThis.setTimeout(() => state.popUpManager?.removePopUp());
81
85
  }
82
86
  })}
83
87
  >
@@ -1,8 +1,10 @@
1
+ import { check } from '@augment-vir/assert';
1
2
  import { nav, navAttribute, NavController, NavValue } from 'device-navigation';
2
3
  import { classMap, css, html, ifDefined, testId } from 'element-vir';
3
4
  import { viraFormCssVars } from '../../styles/form-themes.js';
4
5
  import { noNativeFormStyles, viraDisabledStyles } from '../../styles/index.js';
5
6
  import { defineViraElement } from '../define-vira-element.js';
7
+ import { ViraLink } from '../vira-link.element.js';
6
8
  import { assertUniqueIdProps } from './pop-up-helpers.js';
7
9
  import { ViraMenuItem } from './vira-menu-item.element.js';
8
10
  /**
@@ -47,7 +49,8 @@ export const ViraMenu = defineViraElement()({
47
49
 
48
50
  .menu-item {
49
51
  ${noNativeFormStyles};
50
- background-color: white;
52
+ will-change: background-color;
53
+ background-color: inherit;
51
54
  outline: none;
52
55
  cursor: pointer;
53
56
  }
@@ -99,29 +102,50 @@ export const ViraMenu = defineViraElement()({
99
102
  assertUniqueIdProps(inputs.items);
100
103
  const itemTemplates = inputs.items.map((item) => {
101
104
  const selected = !!inputs.selected?.includes(item.id);
102
- const innerTemplate = item.template ||
103
- html `
104
- <${ViraMenuItem.assign({
105
+ const innerTemplate = check.isString(item.label)
106
+ ? html `
107
+ <${ViraMenuItem.assign({
105
108
  label: item.label,
106
109
  selected,
107
110
  hideCheckIcon: inputs.hideCheckIcons,
108
111
  })}></${ViraMenuItem}>
109
- `;
112
+ `
113
+ : item.label;
110
114
  const disabled = item.disabled || (!inputs.isMultiSelect && selected);
111
- return html `
112
- <button
113
- class="menu-item ${classMap({
114
- disabled: !!item.disabled,
115
- selected,
116
- })}"
117
- ${testId(viraMenuTestIds.item)}
118
- title=${ifDefined(item.titleText || undefined)}
119
- role="option"
120
- ${nav(state.internalNavController, { disabled })}
121
- >
122
- ${innerTemplate}
123
- </button>
124
- `;
115
+ if (item.route) {
116
+ return html `
117
+ <${ViraLink.assign({
118
+ route: item.route,
119
+ })}
120
+ class="menu-item ${classMap({
121
+ disabled: !!item.disabled,
122
+ selected,
123
+ })}"
124
+ ${testId(viraMenuTestIds.item)}
125
+ title=${ifDefined(item.titleText || undefined)}
126
+ role="option"
127
+ ${nav(state.internalNavController, { disabled })}
128
+ >
129
+ ${innerTemplate}
130
+ </${ViraLink}>
131
+ `;
132
+ }
133
+ else {
134
+ return html `
135
+ <button
136
+ class="menu-item ${classMap({
137
+ disabled: !!item.disabled,
138
+ selected,
139
+ })}"
140
+ ${testId(viraMenuTestIds.item)}
141
+ title=${ifDefined(item.titleText || undefined)}
142
+ role="option"
143
+ ${nav(state.internalNavController, { disabled })}
144
+ >
145
+ ${innerTemplate}
146
+ </button>
147
+ `;
148
+ }
125
149
  });
126
150
  return html `
127
151
  ${itemTemplates}
@@ -31,11 +31,6 @@ export declare const ViraDropdown: import("element-vir").DeclarativeElementDefin
31
31
  * multiple.
32
32
  */
33
33
  isMultiSelect: boolean;
34
- /**
35
- * Shows the selection quantity rather than a list of selections. Only used when
36
- * `isMultiSelect` is `true`.
37
- */
38
- showSelectionCount: boolean;
39
34
  icon: ViraIconSvg;
40
35
  selectionPrefix: string;
41
36
  isDisabled: boolean;
@@ -128,11 +128,9 @@ export const ViraDropdown = defineViraElement()({
128
128
  : nothing;
129
129
  const selectionDisplay = shouldUsePlaceholder
130
130
  ? inputs.placeholder || ''
131
- : inputs.isMultiSelect && inputs.showSelectionCount
131
+ : inputs.isMultiSelect && selectedOptions.length > 1
132
132
  ? `${selectedOptions.length} Selected`
133
- : inputs.isMultiSelect
134
- ? selectedOptions.map((item) => item.label).join(', ')
135
- : selectedOptions[0]?.label || '';
133
+ : selectedOptions[0]?.label || '';
136
134
  return html `
137
135
  <${ViraMenuTrigger.assign({
138
136
  items: inputs.options,
@@ -165,10 +163,7 @@ export const ViraDropdown = defineViraElement()({
165
163
  class="selection-display ${classMap({
166
164
  'using-placeholder': shouldUsePlaceholder,
167
165
  })}"
168
- title=${ifDefined(shouldUsePlaceholder ||
169
- (inputs.isMultiSelect && inputs.showSelectionCount)
170
- ? undefined
171
- : selectionDisplay)}
166
+ title=${ifDefined(shouldUsePlaceholder ? undefined : selectionDisplay)}
172
167
  >
173
168
  ${prefixTemplate} ${selectionDisplay}
174
169
  </span>
@@ -1,5 +1,15 @@
1
1
  import { type PartialWithUndefined } from '@augment-vir/common';
2
2
  import { type SpaRoute, type SpaRouter } from 'spa-router-vir';
3
+ /**
4
+ * The route properties required for using {@link ViraLink} with a route.
5
+ *
6
+ * @category Internal
7
+ */
8
+ export type ViraLinkRoute = Readonly<{
9
+ route: SpaRoute<any, any, any>;
10
+ router: Pick<SpaRouter<any, any, any>, 'createRouteUrl' | 'setRouteOnDirectNavigation'>;
11
+ scrollToTop?: boolean;
12
+ }>;
3
13
  /**
4
14
  * A hyperlink wrapper element that can be configured to emit route change events rather than just
5
15
  * being a raw link.
@@ -21,11 +31,7 @@ export declare const ViraLink: import("element-vir").DeclarativeElementDefinitio
21
31
  * A route that'll change that current page without navigating the window. If this property
22
32
  * is provided for the inputs, don't provide a link property.
23
33
  */
24
- route: {
25
- route: SpaRoute<any, any, any>;
26
- router: Pick<SpaRouter<any, any, any>, "createRouteUrl" | "setRouteOnDirectNavigation">;
27
- scrollToTop?: boolean;
28
- };
34
+ route: ViraLinkRoute;
29
35
  }, "link" | "route"> & PartialWithUndefined<{
30
36
  aria?: {
31
37
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vira",
3
- "version": "25.14.0",
3
+ "version": "25.15.0",
4
4
  "description": "A simple and highly versatile design system using element-vir.",
5
5
  "keywords": [
6
6
  "design",
@@ -67,7 +67,7 @@
67
67
  "vite-tsconfig-paths": "^5.1.4"
68
68
  },
69
69
  "peerDependencies": {
70
- "element-vir": "^25.14.0"
70
+ "element-vir": "^25.15.0"
71
71
  },
72
72
  "engines": {
73
73
  "node": ">=22"