vira 31.24.1 → 31.25.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.
- package/dist/elements/pop-up/vira-menu-item.element.d.ts +8 -1
- package/dist/elements/pop-up/vira-menu-item.element.js +26 -2
- package/dist/elements/pop-up/vira-pop-up-trigger.element.js +9 -0
- package/dist/elements/vira-date-input.element.d.ts +3 -1
- package/dist/elements/vira-date-input.element.js +1 -1
- package/dist/elements/vira-form.element.js +1 -0
- package/dist/elements/vira-tabs.element.js +15 -1
- package/dist/icons/colored-icon.d.ts +1 -1
- package/dist/icons/colored-icon.js +21 -12
- package/dist/util/vira-form-fields.d.ts +2 -0
- package/package.json +15 -15
|
@@ -22,4 +22,11 @@ export declare const ViraMenuItem: import("element-vir").DeclarativeElementDefin
|
|
|
22
22
|
}>, {
|
|
23
23
|
/** Removes event listeners registered during init. */
|
|
24
24
|
cleanupListeners: undefined | (() => void);
|
|
25
|
-
}, {
|
|
25
|
+
}, {
|
|
26
|
+
/**
|
|
27
|
+
* Fired when this menu item is activated by the user (a non-disabled click). Pop-up
|
|
28
|
+
* containers (e.g. `ViraPopUpTrigger`) listen to this to close the pop-up on selection,
|
|
29
|
+
* gated by `keepOpenAfterInteraction`.
|
|
30
|
+
*/
|
|
31
|
+
activate: import("element-vir").DefineEvent<undefined>;
|
|
32
|
+
}, "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,5 +1,5 @@
|
|
|
1
1
|
import { assertWrap } from '@augment-vir/assert';
|
|
2
|
-
import { css, html } from 'element-vir';
|
|
2
|
+
import { css, defineElementEvent, html } from 'element-vir';
|
|
3
3
|
import { listenTo } from 'typed-event-target';
|
|
4
4
|
import { Check24Icon } from '../../icons/icon-svgs/24/check-24.icon.js';
|
|
5
5
|
import { viraFormCssVars } from '../../styles/form-styles.js';
|
|
@@ -20,6 +20,14 @@ export const ViraMenuItem = defineViraElement()({
|
|
|
20
20
|
cleanupListeners: undefined,
|
|
21
21
|
};
|
|
22
22
|
},
|
|
23
|
+
events: {
|
|
24
|
+
/**
|
|
25
|
+
* Fired when this menu item is activated by the user (a non-disabled click). Pop-up
|
|
26
|
+
* containers (e.g. `ViraPopUpTrigger`) listen to this to close the pop-up on selection,
|
|
27
|
+
* gated by `keepOpenAfterInteraction`.
|
|
28
|
+
*/
|
|
29
|
+
activate: defineElementEvent(),
|
|
30
|
+
},
|
|
23
31
|
hostClasses: {
|
|
24
32
|
'vira-menu-item-selected': ({ inputs }) => !!inputs.selected || !!inputs.iconOverride,
|
|
25
33
|
'vira-menu-item-disabled': ({ inputs }) => !!inputs.disabled,
|
|
@@ -95,7 +103,7 @@ export const ViraMenuItem = defineViraElement()({
|
|
|
95
103
|
min-width: 0;
|
|
96
104
|
}
|
|
97
105
|
`,
|
|
98
|
-
init({ state, updateState, host, inputs }) {
|
|
106
|
+
init({ state, updateState, host, inputs, dispatch, events }) {
|
|
99
107
|
host.setAttribute('role', 'menuitem');
|
|
100
108
|
host.setAttribute('tabindex', inputs.disabled ? '-1' : '0');
|
|
101
109
|
host.setAttribute('aria-selected', String(!!inputs.selected));
|
|
@@ -152,6 +160,22 @@ export const ViraMenuItem = defineViraElement()({
|
|
|
152
160
|
const listenerRemovers = [
|
|
153
161
|
listenTo(host, 'click', propagateMouseEvent),
|
|
154
162
|
listenTo(host, 'mousedown', propagateMouseEvent),
|
|
163
|
+
/**
|
|
164
|
+
* Emit `select` on a non-disabled activation so the containing pop-up can close. This
|
|
165
|
+
* uses the _capture_ phase because interactive slotted content can stop the click from
|
|
166
|
+
* bubbling back up to this host (which would prevent a bubble-phase listener from ever
|
|
167
|
+
* running). The `propagating` guard skips the synthetic click that
|
|
168
|
+
* `propagateMouseEvent` re-dispatches onto slotted content, so `select` fires exactly
|
|
169
|
+
* once per activation.
|
|
170
|
+
*/
|
|
171
|
+
listenTo(host, 'click', (event) => {
|
|
172
|
+
if (propagating[event.type] || inputs.disabled) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
dispatch(new events.activate(undefined));
|
|
176
|
+
}, {
|
|
177
|
+
capture: true,
|
|
178
|
+
}),
|
|
155
179
|
listenTo(host, 'mouseenter', () => {
|
|
156
180
|
if (!inputs.disabled) {
|
|
157
181
|
host.focus();
|
|
@@ -7,6 +7,7 @@ import { noNativeFormStyles, noUserSelect, viraDisabledStyles } from '../../styl
|
|
|
7
7
|
import { defineViraElement } from '../../util/define-vira-element.js';
|
|
8
8
|
import { triggerPopUpState } from '../../util/pop-up-helpers.js';
|
|
9
9
|
import { HidePopUpEvent, isInputLikeElement, NavSelectEvent, PopUpManager, } from '../../util/pop-up-manager.js';
|
|
10
|
+
import { ViraMenuItem } from './vira-menu-item.element.js';
|
|
10
11
|
/**
|
|
11
12
|
* Anchor options for pop-ups.
|
|
12
13
|
*
|
|
@@ -359,6 +360,14 @@ export const ViraPopUpTrigger = defineViraElement()({
|
|
|
359
360
|
if (event.composedPath().includes(dropdownTrigger)) {
|
|
360
361
|
respondToClick(event);
|
|
361
362
|
}
|
|
363
|
+
})}
|
|
364
|
+
${listen(ViraMenuItem.events.activate, (event) => {
|
|
365
|
+
if (state.showPopUpResult) {
|
|
366
|
+
triggerPopUp({
|
|
367
|
+
emitEvent: true,
|
|
368
|
+
open: false,
|
|
369
|
+
}, event);
|
|
370
|
+
}
|
|
362
371
|
})}
|
|
363
372
|
>
|
|
364
373
|
<div class="dropdown-trigger">
|
|
@@ -23,6 +23,8 @@ export declare const ViraDateInput: import("element-vir").DeclarativeElementDefi
|
|
|
23
23
|
isDisabled: boolean;
|
|
24
24
|
/** If true, the current value is rendered as plain text instead of an editable input. */
|
|
25
25
|
isReadonly: boolean;
|
|
26
|
+
/** Timezone used to interpret the selected date. Defaults to the user's timezone. */
|
|
27
|
+
timezone: string;
|
|
26
28
|
}>, {
|
|
27
29
|
/** Used to couple the label and input together. Not applied when no label is provided. */
|
|
28
30
|
randomId: string;
|
|
@@ -36,6 +38,6 @@ export declare const ViraDateInput: import("element-vir").DeclarativeElementDefi
|
|
|
36
38
|
month: import("date-vir").MonthNumber;
|
|
37
39
|
day: import("date-vir").DayOfMonth;
|
|
38
40
|
second: import("date-vir").Second;
|
|
39
|
-
timezone:
|
|
41
|
+
timezone: string;
|
|
40
42
|
} | undefined>;
|
|
41
43
|
}, "vira-date-input-error" | "vira-date-input-disabled", "vira-date-input-", readonly [], readonly []>;
|
|
@@ -113,7 +113,7 @@ export const ViraDateInput = defineViraElement()({
|
|
|
113
113
|
.value=${inputValue}
|
|
114
114
|
${listen('input', (event) => {
|
|
115
115
|
const element = extractEventTarget(event, HTMLInputElement);
|
|
116
|
-
dispatch(new events.valueChange(parseInputElementValue(element, userTimezone)));
|
|
116
|
+
dispatch(new events.valueChange(parseInputElementValue(element, inputs.timezone || userTimezone)));
|
|
117
117
|
})}
|
|
118
118
|
/>
|
|
119
119
|
`;
|
|
@@ -414,6 +414,13 @@ export const ViraTabs = defineViraElement()({
|
|
|
414
414
|
const isSelected = routeHasPaths(inputs.currentRoute, tab.paths, {
|
|
415
415
|
exactMatch: tab.exactMatch,
|
|
416
416
|
});
|
|
417
|
+
const iconTemplate = tab.icon
|
|
418
|
+
? html `
|
|
419
|
+
<${ViraIcon.assign({
|
|
420
|
+
icon: tab.icon,
|
|
421
|
+
})}></${ViraIcon}>
|
|
422
|
+
`
|
|
423
|
+
: nothing;
|
|
417
424
|
return {
|
|
418
425
|
content: html `
|
|
419
426
|
<${ViraLink.assign({
|
|
@@ -425,8 +432,15 @@ export const ViraTabs = defineViraElement()({
|
|
|
425
432
|
scrollToTop: true,
|
|
426
433
|
},
|
|
427
434
|
disableLinkStyles: true,
|
|
435
|
+
stylePassthrough: {
|
|
436
|
+
a: css `
|
|
437
|
+
display: flex;
|
|
438
|
+
align-items: center;
|
|
439
|
+
gap: 8px;
|
|
440
|
+
`,
|
|
441
|
+
},
|
|
428
442
|
})}>
|
|
429
|
-
${tab.label}
|
|
443
|
+
${iconTemplate} ${tab.label}
|
|
430
444
|
</${ViraLink}>
|
|
431
445
|
`,
|
|
432
446
|
selected: isSelected,
|
|
@@ -4,7 +4,7 @@ import { viraIconCssVars } from './icon-css-vars.js';
|
|
|
4
4
|
import { type ViraIconSvg } from './icon-svg.js';
|
|
5
5
|
/**
|
|
6
6
|
* Wraps an existing icon with a specific color and outputs another icon that can be used anywhere
|
|
7
|
-
* the original icon can be used.
|
|
7
|
+
* the original icon can be used. Results are cached per source icon and color combination.
|
|
8
8
|
*
|
|
9
9
|
* @category Icon
|
|
10
10
|
*/
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import { check } from '@augment-vir/assert';
|
|
2
|
-
import { getObjectTypedKeys } from '@augment-vir/common';
|
|
2
|
+
import { getObjectTypedKeys, getOrSetFromMap } from '@augment-vir/common';
|
|
3
3
|
import { css, html, unsafeCSS } from 'element-vir';
|
|
4
4
|
import { viraIconCssVars } from './icon-css-vars.js';
|
|
5
5
|
import { defineIcon } from './icon-svg.js';
|
|
6
|
+
/**
|
|
7
|
+
* Caches colored icons keyed first by the source icon and then by the generated color styles. The
|
|
8
|
+
* outer `WeakMap` lets the entire cache for a given icon be garbage collected once that icon is no
|
|
9
|
+
* longer referenced, preventing a memory leak from unbounded icon definitions.
|
|
10
|
+
*/
|
|
11
|
+
const coloredIconCache = new WeakMap();
|
|
6
12
|
/**
|
|
7
13
|
* Wraps an existing icon with a specific color and outputs another icon that can be used anywhere
|
|
8
|
-
* the original icon can be used.
|
|
14
|
+
* the original icon can be used. Results are cached per source icon and color combination.
|
|
9
15
|
*
|
|
10
16
|
* @category Icon
|
|
11
17
|
*/
|
|
@@ -21,15 +27,18 @@ export function createColoredIcon(icon, colors) {
|
|
|
21
27
|
})
|
|
22
28
|
.filter(check.isTruthy)
|
|
23
29
|
.join(' ');
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
const iconCache = getOrSetFromMap(coloredIconCache, icon, () => new Map());
|
|
31
|
+
return getOrSetFromMap(iconCache, colorStyles, () => {
|
|
32
|
+
const styles = css `
|
|
33
|
+
${unsafeCSS(colorStyles)}
|
|
34
|
+
display: inline-flex;
|
|
35
|
+
vertical-align: middle;
|
|
36
|
+
`;
|
|
37
|
+
return defineIcon({
|
|
38
|
+
name: icon.name,
|
|
39
|
+
svgTemplate: html `
|
|
40
|
+
<div style=${styles}>${icon.svgTemplate}</div>
|
|
41
|
+
`,
|
|
42
|
+
});
|
|
34
43
|
});
|
|
35
44
|
}
|
|
@@ -114,6 +114,8 @@ export type ViraFormField = ({
|
|
|
114
114
|
min: FullDate;
|
|
115
115
|
/** Upper bound for selectable dates. Defaults to 10 years from now when omitted. */
|
|
116
116
|
max: FullDate;
|
|
117
|
+
/** Timezone used to interpret the selected date. Defaults to the user's timezone. */
|
|
118
|
+
timezone: string;
|
|
117
119
|
}> & CommonViraFormFields);
|
|
118
120
|
/**
|
|
119
121
|
* A collection of form fields for `ViraForm`.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vira",
|
|
3
|
-
"version": "31.
|
|
3
|
+
"version": "31.25.0",
|
|
4
4
|
"description": "A simple and highly versatile design system using element-vir.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"design",
|
|
@@ -38,37 +38,37 @@
|
|
|
38
38
|
"test:docs": "virmator docs check"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@augment-vir/assert": "^31.
|
|
42
|
-
"@augment-vir/common": "^31.
|
|
43
|
-
"@augment-vir/web": "^31.
|
|
44
|
-
"@electrovir/color": "^1.7.
|
|
41
|
+
"@augment-vir/assert": "^31.73.2",
|
|
42
|
+
"@augment-vir/common": "^31.73.2",
|
|
43
|
+
"@augment-vir/web": "^31.73.2",
|
|
44
|
+
"@electrovir/color": "^1.7.10",
|
|
45
45
|
"@electrovir/local-storage-client": "^0.1.0",
|
|
46
|
-
"date-vir": "^8.
|
|
47
|
-
"device-navigation": "^4.
|
|
46
|
+
"date-vir": "^8.6.1",
|
|
47
|
+
"device-navigation": "^4.7.2",
|
|
48
48
|
"json-schema-to-ts": "^3.1.1",
|
|
49
49
|
"lit-css-vars": "^3.6.2",
|
|
50
|
-
"object-shape-tester": "^6.
|
|
50
|
+
"object-shape-tester": "^6.14.0",
|
|
51
51
|
"observavir": "^2.3.2",
|
|
52
52
|
"page-active": "^1.0.3",
|
|
53
53
|
"spa-router-vir": "^6.6.0",
|
|
54
|
-
"type-fest": "^5.
|
|
55
|
-
"typed-event-target": "^4.3.
|
|
54
|
+
"type-fest": "^5.7.0",
|
|
55
|
+
"typed-event-target": "^4.3.1"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
|
-
"@augment-vir/test": "^31.
|
|
58
|
+
"@augment-vir/test": "^31.73.2",
|
|
59
59
|
"@web/dev-server-esbuild": "^1.0.5",
|
|
60
60
|
"@web/test-runner": "^0.20.2",
|
|
61
61
|
"@web/test-runner-commands": "^0.9.0",
|
|
62
62
|
"@web/test-runner-playwright": "^0.11.1",
|
|
63
63
|
"@web/test-runner-visual-regression": "^0.10.0",
|
|
64
|
-
"esbuild": "^0.28.
|
|
64
|
+
"esbuild": "^0.28.1",
|
|
65
65
|
"istanbul-smart-text-reporter": "^1.1.5",
|
|
66
|
-
"lucide-static": "^1.
|
|
66
|
+
"lucide-static": "^1.21.0",
|
|
67
67
|
"markdown-code-example-inserter": "^3.0.5",
|
|
68
68
|
"theme-vir": "^28.25.0",
|
|
69
69
|
"typedoc": "^0.28.19",
|
|
70
|
-
"typescript": "
|
|
71
|
-
"vite": "^8.0.
|
|
70
|
+
"typescript": "6.0.3",
|
|
71
|
+
"vite": "^8.0.16",
|
|
72
72
|
"vite-tsconfig-paths": "^6.1.1"
|
|
73
73
|
},
|
|
74
74
|
"peerDependencies": {
|