vira 28.19.4 → 28.19.6
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/package.json +13 -13
- package/src/elements/define-vira-element.ts +29 -0
- package/src/elements/form/vira-form-fields.ts +140 -0
- package/src/elements/form/vira-form.element.ts +204 -0
- package/src/elements/pop-up/pop-up-helpers.ts +85 -0
- package/{dist/elements/pop-up/pop-up-menu-item.d.ts → src/elements/pop-up/pop-up-menu-item.ts} +4 -3
- package/{dist/elements/pop-up/vira-menu-item.element.js → src/elements/pop-up/vira-menu-item.element.ts} +28 -11
- package/src/elements/pop-up/vira-menu-trigger.element.ts +158 -0
- package/{dist/elements/pop-up/vira-menu.element.js → src/elements/pop-up/vira-menu.element.ts} +76 -49
- package/{dist/elements/pop-up/vira-pop-up-menu.element.js → src/elements/pop-up/vira-pop-up-menu.element.ts} +34 -22
- package/{dist/elements/pop-up/vira-pop-up-trigger.element.js → src/elements/pop-up/vira-pop-up-trigger.element.ts} +200 -91
- package/src/elements/shared-text-input-logic.ts +173 -0
- package/{dist/elements/vira-bold-text.element.js → src/elements/vira-bold-text.element.ts} +8 -7
- package/{dist/elements/vira-button.element.js → src/elements/vira-button.element.ts} +64 -33
- package/{dist/elements/vira-card.element.js → src/elements/vira-card.element.ts} +16 -13
- package/{dist/elements/vira-checkbox.element.js → src/elements/vira-checkbox.element.ts} +71 -28
- package/{dist/elements/vira-collapsible-wrapper.element.js → src/elements/vira-collapsible-wrapper.element.ts} +18 -16
- package/{dist/elements/vira-dropdown.element.js → src/elements/vira-dropdown.element.ts} +94 -48
- package/{dist/elements/vira-error.element.js → src/elements/vira-error.element.ts} +6 -5
- package/{dist/elements/vira-icon.element.js → src/elements/vira-icon.element.ts} +13 -6
- package/{dist/elements/vira-image.element.js → src/elements/vira-image.element.ts} +63 -43
- package/{dist/elements/vira-input.element.js → src/elements/vira-input.element.ts} +151 -85
- package/{dist/elements/vira-link.element.js → src/elements/vira-link.element.ts} +62 -11
- package/{dist/elements/vira-modal.element.js → src/elements/vira-modal.element.ts} +89 -50
- package/src/elements/vira-overflow-switch.element.ts +137 -0
- package/{dist/elements/vira-progress.element.js → src/elements/vira-progress.element.ts} +26 -11
- package/{dist/elements/vira-select.element.js → src/elements/vira-select.element.ts} +96 -41
- package/src/icons/icon-color.test-helper.ts +9 -0
- package/{dist/icons/icon-css-vars.js → src/icons/icon-css-vars.ts} +2 -1
- package/src/icons/icon-svg.ts +71 -0
- package/{dist/icons/icon-svgs/bell-24.icon.js → src/icons/icon-svgs/bell-24.icon.ts} +5 -4
- package/{dist/icons/icon-svgs/chat-24.icon.js → src/icons/icon-svgs/chat-24.icon.ts} +5 -4
- package/{dist/icons/icon-svgs/check-24.icon.js → src/icons/icon-svgs/check-24.icon.ts} +5 -4
- package/{dist/icons/icon-svgs/chevron-down-24.icon.js → src/icons/icon-svgs/chevron-down-24.icon.ts} +5 -4
- package/{dist/icons/icon-svgs/chevron-up-24.icon.js → src/icons/icon-svgs/chevron-up-24.icon.ts} +5 -4
- package/{dist/icons/icon-svgs/close-x-24.icon.js → src/icons/icon-svgs/close-x-24.icon.ts} +5 -4
- package/{dist/icons/icon-svgs/commit-24.icon.js → src/icons/icon-svgs/commit-24.icon.ts} +5 -4
- package/{dist/icons/icon-svgs/copy-24.icon.js → src/icons/icon-svgs/copy-24.icon.ts} +5 -4
- package/{dist/icons/icon-svgs/document-24.icon.js → src/icons/icon-svgs/document-24.icon.ts} +5 -4
- package/{dist/icons/icon-svgs/document-search-24.icon.js → src/icons/icon-svgs/document-search-24.icon.ts} +5 -4
- package/{dist/icons/icon-svgs/double-chevron-24.icon.js → src/icons/icon-svgs/double-chevron-24.icon.ts} +5 -4
- package/{dist/icons/icon-svgs/element-16.icon.js → src/icons/icon-svgs/element-16.icon.ts} +5 -4
- package/{dist/icons/icon-svgs/element-24.icon.js → src/icons/icon-svgs/element-24.icon.ts} +5 -4
- package/{dist/icons/icon-svgs/external-link-24.icon.js → src/icons/icon-svgs/external-link-24.icon.ts} +5 -4
- package/{dist/icons/icon-svgs/eye-closed-24.icon.js → src/icons/icon-svgs/eye-closed-24.icon.ts} +5 -4
- package/{dist/icons/icon-svgs/eye-open-24.icon.js → src/icons/icon-svgs/eye-open-24.icon.ts} +5 -4
- package/{dist/icons/icon-svgs/filter-24.icon.js → src/icons/icon-svgs/filter-24.icon.ts} +5 -4
- package/{dist/icons/icon-svgs/link-24.icon.js → src/icons/icon-svgs/link-24.icon.ts} +5 -4
- package/{dist/icons/icon-svgs/loader-24.icon.js → src/icons/icon-svgs/loader-24.icon.ts} +5 -4
- package/{dist/icons/icon-svgs/loader-animated-24.icon.js → src/icons/icon-svgs/loader-animated-24.icon.ts} +8 -6
- package/{dist/icons/icon-svgs/lock-24.icon.js → src/icons/icon-svgs/lock-24.icon.ts} +5 -4
- package/{dist/icons/icon-svgs/options-24.icon.js → src/icons/icon-svgs/options-24.icon.ts} +5 -4
- package/{dist/icons/icon-svgs/pencil-24.icon.js → src/icons/icon-svgs/pencil-24.icon.ts} +5 -4
- package/{dist/icons/icon-svgs/shield-24.icon.js → src/icons/icon-svgs/shield-24.icon.ts} +5 -4
- package/{dist/icons/icon-svgs/sort-ascending-24.icon.js → src/icons/icon-svgs/sort-ascending-24.icon.ts} +5 -4
- package/{dist/icons/icon-svgs/sort-descending-24.icon.js → src/icons/icon-svgs/sort-descending-24.icon.ts} +5 -4
- package/{dist/icons/icon-svgs/speaker-loud-24.icon.js → src/icons/icon-svgs/speaker-loud-24.icon.ts} +5 -4
- package/{dist/icons/icon-svgs/speaker-medium-24.icon.js → src/icons/icon-svgs/speaker-medium-24.icon.ts} +5 -4
- package/{dist/icons/icon-svgs/speaker-muted-24.icon.js → src/icons/icon-svgs/speaker-muted-24.icon.ts} +5 -4
- package/{dist/icons/icon-svgs/speaker-quiet-24.icon.js → src/icons/icon-svgs/speaker-quiet-24.icon.ts} +5 -4
- package/{dist/icons/icon-svgs/star-24.icon.js → src/icons/icon-svgs/star-24.icon.ts} +5 -4
- package/{dist/icons/icon-svgs/status-failure-24.icon.js → src/icons/icon-svgs/status-failure-24.icon.ts} +5 -4
- package/{dist/icons/icon-svgs/status-in-progress-24.icon.js → src/icons/icon-svgs/status-in-progress-24.icon.ts} +5 -4
- package/{dist/icons/icon-svgs/status-success-24.icon.js → src/icons/icon-svgs/status-success-24.icon.ts} +5 -4
- package/{dist/icons/icon-svgs/status-unknown-24.icon.js → src/icons/icon-svgs/status-unknown-24.icon.ts} +5 -4
- package/{dist/icons/icon-svgs/status-warning-24.icon.js → src/icons/icon-svgs/status-warning-24.icon.ts} +5 -4
- package/{dist/icons/icon-svgs/upload-24.icon.js → src/icons/icon-svgs/upload-24.icon.ts} +5 -4
- package/{dist/icons/icon-svgs/x-24.icon.js → src/icons/icon-svgs/x-24.icon.ts} +5 -4
- package/{dist/icons/index.js → src/icons/index.ts} +43 -39
- package/{dist/styles/border.js → src/styles/border.ts} +2 -1
- package/{dist/styles/disabled.js → src/styles/disabled.ts} +3 -2
- package/{dist/styles/durations.js → src/styles/durations.ts} +2 -1
- package/{dist/styles/focus.js → src/styles/focus.ts} +32 -8
- package/{dist/styles/font.js → src/styles/font.ts} +2 -1
- package/{dist/styles/form-styles.js → src/styles/form-styles.ts} +6 -1
- package/{dist/styles/index.js → src/styles/index.ts} +1 -0
- package/{dist/styles/native-styles.js → src/styles/native-styles.ts} +5 -3
- package/{dist/styles/scrollbar.js → src/styles/scrollbar.ts} +4 -3
- package/{dist/styles/shadows.js → src/styles/shadows.ts} +8 -6
- package/{dist/styles/user-select.js → src/styles/user-select.ts} +3 -2
- package/{dist/styles/vira-color-palette.js → src/styles/vira-color-palette.ts} +11 -1
- package/src/styles/vira-color-theme.ts +1142 -0
- package/src/util/define-table.ts +279 -0
- package/src/util/dynamic-element.ts +129 -0
- package/src/util/pop-up-manager.ts +380 -0
- package/dist/elements/define-vira-element.d.ts +0 -18
- package/dist/elements/define-vira-element.js +0 -19
- package/dist/elements/form/vira-form-fields.d.ts +0 -100
- package/dist/elements/form/vira-form-fields.js +0 -60
- package/dist/elements/form/vira-form.element.d.ts +0 -35
- package/dist/elements/form/vira-form.element.js +0 -151
- package/dist/elements/index.js +0 -25
- package/dist/elements/pop-up/pop-up-helpers.d.ts +0 -33
- package/dist/elements/pop-up/pop-up-helpers.js +0 -58
- package/dist/elements/pop-up/pop-up-menu-item.js +0 -1
- package/dist/elements/pop-up/vira-menu-item.element.d.ts +0 -19
- package/dist/elements/pop-up/vira-menu-trigger.element.d.ts +0 -41
- package/dist/elements/pop-up/vira-menu-trigger.element.js +0 -121
- package/dist/elements/pop-up/vira-menu.element.d.ts +0 -38
- package/dist/elements/pop-up/vira-pop-up-menu.element.d.ts +0 -35
- package/dist/elements/pop-up/vira-pop-up-trigger.element.d.ts +0 -105
- package/dist/elements/shared-text-input-logic.d.ts +0 -63
- package/dist/elements/shared-text-input-logic.js +0 -101
- package/dist/elements/vira-bold-text.element.d.ts +0 -9
- package/dist/elements/vira-button.element.d.ts +0 -31
- package/dist/elements/vira-card.element.d.ts +0 -18
- package/dist/elements/vira-checkbox.element.d.ts +0 -34
- package/dist/elements/vira-collapsible-wrapper.element.d.ts +0 -14
- package/dist/elements/vira-dropdown.element.d.ts +0 -46
- package/dist/elements/vira-error.element.d.ts +0 -7
- package/dist/elements/vira-icon.element.d.ts +0 -13
- package/dist/elements/vira-image.element.d.ts +0 -45
- package/dist/elements/vira-input.element.d.ts +0 -62
- package/dist/elements/vira-link.element.d.ts +0 -73
- package/dist/elements/vira-modal.element.d.ts +0 -39
- package/dist/elements/vira-overflow-switch.element.d.ts +0 -21
- package/dist/elements/vira-overflow-switch.element.js +0 -110
- package/dist/elements/vira-progress.element.d.ts +0 -18
- package/dist/elements/vira-select.element.d.ts +0 -48
- package/dist/icons/icon-color.test-helper.d.ts +0 -6
- package/dist/icons/icon-color.test-helper.js +0 -9
- package/dist/icons/icon-css-vars.d.ts +0 -14
- package/dist/icons/icon-svg.d.ts +0 -27
- package/dist/icons/icon-svg.js +0 -48
- package/dist/icons/icon-svgs/bell-24.icon.d.ts +0 -8
- package/dist/icons/icon-svgs/chat-24.icon.d.ts +0 -8
- package/dist/icons/icon-svgs/check-24.icon.d.ts +0 -8
- package/dist/icons/icon-svgs/chevron-down-24.icon.d.ts +0 -8
- package/dist/icons/icon-svgs/chevron-up-24.icon.d.ts +0 -8
- package/dist/icons/icon-svgs/close-x-24.icon.d.ts +0 -8
- package/dist/icons/icon-svgs/commit-24.icon.d.ts +0 -8
- package/dist/icons/icon-svgs/copy-24.icon.d.ts +0 -8
- package/dist/icons/icon-svgs/document-24.icon.d.ts +0 -8
- package/dist/icons/icon-svgs/document-search-24.icon.d.ts +0 -8
- package/dist/icons/icon-svgs/double-chevron-24.icon.d.ts +0 -8
- package/dist/icons/icon-svgs/element-16.icon.d.ts +0 -8
- package/dist/icons/icon-svgs/element-24.icon.d.ts +0 -8
- package/dist/icons/icon-svgs/external-link-24.icon.d.ts +0 -8
- package/dist/icons/icon-svgs/eye-closed-24.icon.d.ts +0 -8
- package/dist/icons/icon-svgs/eye-open-24.icon.d.ts +0 -8
- package/dist/icons/icon-svgs/filter-24.icon.d.ts +0 -8
- package/dist/icons/icon-svgs/link-24.icon.d.ts +0 -8
- package/dist/icons/icon-svgs/loader-24.icon.d.ts +0 -8
- package/dist/icons/icon-svgs/loader-animated-24.icon.d.ts +0 -8
- package/dist/icons/icon-svgs/lock-24.icon.d.ts +0 -8
- package/dist/icons/icon-svgs/options-24.icon.d.ts +0 -8
- package/dist/icons/icon-svgs/pencil-24.icon.d.ts +0 -8
- package/dist/icons/icon-svgs/shield-24.icon.d.ts +0 -8
- package/dist/icons/icon-svgs/sort-ascending-24.icon.d.ts +0 -8
- package/dist/icons/icon-svgs/sort-descending-24.icon.d.ts +0 -8
- package/dist/icons/icon-svgs/speaker-loud-24.icon.d.ts +0 -8
- package/dist/icons/icon-svgs/speaker-medium-24.icon.d.ts +0 -8
- package/dist/icons/icon-svgs/speaker-muted-24.icon.d.ts +0 -8
- package/dist/icons/icon-svgs/speaker-quiet-24.icon.d.ts +0 -8
- package/dist/icons/icon-svgs/star-24.icon.d.ts +0 -8
- package/dist/icons/icon-svgs/status-failure-24.icon.d.ts +0 -8
- package/dist/icons/icon-svgs/status-in-progress-24.icon.d.ts +0 -8
- package/dist/icons/icon-svgs/status-success-24.icon.d.ts +0 -8
- package/dist/icons/icon-svgs/status-unknown-24.icon.d.ts +0 -8
- package/dist/icons/icon-svgs/status-warning-24.icon.d.ts +0 -8
- package/dist/icons/icon-svgs/upload-24.icon.d.ts +0 -8
- package/dist/icons/icon-svgs/x-24.icon.d.ts +0 -8
- package/dist/icons/index.d.ts +0 -86
- package/dist/index.js +0 -4
- package/dist/styles/border.d.ts +0 -9
- package/dist/styles/disabled.d.ts +0 -6
- package/dist/styles/durations.d.ts +0 -22
- package/dist/styles/focus.d.ts +0 -31
- package/dist/styles/font.d.ts +0 -9
- package/dist/styles/form-styles.d.ts +0 -20
- package/dist/styles/index.d.ts +0 -13
- package/dist/styles/native-styles.d.ts +0 -13
- package/dist/styles/scrollbar.d.ts +0 -6
- package/dist/styles/shadows.d.ts +0 -20
- package/dist/styles/user-select.d.ts +0 -6
- package/dist/styles/vira-color-palette.d.ts +0 -95
- package/dist/styles/vira-color-theme.d.ts +0 -1184
- package/dist/styles/vira-color-theme.js +0 -1137
- package/dist/util/define-table.d.ts +0 -110
- package/dist/util/define-table.js +0 -115
- package/dist/util/dynamic-element.d.ts +0 -63
- package/dist/util/dynamic-element.js +0 -61
- package/dist/util/index.js +0 -3
- package/dist/util/pop-up-manager.d.ts +0 -180
- package/dist/util/pop-up-manager.js +0 -203
- /package/{dist/elements/index.d.ts → src/elements/index.ts} +0 -0
- /package/{dist/index.d.ts → src/index.ts} +0 -0
- /package/{dist/util/index.d.ts → src/util/index.ts} +0 -0
|
@@ -1,5 +1,28 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import {type PartialWithUndefined} from '@augment-vir/common';
|
|
2
|
+
import {
|
|
3
|
+
attributes,
|
|
4
|
+
css,
|
|
5
|
+
html,
|
|
6
|
+
ifDefined,
|
|
7
|
+
listen,
|
|
8
|
+
type AttributeValues,
|
|
9
|
+
type CSSResult,
|
|
10
|
+
} from 'element-vir';
|
|
11
|
+
import {type SpaRoute, type SpaRouter} from 'spa-router-vir';
|
|
12
|
+
import {type RequireExactlyOne} from 'type-fest';
|
|
13
|
+
import {defineViraElement} from './define-vira-element.js';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* The route properties required for using {@link ViraLink} with a route.
|
|
17
|
+
*
|
|
18
|
+
* @category Internal
|
|
19
|
+
*/
|
|
20
|
+
export type ViraLinkRoute = Readonly<{
|
|
21
|
+
route: SpaRoute<any, any, any>;
|
|
22
|
+
router: Pick<SpaRouter<any, any, any>, 'createRouteUrl' | 'setRouteOnDirectNavigation'>;
|
|
23
|
+
scrollToTop?: boolean;
|
|
24
|
+
}>;
|
|
25
|
+
|
|
3
26
|
/**
|
|
4
27
|
* A hyperlink wrapper element that can be configured to emit route change events rather than just
|
|
5
28
|
* being a raw link.
|
|
@@ -8,12 +31,34 @@ import { defineViraElement } from './define-vira-element.js';
|
|
|
8
31
|
* @category Elements
|
|
9
32
|
* @see https://electrovir.github.io/vira/book/elements/vira-link
|
|
10
33
|
*/
|
|
11
|
-
export const ViraLink = defineViraElement
|
|
34
|
+
export const ViraLink = defineViraElement<
|
|
35
|
+
RequireExactlyOne<{
|
|
36
|
+
/**
|
|
37
|
+
* A full raw URL link that will navigate the current window away or open a new tab. If this
|
|
38
|
+
* property is provided for the inputs, don't provide a route property.
|
|
39
|
+
*/
|
|
40
|
+
link: {
|
|
41
|
+
url: string;
|
|
42
|
+
newTab: boolean;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* A route that'll change that current page without navigating the window. If this property
|
|
46
|
+
* is provided for the inputs, don't provide a link property.
|
|
47
|
+
*/
|
|
48
|
+
route: ViraLinkRoute;
|
|
49
|
+
}> &
|
|
50
|
+
PartialWithUndefined<{
|
|
51
|
+
/** Styles that will be applied directly to the inner elements. */
|
|
52
|
+
stylePassthrough: Readonly<PartialWithUndefined<{a: CSSResult}>>;
|
|
53
|
+
/** Attributes that will be applied directly to the inner elements. */
|
|
54
|
+
attributePassthrough: Readonly<PartialWithUndefined<{a: AttributeValues}>>;
|
|
55
|
+
}>
|
|
56
|
+
>()({
|
|
12
57
|
tagName: 'vira-link',
|
|
13
58
|
cssVars: {
|
|
14
59
|
'vira-link-hover-color': 'currentColor',
|
|
15
60
|
},
|
|
16
|
-
styles: ({
|
|
61
|
+
styles: ({cssVars}) => css`
|
|
17
62
|
:host {
|
|
18
63
|
display: inline;
|
|
19
64
|
text-decoration: underline;
|
|
@@ -36,12 +81,17 @@ export const ViraLink = defineViraElement()({
|
|
|
36
81
|
color: ${cssVars['vira-link-hover-color'].value};
|
|
37
82
|
}
|
|
38
83
|
`,
|
|
39
|
-
render({
|
|
40
|
-
function clickCallback(event) {
|
|
84
|
+
render({inputs}) {
|
|
85
|
+
function clickCallback(event: MouseEvent) {
|
|
41
86
|
if (!inputs.route) {
|
|
42
87
|
return;
|
|
43
88
|
}
|
|
44
|
-
|
|
89
|
+
|
|
90
|
+
const routed = inputs.route.router.setRouteOnDirectNavigation(
|
|
91
|
+
inputs.route.route,
|
|
92
|
+
event,
|
|
93
|
+
);
|
|
94
|
+
|
|
45
95
|
if (routed && inputs.route.scrollToTop) {
|
|
46
96
|
window.scrollTo({
|
|
47
97
|
left: 0,
|
|
@@ -50,9 +100,10 @@ export const ViraLink = defineViraElement()({
|
|
|
50
100
|
});
|
|
51
101
|
}
|
|
52
102
|
}
|
|
103
|
+
|
|
53
104
|
if (inputs.link?.newTab) {
|
|
54
105
|
/** Noopener and noreferrer are needed for security reasons, do not remove! */
|
|
55
|
-
return html
|
|
106
|
+
return html`
|
|
56
107
|
<a
|
|
57
108
|
href=${inputs.link.url}
|
|
58
109
|
target="_blank"
|
|
@@ -63,13 +114,13 @@ export const ViraLink = defineViraElement()({
|
|
|
63
114
|
<slot></slot>
|
|
64
115
|
</a>
|
|
65
116
|
`;
|
|
66
|
-
}
|
|
67
|
-
else {
|
|
117
|
+
} else {
|
|
68
118
|
const linkUrl = inputs.link
|
|
69
119
|
? inputs.link.url
|
|
70
120
|
: inputs.route.router.createRouteUrl(inputs.route.route);
|
|
121
|
+
|
|
71
122
|
/** Noopener and noreferrer are needed for security reasons, do not remove! */
|
|
72
|
-
return html
|
|
123
|
+
return html`
|
|
73
124
|
<a
|
|
74
125
|
href=${linkUrl}
|
|
75
126
|
rel="noopener noreferrer"
|
|
@@ -1,41 +1,71 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
1
|
+
import {assertWrap} from '@augment-vir/assert';
|
|
2
|
+
import {type PartialWithUndefined} from '@augment-vir/common';
|
|
3
|
+
import {css, defineElementEvent, html, listen, nothing, onDomCreated} from 'element-vir';
|
|
4
|
+
import {listenToGlobal} from 'typed-event-target';
|
|
5
|
+
import {X24Icon} from '../icons/icon-svgs/x-24.icon.js';
|
|
6
|
+
import {noNativeFormStyles, noNativeSpacing} from '../styles/native-styles.js';
|
|
7
|
+
import {viraShadows} from '../styles/shadows.js';
|
|
8
|
+
import {defineViraElement} from './define-vira-element.js';
|
|
9
|
+
import {ViraIcon} from './vira-icon.element.js';
|
|
10
|
+
|
|
9
11
|
const globalEventsToCloseModalOn = [
|
|
10
12
|
'pagehide',
|
|
11
13
|
'pageshow',
|
|
12
14
|
'popstate',
|
|
13
|
-
];
|
|
15
|
+
] as const satisfies (keyof WindowEventMap)[];
|
|
16
|
+
|
|
14
17
|
/**
|
|
15
18
|
* A modal element that uses the built-in `dialog` element.
|
|
16
19
|
*
|
|
17
20
|
* @category Elements
|
|
18
21
|
* @see https://electrovir.github.io/vira/book/elements/vira-modal
|
|
19
22
|
*/
|
|
20
|
-
export const ViraModal = defineViraElement
|
|
23
|
+
export const ViraModal = defineViraElement<
|
|
24
|
+
Readonly<
|
|
25
|
+
{
|
|
26
|
+
open: boolean;
|
|
27
|
+
} & PartialWithUndefined<{
|
|
28
|
+
/** If this isn't set, make sure to use the modal title slot to fill it in. */
|
|
29
|
+
modalTitle: string;
|
|
30
|
+
/**
|
|
31
|
+
* If `true`, the following conditions trigger the modal to close:
|
|
32
|
+
*
|
|
33
|
+
* - The user clicks the "x" close button
|
|
34
|
+
* - The `open` input is set to `false`
|
|
35
|
+
*
|
|
36
|
+
* If set to `false` (the default), the following conditions trigger the modal to close:
|
|
37
|
+
*
|
|
38
|
+
* - The user clicks outside of the modal
|
|
39
|
+
* - The user presses the "Escape" key
|
|
40
|
+
* - The user clicks the "x" close button
|
|
41
|
+
* - The `open` input is set to `false`
|
|
42
|
+
*
|
|
43
|
+
* @default false
|
|
44
|
+
*/
|
|
45
|
+
blockLightDismissal: boolean;
|
|
46
|
+
modalSubtitle: string;
|
|
47
|
+
isMobileSize: boolean;
|
|
48
|
+
}>
|
|
49
|
+
>
|
|
50
|
+
>()({
|
|
21
51
|
tagName: 'vira-modal',
|
|
22
52
|
events: {
|
|
23
|
-
modalClose: defineElementEvent(),
|
|
53
|
+
modalClose: defineElementEvent<void>(),
|
|
24
54
|
},
|
|
25
55
|
state() {
|
|
26
56
|
return {
|
|
27
|
-
dialogElement: undefined,
|
|
28
|
-
contentElement: undefined,
|
|
29
|
-
previousOpenValue: undefined,
|
|
57
|
+
dialogElement: undefined as HTMLDialogElement | undefined,
|
|
58
|
+
contentElement: undefined as HTMLDivElement | undefined,
|
|
59
|
+
previousOpenValue: undefined as undefined | boolean,
|
|
30
60
|
/** Remove listeners. */
|
|
31
|
-
cleanup: undefined,
|
|
61
|
+
cleanup: undefined as undefined | (() => void),
|
|
32
62
|
};
|
|
33
63
|
},
|
|
34
|
-
cleanup({
|
|
64
|
+
cleanup({state}) {
|
|
35
65
|
state.cleanup?.();
|
|
36
66
|
},
|
|
37
67
|
hostClasses: {
|
|
38
|
-
'vira-modal-phone-size': ({
|
|
68
|
+
'vira-modal-phone-size': ({inputs}) => !!inputs.isMobileSize,
|
|
39
69
|
},
|
|
40
70
|
slotNames: ['modalTitle'],
|
|
41
71
|
cssVars: {
|
|
@@ -45,7 +75,7 @@ export const ViraModal = defineViraElement()({
|
|
|
45
75
|
'vira-modal-close-button-hover-radius': '8px',
|
|
46
76
|
'vira-modal-close-button-hover-background-color': '#E4E4E4',
|
|
47
77
|
},
|
|
48
|
-
styles: ({
|
|
78
|
+
styles: ({hostClasses, cssVars}) => css`
|
|
49
79
|
:host {
|
|
50
80
|
display: contents;
|
|
51
81
|
min-width: 280px;
|
|
@@ -111,7 +141,9 @@ export const ViraModal = defineViraElement()({
|
|
|
111
141
|
border-radius: ${cssVars['vira-modal-close-button-hover-radius'].value};
|
|
112
142
|
|
|
113
143
|
&:hover {
|
|
114
|
-
background-color: ${cssVars[
|
|
144
|
+
background-color: ${cssVars[
|
|
145
|
+
'vira-modal-close-button-hover-background-color'
|
|
146
|
+
].value};
|
|
115
147
|
}
|
|
116
148
|
|
|
117
149
|
& ${ViraIcon} {
|
|
@@ -134,22 +166,25 @@ export const ViraModal = defineViraElement()({
|
|
|
134
166
|
}
|
|
135
167
|
}
|
|
136
168
|
`,
|
|
137
|
-
render({
|
|
169
|
+
render({inputs, state, updateState, events, dispatch, slotNames}) {
|
|
138
170
|
if (state.dialogElement && inputs.open !== state.dialogElement.open) {
|
|
139
171
|
if (inputs.open) {
|
|
140
172
|
state.dialogElement.showModal();
|
|
141
|
-
}
|
|
142
|
-
else {
|
|
173
|
+
} else {
|
|
143
174
|
state.dialogElement.close();
|
|
144
175
|
}
|
|
145
176
|
}
|
|
177
|
+
|
|
146
178
|
if (state.previousOpenValue !== inputs.open) {
|
|
147
179
|
state.cleanup?.();
|
|
148
|
-
updateState({
|
|
180
|
+
updateState({previousOpenValue: inputs.open});
|
|
149
181
|
if (inputs.open) {
|
|
150
|
-
const removers = globalEventsToCloseModalOn.map((eventName) =>
|
|
151
|
-
|
|
152
|
-
|
|
182
|
+
const removers = globalEventsToCloseModalOn.map((eventName) =>
|
|
183
|
+
listenToGlobal(eventName, () => {
|
|
184
|
+
dispatch(new events.modalClose());
|
|
185
|
+
}),
|
|
186
|
+
);
|
|
187
|
+
|
|
153
188
|
updateState({
|
|
154
189
|
cleanup: () => {
|
|
155
190
|
removers.forEach((remover) => remover());
|
|
@@ -157,65 +192,69 @@ export const ViraModal = defineViraElement()({
|
|
|
157
192
|
});
|
|
158
193
|
}
|
|
159
194
|
}
|
|
195
|
+
|
|
160
196
|
function close() {
|
|
161
197
|
if (inputs.open) {
|
|
162
198
|
state.cleanup?.();
|
|
163
199
|
dispatch(new events.modalClose());
|
|
164
200
|
}
|
|
165
201
|
}
|
|
166
|
-
|
|
202
|
+
|
|
203
|
+
return html`
|
|
167
204
|
<dialog
|
|
168
205
|
${onDomCreated((element) => {
|
|
169
|
-
|
|
170
|
-
|
|
206
|
+
updateState({dialogElement: assertWrap.instanceOf(element, HTMLDialogElement)});
|
|
207
|
+
})}
|
|
171
208
|
${listen('close', () => {
|
|
172
|
-
|
|
173
|
-
|
|
209
|
+
close();
|
|
210
|
+
})}
|
|
174
211
|
${listen('click', (event) => {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
212
|
+
if (
|
|
213
|
+
state.contentElement &&
|
|
214
|
+
!event.composedPath().includes(state.contentElement) &&
|
|
215
|
+
!inputs.blockLightDismissal
|
|
216
|
+
) {
|
|
217
|
+
/** Background click. */
|
|
218
|
+
close();
|
|
219
|
+
}
|
|
220
|
+
})}
|
|
182
221
|
>
|
|
183
222
|
<div
|
|
184
223
|
class="modal-content-wrapper"
|
|
185
224
|
${onDomCreated((element) => {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
225
|
+
updateState({
|
|
226
|
+
contentElement: assertWrap.instanceOf(element, HTMLDivElement),
|
|
227
|
+
});
|
|
228
|
+
})}
|
|
190
229
|
>
|
|
191
230
|
<div class="header">
|
|
192
231
|
<div class="header-text-wrapper">
|
|
193
232
|
<h1><slot name=${slotNames.modalTitle}>${inputs.modalTitle}</slot></h1>
|
|
194
233
|
${inputs.modalSubtitle
|
|
195
|
-
|
|
234
|
+
? html`
|
|
196
235
|
<sub>${inputs.modalSubtitle}</sub>
|
|
197
236
|
`
|
|
198
|
-
|
|
237
|
+
: nothing}
|
|
199
238
|
</div>
|
|
200
239
|
<button
|
|
201
240
|
class="close"
|
|
202
241
|
aria-label="Close"
|
|
203
242
|
${listen('click', () => {
|
|
204
|
-
|
|
205
|
-
|
|
243
|
+
state.dialogElement?.close();
|
|
244
|
+
})}
|
|
206
245
|
>
|
|
207
246
|
<${ViraIcon.assign({
|
|
208
|
-
|
|
209
|
-
|
|
247
|
+
icon: X24Icon,
|
|
248
|
+
})}></${ViraIcon}>
|
|
210
249
|
</button>
|
|
211
250
|
</div>
|
|
212
251
|
${inputs.open
|
|
213
|
-
|
|
252
|
+
? html`
|
|
214
253
|
<div class="body">
|
|
215
254
|
<slot></slot>
|
|
216
255
|
</div>
|
|
217
256
|
`
|
|
218
|
-
|
|
257
|
+
: nothing}
|
|
219
258
|
</div>
|
|
220
259
|
</dialog>
|
|
221
260
|
`;
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import {css, html, onDomCreated} from 'element-vir';
|
|
2
|
+
import {type RequireExactlyOne} from 'type-fest';
|
|
3
|
+
import {listenTo} from 'typed-event-target';
|
|
4
|
+
import {defineViraElement} from './define-vira-element.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* An element switches between two slots based on their overflow.
|
|
8
|
+
*
|
|
9
|
+
* @category Elements
|
|
10
|
+
* @see https://electrovir.github.io/vira/book/elements/vira-overflow-switch
|
|
11
|
+
*/
|
|
12
|
+
export const ViraOverflowSwitch = defineViraElement<
|
|
13
|
+
Readonly<
|
|
14
|
+
RequireExactlyOne<{
|
|
15
|
+
automaticallySwitch: boolean;
|
|
16
|
+
useSmall: boolean;
|
|
17
|
+
}>
|
|
18
|
+
>
|
|
19
|
+
>()({
|
|
20
|
+
tagName: 'vira-overflow-switch',
|
|
21
|
+
slotNames: [
|
|
22
|
+
/** The child to render, if it fits. */
|
|
23
|
+
'large',
|
|
24
|
+
/** The child to render if the large one does not fit. */
|
|
25
|
+
'small',
|
|
26
|
+
],
|
|
27
|
+
state() {
|
|
28
|
+
return {
|
|
29
|
+
isOverflowing: false,
|
|
30
|
+
resizeObserver: undefined as undefined | ResizeObserver,
|
|
31
|
+
/** Called on cleanup to clear all listeners. */
|
|
32
|
+
cleanup: undefined as undefined | (() => void),
|
|
33
|
+
};
|
|
34
|
+
},
|
|
35
|
+
hostClasses: {
|
|
36
|
+
'vira-overflow-switch-show-small': ({state, inputs}) =>
|
|
37
|
+
state.isOverflowing || !!inputs.useSmall,
|
|
38
|
+
},
|
|
39
|
+
styles: ({hostClasses}) => css`
|
|
40
|
+
:host {
|
|
41
|
+
display: inline-block;
|
|
42
|
+
max-width: 100%;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.large,
|
|
46
|
+
.small {
|
|
47
|
+
display: inline-block;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.small {
|
|
51
|
+
display: none;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* When the large content overflows, hide it but keep it in layout so we can measure it.
|
|
56
|
+
* The small content is then shown instead.
|
|
57
|
+
*/
|
|
58
|
+
${hostClasses['vira-overflow-switch-show-small'].selector} .large {
|
|
59
|
+
visibility: hidden;
|
|
60
|
+
position: absolute;
|
|
61
|
+
top: 0;
|
|
62
|
+
left: 0;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
${hostClasses['vira-overflow-switch-show-small'].selector} .small {
|
|
66
|
+
display: inline-block;
|
|
67
|
+
}
|
|
68
|
+
`,
|
|
69
|
+
cleanup({state, updateState}) {
|
|
70
|
+
state.cleanup?.();
|
|
71
|
+
updateState({
|
|
72
|
+
cleanup: undefined,
|
|
73
|
+
});
|
|
74
|
+
},
|
|
75
|
+
render({slotNames, updateState, inputs, host, state}) {
|
|
76
|
+
return html`
|
|
77
|
+
<div
|
|
78
|
+
class="large"
|
|
79
|
+
${onDomCreated((largeElement) => {
|
|
80
|
+
if (!inputs.automaticallySwitch) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const overflowParams: Parameters<typeof updateOverflowing>[0] = {
|
|
85
|
+
elementToTest: largeElement,
|
|
86
|
+
host,
|
|
87
|
+
updateState,
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
91
|
+
updateOverflowing(overflowParams);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
resizeObserver.observe(host);
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Also observe the large slot wrapper itself in case its own layout changes
|
|
98
|
+
* without host resizing.
|
|
99
|
+
*/
|
|
100
|
+
resizeObserver.observe(largeElement);
|
|
101
|
+
|
|
102
|
+
const removeSlotChangeListener = listenTo(largeElement, 'slotchange', () => {
|
|
103
|
+
updateOverflowing(overflowParams);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
/** Initial measurement: defer until after first layout. */
|
|
107
|
+
updateOverflowing(overflowParams);
|
|
108
|
+
|
|
109
|
+
state.cleanup?.();
|
|
110
|
+
updateState({
|
|
111
|
+
cleanup() {
|
|
112
|
+
resizeObserver.disconnect();
|
|
113
|
+
removeSlotChangeListener();
|
|
114
|
+
},
|
|
115
|
+
});
|
|
116
|
+
})}
|
|
117
|
+
>
|
|
118
|
+
<slot name=${slotNames.large}></slot>
|
|
119
|
+
</div>
|
|
120
|
+
<div class="small"><slot name=${slotNames.small}></slot></div>
|
|
121
|
+
`;
|
|
122
|
+
},
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
function updateOverflowing({
|
|
126
|
+
elementToTest,
|
|
127
|
+
host,
|
|
128
|
+
updateState,
|
|
129
|
+
}: {
|
|
130
|
+
host: Element;
|
|
131
|
+
updateState: (newState: Partial<{isOverflowing: boolean}>) => void;
|
|
132
|
+
elementToTest: Element;
|
|
133
|
+
}) {
|
|
134
|
+
const isOverflowing = elementToTest.scrollWidth > host.clientWidth;
|
|
135
|
+
|
|
136
|
+
updateState({isOverflowing});
|
|
137
|
+
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import {clamp, type PartialWithUndefined} from '@augment-vir/common';
|
|
2
|
+
import {applyAttributes} from 'device-navigation';
|
|
3
|
+
import {css, html} from 'element-vir';
|
|
4
|
+
import {defineViraElement} from './define-vira-element.js';
|
|
5
|
+
|
|
5
6
|
/**
|
|
6
7
|
* A [`<progress>`](https://developer.mozilla.org/docs/Web/HTML/Reference/Elements/progress)
|
|
7
8
|
* alternative that supports custom styling in _all_ browsers via CSS vars _and_ prevents background
|
|
@@ -11,7 +12,18 @@ import { defineViraElement } from './define-vira-element.js';
|
|
|
11
12
|
* @category Elements
|
|
12
13
|
* @see https://electrovir.github.io/vira/book/elements/vira-progress
|
|
13
14
|
*/
|
|
14
|
-
export const ViraProgress = defineViraElement
|
|
15
|
+
export const ViraProgress = defineViraElement<
|
|
16
|
+
Readonly<
|
|
17
|
+
{
|
|
18
|
+
value: number;
|
|
19
|
+
} & PartialWithUndefined<{
|
|
20
|
+
/** @default 0 */
|
|
21
|
+
min: number;
|
|
22
|
+
/** @default 100 */
|
|
23
|
+
max: number;
|
|
24
|
+
}>
|
|
25
|
+
>
|
|
26
|
+
>()({
|
|
15
27
|
tagName: 'vira-progress',
|
|
16
28
|
cssVars: {
|
|
17
29
|
/**
|
|
@@ -22,7 +34,7 @@ export const ViraProgress = defineViraElement()({
|
|
|
22
34
|
'vira-progress-background-color': '#eee',
|
|
23
35
|
'vira-progress-foreground-color': 'dodgerblue',
|
|
24
36
|
},
|
|
25
|
-
styles: ({
|
|
37
|
+
styles: ({cssVars}) => css`
|
|
26
38
|
:host {
|
|
27
39
|
/* Default width that can easily be overridden because it's applied on the host. */
|
|
28
40
|
width: 100px;
|
|
@@ -46,26 +58,29 @@ export const ViraProgress = defineViraElement()({
|
|
|
46
58
|
flex-grow: 1;
|
|
47
59
|
}
|
|
48
60
|
`,
|
|
49
|
-
render({
|
|
61
|
+
render({inputs, host}) {
|
|
50
62
|
const min = inputs.min || 0;
|
|
51
63
|
const max = inputs.max || 100;
|
|
52
64
|
const totalRange = max - min;
|
|
53
65
|
const value = inputs.value - min;
|
|
54
|
-
|
|
66
|
+
|
|
67
|
+
const percentFull = clamp(Math.round((value / totalRange) * 100), {min: 0, max: 100});
|
|
68
|
+
|
|
55
69
|
applyAttributes(host, {
|
|
56
70
|
'aria-valuemin': inputs.min,
|
|
57
71
|
'aria-valuemax': inputs.max,
|
|
58
72
|
'aria-valuenow': inputs.value,
|
|
59
73
|
'aria-role': 'progressbar',
|
|
60
74
|
});
|
|
61
|
-
|
|
75
|
+
|
|
76
|
+
return html`
|
|
62
77
|
<div
|
|
63
78
|
class="progress-bar"
|
|
64
79
|
style=${percentFull
|
|
65
|
-
|
|
80
|
+
? css`
|
|
66
81
|
width: ${percentFull}%;
|
|
67
82
|
`
|
|
68
|
-
|
|
83
|
+
: css`
|
|
69
84
|
display: none;
|
|
70
85
|
`}
|
|
71
86
|
></div>
|