@eunomia/elements 1.0.0-beta.4 → 1.0.0-beta.5
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-SIHZFOTK.js → chunk-2XASWWKR.js} +1 -1
- package/dist/cdn/components/chunks/chunk-32DTNR52.js +1 -0
- package/dist/cdn/components/chunks/chunk-3MTUVMM5.js +1 -0
- package/dist/cdn/components/chunks/chunk-5GKM5DIB.js +1 -0
- package/dist/cdn/components/chunks/{chunk-GSJEJLFA.js → chunk-6ETDXUH2.js} +1 -1
- package/dist/cdn/components/chunks/{chunk-EJIX2D4Z.js → chunk-AIS3UICU.js} +7 -7
- package/dist/cdn/components/chunks/{chunk-BMQOI7HX.js → chunk-DKOPI7QA.js} +99 -55
- package/dist/cdn/components/chunks/{chunk-NHFWATVN.js → chunk-EAKYD33D.js} +3 -3
- package/dist/cdn/components/chunks/{chunk-EOWBYZV7.js → chunk-IDKZKLJR.js} +5 -5
- package/dist/cdn/components/chunks/chunk-JRGM3W7I.js +53 -0
- package/dist/cdn/components/chunks/{chunk-UAGCQF23.js → chunk-L65WUTXM.js} +5 -5
- package/dist/cdn/components/chunks/chunk-LFCXUVDO.js +1 -0
- package/dist/cdn/components/chunks/{chunk-YGUJJ25C.js → chunk-MPQP4R54.js} +2 -2
- package/dist/cdn/components/chunks/{chunk-RJCJXB7Y.js → chunk-NBIENHLV.js} +1 -1
- package/dist/cdn/components/chunks/{chunk-4MXL6PZC.js → chunk-OW7XKDCH.js} +13 -13
- package/dist/cdn/components/chunks/{chunk-IJ5WFMK4.js → chunk-SD2WHGPF.js} +7 -6
- package/dist/cdn/components/chunks/chunk-SJWRE6PW.js +1 -0
- package/dist/cdn/components/eun-animate.js +5 -3
- package/dist/cdn/components/eun-badge.js +7 -7
- package/dist/cdn/components/eun-breadcrumb-item.js +1 -1
- package/dist/cdn/components/eun-breadcrumb.js +1 -1
- package/dist/cdn/components/eun-button.js +1 -1
- package/dist/cdn/components/eun-calendar.js +13 -13
- package/dist/cdn/components/eun-card.js +42 -3
- package/dist/cdn/components/eun-carousel.js +2 -2
- package/dist/cdn/components/eun-check-card.js +1 -1
- package/dist/cdn/components/eun-checkbox-list.js +1 -1
- package/dist/cdn/components/eun-checkbox.js +1 -1
- package/dist/cdn/components/eun-chip.js +1 -1
- package/dist/cdn/components/eun-collapse.js +39 -20
- package/dist/cdn/components/eun-color-picker.js +3 -3
- package/dist/cdn/components/eun-counter.js +8 -8
- package/dist/cdn/components/eun-date-picker.js +19 -19
- package/dist/cdn/components/eun-drawer.js +9 -9
- package/dist/cdn/components/eun-dropdown-button.js +1 -1
- package/dist/cdn/components/eun-fab.js +6 -6
- package/dist/cdn/components/eun-icon.js +1 -1
- package/dist/cdn/components/eun-image-card.js +1 -1
- package/dist/cdn/components/eun-image-carousel.js +3 -3
- package/dist/cdn/components/eun-input-file.js +1 -1
- package/dist/cdn/components/eun-input-phone.js +18 -18
- package/dist/cdn/components/eun-input.js +1 -1
- package/dist/cdn/components/eun-link.js +116 -18
- package/dist/cdn/components/eun-modal.js +15 -15
- package/dist/cdn/components/eun-radio-card.js +1 -1
- package/dist/cdn/components/eun-radio-list.js +1 -1
- package/dist/cdn/components/eun-radio.js +1 -1
- package/dist/cdn/components/eun-scheduler-event-editor.js +7 -7
- package/dist/cdn/components/eun-scheduler-event.js +1 -1
- package/dist/cdn/components/eun-scheduler.js +18 -18
- package/dist/cdn/components/eun-search.js +15 -15
- package/dist/cdn/components/eun-select.js +2 -2
- package/dist/cdn/components/eun-slider.js +1 -1
- package/dist/cdn/components/eun-sliding-card.js +1 -1
- package/dist/cdn/components/eun-switch.js +1 -1
- package/dist/cdn/components/eun-tab-group.js +1 -1
- package/dist/cdn/components/eun-tab.js +1 -1
- package/dist/cdn/components/eun-table-action-bar.js +1 -1
- package/dist/cdn/components/eun-table.js +1 -1
- package/dist/cdn/components/eun-textarea.js +2 -2
- package/dist/cdn/components/eun-time-picker.js +11 -11
- package/dist/cdn/components/eun-toggle-group.js +30 -22
- package/dist/cdn/components/eun-toggle-item.js +10 -8
- package/dist/cdn/components/eun-toggle.js +1 -1
- package/dist/cdn/components/eun-toolbar.js +1 -1
- package/dist/components/action/button/button.d.ts +44 -17
- package/dist/components/action/button/button.js +100 -22
- package/dist/components/action/button/button.styles.js +77 -39
- package/dist/components/action/dropdown-button/dropdown-button.d.ts +8 -8
- package/dist/components/action/dropdown-button/dropdown-button.js +7 -7
- package/dist/components/action/fab/fab.d.ts +7 -6
- package/dist/components/action/fab/fab.js +11 -8
- package/dist/components/action/fab/fab.styles.js +4 -4
- package/dist/components/action/link/link.d.ts +65 -6
- package/dist/components/action/link/link.js +176 -20
- package/dist/components/action/link/link.styles.js +86 -1
- package/dist/components/action/shared-styles/button-palette.styles.d.ts +3 -3
- package/dist/components/action/shared-styles/button-palette.styles.js +14 -14
- package/dist/components/action/toggle/toggle-group.d.ts +15 -5
- package/dist/components/action/toggle/toggle-group.js +42 -17
- package/dist/components/action/toggle/toggle-group.styles.d.ts +2 -1
- package/dist/components/action/toggle/toggle-group.styles.js +15 -7
- package/dist/components/action/toggle/toggle-item.d.ts +4 -4
- package/dist/components/action/toggle/toggle-item.js +2 -2
- package/dist/components/action/toggle/toggle-item.styles.js +8 -6
- package/dist/components/alert/drawer/drawer.js +1 -1
- package/dist/components/alert/modal/modal.d.ts +8 -8
- package/dist/components/alert/modal/modal.js +11 -11
- package/dist/components/content/badge/badge.d.ts +6 -6
- package/dist/components/content/badge/badge.js +4 -4
- package/dist/components/content/badge/badge.styles.js +4 -4
- package/dist/components/content/card/card.d.ts +32 -4
- package/dist/components/content/card/card.js +64 -4
- package/dist/components/content/card/card.styles.js +33 -1
- package/dist/components/content/card/image-card.d.ts +2 -1
- package/dist/components/content/card/image-card.js +1 -0
- package/dist/components/content/card/sliding-card.d.ts +2 -1
- package/dist/components/content/card/sliding-card.js +1 -0
- package/dist/components/content/collapse/collapse.d.ts +29 -11
- package/dist/components/content/collapse/collapse.js +53 -23
- package/dist/components/content/collapse/collapse.styles.js +13 -0
- package/dist/components/content/icon/icon.d.ts +12 -2
- package/dist/components/content/icon/icon.js +52 -22
- package/dist/components/content/icon/icon.style.d.ts +2 -0
- package/dist/components/content/icon/icon.style.js +4 -1
- package/dist/components/content/shared-styles/card-link.styles.js +1 -0
- package/dist/components/form/color-picker/color-picker.d.ts +3 -3
- package/dist/components/form/color-picker/color-picker.js +4 -4
- package/dist/components/form/counter/counter.d.ts +3 -3
- package/dist/components/form/counter/counter.js +3 -3
- package/dist/components/form/counter/counter.styles.js +5 -5
- package/dist/components/form/date-picker/date-picker.d.ts +3 -3
- package/dist/components/form/date-picker/date-picker.js +3 -3
- package/dist/components/form/date-picker/date-picker.styles.js +5 -5
- package/dist/components/form/input/input.d.ts +3 -3
- package/dist/components/form/input/input.js +4 -4
- package/dist/components/form/input-phone/input-phone.d.ts +3 -3
- package/dist/components/form/input-phone/input-phone.js +3 -3
- package/dist/components/form/input-phone/input-phone.styles.js +12 -12
- package/dist/components/form/search/search.styles.js +3 -3
- package/dist/components/form/select/select.d.ts +3 -3
- package/dist/components/form/select/select.js +3 -3
- package/dist/components/form/shared-styles/field.styles.js +5 -5
- package/dist/components/form/textarea/textarea.d.ts +3 -3
- package/dist/components/form/textarea/textarea.js +4 -4
- package/dist/components/form/time-picker/time-picker.d.ts +3 -3
- package/dist/components/form/time-picker/time-picker.js +3 -3
- package/dist/components/form/time-picker/time-picker.styles.js +5 -5
- package/dist/components/layout/animate/animate.d.ts +8 -0
- package/dist/components/layout/animate/animate.js +20 -8
- package/dist/features/scheduler/calendar/calendar.d.ts +6 -6
- package/dist/features/scheduler/calendar/calendar.js +9 -9
- package/dist/features/scheduler/scheduler/scheduler.d.ts +6 -6
- package/dist/features/scheduler/scheduler/scheduler.js +13 -13
- package/dist/features/scheduler/scheduler-event/scheduler-event.d.ts +10 -8
- package/dist/features/scheduler/scheduler-event/scheduler-event.js +7 -7
- package/dist/features/scheduler/scheduler-event/scheduler-event.styles.js +6 -6
- package/dist/features/scheduler/scheduler-event-editor/scheduler-event-editor.js +5 -5
- package/dist/features/scheduler/shared/scheduler-event-popover.js +2 -2
- package/dist/features/scheduler/shared/scheduler-hour-grid.d.ts +2 -2
- package/dist/features/scheduler/shared/scheduler-hour-grid.js +3 -3
- package/dist/features/scheduler/shared/scheduler-month-view.d.ts +3 -3
- package/dist/features/scheduler/shared/scheduler-month-view.js +2 -2
- package/dist/features/table/table/table.types.d.ts +7 -3
- package/dist/features/table/table-action-bar/table-action-bar.js +3 -3
- package/dist/features/table/table-managed/table-managed.js +2 -2
- package/dist/i18n/en.d.ts +3 -0
- package/dist/i18n/en.js +3 -0
- package/dist/i18n/fr.js +3 -0
- package/dist/index.d.ts +3 -3
- package/dist/jsx.d.ts +1 -1
- package/dist/mixins/button.mixin.d.ts +10 -9
- package/dist/mixins/button.mixin.js +14 -6
- package/dist/mixins/card-link.mixin.d.ts +3 -2
- package/dist/mixins/card-link.mixin.js +12 -5
- package/dist/mixins/disabled.mixin.d.ts +3 -3
- package/dist/mixins/disabled.mixin.js +10 -5
- package/dist/mixins/field-appearance.mixin.d.ts +19 -0
- package/dist/mixins/{field-variant.mixin.js → field-appearance.mixin.js} +11 -11
- package/dist/ssr/animate-ssr.css +26 -72
- package/dist/ssr/links-ssr.css +35 -0
- package/dist/ssr/overlay-ssr.css +0 -41
- package/dist/ssr/rich-text.css +38 -0
- package/dist/ssr/sidebar-ssr.css +0 -38
- package/dist/ssr/toolbar-ssr.css +73 -39
- package/dist/types/variant.type.d.ts +26 -10
- package/dist/utils/navigation.utils.d.ts +14 -0
- package/dist/utils/navigation.utils.js +33 -0
- package/dist/utils/new-tab-anchor.controller.d.ts +44 -0
- package/dist/utils/new-tab-anchor.controller.js +102 -0
- package/dist/utils/severity-icon.utils.d.ts +1 -1
- package/dist/utils/severity-icon.utils.js +1 -1
- package/dist/utils/theme-generator.utils.d.ts +3 -1
- package/dist/utils/theme-generator.utils.js +3 -1
- package/package.json +8 -2
- package/dist/cdn/components/chunks/chunk-2JLDJFYD.js +0 -48
- package/dist/cdn/components/chunks/chunk-ATH2OAMU.js +0 -1
- package/dist/cdn/components/chunks/chunk-BKHD4S57.js +0 -1
- package/dist/cdn/components/chunks/chunk-T7WABJEJ.js +0 -1
- package/dist/cdn/components/chunks/chunk-XSMCT4DF.js +0 -1
- package/dist/mixins/field-variant.mixin.d.ts +0 -22
|
@@ -10,6 +10,7 @@ import { ifDefined } from "lit/directives/if-defined.js";
|
|
|
10
10
|
import { ButtonMixin } from "../../../mixins/button.mixin.js";
|
|
11
11
|
import { CommandMixin } from "../../../mixins/command.mixin.js";
|
|
12
12
|
import { DisabledMixin } from "../../../mixins/disabled.mixin.js";
|
|
13
|
+
import { LocalizableMixin } from "../../../mixins/localizable.mixin.js";
|
|
13
14
|
import { handleLinkNavigation } from "../../../utils/navigation.utils.js";
|
|
14
15
|
import { fabStyles } from "./fab.styles.js";
|
|
15
16
|
/**
|
|
@@ -18,7 +19,7 @@ import { fabStyles } from "./fab.styles.js";
|
|
|
18
19
|
export const EunomiaFabTagName = "eun-fab";
|
|
19
20
|
/**
|
|
20
21
|
* A circular icon button for a screen's single primary action. It shares
|
|
21
|
-
* its
|
|
22
|
+
* its color, size, href, loading, and keyboard behavior with the regular
|
|
22
23
|
* button.
|
|
23
24
|
*
|
|
24
25
|
* When label is set, the button becomes extendable. It stays a plain circle
|
|
@@ -32,13 +33,14 @@ export const EunomiaFabTagName = "eun-fab";
|
|
|
32
33
|
* @prop {EunomiaIconName} icon - The icon displayed at all times
|
|
33
34
|
* @prop {string} label - An optional text label, revealed on hover or focus by the slide animation. Omit it for an icon only button
|
|
34
35
|
* @prop {'bottom-right' | 'bottom-left' | 'top-right' | 'top-left'} position - Fixes the button to a corner of the viewport. Left unset, the button follows the normal document flow
|
|
35
|
-
* @prop {'primary' | 'secondary' | 'critical' | 'success' | 'warning'} [
|
|
36
|
-
* @prop {boolean} [fixedColor=false] - Keeps a light or dark button white or black in every theme. Without it, they follow the grey scale, which flips with the active theme. Has no effect on the other
|
|
37
|
-
* @attr {boolean} [fixed-color=false] - Keeps a light or dark button white or black in every theme. Without it, they follow the grey scale, which flips with the active theme. Has no effect on the other
|
|
36
|
+
* @prop {'primary' | 'secondary' | 'critical' | 'success' | 'warning'} [color='primary'] - The color applied to the button
|
|
37
|
+
* @prop {boolean} [fixedColor=false] - Keeps a light or dark button white or black in every theme. Without it, they follow the grey scale, which flips with the active theme. Has no effect on the other colors
|
|
38
|
+
* @attr {boolean} [fixed-color=false] - Keeps a light or dark button white or black in every theme. Without it, they follow the grey scale, which flips with the active theme. Has no effect on the other colors
|
|
38
39
|
* @prop {'xs' | 's' | 'm' | 'l' | 'xl'} [size='m'] - The size of the button
|
|
39
40
|
* @prop {boolean} [disabled=false] - Whether the button is disabled. For a link button, this removes the href instead, since links have no native disabled state
|
|
40
41
|
* @prop {string} href - The URL the button navigates to. When set, the button renders as a link instead of a button
|
|
41
42
|
* @prop {'_blank' | '_self' | '_parent' | '_top'} target - Where to open the linked URL. Only used when href is set. Opening in a new tab automatically announces it to assistive technology, and adds an external link icon when label is also set
|
|
43
|
+
* @prop {string} [locale] - The locale used to resolve the "opens in a new tab" announcement. Defaults to the one set with setDefaultLocale, English otherwise
|
|
42
44
|
* @prop {string} download - The filename used when the linked URL is downloaded instead of navigated to. Only used when href is set
|
|
43
45
|
* @prop {boolean} [loading=false] - Whether the button shows a loading indicator. Like disabled, it blocks interaction, but keeps the icon and label in place so the button doesn't change size
|
|
44
46
|
* @prop {string} [loadingLabel='Loading…'] - The accessible label announced while the button is loading
|
|
@@ -47,7 +49,7 @@ export const EunomiaFabTagName = "eun-fab";
|
|
|
47
49
|
* @attr {string} aria-label - The accessible label for the button. Required when label isn't set, since an icon alone has no accessible name, and recommended even when it is if the label text alone doesn't describe the action
|
|
48
50
|
* @fires click - Fired when the button is activated by mouse, Enter, or Space
|
|
49
51
|
* @fires {NavigationEvent} eunnavigate - Fired before following href, so a client-side router can intercept the navigation. Not fired for downloads, and cancelable
|
|
50
|
-
* @cssprop [--fab-background] - Sets the background color, for every
|
|
52
|
+
* @cssprop [--fab-background] - Sets the background color, for every color
|
|
51
53
|
* @cssprop [--fab-background-hover] - Sets the background color on hover
|
|
52
54
|
* @cssprop [--fab-text] - Sets the color of the text and icon
|
|
53
55
|
* @cssprop [--fab-focus-outline] - Sets the color of the focus outline
|
|
@@ -56,7 +58,7 @@ export const EunomiaFabTagName = "eun-fab";
|
|
|
56
58
|
* @cssprop [--fab-offset] - Sets the distance from the viewport edge for a positioned button
|
|
57
59
|
* @element eun-fab
|
|
58
60
|
*/
|
|
59
|
-
let EunomiaFab = class EunomiaFab extends ButtonMixin(CommandMixin(DisabledMixin(LitElement))) {
|
|
61
|
+
let EunomiaFab = class EunomiaFab extends ButtonMixin(CommandMixin(DisabledMixin(LocalizableMixin(LitElement)))) {
|
|
60
62
|
constructor() {
|
|
61
63
|
super(...arguments);
|
|
62
64
|
/**
|
|
@@ -132,7 +134,8 @@ let EunomiaFab = class EunomiaFab extends ButtonMixin(CommandMixin(DisabledMixin
|
|
|
132
134
|
if (!this.isBlank || this.ariaLabel) {
|
|
133
135
|
return nothing;
|
|
134
136
|
}
|
|
135
|
-
|
|
137
|
+
const hint = this.dictionary.link.opensInNewTab;
|
|
138
|
+
return html `<span class="sr-only"> (${hint})</span>`;
|
|
136
139
|
}
|
|
137
140
|
/**
|
|
138
141
|
* Renders `label`, with an appended external-link icon (mirroring
|
|
@@ -198,7 +201,7 @@ let EunomiaFab = class EunomiaFab extends ButtonMixin(CommandMixin(DisabledMixin
|
|
|
198
201
|
rel=${ifDefined(this.isBlank ? "noopener noreferrer" : undefined)}
|
|
199
202
|
download=${ifDefined(this.download)}
|
|
200
203
|
aria-label=${ifDefined(this.isBlank && this.ariaLabel
|
|
201
|
-
? `${this.ariaLabel} (
|
|
204
|
+
? `${this.ariaLabel} (${this.dictionary.link.opensInNewTab})`
|
|
202
205
|
: (this.ariaLabel ?? undefined))}
|
|
203
206
|
aria-disabled=${ifDefined(this.disabled ? "true" : undefined)}
|
|
204
207
|
aria-busy=${ifDefined(this.loading ? "true" : undefined)}
|
|
@@ -3,15 +3,15 @@ import { buttonPaletteStyles } from "../shared-styles/button-palette.styles.js";
|
|
|
3
3
|
/**
|
|
4
4
|
* Base style for the floating action button.
|
|
5
5
|
*
|
|
6
|
-
* The
|
|
6
|
+
* The color palette is shared with `eun-button` (see
|
|
7
7
|
* {@link buttonPaletteStyles}) and read *behind* the `--fab-*` custom
|
|
8
|
-
* properties, so those win over every
|
|
8
|
+
* properties, so those win over every color. A fab only has a solid look,
|
|
9
9
|
* so it only reads the solid slots.
|
|
10
10
|
*
|
|
11
11
|
* Custom css variables:
|
|
12
|
-
* [--fab-background] - Set a custom background color, for every
|
|
12
|
+
* [--fab-background] - Set a custom background color, for every color
|
|
13
13
|
* [--fab-background-hover] - Set a custom background color for hover state. Derived from --fab-background when only that one is set
|
|
14
|
-
* [--fab-text] - Set a custom text/icon color, for every
|
|
14
|
+
* [--fab-text] - Set a custom text/icon color, for every color
|
|
15
15
|
* [--fab-focus-outline] - Set a custom color to the focus outline
|
|
16
16
|
* [--fab-transition] - Set a custom transition time, shared by the slide-open animation and the hover/focus color changes (mirrors `eun-button`'s own `--button-transition`)
|
|
17
17
|
* [--fab-z-index] - Set a custom z-index for a positioned FAB
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { LitElement, TemplateResult } from "lit";
|
|
1
|
+
import { LitElement, PropertyValues, TemplateResult } from "lit";
|
|
2
2
|
import { EunomiaIconName } from "../../content/icon/icon.type.js";
|
|
3
3
|
/**
|
|
4
4
|
* Tag name of the link component.
|
|
5
5
|
*/
|
|
6
6
|
export declare const EunomiaLinkTagName = "eun-link";
|
|
7
|
+
declare const EunomiaLink_base: import("../../../utils/constructor.type.js").Constructor<import("../../../mixins/localizable.mixin.js").LocalizableMixinInterface> & typeof LitElement;
|
|
7
8
|
/**
|
|
8
9
|
* A basic link with an optional decorative leading icon.
|
|
9
10
|
*
|
|
@@ -11,14 +12,22 @@ export declare const EunomiaLinkTagName = "eun-link";
|
|
|
11
12
|
* prevent the new page from controlling the original one, without affecting
|
|
12
13
|
* same-tab navigation.
|
|
13
14
|
*
|
|
14
|
-
*
|
|
15
|
+
* Without href, a native anchor placed as a direct child becomes the link
|
|
16
|
+
* instead, such as a framework's own link component. The anchor then exists
|
|
17
|
+
* in the server-rendered HTML, so crawlers that don't run JavaScript still
|
|
18
|
+
* find it, and it keeps the link styles and the current state. When that
|
|
19
|
+
* anchor opens in a new tab, the link shows the same end icon and announces
|
|
20
|
+
* it the same way, through the anchor's aria-description.
|
|
21
|
+
*
|
|
22
|
+
* @slot [default] - The link content, or a native anchor carrying the href itself when href is unset
|
|
15
23
|
* @slot [icon] - Replaces the leading icon entirely with any content, not just an icon element. Falls back to icon when empty
|
|
16
24
|
* @prop {string} href - The destination URL
|
|
17
|
-
* @prop {'_blank' | '_self' | '_parent' | '_top'} [target='_self'] - Where to open the linked URL. Opening in a new tab automatically announces it to assistive technology
|
|
25
|
+
* @prop {'_blank' | '_self' | '_parent' | '_top'} [target='_self'] - Where to open the linked URL. Opening in a new tab automatically adds an external link icon at the end and announces it to assistive technology, in the current locale
|
|
18
26
|
* @prop {import('../../content/icon/icon.type.js').EunomiaIconName} icon - An optional decorative icon displayed to the left of the link
|
|
19
27
|
* @prop {'light' | 'dark'} [theme='light'] - The text color theme. Use dark on a dark background
|
|
20
28
|
* @prop {'auto' | 'off' | 'on'} [visitedStyle='auto'] - Controls the visited state color. Auto follows the browser's real navigation history, off always renders as unvisited, and on always renders as visited
|
|
21
29
|
* @prop {boolean} [current=false] - Marks the link as the current page: it renders with aria-current="page" and keeps the --link-color-current color in every state (hover, focus, visited), for example an active item in a navigation
|
|
30
|
+
* @prop {string} [locale] - The locale used to resolve the "opens in a new tab" announcement. Defaults to the one set with setDefaultLocale, English otherwise
|
|
22
31
|
* @attr {string} aria-label - An accessible label that overrides the link content. When the link also opens in a new tab, a note announcing it is appended automatically
|
|
23
32
|
* @fires {NavigationEvent} eunnavigate - Fired before following the link, so a client-side router can intercept the navigation. Cancelable
|
|
24
33
|
* @cssprop [--link-color] - Sets the color of the link
|
|
@@ -37,7 +46,8 @@ export declare const EunomiaLinkTagName = "eun-link";
|
|
|
37
46
|
* @cssstate focus-visible - Set while the link is keyboard-focused (never after a mouse click), so it can be styled from outside the shadow root with eun-link:state(focus-visible). Turbopack's CSS parser (lightningcss) doesn't recognize :state() yet and rejects the whole stylesheet it's in ; ship that rule as a runtime <style>/<link> instead until it's supported
|
|
38
47
|
* @element eun-link
|
|
39
48
|
*/
|
|
40
|
-
export declare class EunomiaLink extends
|
|
49
|
+
export declare class EunomiaLink extends EunomiaLink_base {
|
|
50
|
+
#private;
|
|
41
51
|
/**
|
|
42
52
|
* Styles to import to the component.
|
|
43
53
|
*
|
|
@@ -60,14 +70,17 @@ export declare class EunomiaLink extends LitElement {
|
|
|
60
70
|
*/
|
|
61
71
|
icon?: EunomiaIconName;
|
|
62
72
|
/**
|
|
63
|
-
* Text color theme, use `dark` on a dark background.
|
|
73
|
+
* Text color theme, use `dark` on a dark background. Only reflected once
|
|
74
|
+
* it differs from the default, so an SSR framework doesn't see an
|
|
75
|
+
* attribute it never rendered.
|
|
64
76
|
* @default light
|
|
65
77
|
*/
|
|
66
78
|
theme: "light" | "dark";
|
|
67
79
|
/**
|
|
68
80
|
* Controls the visited-state color: `auto` follows the browser's real
|
|
69
81
|
* navigation history for `href`, `off` always renders as unvisited, `on`
|
|
70
|
-
* always renders as visited.
|
|
82
|
+
* always renders as visited. Only reflected once it differs from the
|
|
83
|
+
* default, like {@link theme}.
|
|
71
84
|
* @default auto
|
|
72
85
|
*/
|
|
73
86
|
visitedStyle: "auto" | "off" | "on";
|
|
@@ -101,6 +114,45 @@ export declare class EunomiaLink extends LitElement {
|
|
|
101
114
|
*/
|
|
102
115
|
static get observedAttributes(): string[];
|
|
103
116
|
attributeChangedCallback(name: string, oldValue: string | null, value: string | null): void;
|
|
117
|
+
/**
|
|
118
|
+
* The native `<a>` slotted as a direct child while `href` is unset, which
|
|
119
|
+
* then acts as the link itself : it's in the light DOM, so it's part of
|
|
120
|
+
* the server-rendered HTML, and a framework's own link component (Next's
|
|
121
|
+
* `<Link>`, Angular's `routerLink`, ...) can be that anchor. Navigation,
|
|
122
|
+
* `target`/`rel` and the new-tab hint are the consumer's own in this mode.
|
|
123
|
+
* @internal
|
|
124
|
+
*/
|
|
125
|
+
private get slottedAnchor();
|
|
126
|
+
connectedCallback(): void;
|
|
127
|
+
disconnectedCallback(): void;
|
|
128
|
+
protected updated(changed: PropertyValues): void;
|
|
129
|
+
/**
|
|
130
|
+
* Mirrors {@link current} onto the slotted anchor as `aria-current`,
|
|
131
|
+
* since that anchor, not the wrapper around it, is what assistive
|
|
132
|
+
* technology announces.
|
|
133
|
+
* @private
|
|
134
|
+
*/
|
|
135
|
+
private syncSlottedAnchor;
|
|
136
|
+
/**
|
|
137
|
+
* Re-renders when the default slot changes, so an anchor added or removed
|
|
138
|
+
* after the first render switches between the two modes.
|
|
139
|
+
* @private
|
|
140
|
+
*/
|
|
141
|
+
private handleDefaultSlotChange;
|
|
142
|
+
/**
|
|
143
|
+
* The slotted anchor's counterpart of {@link handleFocus} : it lives in
|
|
144
|
+
* the light DOM, so its focus reaches the host as a plain `focusin`.
|
|
145
|
+
* @param event the host's focusin event.
|
|
146
|
+
* @private
|
|
147
|
+
*/
|
|
148
|
+
private handleSlottedFocusIn;
|
|
149
|
+
/**
|
|
150
|
+
* Clears the `focus-visible` custom state once the slotted anchor loses
|
|
151
|
+
* focus.
|
|
152
|
+
* @param event the host's focusout event.
|
|
153
|
+
* @private
|
|
154
|
+
*/
|
|
155
|
+
private handleSlottedFocusOut;
|
|
104
156
|
/**
|
|
105
157
|
* Elements assigned to the `icon` slot, if any ; queried live so
|
|
106
158
|
* {@link render} can decide whether to fall back to the `icon` prop.
|
|
@@ -141,6 +193,12 @@ export declare class EunomiaLink extends LitElement {
|
|
|
141
193
|
* @private
|
|
142
194
|
*/
|
|
143
195
|
private handleClick;
|
|
196
|
+
/**
|
|
197
|
+
* The decorative icon at the end of a link opening in a new tab, the
|
|
198
|
+
* wording being announced separately.
|
|
199
|
+
* @private
|
|
200
|
+
*/
|
|
201
|
+
private renderExternalLinkIcon;
|
|
144
202
|
/**
|
|
145
203
|
* Renders the link template.
|
|
146
204
|
* @returns The rendered HTML template
|
|
@@ -152,3 +210,4 @@ declare global {
|
|
|
152
210
|
[EunomiaLinkTagName]: EunomiaLink;
|
|
153
211
|
}
|
|
154
212
|
}
|
|
213
|
+
export {};
|
|
@@ -4,12 +4,26 @@ 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
|
+
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
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
13
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
14
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
15
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
16
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
17
|
+
};
|
|
18
|
+
var _EunomiaLink_currentAnchor, _EunomiaLink_newTab;
|
|
7
19
|
import { customElement, property, queryAssignedElements, } from "lit/decorators.js";
|
|
8
20
|
import { html, LitElement, nothing } from "lit";
|
|
9
21
|
import { classMap } from "lit/directives/class-map.js";
|
|
10
22
|
import { ifDefined } from "lit/directives/if-defined.js";
|
|
11
23
|
import { linkStyles } from "./link.styles.js";
|
|
12
|
-
import { handleLinkNavigation } from "../../../utils/navigation.utils.js";
|
|
24
|
+
import { handleLinkNavigation, warnIgnoredHostLinkAttributes, } from "../../../utils/navigation.utils.js";
|
|
25
|
+
import { LocalizableMixin } from "../../../mixins/localizable.mixin.js";
|
|
26
|
+
import { NewTabAnchorController } from "../../../utils/new-tab-anchor.controller.js";
|
|
13
27
|
/**
|
|
14
28
|
* Tag name of the link component.
|
|
15
29
|
*/
|
|
@@ -21,14 +35,22 @@ export const EunomiaLinkTagName = "eun-link";
|
|
|
21
35
|
* prevent the new page from controlling the original one, without affecting
|
|
22
36
|
* same-tab navigation.
|
|
23
37
|
*
|
|
24
|
-
*
|
|
38
|
+
* Without href, a native anchor placed as a direct child becomes the link
|
|
39
|
+
* instead, such as a framework's own link component. The anchor then exists
|
|
40
|
+
* in the server-rendered HTML, so crawlers that don't run JavaScript still
|
|
41
|
+
* find it, and it keeps the link styles and the current state. When that
|
|
42
|
+
* anchor opens in a new tab, the link shows the same end icon and announces
|
|
43
|
+
* it the same way, through the anchor's aria-description.
|
|
44
|
+
*
|
|
45
|
+
* @slot [default] - The link content, or a native anchor carrying the href itself when href is unset
|
|
25
46
|
* @slot [icon] - Replaces the leading icon entirely with any content, not just an icon element. Falls back to icon when empty
|
|
26
47
|
* @prop {string} href - The destination URL
|
|
27
|
-
* @prop {'_blank' | '_self' | '_parent' | '_top'} [target='_self'] - Where to open the linked URL. Opening in a new tab automatically announces it to assistive technology
|
|
48
|
+
* @prop {'_blank' | '_self' | '_parent' | '_top'} [target='_self'] - Where to open the linked URL. Opening in a new tab automatically adds an external link icon at the end and announces it to assistive technology, in the current locale
|
|
28
49
|
* @prop {import('../../content/icon/icon.type.js').EunomiaIconName} icon - An optional decorative icon displayed to the left of the link
|
|
29
50
|
* @prop {'light' | 'dark'} [theme='light'] - The text color theme. Use dark on a dark background
|
|
30
51
|
* @prop {'auto' | 'off' | 'on'} [visitedStyle='auto'] - Controls the visited state color. Auto follows the browser's real navigation history, off always renders as unvisited, and on always renders as visited
|
|
31
52
|
* @prop {boolean} [current=false] - Marks the link as the current page: it renders with aria-current="page" and keeps the --link-color-current color in every state (hover, focus, visited), for example an active item in a navigation
|
|
53
|
+
* @prop {string} [locale] - The locale used to resolve the "opens in a new tab" announcement. Defaults to the one set with setDefaultLocale, English otherwise
|
|
32
54
|
* @attr {string} aria-label - An accessible label that overrides the link content. When the link also opens in a new tab, a note announcing it is appended automatically
|
|
33
55
|
* @fires {NavigationEvent} eunnavigate - Fired before following the link, so a client-side router can intercept the navigation. Cancelable
|
|
34
56
|
* @cssprop [--link-color] - Sets the color of the link
|
|
@@ -47,7 +69,7 @@ export const EunomiaLinkTagName = "eun-link";
|
|
|
47
69
|
* @cssstate focus-visible - Set while the link is keyboard-focused (never after a mouse click), so it can be styled from outside the shadow root with eun-link:state(focus-visible). Turbopack's CSS parser (lightningcss) doesn't recognize :state() yet and rejects the whole stylesheet it's in ; ship that rule as a runtime <style>/<link> instead until it's supported
|
|
48
70
|
* @element eun-link
|
|
49
71
|
*/
|
|
50
|
-
let EunomiaLink = class EunomiaLink extends LitElement {
|
|
72
|
+
let EunomiaLink = class EunomiaLink extends LocalizableMixin(LitElement) {
|
|
51
73
|
/**
|
|
52
74
|
* The element's custom state set, typed locally since the bundled DOM
|
|
53
75
|
* typings don't declare `ElementInternals.states` yet.
|
|
@@ -64,14 +86,17 @@ let EunomiaLink = class EunomiaLink extends LitElement {
|
|
|
64
86
|
*/
|
|
65
87
|
this.target = "_self";
|
|
66
88
|
/**
|
|
67
|
-
* Text color theme, use `dark` on a dark background.
|
|
89
|
+
* Text color theme, use `dark` on a dark background. Only reflected once
|
|
90
|
+
* it differs from the default, so an SSR framework doesn't see an
|
|
91
|
+
* attribute it never rendered.
|
|
68
92
|
* @default light
|
|
69
93
|
*/
|
|
70
94
|
this.theme = "light";
|
|
71
95
|
/**
|
|
72
96
|
* Controls the visited-state color: `auto` follows the browser's real
|
|
73
97
|
* navigation history for `href`, `off` always renders as unvisited, `on`
|
|
74
|
-
* always renders as visited.
|
|
98
|
+
* always renders as visited. Only reflected once it differs from the
|
|
99
|
+
* default, like {@link theme}.
|
|
75
100
|
* @default auto
|
|
76
101
|
*/
|
|
77
102
|
this.visitedStyle = "auto";
|
|
@@ -82,6 +107,48 @@ let EunomiaLink = class EunomiaLink extends LitElement {
|
|
|
82
107
|
* @default false
|
|
83
108
|
*/
|
|
84
109
|
this.current = false;
|
|
110
|
+
/**
|
|
111
|
+
* The anchor {@link current} was last mirrored onto, so its
|
|
112
|
+
* `aria-current` can be cleared once it's swapped out or removed.
|
|
113
|
+
* @internal
|
|
114
|
+
*/
|
|
115
|
+
_EunomiaLink_currentAnchor.set(this, void 0);
|
|
116
|
+
/**
|
|
117
|
+
* Announces the slotted anchor opening in a new tab.
|
|
118
|
+
* @internal
|
|
119
|
+
*/
|
|
120
|
+
_EunomiaLink_newTab.set(this, new NewTabAnchorController(this, () => this.slottedAnchor, () => this.dictionary.link.opensInNewTab));
|
|
121
|
+
/**
|
|
122
|
+
* Re-renders when the default slot changes, so an anchor added or removed
|
|
123
|
+
* after the first render switches between the two modes.
|
|
124
|
+
* @private
|
|
125
|
+
*/
|
|
126
|
+
this.handleDefaultSlotChange = () => {
|
|
127
|
+
this.requestUpdate();
|
|
128
|
+
};
|
|
129
|
+
/**
|
|
130
|
+
* The slotted anchor's counterpart of {@link handleFocus} : it lives in
|
|
131
|
+
* the light DOM, so its focus reaches the host as a plain `focusin`.
|
|
132
|
+
* @param event the host's focusin event.
|
|
133
|
+
* @private
|
|
134
|
+
*/
|
|
135
|
+
this.handleSlottedFocusIn = (event) => {
|
|
136
|
+
const target = event.target;
|
|
137
|
+
if (target === this.slottedAnchor && target.matches(":focus-visible")) {
|
|
138
|
+
this.states?.add("focus-visible");
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
/**
|
|
142
|
+
* Clears the `focus-visible` custom state once the slotted anchor loses
|
|
143
|
+
* focus.
|
|
144
|
+
* @param event the host's focusout event.
|
|
145
|
+
* @private
|
|
146
|
+
*/
|
|
147
|
+
this.handleSlottedFocusOut = (event) => {
|
|
148
|
+
if (event.target === this.slottedAnchor) {
|
|
149
|
+
this.states?.delete("focus-visible");
|
|
150
|
+
}
|
|
151
|
+
};
|
|
85
152
|
/**
|
|
86
153
|
* Re-renders when the `icon` slot's assigned content changes, so the
|
|
87
154
|
* `icon` prop fallback correctly appears/disappears as content is
|
|
@@ -113,6 +180,56 @@ let EunomiaLink = class EunomiaLink extends LitElement {
|
|
|
113
180
|
}
|
|
114
181
|
super.attributeChangedCallback(name, oldValue, value);
|
|
115
182
|
}
|
|
183
|
+
/**
|
|
184
|
+
* The native `<a>` slotted as a direct child while `href` is unset, which
|
|
185
|
+
* then acts as the link itself : it's in the light DOM, so it's part of
|
|
186
|
+
* the server-rendered HTML, and a framework's own link component (Next's
|
|
187
|
+
* `<Link>`, Angular's `routerLink`, ...) can be that anchor. Navigation,
|
|
188
|
+
* `target`/`rel` and the new-tab hint are the consumer's own in this mode.
|
|
189
|
+
* @internal
|
|
190
|
+
*/
|
|
191
|
+
get slottedAnchor() {
|
|
192
|
+
return this.href ? null : this.querySelector(":scope > a");
|
|
193
|
+
}
|
|
194
|
+
connectedCallback() {
|
|
195
|
+
super.connectedCallback();
|
|
196
|
+
this.addEventListener("focusin", this.handleSlottedFocusIn);
|
|
197
|
+
this.addEventListener("focusout", this.handleSlottedFocusOut);
|
|
198
|
+
}
|
|
199
|
+
disconnectedCallback() {
|
|
200
|
+
this.removeEventListener("focusin", this.handleSlottedFocusIn);
|
|
201
|
+
this.removeEventListener("focusout", this.handleSlottedFocusOut);
|
|
202
|
+
super.disconnectedCallback();
|
|
203
|
+
}
|
|
204
|
+
updated(changed) {
|
|
205
|
+
super.updated(changed);
|
|
206
|
+
this.syncSlottedAnchor();
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Mirrors {@link current} onto the slotted anchor as `aria-current`,
|
|
210
|
+
* since that anchor, not the wrapper around it, is what assistive
|
|
211
|
+
* technology announces.
|
|
212
|
+
* @private
|
|
213
|
+
*/
|
|
214
|
+
syncSlottedAnchor() {
|
|
215
|
+
const anchor = this.slottedAnchor;
|
|
216
|
+
if (__classPrivateFieldGet(this, _EunomiaLink_currentAnchor, "f") && __classPrivateFieldGet(this, _EunomiaLink_currentAnchor, "f") !== anchor) {
|
|
217
|
+
__classPrivateFieldGet(this, _EunomiaLink_currentAnchor, "f").removeAttribute("aria-current");
|
|
218
|
+
__classPrivateFieldSet(this, _EunomiaLink_currentAnchor, undefined, "f");
|
|
219
|
+
}
|
|
220
|
+
if (!anchor) {
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
warnIgnoredHostLinkAttributes(this);
|
|
224
|
+
if (this.current) {
|
|
225
|
+
anchor.setAttribute("aria-current", "page");
|
|
226
|
+
__classPrivateFieldSet(this, _EunomiaLink_currentAnchor, anchor, "f");
|
|
227
|
+
}
|
|
228
|
+
else if (__classPrivateFieldGet(this, _EunomiaLink_currentAnchor, "f") === anchor) {
|
|
229
|
+
anchor.removeAttribute("aria-current");
|
|
230
|
+
__classPrivateFieldSet(this, _EunomiaLink_currentAnchor, undefined, "f");
|
|
231
|
+
}
|
|
232
|
+
}
|
|
116
233
|
/**
|
|
117
234
|
* Mirrors the inner anchor's real `:focus-visible` state onto the host as
|
|
118
235
|
* the `focus-visible` custom state, styled from outside with
|
|
@@ -147,6 +264,16 @@ let EunomiaLink = class EunomiaLink extends LitElement {
|
|
|
147
264
|
handleClick(event) {
|
|
148
265
|
handleLinkNavigation(this, event, this.href, this.target);
|
|
149
266
|
}
|
|
267
|
+
/**
|
|
268
|
+
* The decorative icon at the end of a link opening in a new tab, the
|
|
269
|
+
* wording being announced separately.
|
|
270
|
+
* @private
|
|
271
|
+
*/
|
|
272
|
+
renderExternalLinkIcon() {
|
|
273
|
+
return html `<span id="external-link-icon">
|
|
274
|
+
<eun-icon name="arrow_forward" shape="round" size="14"></eun-icon>
|
|
275
|
+
</span>`;
|
|
276
|
+
}
|
|
150
277
|
/**
|
|
151
278
|
* Renders the link template.
|
|
152
279
|
* @returns The rendered HTML template
|
|
@@ -154,6 +281,29 @@ let EunomiaLink = class EunomiaLink extends LitElement {
|
|
|
154
281
|
render() {
|
|
155
282
|
const isBlank = this.target === "_blank";
|
|
156
283
|
const hasIcon = !!this.icon || this.iconSlotEls?.length > 0;
|
|
284
|
+
const iconSlot = html `<slot
|
|
285
|
+
name="icon"
|
|
286
|
+
class=${classMap({ "has-icon": hasIcon })}
|
|
287
|
+
@slotchange=${this.handleIconSlotChange}
|
|
288
|
+
>
|
|
289
|
+
${this.icon
|
|
290
|
+
? html `<eun-icon name=${this.icon} size="18"></eun-icon>`
|
|
291
|
+
: nothing}
|
|
292
|
+
</slot>`;
|
|
293
|
+
if (this.slottedAnchor) {
|
|
294
|
+
return html `
|
|
295
|
+
<span
|
|
296
|
+
id="link"
|
|
297
|
+
part="link"
|
|
298
|
+
class=${classMap({ "has-icon": hasIcon, "slotted-link": true })}
|
|
299
|
+
>
|
|
300
|
+
${iconSlot}
|
|
301
|
+
<slot @slotchange=${this.handleDefaultSlotChange}></slot>
|
|
302
|
+
${__classPrivateFieldGet(this, _EunomiaLink_newTab, "f").isBlank ? this.renderExternalLinkIcon() : nothing}
|
|
303
|
+
</span>
|
|
304
|
+
`;
|
|
305
|
+
}
|
|
306
|
+
const newTabHint = `(${this.dictionary.link.opensInNewTab})`;
|
|
157
307
|
return html `
|
|
158
308
|
<a
|
|
159
309
|
id="link"
|
|
@@ -164,29 +314,24 @@ let EunomiaLink = class EunomiaLink extends LitElement {
|
|
|
164
314
|
aria-current=${ifDefined(this.current ? "page" : undefined)}
|
|
165
315
|
rel=${ifDefined(isBlank ? "noopener noreferrer" : undefined)}
|
|
166
316
|
aria-label=${ifDefined(isBlank && this.ariaLabel
|
|
167
|
-
? `${this.ariaLabel}
|
|
317
|
+
? `${this.ariaLabel} ${newTabHint}`
|
|
168
318
|
: (this.ariaLabel ?? undefined))}
|
|
169
319
|
@click=${this.handleClick}
|
|
170
320
|
@focus=${this.handleFocus}
|
|
171
321
|
@blur=${this.handleBlur}
|
|
172
322
|
>
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
class=${classMap({ "has-icon": hasIcon })}
|
|
176
|
-
@slotchange=${this.handleIconSlotChange}
|
|
177
|
-
>
|
|
178
|
-
${this.icon
|
|
179
|
-
? html `<eun-icon name=${this.icon} size="18"></eun-icon>`
|
|
180
|
-
: nothing}
|
|
181
|
-
</slot>
|
|
182
|
-
<slot></slot>
|
|
323
|
+
${iconSlot}
|
|
324
|
+
<slot @slotchange=${this.handleDefaultSlotChange}></slot>
|
|
183
325
|
${isBlank && !this.ariaLabel
|
|
184
|
-
? html `<span class="sr-only">
|
|
326
|
+
? html `<span class="sr-only"> ${newTabHint}</span>`
|
|
185
327
|
: nothing}
|
|
328
|
+
${isBlank ? this.renderExternalLinkIcon() : nothing}
|
|
186
329
|
</a>
|
|
187
330
|
`;
|
|
188
331
|
}
|
|
189
332
|
};
|
|
333
|
+
_EunomiaLink_currentAnchor = new WeakMap();
|
|
334
|
+
_EunomiaLink_newTab = new WeakMap();
|
|
190
335
|
/**
|
|
191
336
|
* Styles to import to the component.
|
|
192
337
|
*
|
|
@@ -205,10 +350,21 @@ __decorate([
|
|
|
205
350
|
property()
|
|
206
351
|
], EunomiaLink.prototype, "icon", void 0);
|
|
207
352
|
__decorate([
|
|
208
|
-
property({
|
|
353
|
+
property({
|
|
354
|
+
reflect: true,
|
|
355
|
+
converter: {
|
|
356
|
+
toAttribute: (value) => (value === "light" ? null : value),
|
|
357
|
+
},
|
|
358
|
+
})
|
|
209
359
|
], EunomiaLink.prototype, "theme", void 0);
|
|
210
360
|
__decorate([
|
|
211
|
-
property({
|
|
361
|
+
property({
|
|
362
|
+
reflect: true,
|
|
363
|
+
attribute: "visited-style",
|
|
364
|
+
converter: {
|
|
365
|
+
toAttribute: (value) => (value === "auto" ? null : value),
|
|
366
|
+
},
|
|
367
|
+
})
|
|
212
368
|
], EunomiaLink.prototype, "visitedStyle", void 0);
|
|
213
369
|
__decorate([
|
|
214
370
|
property({ type: Boolean, reflect: true })
|
|
@@ -65,6 +65,12 @@ const base = css `
|
|
|
65
65
|
display: inline-flex;
|
|
66
66
|
flex-shrink: 0;
|
|
67
67
|
}
|
|
68
|
+
#external-link-icon {
|
|
69
|
+
display: inline-flex;
|
|
70
|
+
flex-shrink: 0;
|
|
71
|
+
margin-inline-start: calc(-1 * var(--eun-space-xs, 4px));
|
|
72
|
+
transform: rotate(-45deg);
|
|
73
|
+
}
|
|
68
74
|
#link {
|
|
69
75
|
display: inline-flex;
|
|
70
76
|
align-items: center;
|
|
@@ -134,8 +140,87 @@ const base = css `
|
|
|
134
140
|
--icon-color: var(--link-icon-color, var(--_colorCurrent));
|
|
135
141
|
}
|
|
136
142
|
|
|
143
|
+
#link.slotted-link {
|
|
144
|
+
position: relative;
|
|
145
|
+
text-decoration: none;
|
|
146
|
+
cursor: auto;
|
|
147
|
+
}
|
|
148
|
+
::slotted(a)::after {
|
|
149
|
+
content: "";
|
|
150
|
+
position: absolute;
|
|
151
|
+
inset: 0;
|
|
152
|
+
border-radius: inherit;
|
|
153
|
+
}
|
|
154
|
+
::slotted(a) {
|
|
155
|
+
color: var(--_color);
|
|
156
|
+
font: inherit;
|
|
157
|
+
text-decoration: var(--_textDecoration);
|
|
158
|
+
text-wrap: pretty;
|
|
159
|
+
border-radius: var(--link-border-radius, var(--eun-border-radius-m, 8px));
|
|
160
|
+
transition:
|
|
161
|
+
color 0.3s ease-out,
|
|
162
|
+
background-color 0.3s ease-out,
|
|
163
|
+
text-decoration-color 0.3s ease-out;
|
|
164
|
+
}
|
|
165
|
+
::slotted(a:visited) {
|
|
166
|
+
color: var(--_colorVisited);
|
|
167
|
+
text-decoration-color: var(--_colorVisited);
|
|
168
|
+
}
|
|
169
|
+
::slotted(a:visited:hover) {
|
|
170
|
+
color: var(--_colorVisitedHover);
|
|
171
|
+
text-decoration-color: var(--_colorVisitedHover);
|
|
172
|
+
}
|
|
173
|
+
:host([visited-style="off"]) ::slotted(a:visited) {
|
|
174
|
+
color: var(--_color);
|
|
175
|
+
text-decoration-color: currentColor;
|
|
176
|
+
}
|
|
177
|
+
:host([visited-style="off"]) ::slotted(a:visited:hover) {
|
|
178
|
+
color: var(--_colorHover);
|
|
179
|
+
text-decoration-color: currentColor;
|
|
180
|
+
}
|
|
181
|
+
:host([visited-style="on"]) ::slotted(a) {
|
|
182
|
+
color: var(--_colorVisited);
|
|
183
|
+
text-decoration-color: var(--_colorVisited);
|
|
184
|
+
}
|
|
185
|
+
:host([visited-style="on"]) ::slotted(a:hover) {
|
|
186
|
+
color: var(--_colorVisitedHover);
|
|
187
|
+
text-decoration-color: var(--_colorVisitedHover);
|
|
188
|
+
}
|
|
189
|
+
::slotted(a:hover) {
|
|
190
|
+
color: var(--_colorHover);
|
|
191
|
+
}
|
|
192
|
+
#link.slotted-link:hover {
|
|
193
|
+
--icon-color: var(--link-icon-color, var(--_colorHover));
|
|
194
|
+
}
|
|
195
|
+
::slotted(a:focus-visible) {
|
|
196
|
+
color: var(--_colorHover) !important;
|
|
197
|
+
text-decoration: none;
|
|
198
|
+
outline: none !important;
|
|
199
|
+
}
|
|
200
|
+
:host(:state(focus-visible)) #link.slotted-link {
|
|
201
|
+
background: var(
|
|
202
|
+
--link-background-focus,
|
|
203
|
+
var(--link-background, transparent)
|
|
204
|
+
);
|
|
205
|
+
outline-color: var(--_colorFocus);
|
|
206
|
+
outline-offset: 2px;
|
|
207
|
+
--icon-color: var(--link-icon-color, var(--_colorHover));
|
|
208
|
+
}
|
|
209
|
+
:host([current]) ::slotted(a),
|
|
210
|
+
:host([current]) ::slotted(a:visited),
|
|
211
|
+
:host([current]) ::slotted(a:hover),
|
|
212
|
+
:host([current]) ::slotted(a:visited:hover),
|
|
213
|
+
:host([current]) ::slotted(a:focus-visible) {
|
|
214
|
+
color: var(--_colorCurrent) !important;
|
|
215
|
+
text-decoration-color: var(--_colorCurrent);
|
|
216
|
+
}
|
|
217
|
+
:host([current]) #link.slotted-link {
|
|
218
|
+
--icon-color: var(--link-icon-color, var(--_colorCurrent));
|
|
219
|
+
}
|
|
220
|
+
|
|
137
221
|
@media (prefers-reduced-motion: reduce) {
|
|
138
|
-
#link
|
|
222
|
+
#link,
|
|
223
|
+
::slotted(a) {
|
|
139
224
|
transition: none;
|
|
140
225
|
}
|
|
141
226
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Shared color palette of the button family (`eun-button`, `eun-fab`, and so
|
|
3
|
-
* `eun-dropdown-button`, which renders an `eun-button`). A `
|
|
3
|
+
* `eun-dropdown-button`, which renders an `eun-button`). A `color` fills
|
|
4
4
|
* the same slots on the host, and each component's stylesheet then reads
|
|
5
5
|
* them, per appearance and state, *behind* its public `--<component>-*`
|
|
6
|
-
* custom properties, so those always win over any
|
|
6
|
+
* custom properties, so those always win over any color and appearance.
|
|
7
7
|
*
|
|
8
8
|
* Slots :
|
|
9
9
|
* - `--_solid`, `--_solid-hover`, `--_solid-active` : the strong color, at
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
* `light` and `dark` are absolute colors : white and black, whatever the
|
|
21
21
|
* appearance. They have no pale wash, so the tinted surface is as solid as
|
|
22
22
|
* the strong one, and `flat` is a faint wash of the color itself rather than
|
|
23
|
-
* the neutral surface every other
|
|
23
|
+
* the neutral surface every other color shares. By default they follow the
|
|
24
24
|
* grey scale, which flips with the active theme ; `fixed-color` pins them to
|
|
25
25
|
* the light theme's white and black instead.
|
|
26
26
|
*/
|