@eunomia/elements 1.0.0-beta.2 → 1.0.0-beta.3
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/cdn/components/chunks/chunk-3LMI7KUA.js +48 -0
- package/dist/cdn/components/chunks/{chunk-74HHV4CX.js → chunk-53QH6MPM.js} +2 -2
- package/dist/cdn/components/chunks/{chunk-7WTSHE7M.js → chunk-EAGGN3ZI.js} +1 -1
- package/dist/cdn/components/chunks/chunk-GU6BVMFJ.js +1 -0
- package/dist/cdn/components/chunks/chunk-KNM5QHDK.js +38 -0
- package/dist/cdn/components/chunks/{chunk-AQQMW353.js → chunk-TBKKTJOX.js} +1 -1
- package/dist/cdn/components/chunks/chunk-YYCEPZUN.js +1 -0
- package/dist/cdn/components/chunks/{chunk-27Q2SLRY.js → chunk-Z6PJYSC3.js} +30 -11
- package/dist/cdn/components/eun-animate.js +178 -2
- package/dist/cdn/components/eun-button.js +1 -1
- package/dist/cdn/components/eun-card.js +15 -7
- package/dist/cdn/components/eun-carousel.js +1 -1
- package/dist/cdn/components/eun-check-card.js +1 -1
- package/dist/cdn/components/eun-checkbox-list.js +2 -2
- package/dist/cdn/components/eun-checkbox.js +1 -1
- package/dist/cdn/components/eun-chip.js +11 -14
- package/dist/cdn/components/eun-collapse.js +8 -15
- package/dist/cdn/components/eun-color-picker.js +19 -19
- package/dist/cdn/components/eun-counter.js +4 -4
- package/dist/cdn/components/eun-date-picker.js +2 -2
- package/dist/cdn/components/eun-icon.js +1 -1
- package/dist/cdn/components/eun-input-file.js +11 -11
- package/dist/cdn/components/eun-input-phone.js +3 -3
- package/dist/cdn/components/eun-input.js +1 -1
- package/dist/cdn/components/eun-radio-card.js +1 -1
- package/dist/cdn/components/eun-radio-list.js +3 -3
- package/dist/cdn/components/eun-radio.js +1 -1
- package/dist/cdn/components/eun-search.js +1 -1
- package/dist/cdn/components/eun-select.js +33 -12
- package/dist/cdn/components/eun-sidebar.js +1 -1
- package/dist/cdn/components/eun-slider.js +3 -3
- package/dist/cdn/components/eun-sliding-card.js +4 -8
- package/dist/cdn/components/eun-switch.js +1 -1
- package/dist/cdn/components/eun-table.js +1 -1
- package/dist/cdn/components/eun-tag.js +13 -9
- package/dist/cdn/components/eun-textarea.js +11 -11
- package/dist/cdn/components/eun-time-picker.js +2 -2
- package/dist/cdn/components/eun-toggle-group.js +2 -2
- package/dist/cdn/components/eun-toggle-item.js +1 -1
- package/dist/cdn/components/eun-toggle.js +2 -2
- package/dist/cdn/components/eun-toolbar.js +14 -12
- package/dist/cdn/components/eun-tooltip.js +2 -2
- package/dist/components/action/button/button.d.ts +5 -6
- package/dist/components/action/button/button.js +5 -6
- package/dist/components/action/button/button.styles.js +31 -9
- package/dist/components/action/toggle/toggle-group.js +1 -1
- package/dist/components/action/toggle/toggle-item.styles.js +1 -1
- package/dist/components/action/toggle/toggle.js +1 -1
- package/dist/components/content/card/card.d.ts +1 -1
- package/dist/components/content/card/card.js +1 -1
- package/dist/components/content/card/card.styles.js +13 -5
- package/dist/components/content/card/sliding-card.styles.js +0 -4
- package/dist/components/content/chip/chip.styles.js +6 -9
- package/dist/components/content/collapse/collapse.styles.js +0 -7
- package/dist/components/content/icon/icon.d.ts +48 -5
- package/dist/components/content/icon/icon.js +92 -20
- package/dist/components/content/tag/tag.styles.js +10 -6
- package/dist/components/content/tooltip/tooltip.styles.js +2 -2
- package/dist/components/form/checkbox/checkbox-list.js +1 -1
- package/dist/components/form/color-picker/color-picker.js +9 -7
- package/dist/components/form/counter/counter.js +3 -3
- package/dist/components/form/date-picker/date-picker.js +3 -3
- package/dist/components/form/input/input.js +2 -2
- package/dist/components/form/input-file/input-file.js +5 -5
- package/dist/components/form/input-phone/input-phone.js +3 -3
- package/dist/components/form/radio/radio-list.js +2 -2
- package/dist/components/form/select/select.d.ts +16 -0
- package/dist/components/form/select/select.js +28 -5
- package/dist/components/form/select/select.styles.js +11 -0
- package/dist/components/form/slider/slider.js +2 -2
- package/dist/components/form/textarea/textarea.js +4 -4
- package/dist/components/form/time-picker/time-picker.js +3 -3
- package/dist/components/layout/animate/animate.d.ts +40 -5
- package/dist/components/layout/animate/animate.js +30 -11
- package/dist/components/layout/animate/animate.styles.d.ts +1 -1
- package/dist/components/layout/animate/animate.styles.js +191 -1
- package/dist/components/navigation/carousel/carousel.styles.js +1 -1
- package/dist/components/navigation/toolbar/toolbar.d.ts +22 -0
- package/dist/components/navigation/toolbar/toolbar.js +28 -2
- package/dist/components/navigation/toolbar/toolbar.styles.js +4 -3
- package/dist/events/change.event.d.ts +13 -1
- package/dist/events/change.event.js +2 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/mixins/check.mixin.js +6 -2
- package/dist/mixins/form.mixin.d.ts +4 -0
- package/dist/mixins/form.mixin.js +78 -2
- package/dist/mixins/radio.mixin.js +6 -2
- package/dist/ssr/animate-ssr.css +149 -0
- package/dist/ssr/overlay-ssr.css +57 -0
- package/dist/ssr/sidebar-ssr.css +57 -0
- package/dist/ssr/toolbar-ssr.css +41 -0
- package/package.json +9 -3
- package/dist/cdn/components/chunks/chunk-2IQUMAMI.js +0 -38
- package/dist/cdn/components/chunks/chunk-7Q6AHVI5.js +0 -1
- package/dist/cdn/components/chunks/chunk-DENMN3WH.js +0 -48
- package/dist/cdn/components/chunks/chunk-ONYUXQV2.js +0 -1
- package/dist/components/layout/animate/animate-ssr.css +0 -64
|
@@ -4,7 +4,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
import { customElement, property, query } from "lit/decorators.js";
|
|
7
|
+
import { customElement, property, query, queryAssignedElements, } from "lit/decorators.js";
|
|
8
8
|
import { html, LitElement, nothing } from "lit";
|
|
9
9
|
import { ChangeEvent } from "../../../events/change.event.js";
|
|
10
10
|
import { handleLinkNavigation } from "../../../utils/navigation.utils.js";
|
|
@@ -53,6 +53,8 @@ export const EunomiaToolbarTagName = "eun-toolbar";
|
|
|
53
53
|
* everything behind it, including the logo and any other bar content;
|
|
54
54
|
* the burger is the only thing that stays visible in front of it.
|
|
55
55
|
*
|
|
56
|
+
* @slot [menu-icon] - Replaces the burger's default open icon (an `eun-icon name="menu"`) with any content, shown while the panel is closed. Useful wherever `eun-icon`'s own dynamic SVG resolution doesn't fit, e.g. some bundler setups
|
|
57
|
+
* @slot [close-icon] - Replaces the burger's default close icon (an `eun-icon name="close"`) with any content, shown while the panel is open. See `menu-icon` above
|
|
56
58
|
* @slot start - Left-side content, rendered after a logo image linking to logoHref whenever logoSrc is set
|
|
57
59
|
* @slot center - Center content, truly centered independently of the start and end widths
|
|
58
60
|
* @slot end - Right-side content
|
|
@@ -134,6 +136,7 @@ export const EunomiaToolbarTagName = "eun-toolbar";
|
|
|
134
136
|
* @cssprop [--toolbar-skip-links-background] - Sets the background of the skip-links bar, defaulting to a darker mix of the bar's own background
|
|
135
137
|
* @cssprop [--toolbar-skip-links-color] - Sets the text color of the skip-links bar
|
|
136
138
|
* @cssprop [--toolbar-skip-links-separator-color] - Sets the color of the divider drawn between skip links
|
|
139
|
+
* @cssprop [--toolbar-skip-links-gap] - Sets the gap between skip links, with the divider centered in it
|
|
137
140
|
* @element eun-toolbar
|
|
138
141
|
*/
|
|
139
142
|
let EunomiaToolbar = class EunomiaToolbar extends DialogSurfaceMixin(LitElement) {
|
|
@@ -256,6 +259,14 @@ let EunomiaToolbar = class EunomiaToolbar extends DialogSurfaceMixin(LitElement)
|
|
|
256
259
|
* @internal
|
|
257
260
|
*/
|
|
258
261
|
this.mobile = false;
|
|
262
|
+
/**
|
|
263
|
+
* Re-renders once a `menu-icon`/`close-icon` slot's content changes, so
|
|
264
|
+
* the default `eun-icon` fallback correctly appears/disappears.
|
|
265
|
+
* @private
|
|
266
|
+
*/
|
|
267
|
+
this.handleIconSlotChange = () => {
|
|
268
|
+
this.requestUpdate();
|
|
269
|
+
};
|
|
259
270
|
/**
|
|
260
271
|
* The element (or `window`) {@link handleScroll} is currently listening
|
|
261
272
|
* on, resolved from `scrollTarget`.
|
|
@@ -834,6 +845,11 @@ let EunomiaToolbar = class EunomiaToolbar extends DialogSurfaceMixin(LitElement)
|
|
|
834
845
|
* @private
|
|
835
846
|
*/
|
|
836
847
|
renderBurger() {
|
|
848
|
+
const slotName = this.open ? "close-icon" : "menu-icon";
|
|
849
|
+
const iconName = this.open ? "close" : "menu";
|
|
850
|
+
const hasSlotted = this.open
|
|
851
|
+
? this.closeIconSlotEls.length
|
|
852
|
+
: this.menuIconSlotEls.length;
|
|
837
853
|
return html `
|
|
838
854
|
<eun-button
|
|
839
855
|
id="burger"
|
|
@@ -846,7 +862,11 @@ let EunomiaToolbar = class EunomiaToolbar extends DialogSurfaceMixin(LitElement)
|
|
|
846
862
|
: this.ariaLabelMenuOpen}
|
|
847
863
|
@click=${() => this.toggle()}
|
|
848
864
|
>
|
|
849
|
-
<
|
|
865
|
+
<slot name=${slotName} @slotchange=${this.handleIconSlotChange}>
|
|
866
|
+
${hasSlotted
|
|
867
|
+
? nothing
|
|
868
|
+
: html `<eun-icon name=${iconName} size="20"></eun-icon>`}
|
|
869
|
+
</slot>
|
|
850
870
|
</eun-button>
|
|
851
871
|
`;
|
|
852
872
|
}
|
|
@@ -996,6 +1016,12 @@ __decorate([
|
|
|
996
1016
|
__decorate([
|
|
997
1017
|
query("#burger")
|
|
998
1018
|
], EunomiaToolbar.prototype, "burgerEl", void 0);
|
|
1019
|
+
__decorate([
|
|
1020
|
+
queryAssignedElements({ slot: "menu-icon" })
|
|
1021
|
+
], EunomiaToolbar.prototype, "menuIconSlotEls", void 0);
|
|
1022
|
+
__decorate([
|
|
1023
|
+
queryAssignedElements({ slot: "close-icon" })
|
|
1024
|
+
], EunomiaToolbar.prototype, "closeIconSlotEls", void 0);
|
|
999
1025
|
EunomiaToolbar = __decorate([
|
|
1000
1026
|
customElement(EunomiaToolbarTagName)
|
|
1001
1027
|
], EunomiaToolbar);
|
|
@@ -32,6 +32,7 @@ import { css } from "lit";
|
|
|
32
32
|
* [--toolbar-skip-links-background] - Set a custom background for the skip-links bar, default a darker mix of the bar's own background
|
|
33
33
|
* [--toolbar-skip-links-color] - Set a custom text color for the skip-links bar
|
|
34
34
|
* [--toolbar-skip-links-separator-color] - Set a custom color for the divider drawn between skip links
|
|
35
|
+
* [--toolbar-skip-links-gap] - Set a custom gap between skip links, with the divider centered in it
|
|
35
36
|
*/
|
|
36
37
|
const base = css `
|
|
37
38
|
:host {
|
|
@@ -79,6 +80,7 @@ const base = css `
|
|
|
79
80
|
color-mix(in srgb, var(--_skipLinksBase) 82%, black 18%)
|
|
80
81
|
);
|
|
81
82
|
--_skipLinksColor: var(--toolbar-skip-links-color, #fff);
|
|
83
|
+
--_skipLinksGap: var(--toolbar-skip-links-gap, var(--eun-space-m, 16px));
|
|
82
84
|
--_skipLinksSeparatorColor: var(
|
|
83
85
|
--toolbar-skip-links-separator-color,
|
|
84
86
|
color-mix(in srgb, var(--_skipLinksColor) 50%, transparent)
|
|
@@ -201,7 +203,7 @@ const base = css `
|
|
|
201
203
|
z-index: calc(var(--_zIndex) + 2);
|
|
202
204
|
display: flex;
|
|
203
205
|
align-items: center;
|
|
204
|
-
gap: var(--
|
|
206
|
+
gap: var(--_skipLinksGap);
|
|
205
207
|
overflow: hidden;
|
|
206
208
|
height: var(--_skipLinksHeight);
|
|
207
209
|
padding-inline: var(--eun-space-m);
|
|
@@ -253,13 +255,12 @@ const base = css `
|
|
|
253
255
|
#skip-links ::slotted(a:not(:first-child)),
|
|
254
256
|
#skip-links ::slotted(eun-link:not(:first-child)) {
|
|
255
257
|
position: relative;
|
|
256
|
-
padding-inline-start: var(--eun-space-s);
|
|
257
258
|
}
|
|
258
259
|
#skip-links ::slotted(a:not(:first-child))::before,
|
|
259
260
|
#skip-links ::slotted(eun-link:not(:first-child))::before {
|
|
260
261
|
content: "";
|
|
261
262
|
position: absolute;
|
|
262
|
-
inset-inline-start:
|
|
263
|
+
inset-inline-start: calc(var(--_skipLinksGap) / -2);
|
|
263
264
|
inset-block: 0;
|
|
264
265
|
width: 1px;
|
|
265
266
|
background: var(--_skipLinksSeparatorColor);
|
|
@@ -11,7 +11,19 @@ export declare class ChangeEvent<T = unknown> extends Event {
|
|
|
11
11
|
* Declaration of the element that dispatches the event.
|
|
12
12
|
*/
|
|
13
13
|
target: LitElement & FormMixinInterface<T>;
|
|
14
|
-
|
|
14
|
+
/**
|
|
15
|
+
* The new value (or `checked` state, for a checkable field) at the
|
|
16
|
+
* moment this event was dispatched — the same one already readable from
|
|
17
|
+
* `event.target.value`/`.checked`, exposed directly on the event too so
|
|
18
|
+
* a listener attached higher up the tree (delegation on a `<form>`, for
|
|
19
|
+
* instance) can read it as `event.value` without narrowing
|
|
20
|
+
* `event.target`'s type itself. `undefined` for a dispatcher with no
|
|
21
|
+
* single value of its own (toolbar, sidebar, collapse still only ever
|
|
22
|
+
* construct this with no argument, reporting their own state through
|
|
23
|
+
* `event.target` instead, same as before).
|
|
24
|
+
*/
|
|
25
|
+
readonly value: T;
|
|
26
|
+
constructor(value?: T);
|
|
15
27
|
}
|
|
16
28
|
declare global {
|
|
17
29
|
interface GlobalEventHandlersEventMap {
|
package/dist/index.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ export { EunomiaToggleItem, EunomiaToggleItemTagName, } from "./components/actio
|
|
|
15
15
|
export { EunomiaToggleGroup, EunomiaToggleGroupTagName, } from "./components/action/toggle/toggle-group.js";
|
|
16
16
|
export type { EunomiaToggleGroupOption, EunomiaToggleGroupAppearance, } from "./components/action/toggle/toggle-group.js";
|
|
17
17
|
export { EunomiaLink, EunomiaLinkTagName, } from "./components/action/link/link.js";
|
|
18
|
-
export { EunomiaIcon, EunomiaIconTagName, } from "./components/content/icon/icon.js";
|
|
18
|
+
export { EunomiaIcon, EunomiaIconTagName, setIconBaseUrl, } from "./components/content/icon/icon.js";
|
|
19
19
|
export type { EunomiaIconName, EunomiaIconType, } from "./components/content/icon/icon.type.js";
|
|
20
20
|
export { EunomiaTag, EunomiaTagTagName } from "./components/content/tag/tag.js";
|
|
21
21
|
export { EunomiaChip, EunomiaChipTagName, } from "./components/content/chip/chip.js";
|
package/dist/index.js
CHANGED
|
@@ -39,7 +39,7 @@ export { EunomiaToggle, EunomiaToggleTagName, } from "./components/action/toggle
|
|
|
39
39
|
export { EunomiaToggleItem, EunomiaToggleItemTagName, } from "./components/action/toggle/toggle-item.js";
|
|
40
40
|
export { EunomiaToggleGroup, EunomiaToggleGroupTagName, } from "./components/action/toggle/toggle-group.js";
|
|
41
41
|
export { EunomiaLink, EunomiaLinkTagName, } from "./components/action/link/link.js";
|
|
42
|
-
export { EunomiaIcon, EunomiaIconTagName, } from "./components/content/icon/icon.js";
|
|
42
|
+
export { EunomiaIcon, EunomiaIconTagName, setIconBaseUrl, } from "./components/content/icon/icon.js";
|
|
43
43
|
export { EunomiaTag, EunomiaTagTagName } from "./components/content/tag/tag.js";
|
|
44
44
|
export { EunomiaChip, EunomiaChipTagName, } from "./components/content/chip/chip.js";
|
|
45
45
|
export { EunomiaBadge, EunomiaBadgeTagName, } from "./components/content/badge/badge.js";
|
|
@@ -73,10 +73,14 @@ export const CheckMixin = (superClass) => {
|
|
|
73
73
|
* Resets `checked` to `defaultChecked` (or `false`, if never set) on a
|
|
74
74
|
* native form `reset()` — overrides `FormMixin`'s own
|
|
75
75
|
* `formResetCallback`, which unconditionally forces checkable fields
|
|
76
|
-
* to `false` with no notion of a default checked state.
|
|
76
|
+
* to `false` with no notion of a default checked state. Also resets
|
|
77
|
+
* `dirty`/`touched` itself, since it doesn't call `super` to reach
|
|
78
|
+
* `FormMixin`'s own reset of those two.
|
|
77
79
|
*/
|
|
78
80
|
formResetCallback() {
|
|
79
81
|
this.checked = this.defaultChecked ?? false;
|
|
82
|
+
this.dirty = false;
|
|
83
|
+
this.touched = false;
|
|
80
84
|
}
|
|
81
85
|
/**
|
|
82
86
|
* Lifecycle: Called when the component is disconnected from the DOM.
|
|
@@ -140,7 +144,7 @@ export const CheckMixin = (superClass) => {
|
|
|
140
144
|
else {
|
|
141
145
|
this.removeAttribute("aria-description");
|
|
142
146
|
}
|
|
143
|
-
this.dispatchEvent(new ChangeEvent());
|
|
147
|
+
this.dispatchEvent(new ChangeEvent(this.checked));
|
|
144
148
|
}
|
|
145
149
|
/**
|
|
146
150
|
* Handles keydown interactions.
|
|
@@ -17,6 +17,10 @@ export declare class FormMixinInterface<T> {
|
|
|
17
17
|
valueState?: T;
|
|
18
18
|
hideError?: boolean;
|
|
19
19
|
form: HTMLFormElement | null;
|
|
20
|
+
dirty: boolean;
|
|
21
|
+
touched: boolean;
|
|
22
|
+
get pristine(): boolean;
|
|
23
|
+
get untouched(): boolean;
|
|
20
24
|
get value(): T;
|
|
21
25
|
set value(value: T);
|
|
22
26
|
get defaultValue(): T | undefined;
|
|
@@ -4,9 +4,15 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
|
|
7
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
8
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
9
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
10
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
|
+
};
|
|
12
|
+
import { html, nothing } from "lit";
|
|
8
13
|
import { property, state } from "lit/decorators.js";
|
|
9
14
|
import { when } from "lit/directives/when.js";
|
|
15
|
+
import { ChangeEvent } from "../events/change.event.js";
|
|
10
16
|
/**
|
|
11
17
|
* Mixin that adds form-related behavior and value management.
|
|
12
18
|
*
|
|
@@ -15,6 +21,7 @@ import { when } from "lit/directives/when.js";
|
|
|
15
21
|
* @returns A class extending the provided base with form capabilities.
|
|
16
22
|
*/
|
|
17
23
|
export const FormMixin = (superClass) => {
|
|
24
|
+
var _FormMixinClass_markDirty, _FormMixinClass_markTouched;
|
|
18
25
|
class FormMixinClass extends superClass {
|
|
19
26
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
20
27
|
constructor(...args) {
|
|
@@ -36,11 +43,60 @@ export const FormMixin = (superClass) => {
|
|
|
36
43
|
* @private
|
|
37
44
|
*/
|
|
38
45
|
this.checked = false;
|
|
39
|
-
|
|
46
|
+
/**
|
|
47
|
+
* Whether the value has changed since the field connected (or since the
|
|
48
|
+
* last reset). Derived from `eunchange`, the event every field's own
|
|
49
|
+
* user-interaction handler already dispatches (and only that: setting
|
|
50
|
+
* `.value`/`.defaultValue` from outside, as a controlled React field
|
|
51
|
+
* does on every render, never dispatches it), so a controlled field
|
|
52
|
+
* stays pristine across ordinary re-renders and only turns dirty from
|
|
53
|
+
* genuine user input.
|
|
54
|
+
* @default false
|
|
55
|
+
*/
|
|
56
|
+
this.dirty = false;
|
|
57
|
+
/**
|
|
58
|
+
* Whether the field has lost focus at least once since it connected (or
|
|
59
|
+
* since the last reset).
|
|
60
|
+
* @default false
|
|
61
|
+
*/
|
|
62
|
+
this.touched = false;
|
|
63
|
+
/**
|
|
64
|
+
* Marks the field dirty on its own `eunchange` — dispatched only from a
|
|
65
|
+
* genuine user-interaction handler, never from the `value`/`checked`
|
|
66
|
+
* setters themselves — so a re-render setting the same property from
|
|
67
|
+
* outside never flips this.
|
|
68
|
+
*/
|
|
69
|
+
_FormMixinClass_markDirty.set(this, () => {
|
|
70
|
+
if (!this.dirty) {
|
|
71
|
+
this.dirty = true;
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
/**
|
|
75
|
+
* Marks the field touched the first time focus leaves it.
|
|
76
|
+
*/
|
|
77
|
+
_FormMixinClass_markTouched.set(this, () => {
|
|
78
|
+
if (!this.touched) {
|
|
79
|
+
this.touched = true;
|
|
80
|
+
}
|
|
81
|
+
});
|
|
40
82
|
if (!this.internals) {
|
|
41
83
|
this.internals = this.attachInternals();
|
|
42
84
|
}
|
|
43
85
|
}
|
|
86
|
+
/**
|
|
87
|
+
* Whether the value hasn't changed since the field connected (or since
|
|
88
|
+
* the last reset). The inverse of {@link dirty}.
|
|
89
|
+
*/
|
|
90
|
+
get pristine() {
|
|
91
|
+
return !this.dirty;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Whether the field hasn't lost focus yet since it connected (or since
|
|
95
|
+
* the last reset). The inverse of {@link touched}.
|
|
96
|
+
*/
|
|
97
|
+
get untouched() {
|
|
98
|
+
return !this.touched;
|
|
99
|
+
}
|
|
44
100
|
/**
|
|
45
101
|
* Gets the default value of the field.
|
|
46
102
|
*
|
|
@@ -128,6 +184,17 @@ export const FormMixin = (superClass) => {
|
|
|
128
184
|
this.value = this.defaultValue;
|
|
129
185
|
}
|
|
130
186
|
this.checkValidity(this.value);
|
|
187
|
+
this.addEventListener(ChangeEvent.eventName, __classPrivateFieldGet(this, _FormMixinClass_markDirty, "f"));
|
|
188
|
+
this.addEventListener("focusout", __classPrivateFieldGet(this, _FormMixinClass_markTouched, "f"));
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Lifecycle callback called when element is disconnected from the DOM.
|
|
192
|
+
* Removes the listeners driving {@link dirty} and {@link touched}.
|
|
193
|
+
*/
|
|
194
|
+
disconnectedCallback() {
|
|
195
|
+
this.removeEventListener(ChangeEvent.eventName, __classPrivateFieldGet(this, _FormMixinClass_markDirty, "f"));
|
|
196
|
+
this.removeEventListener("focusout", __classPrivateFieldGet(this, _FormMixinClass_markTouched, "f"));
|
|
197
|
+
super.disconnectedCallback?.();
|
|
131
198
|
}
|
|
132
199
|
/**
|
|
133
200
|
* LitElement lifecycle method called before update.
|
|
@@ -196,6 +263,8 @@ export const FormMixin = (superClass) => {
|
|
|
196
263
|
else {
|
|
197
264
|
this.value = this.defaultValue;
|
|
198
265
|
}
|
|
266
|
+
this.dirty = false;
|
|
267
|
+
this.touched = false;
|
|
199
268
|
}
|
|
200
269
|
/**
|
|
201
270
|
* Renders the description or error messages.
|
|
@@ -237,6 +306,7 @@ export const FormMixin = (superClass) => {
|
|
|
237
306
|
`;
|
|
238
307
|
}
|
|
239
308
|
}
|
|
309
|
+
_FormMixinClass_markDirty = new WeakMap(), _FormMixinClass_markTouched = new WeakMap();
|
|
240
310
|
FormMixinClass.formAssociated = true;
|
|
241
311
|
__decorate([
|
|
242
312
|
property({ reflect: true })
|
|
@@ -250,6 +320,12 @@ export const FormMixin = (superClass) => {
|
|
|
250
320
|
__decorate([
|
|
251
321
|
state()
|
|
252
322
|
], FormMixinClass.prototype, "valueState", void 0);
|
|
323
|
+
__decorate([
|
|
324
|
+
state()
|
|
325
|
+
], FormMixinClass.prototype, "dirty", void 0);
|
|
326
|
+
__decorate([
|
|
327
|
+
state()
|
|
328
|
+
], FormMixinClass.prototype, "touched", void 0);
|
|
253
329
|
__decorate([
|
|
254
330
|
property({
|
|
255
331
|
attribute: "default-value",
|
|
@@ -80,10 +80,14 @@ export const RadioMixin = (superClass) => {
|
|
|
80
80
|
* Resets `checked` to `defaultChecked` (or `false`, if never set) on a
|
|
81
81
|
* native form `reset()` — overrides `FormMixin`'s own
|
|
82
82
|
* `formResetCallback`, which unconditionally forces checkable fields
|
|
83
|
-
* to `false` with no notion of a default checked state.
|
|
83
|
+
* to `false` with no notion of a default checked state. Also resets
|
|
84
|
+
* `dirty`/`touched` itself, since it doesn't call `super` to reach
|
|
85
|
+
* `FormMixin`'s own reset of those two.
|
|
84
86
|
*/
|
|
85
87
|
formResetCallback() {
|
|
86
88
|
this.checked = this.defaultChecked ?? false;
|
|
89
|
+
this.dirty = false;
|
|
90
|
+
this.touched = false;
|
|
87
91
|
}
|
|
88
92
|
/**
|
|
89
93
|
* Lifecycle: Called when the component is disconnected from the DOM.
|
|
@@ -147,7 +151,7 @@ export const RadioMixin = (superClass) => {
|
|
|
147
151
|
else {
|
|
148
152
|
this.removeAttribute("aria-description");
|
|
149
153
|
}
|
|
150
|
-
this.dispatchEvent(new ChangeEvent());
|
|
154
|
+
this.dispatchEvent(new ChangeEvent(this.checked));
|
|
151
155
|
}
|
|
152
156
|
/**
|
|
153
157
|
* Handles keydown interactions.
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Optional light-DOM stylesheet for `<eun-animate>` in server-rendered
|
|
3
|
+
* pages (Next.js, or any framework/setup without Declarative Shadow DOM
|
|
4
|
+
* for Lit components). It closes the SSR flash described in the eun-animate
|
|
5
|
+
* documentation's Accessibility/SSR notes : server HTML has no Shadow DOM
|
|
6
|
+
* yet, so `<eun-animate>`'s own `:host([animation="fade"]) { opacity: 0 }`
|
|
7
|
+
* (and the other animation variants) can't apply until the element is
|
|
8
|
+
* upgraded client-side, meaning content renders visible first, then snaps
|
|
9
|
+
* hidden the instant the custom element registers, then fades back in.
|
|
10
|
+
*
|
|
11
|
+
* This stylesheet lives in the host document instead, applying the exact
|
|
12
|
+
* same starting state through `:not(:defined)`, which is true from first
|
|
13
|
+
* paint and stops matching permanently the moment the browser upgrades the
|
|
14
|
+
* element — handing off to the component's own Shadow DOM styles at
|
|
15
|
+
* exactly the point they take over, with no gap and no double transition.
|
|
16
|
+
*
|
|
17
|
+
* Usage — link it in the page `<head>`, alongside (not instead of)
|
|
18
|
+
* importing "@eunomia/elements/animate.js" :
|
|
19
|
+
*
|
|
20
|
+
* <link
|
|
21
|
+
* rel="stylesheet"
|
|
22
|
+
* href="node_modules/@eunomia/elements/dist/ssr/animate-ssr.css"
|
|
23
|
+
* />
|
|
24
|
+
*
|
|
25
|
+
* Requires every server-rendered `<eun-animate>` to write its `animation`
|
|
26
|
+
* attribute explicitly (even when it's the "fade" default), since that
|
|
27
|
+
* default only ever becomes an attribute once Lit initializes the
|
|
28
|
+
* property client-side — invisible to this stylesheet, or any plain CSS,
|
|
29
|
+
* before then :
|
|
30
|
+
*
|
|
31
|
+
* <eun-animate animation="fade">...</eun-animate>
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
eun-animate:not(:defined) {
|
|
35
|
+
--_distance: var(--animate-distance, 80px);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
eun-animate[animation="fade"]:not(:defined),
|
|
39
|
+
eun-animate[animation="faded-scroll-right"]:not(:defined),
|
|
40
|
+
eun-animate[animation="faded-scroll-left"]:not(:defined),
|
|
41
|
+
eun-animate[animation="faded-scroll-top"]:not(:defined),
|
|
42
|
+
eun-animate[animation="faded-scroll-bottom"]:not(:defined) {
|
|
43
|
+
opacity: 0;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
eun-animate[animation="scroll-right"]:not(:defined),
|
|
47
|
+
eun-animate[animation="faded-scroll-right"]:not(:defined) {
|
|
48
|
+
transform: translateX(calc(-1 * var(--_distance)));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
eun-animate[animation="scroll-left"]:not(:defined),
|
|
52
|
+
eun-animate[animation="faded-scroll-left"]:not(:defined) {
|
|
53
|
+
transform: translateX(var(--_distance));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
eun-animate[animation="scroll-top"]:not(:defined),
|
|
57
|
+
eun-animate[animation="faded-scroll-top"]:not(:defined) {
|
|
58
|
+
transform: translateY(var(--_distance));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
eun-animate[animation="scroll-bottom"]:not(:defined),
|
|
62
|
+
eun-animate[animation="faded-scroll-bottom"]:not(:defined) {
|
|
63
|
+
transform: translateY(calc(-1 * var(--_distance)));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* `tablet-animation`/`mobile-animation` overrides, mirroring the rules
|
|
68
|
+
* above and the same-named `@media` blocks in the component's own
|
|
69
|
+
* `animate.styles.ts` — kept in sync by hand, since this file has to
|
|
70
|
+
* duplicate the shadow DOM's styles for the light-DOM pre-hydration
|
|
71
|
+
* window regardless. Placed after the unscoped rules above so an
|
|
72
|
+
* equal-specificity tie (e.g. both `animation="fade"` and
|
|
73
|
+
* `tablet-animation="none"` set at once) resolves in the narrower
|
|
74
|
+
* breakpoint's favor, once its `@media` condition is true — same
|
|
75
|
+
* source-order reasoning as `animate.styles.ts`.
|
|
76
|
+
*
|
|
77
|
+
* `max-width` values match `EUNOMIA_BREAKPOINTS.tablet`/`.mobile`
|
|
78
|
+
* (`breakpoints.ts`) — hardcoded here since plain CSS can't read a JS
|
|
79
|
+
* constant.
|
|
80
|
+
*/
|
|
81
|
+
@media (max-width: 768px) {
|
|
82
|
+
eun-animate[tablet-animation="none"]:not(:defined) {
|
|
83
|
+
opacity: 1;
|
|
84
|
+
transform: none;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
eun-animate[tablet-animation="fade"]:not(:defined),
|
|
88
|
+
eun-animate[tablet-animation="faded-scroll-right"]:not(:defined),
|
|
89
|
+
eun-animate[tablet-animation="faded-scroll-left"]:not(:defined),
|
|
90
|
+
eun-animate[tablet-animation="faded-scroll-top"]:not(:defined),
|
|
91
|
+
eun-animate[tablet-animation="faded-scroll-bottom"]:not(:defined) {
|
|
92
|
+
opacity: 0;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
eun-animate[tablet-animation="scroll-right"]:not(:defined),
|
|
96
|
+
eun-animate[tablet-animation="faded-scroll-right"]:not(:defined) {
|
|
97
|
+
transform: translateX(calc(-1 * var(--_distance)));
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
eun-animate[tablet-animation="scroll-left"]:not(:defined),
|
|
101
|
+
eun-animate[tablet-animation="faded-scroll-left"]:not(:defined) {
|
|
102
|
+
transform: translateX(var(--_distance));
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
eun-animate[tablet-animation="scroll-top"]:not(:defined),
|
|
106
|
+
eun-animate[tablet-animation="faded-scroll-top"]:not(:defined) {
|
|
107
|
+
transform: translateY(var(--_distance));
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
eun-animate[tablet-animation="scroll-bottom"]:not(:defined),
|
|
111
|
+
eun-animate[tablet-animation="faded-scroll-bottom"]:not(:defined) {
|
|
112
|
+
transform: translateY(calc(-1 * var(--_distance)));
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
@media (max-width: 600px) {
|
|
117
|
+
eun-animate[mobile-animation="none"]:not(:defined) {
|
|
118
|
+
opacity: 1;
|
|
119
|
+
transform: none;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
eun-animate[mobile-animation="fade"]:not(:defined),
|
|
123
|
+
eun-animate[mobile-animation="faded-scroll-right"]:not(:defined),
|
|
124
|
+
eun-animate[mobile-animation="faded-scroll-left"]:not(:defined),
|
|
125
|
+
eun-animate[mobile-animation="faded-scroll-top"]:not(:defined),
|
|
126
|
+
eun-animate[mobile-animation="faded-scroll-bottom"]:not(:defined) {
|
|
127
|
+
opacity: 0;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
eun-animate[mobile-animation="scroll-right"]:not(:defined),
|
|
131
|
+
eun-animate[mobile-animation="faded-scroll-right"]:not(:defined) {
|
|
132
|
+
transform: translateX(calc(-1 * var(--_distance)));
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
eun-animate[mobile-animation="scroll-left"]:not(:defined),
|
|
136
|
+
eun-animate[mobile-animation="faded-scroll-left"]:not(:defined) {
|
|
137
|
+
transform: translateX(var(--_distance));
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
eun-animate[mobile-animation="scroll-top"]:not(:defined),
|
|
141
|
+
eun-animate[mobile-animation="faded-scroll-top"]:not(:defined) {
|
|
142
|
+
transform: translateY(var(--_distance));
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
eun-animate[mobile-animation="scroll-bottom"]:not(:defined),
|
|
146
|
+
eun-animate[mobile-animation="faded-scroll-bottom"]:not(:defined) {
|
|
147
|
+
transform: translateY(calc(-1 * var(--_distance)));
|
|
148
|
+
}
|
|
149
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Optional light-DOM stylesheet for server-rendered pages (Next.js, or
|
|
3
|
+
* any framework/setup without Declarative Shadow DOM for Lit
|
|
4
|
+
* components), covering every closed-by-default overlay/disclosure
|
|
5
|
+
* component in one file : `eun-collapse`, `eun-drawer`, `eun-modal`,
|
|
6
|
+
* `eun-dropdown-button`, and `eun-tooltip`. Each hides its own slotted
|
|
7
|
+
* content only through its own Shadow DOM (a `grid-template-rows: 0fr`
|
|
8
|
+
* panel for collapse, a `popover="manual"`/`popover="auto"` surface for
|
|
9
|
+
* the rest), which doesn't exist yet in server-rendered HTML. That
|
|
10
|
+
* content renders as plain, unstyled light-DOM children instead, on top
|
|
11
|
+
* of everything else on the page, until the element upgrades — the same
|
|
12
|
+
* SSR flash `animate-ssr.css`/`toolbar-ssr.css`/`sidebar-ssr.css`
|
|
13
|
+
* document for their own components, just for content that's meant to
|
|
14
|
+
* stay hidden until something opens it, rather than a starting animation
|
|
15
|
+
* state or a persistent, always-visible layout piece.
|
|
16
|
+
*
|
|
17
|
+
* This stylesheet lives in the host document instead, hiding that exact
|
|
18
|
+
* content through `:not(:defined)`, which is true from first paint and
|
|
19
|
+
* stops matching permanently the moment the browser upgrades the
|
|
20
|
+
* element — handing off to each component's own Shadow DOM at exactly
|
|
21
|
+
* the point it takes over, with no gap.
|
|
22
|
+
*
|
|
23
|
+
* Usage — link it in the page `<head>`, alongside (not instead of)
|
|
24
|
+
* importing whichever of these components the page actually uses :
|
|
25
|
+
*
|
|
26
|
+
* <link
|
|
27
|
+
* rel="stylesheet"
|
|
28
|
+
* href="node_modules/@eunomia/elements/dist/ssr/overlay-ssr.css"
|
|
29
|
+
* />
|
|
30
|
+
*
|
|
31
|
+
* `eun-drawer`/`eun-modal` are skipped whenever `open` is written
|
|
32
|
+
* explicitly in the server-rendered markup, so a dialog meant to be
|
|
33
|
+
* visible on first paint (a startup announcement, for instance) still
|
|
34
|
+
* renders — see the `open` attribute on the component's own doc page for
|
|
35
|
+
* the same requirement `animate-ssr.css` documents for `animation`, and
|
|
36
|
+
* `eun-collapse`'s own `open` attribute for the same reasoning there.
|
|
37
|
+
* `eun-dropdown-button`'s own trigger label (its default slot) and
|
|
38
|
+
* `eun-tooltip`'s own trigger (`slot="anchor"`) are never hidden, only
|
|
39
|
+
* their menu/panel content is.
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
eun-collapse:not(:defined):not([open]) > :not([slot]) {
|
|
43
|
+
display: none;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
eun-drawer:not(:defined):not([open]) > *,
|
|
47
|
+
eun-modal:not(:defined):not([open]) > * {
|
|
48
|
+
display: none;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
eun-dropdown-button:not(:defined) > [slot="items"] {
|
|
52
|
+
display: none;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
eun-tooltip:not(:defined) > :not([slot="anchor"]) {
|
|
56
|
+
display: none;
|
|
57
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Optional light-DOM stylesheet for `<eun-sidebar>` in server-rendered
|
|
3
|
+
* pages (Next.js, or any framework/setup without Declarative Shadow DOM
|
|
4
|
+
* for Lit components). Closes the same SSR flash described in
|
|
5
|
+
* eun-toolbar's own SSR notes (see `toolbar-ssr.css`), but here it hits
|
|
6
|
+
* every instance, not just a mobile-only panel : `display: flex` and the
|
|
7
|
+
* sidebar's own width live in eun-sidebar's Shadow DOM, which doesn't
|
|
8
|
+
* exist yet in server-rendered HTML. An unregistered custom element
|
|
9
|
+
* defaults to `display: inline` with no layout of its own, so a
|
|
10
|
+
* server-rendered sidebar renders as a plain run of unstyled inline
|
|
11
|
+
* content (header, body, footer flowing one after another) first, then
|
|
12
|
+
* snaps into a proper flex column the instant the element upgrades. A
|
|
13
|
+
* sidebar meant to start `collapsed` (mini or fully hidden) makes this
|
|
14
|
+
* worse : that state lives in the same Shadow DOM too, so it renders at
|
|
15
|
+
* full width first, then shrinks down on upgrade instead of the other
|
|
16
|
+
* way around.
|
|
17
|
+
*
|
|
18
|
+
* This stylesheet lives in the host document instead, mirroring
|
|
19
|
+
* eun-sidebar's own resting layout through `:not(:defined)`, which is
|
|
20
|
+
* true from first paint and stops matching permanently the moment the
|
|
21
|
+
* browser upgrades the element — handing off to eun-sidebar's own Shadow
|
|
22
|
+
* DOM styles at exactly the point they take over, with no gap.
|
|
23
|
+
*
|
|
24
|
+
* Usage — link it in the page `<head>`, alongside (not instead of)
|
|
25
|
+
* importing "@eunomia/elements/sidebar.js" :
|
|
26
|
+
*
|
|
27
|
+
* <link
|
|
28
|
+
* rel="stylesheet"
|
|
29
|
+
* href="node_modules/@eunomia/elements/dist/ssr/sidebar-ssr.css"
|
|
30
|
+
* />
|
|
31
|
+
*
|
|
32
|
+
* `collapsed`/`collapse-mode`/`dragged-hidden` only take effect here when
|
|
33
|
+
* written explicitly in the server-rendered markup, same requirement
|
|
34
|
+
* `animate-ssr.css` documents for `animation` :
|
|
35
|
+
*
|
|
36
|
+
* <eun-sidebar collapsed collapse-mode="mini">...</eun-sidebar>
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
eun-sidebar:not(:defined) {
|
|
40
|
+
display: flex;
|
|
41
|
+
position: sticky;
|
|
42
|
+
top: 0;
|
|
43
|
+
flex-shrink: 0;
|
|
44
|
+
height: 100%;
|
|
45
|
+
box-sizing: border-box;
|
|
46
|
+
overflow: hidden;
|
|
47
|
+
width: var(--sidebar-width, 280px);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
eun-sidebar[collapsed][collapse-mode="mini"]:not(:defined) {
|
|
51
|
+
width: var(--sidebar-mini-width, 64px);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
eun-sidebar[collapsed][collapse-mode="hidden"]:not(:defined),
|
|
55
|
+
eun-sidebar[dragged-hidden]:not(:defined) {
|
|
56
|
+
width: 0px;
|
|
57
|
+
}
|