@supersoniks/concorde 5.0.1 → 5.0.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/build-infos.json +1 -1
- package/concorde-core.bundle.js +519 -586
- package/concorde-core.es.js +3783 -3689
- package/dist/concorde-core.bundle.js +519 -586
- package/dist/concorde-core.es.js +3783 -3689
- package/docs/altcha-widget.js +2662 -0
- package/docs/assets/index--GpD7R7a.css +1 -0
- package/docs/assets/index-BnK6OS7w.js +12115 -0
- package/docs/crawl/core/components/functional/date/date.html +190 -0
- package/docs/crawl/core/components/functional/fetch/fetch.html +109 -0
- package/docs/crawl/core/components/functional/if/if.html +27 -0
- package/docs/crawl/core/components/functional/jsonata/jsonata.html +79 -0
- package/docs/crawl/core/components/functional/list/list.html +70 -0
- package/docs/crawl/core/components/functional/mix/mix.html +45 -0
- package/docs/crawl/core/components/functional/queue/queue.html +96 -0
- package/docs/crawl/core/components/functional/router/router.html +106 -0
- package/docs/crawl/core/components/functional/sdui/sdui.html +269 -0
- package/docs/crawl/core/components/functional/states/states.html +66 -0
- package/docs/crawl/core/components/functional/submit/submit.html +160 -0
- package/docs/crawl/core/components/functional/subscriber/subscriber.html +67 -0
- package/docs/crawl/core/components/functional/value/value.html +51 -0
- package/docs/crawl/core/components/ui/alert/alert.html +140 -0
- package/docs/crawl/core/components/ui/alert-messages/alert-messages.html +23 -0
- package/docs/crawl/core/components/ui/badge/badge.html +148 -0
- package/docs/crawl/core/components/ui/button/button.html +150 -0
- package/docs/crawl/core/components/ui/captcha/captcha.html +30 -0
- package/docs/crawl/core/components/ui/card/card.html +143 -0
- package/docs/crawl/core/components/ui/divider/divider.html +58 -0
- package/docs/crawl/core/components/ui/form/checkbox/checkbox.html +73 -0
- package/docs/crawl/core/components/ui/form/fieldset/fieldset.html +135 -0
- package/docs/crawl/core/components/ui/form/form-actions/form-actions.html +79 -0
- package/docs/crawl/core/components/ui/form/form-layout/form-layout.html +62 -0
- package/docs/crawl/core/components/ui/form/input/input.html +109 -0
- package/docs/crawl/core/components/ui/form/input-autocomplete/input-autocomplete.html +38 -0
- package/docs/crawl/core/components/ui/form/radio/radio.html +56 -0
- package/docs/crawl/core/components/ui/form/select/select.html +73 -0
- package/docs/crawl/core/components/ui/form/switch/switch.html +56 -0
- package/docs/crawl/core/components/ui/form/textarea/textarea.html +59 -0
- package/docs/crawl/core/components/ui/group/group.html +82 -0
- package/docs/crawl/core/components/ui/icon/icon.html +133 -0
- package/docs/crawl/core/components/ui/image/image.html +186 -0
- package/docs/crawl/core/components/ui/link/link.html +42 -0
- package/docs/crawl/core/components/ui/loader/loader.html +50 -0
- package/docs/crawl/core/components/ui/menu/menu.html +322 -0
- package/docs/crawl/core/components/ui/modal/modal.html +117 -0
- package/docs/crawl/core/components/ui/pop/pop.html +178 -0
- package/docs/crawl/core/components/ui/progress/progress.html +58 -0
- package/docs/crawl/core/components/ui/table/table.html +413 -0
- package/docs/crawl/core/components/ui/toast/toast.html +122 -0
- package/docs/crawl/core/components/ui/tooltip/tooltip.html +79 -0
- package/docs/crawl/docs/_core-concept/dataFlow.html +177 -0
- package/docs/crawl/docs/_core-concept/overview.html +66 -0
- package/docs/crawl/docs/_core-concept/subscriber.html +75 -0
- package/docs/crawl/docs/_decorators/ancestor-attribute.html +116 -0
- package/docs/crawl/docs/_decorators/auto-subscribe.html +202 -0
- package/docs/crawl/docs/_decorators/bind.html +141 -0
- package/docs/crawl/docs/_decorators/get.html +149 -0
- package/docs/crawl/docs/_decorators/handle.html +165 -0
- package/docs/crawl/docs/_decorators/on-assign.html +355 -0
- package/docs/crawl/docs/_decorators/patch.html +78 -0
- package/docs/crawl/docs/_decorators/post.html +139 -0
- package/docs/crawl/docs/_decorators/publish.html +61 -0
- package/docs/crawl/docs/_decorators/put.html +78 -0
- package/docs/crawl/docs/_decorators/subscribe.html +109 -0
- package/docs/crawl/docs/_decorators/wait-for-ancestors.html +137 -0
- package/docs/crawl/docs/_directives/sub.html +93 -0
- package/docs/crawl/docs/_getting-started/ai-agents.html +173 -0
- package/docs/crawl/docs/_getting-started/concorde-manual-install.html +100 -0
- package/docs/crawl/docs/_getting-started/concorde-outside.html +58 -0
- package/docs/crawl/docs/_getting-started/create-a-component.html +111 -0
- package/docs/crawl/docs/_getting-started/my-first-component.html +189 -0
- package/docs/crawl/docs/_getting-started/my-first-subscriber.html +110 -0
- package/docs/crawl/docs/_getting-started/pubsub.html +62 -0
- package/docs/crawl/docs/_getting-started/start.html +76 -0
- package/docs/crawl/docs/_getting-started/theming.html +85 -0
- package/docs/crawl/docs/_misc/api-configuration.html +149 -0
- package/docs/crawl/docs/_misc/dataProviderKey.html +135 -0
- package/docs/crawl/docs/_misc/docs-mock-api.html +158 -0
- package/docs/crawl/docs/_misc/dynamic-path.html +180 -0
- package/docs/crawl/docs/_misc/endpoint.html +50 -0
- package/docs/crawl/docs/_misc/formelement-subscriber-removal.html +138 -0
- package/docs/crawl/docs/_misc/html-integration.html +48 -0
- package/docs/crawl/hubs/decorators.html +547 -0
- package/docs/crawl/hubs/form-components.html +359 -0
- package/docs/crawl/hubs/remote-data.html +452 -0
- package/docs/crawl/index.html +101 -0
- package/docs/css/docs.css +0 -0
- package/docs/docs-mock-api-sw.js +724 -0
- package/docs/docs-mock-api-sw.js.map +7 -0
- package/docs/fonts/ClashGrotesk-Bold.eot +0 -0
- package/docs/fonts/ClashGrotesk-Bold.ttf +0 -0
- package/docs/fonts/ClashGrotesk-Bold.woff +0 -0
- package/docs/fonts/ClashGrotesk-Bold.woff2 +0 -0
- package/docs/fonts/ClashGrotesk-Extralight.eot +0 -0
- package/docs/fonts/ClashGrotesk-Extralight.ttf +0 -0
- package/docs/fonts/ClashGrotesk-Extralight.woff +0 -0
- package/docs/fonts/ClashGrotesk-Extralight.woff2 +0 -0
- package/docs/fonts/ClashGrotesk-Light.eot +0 -0
- package/docs/fonts/ClashGrotesk-Light.ttf +0 -0
- package/docs/fonts/ClashGrotesk-Light.woff +0 -0
- package/docs/fonts/ClashGrotesk-Light.woff2 +0 -0
- package/docs/fonts/ClashGrotesk-Medium.eot +0 -0
- package/docs/fonts/ClashGrotesk-Medium.ttf +0 -0
- package/docs/fonts/ClashGrotesk-Medium.woff +0 -0
- package/docs/fonts/ClashGrotesk-Medium.woff2 +0 -0
- package/docs/fonts/ClashGrotesk-Regular.eot +0 -0
- package/docs/fonts/ClashGrotesk-Regular.ttf +0 -0
- package/docs/fonts/ClashGrotesk-Regular.woff +0 -0
- package/docs/fonts/ClashGrotesk-Regular.woff2 +0 -0
- package/docs/fonts/ClashGrotesk-Semibold.eot +0 -0
- package/docs/fonts/ClashGrotesk-Semibold.ttf +0 -0
- package/docs/fonts/ClashGrotesk-Semibold.woff +0 -0
- package/docs/fonts/ClashGrotesk-Semibold.woff2 +0 -0
- package/docs/fonts/ClashGrotesk-Variable.eot +0 -0
- package/docs/fonts/ClashGrotesk-Variable.ttf +0 -0
- package/docs/fonts/ClashGrotesk-Variable.woff +0 -0
- package/docs/fonts/ClashGrotesk-Variable.woff2 +0 -0
- package/docs/img/concorde-icon.svg +5 -0
- package/docs/img/concorde-logo.svg +1 -0
- package/docs/img/concorde.png +0 -0
- package/docs/img/concorde_def.png +0 -0
- package/docs/img/concorde_seuil.png.webp +0 -0
- package/docs/img/concorde_seuil_invert.png +0 -0
- package/docs/img/paul_metrand.jpg +0 -0
- package/docs/img/paul_metrand_xs.jpg +0 -0
- package/docs/index.html +93 -0
- package/docs/llms-full.txt +5945 -0
- package/docs/llms.txt +104 -0
- package/docs/robots.txt +16 -0
- package/docs/sitemap.xml +237 -0
- package/docs/src/core/components/functional/date/date.md +290 -0
- package/docs/src/core/components/functional/fetch/fetch.md +125 -0
- package/docs/src/core/components/functional/if/if.md +9 -0
- package/docs/src/core/components/functional/jsonata/jsonata.md +56 -0
- package/docs/src/core/components/functional/list/list.md +65 -0
- package/docs/src/core/components/functional/mix/mix.md +41 -0
- package/docs/src/core/components/functional/queue/queue.md +72 -0
- package/docs/src/core/components/functional/router/router.md +94 -0
- package/docs/src/core/components/functional/sdui/default-library.json +108 -0
- package/docs/src/core/components/functional/sdui/example.json +99 -0
- package/docs/src/core/components/functional/sdui/sdui.md +356 -0
- package/docs/src/core/components/functional/states/states.md +87 -0
- package/docs/src/core/components/functional/submit/submit.md +114 -0
- package/docs/src/core/components/functional/subscriber/subscriber.md +91 -0
- package/docs/src/core/components/functional/value/value.md +35 -0
- package/docs/src/core/components/ui/alert/alert.md +177 -0
- package/docs/src/core/components/ui/alert-messages/alert-messages.md +0 -0
- package/docs/src/core/components/ui/badge/badge.md +175 -0
- package/docs/src/core/components/ui/button/button.md +183 -0
- package/docs/src/core/components/ui/captcha/captcha.md +12 -0
- package/docs/src/core/components/ui/card/card.md +152 -0
- package/docs/src/core/components/ui/divider/divider.md +35 -0
- package/docs/src/core/components/ui/form/checkbox/checkbox.md +77 -0
- package/docs/src/core/components/ui/form/fieldset/fieldset.md +129 -0
- package/docs/src/core/components/ui/form/form-actions/form-actions.md +77 -0
- package/docs/src/core/components/ui/form/form-layout/form-layout.md +44 -0
- package/docs/src/core/components/ui/form/input/input.md +142 -0
- package/docs/src/core/components/ui/form/input-autocomplete/input-autocomplete.md +29 -0
- package/docs/src/core/components/ui/form/radio/radio.md +57 -0
- package/docs/src/core/components/ui/form/select/select.md +71 -0
- package/docs/src/core/components/ui/form/switch/switch.md +57 -0
- package/docs/src/core/components/ui/form/textarea/textarea.md +65 -0
- package/docs/src/core/components/ui/group/group.md +75 -0
- package/docs/src/core/components/ui/icon/icon.md +125 -0
- package/docs/src/core/components/ui/icon/icons.json +1 -0
- package/docs/src/core/components/ui/image/image.md +201 -0
- package/docs/src/core/components/ui/link/link.md +43 -0
- package/docs/src/core/components/ui/loader/loader.md +55 -0
- package/docs/src/core/components/ui/menu/menu.md +329 -0
- package/docs/src/core/components/ui/modal/modal.md +119 -0
- package/docs/src/core/components/ui/pop/pop.md +200 -0
- package/docs/src/core/components/ui/progress/progress.md +63 -0
- package/docs/src/core/components/ui/table/table.md +455 -0
- package/docs/src/core/components/ui/toast/toast.md +166 -0
- package/docs/src/core/components/ui/tooltip/tooltip.md +82 -0
- package/docs/src/docs/_core-concept/dataFlow.md +88 -0
- package/docs/src/docs/_core-concept/overview.md +57 -0
- package/docs/src/docs/_core-concept/subscriber.md +75 -0
- package/docs/src/docs/_decorators/ancestor-attribute.md +127 -0
- package/docs/src/docs/_decorators/auto-subscribe.md +202 -0
- package/docs/src/docs/_decorators/bind.md +167 -0
- package/docs/src/docs/_decorators/get.md +162 -0
- package/docs/src/docs/_decorators/handle.md +175 -0
- package/docs/src/docs/_decorators/on-assign.md +390 -0
- package/docs/src/docs/_decorators/patch.md +70 -0
- package/docs/src/docs/_decorators/post.md +146 -0
- package/docs/src/docs/_decorators/publish.md +55 -0
- package/docs/src/docs/_decorators/put.md +70 -0
- package/docs/src/docs/_decorators/subscribe.md +100 -0
- package/docs/src/docs/_decorators/wait-for-ancestors.md +163 -0
- package/docs/src/docs/_directives/sub.md +91 -0
- package/docs/src/docs/_getting-started/ai-agents.md +76 -0
- package/docs/src/docs/_getting-started/concorde-manual-install.md +133 -0
- package/docs/src/docs/_getting-started/concorde-outside.md +33 -0
- package/docs/src/docs/_getting-started/create-a-component.md +139 -0
- package/docs/src/docs/_getting-started/my-first-component.md +236 -0
- package/docs/src/docs/_getting-started/my-first-subscriber.md +120 -0
- package/docs/src/docs/_getting-started/pubsub.md +37 -0
- package/docs/src/docs/_getting-started/start.md +47 -0
- package/docs/src/docs/_getting-started/theming.md +91 -0
- package/docs/src/docs/_misc/api-configuration.md +81 -0
- package/docs/src/docs/_misc/dataProviderKey.md +168 -0
- package/docs/src/docs/_misc/docs-mock-api.md +63 -0
- package/docs/src/docs/_misc/dynamic-path.md +71 -0
- package/docs/src/docs/_misc/endpoint.md +45 -0
- package/docs/src/docs/_misc/formelement-subscriber-removal.md +115 -0
- package/docs/src/docs/_misc/html-integration.md +15 -0
- package/docs/src/docs/search/docs-search.json +10137 -0
- package/docs/src/tag-list.json +1 -0
- package/docs/src/tsconfig-model.json +23 -0
- package/docs/src/tsconfig.json +1224 -0
- package/docs/svg/regular/plane.svg +1 -0
- package/docs/svg/solid/plane.svg +1 -0
- package/index.html +2 -2
- package/package.json +14 -1
- package/src/core/components/ui/_css/rounded.ts +36 -0
- package/src/core/components/ui/_css/type.ts +49 -0
- package/src/core/components/ui/_i18n/ui-aria-labels.ts +104 -0
- package/src/core/components/ui/alert/alert.md +128 -72
- package/src/core/components/ui/alert/alert.spec.ts +145 -0
- package/src/core/components/ui/alert/alert.ts +86 -91
- package/src/core/components/ui/alert-messages/alert-messages.ts +1 -1
- package/src/core/components/ui/badge/badge.md +126 -78
- package/src/core/components/ui/badge/badge.ts +29 -81
- package/src/core/components/ui/button/button.md +1 -0
- package/src/core/components/ui/button/button.ts +11 -8
- package/src/core/components/ui/card/card-header.ts +7 -2
- package/src/core/components/ui/card/card.md +120 -65
- package/src/core/components/ui/divider/divider.ts +4 -9
- package/src/core/components/ui/form/fieldset/legend-description.ts +1 -1
- package/src/core/components/ui/form/fieldset/legend.ts +1 -1
- package/src/core/components/ui/form/input/input.md +1 -1
- package/src/core/components/ui/form/input/input.ts +19 -15
- package/src/core/components/ui/form/textarea/textarea.md +1 -1
- package/src/core/components/ui/image/image.md +147 -53
- package/src/core/components/ui/image/image.ts +10 -44
- package/src/core/components/ui/link/link.md +2 -2
- package/src/core/components/ui/link/link.ts +42 -37
- package/src/core/components/ui/modal/modal-close.ts +8 -12
- package/src/core/components/ui/modal/modal.ts +18 -18
- package/src/core/components/ui/pop/pop.md +7 -5
- package/src/core/components/ui/pop/pop.ts +78 -38
- package/src/core/components/ui/table/table.ts +2 -8
- package/src/core/components/ui/toast/dismissed.ts +14 -0
- package/src/core/components/ui/toast/toast-item.ts +139 -91
- package/src/core/components/ui/toast/toast.ts +4 -7
- package/src/core/components/ui/tooltip/tooltip.ts +6 -8
- package/src/core/utils/LocationHandler.ts +12 -5
- package/src/core/utils/dismissed.ts +22 -0
- package/src/core/utils/positioning.spec.ts +28 -0
- package/src/core/utils/positioning.ts +19 -0
- package/src/docs/_getting-started/concorde-outside.md +3 -3
- package/src/docs/code.ts +3 -1
- package/src/docs/search/docs-search.json +541 -1
- package/src/docs/tailwind/css/tailwind.css +6 -0
- package/src/tsconfig.json +422 -383
- package/src/tsconfig.tsbuildinfo +1 -1
- package/tailwind.config.js +50 -3
|
@@ -30,29 +30,31 @@
|
|
|
30
30
|
</template>
|
|
31
31
|
</sonic-code>
|
|
32
32
|
|
|
33
|
-
Default placement is `bottom`.
|
|
33
|
+
Default placement is `bottom`. Placement is written `side-align`, like `sonic-tooltip`: `side` is `top`, `right`, `bottom` or `left`, `align` is `start`, `center` or `end`. Without `align`, content is aligned on the start of the trigger. If there is not enough room, content flips to the opposite side and stays inside the viewport.
|
|
34
|
+
|
|
35
|
+
The former space syntax (`placement="bottom center"`) still works but is deprecated.
|
|
34
36
|
|
|
35
37
|
<sonic-code>
|
|
36
38
|
<template>
|
|
37
|
-
<sonic-pop class="inline-block" placement="bottom
|
|
39
|
+
<sonic-pop class="inline-block" placement="bottom-center">
|
|
38
40
|
<sonic-button>Bottom center</sonic-button>
|
|
39
41
|
<sonic-menu slot="content">
|
|
40
42
|
<sonic-menu-item><sonic-icon library="iconoir" name="bell-notification" slot="prefix"></sonic-icon>Notifications</sonic-menu-item>
|
|
41
43
|
</sonic-menu>
|
|
42
44
|
</sonic-pop>
|
|
43
|
-
<sonic-pop class="inline-block" placement="top
|
|
45
|
+
<sonic-pop class="inline-block" placement="top-center">
|
|
44
46
|
<sonic-button>Top center</sonic-button>
|
|
45
47
|
<sonic-menu slot="content">
|
|
46
48
|
<sonic-menu-item><sonic-icon library="iconoir" name="bell-notification" slot="prefix"></sonic-icon>Notifications</sonic-menu-item>
|
|
47
49
|
</sonic-menu>
|
|
48
50
|
</sonic-pop>
|
|
49
|
-
<sonic-pop class="inline-block" placement="left
|
|
51
|
+
<sonic-pop class="inline-block" placement="left-center">
|
|
50
52
|
<sonic-button>Left center</sonic-button>
|
|
51
53
|
<sonic-menu slot="content">
|
|
52
54
|
<sonic-menu-item><sonic-icon library="iconoir" name="bell-notification" slot="prefix"></sonic-icon>Notifications</sonic-menu-item>
|
|
53
55
|
</sonic-menu>
|
|
54
56
|
</sonic-pop>
|
|
55
|
-
<sonic-pop class="inline-block" placement="right
|
|
57
|
+
<sonic-pop class="inline-block" placement="right-center">
|
|
56
58
|
<sonic-button>Right center</sonic-button>
|
|
57
59
|
<sonic-menu slot="content">
|
|
58
60
|
<sonic-menu-item><sonic-icon library="iconoir" name="bell-notification" slot="prefix"></sonic-icon>Notifications</sonic-menu-item>
|
|
@@ -7,20 +7,31 @@ import HTML, {
|
|
|
7
7
|
} from "@supersoniks/concorde/core/utils/HTML";
|
|
8
8
|
import {
|
|
9
9
|
computeFloatingPosition,
|
|
10
|
+
FloatingPlacement,
|
|
10
11
|
FloatingSide,
|
|
11
12
|
getFloatingBounds,
|
|
13
|
+
parsePlacement,
|
|
14
|
+
startFrameLoop,
|
|
12
15
|
supportsPopover,
|
|
13
16
|
} from "@supersoniks/concorde/core/utils/positioning";
|
|
14
17
|
import { Shadow, shadowable } from "../_css/shadow";
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
18
|
+
|
|
19
|
+
/** @deprecated écriture avec espace, utiliser `"bottom-center"`. */
|
|
20
|
+
type LegacyPopPlacement = `${FloatingSide} center`;
|
|
21
|
+
type PopPlacement = FloatingPlacement | LegacyPopPlacement;
|
|
22
|
+
|
|
23
|
+
let legacyPlacementWarned = false;
|
|
24
|
+
|
|
25
|
+
function normalizePopPlacement(placement: PopPlacement): FloatingPlacement {
|
|
26
|
+
if (!placement.includes(" ")) return placement as FloatingPlacement;
|
|
27
|
+
if (!legacyPlacementWarned) {
|
|
28
|
+
legacyPlacementWarned = true;
|
|
29
|
+
console.warn(
|
|
30
|
+
`[concorde] sonic-pop placement="${placement}" est déprécié, utiliser placement="${placement.replace(" ", "-")}".`,
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
return placement.replace(" ", "-") as FloatingPlacement;
|
|
34
|
+
}
|
|
24
35
|
|
|
25
36
|
const tagName = "sonic-pop";
|
|
26
37
|
|
|
@@ -108,7 +119,6 @@ export class Pop extends LitElement {
|
|
|
108
119
|
@property({ type: String, reflect: true }) shadow: Shadow = "lg";
|
|
109
120
|
|
|
110
121
|
@property({ type: String }) placement: PopPlacement = "bottom";
|
|
111
|
-
positioningRuns = false;
|
|
112
122
|
lastContentX = 0;
|
|
113
123
|
lastContentY = 0;
|
|
114
124
|
resizeObserver: ResizeObserver = new ResizeObserver(() =>
|
|
@@ -116,12 +126,9 @@ export class Pop extends LitElement {
|
|
|
116
126
|
);
|
|
117
127
|
|
|
118
128
|
@state() private triggerElement: HTMLElement | null = null;
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
this.computePosition(this.placement);
|
|
123
|
-
window.requestAnimationFrame(() => this.runPositioningLoop());
|
|
124
|
-
}
|
|
129
|
+
private stopPositioning?: () => void;
|
|
130
|
+
private hideDisplayTimeout?: ReturnType<typeof setTimeout>;
|
|
131
|
+
private pendingShow = false;
|
|
125
132
|
|
|
126
133
|
toggle(e: Event) {
|
|
127
134
|
if (this.open && this.noToggle) return;
|
|
@@ -134,12 +141,22 @@ export class Pop extends LitElement {
|
|
|
134
141
|
this.triggerElement = e.target as HTMLElement;
|
|
135
142
|
}
|
|
136
143
|
|
|
137
|
-
this.open
|
|
138
|
-
|
|
144
|
+
if (this.open) this.hide();
|
|
145
|
+
else this.show();
|
|
139
146
|
}
|
|
140
147
|
|
|
141
148
|
show() {
|
|
149
|
+
if (!this.popContent) {
|
|
150
|
+
this.pendingShow = true;
|
|
151
|
+
this.updateComplete.then(() => {
|
|
152
|
+
if (this.pendingShow) this.show();
|
|
153
|
+
});
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
this.pendingShow = false;
|
|
157
|
+
if (this.open) return;
|
|
142
158
|
if (!Pop.supportsPopover) this.setMaxZindex();
|
|
159
|
+
clearTimeout(this.hideDisplayTimeout);
|
|
143
160
|
this.popContent?.style?.removeProperty("display");
|
|
144
161
|
if (Pop.supportsPopover && !this.popContent.matches(":popover-open")) {
|
|
145
162
|
this.popContent.showPopover();
|
|
@@ -148,41 +165,50 @@ export class Pop extends LitElement {
|
|
|
148
165
|
// Pop.pops suit l'ordre d'ouverture : Escape ferme le dernier ouvert.
|
|
149
166
|
if (Pop.pops.delete(this)) Pop.pops.add(this);
|
|
150
167
|
this.popContent.setAttribute("tabindex", "0");
|
|
151
|
-
if (this.popBtn && this.popContent && !this.
|
|
152
|
-
this.positioningRuns = true;
|
|
168
|
+
if (this.popBtn && this.popContent && !this.stopPositioning) {
|
|
153
169
|
this.lastContentX = 0;
|
|
154
170
|
this.lastContentY = 0;
|
|
155
|
-
this.
|
|
171
|
+
this.stopPositioning = startFrameLoop(() =>
|
|
172
|
+
this.computePosition(this.placement),
|
|
173
|
+
);
|
|
156
174
|
}
|
|
157
175
|
this.dispatchEvent(new CustomEvent("show"));
|
|
158
176
|
}
|
|
159
177
|
|
|
160
178
|
hide() {
|
|
179
|
+
this.pendingShow = false;
|
|
180
|
+
if (!this.popContent) {
|
|
181
|
+
this.dispatchEvent(new CustomEvent("hide"));
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
161
184
|
if (!Pop.supportsPopover) this.resetZindexes();
|
|
162
185
|
if (Pop.supportsPopover && this.popContent?.matches(":popover-open")) {
|
|
163
186
|
this.popContent.hidePopover();
|
|
164
187
|
}
|
|
165
188
|
this.open = false;
|
|
166
189
|
this.popContent.setAttribute("tabindex", "-1");
|
|
167
|
-
this.
|
|
190
|
+
this.stopPositionLoop();
|
|
191
|
+
if (!Pop.supportsPopover) this.hideContentAfterTransition();
|
|
168
192
|
if (this.triggerElement) {
|
|
169
193
|
this.triggerElement.focus();
|
|
170
194
|
this.triggerElement = null;
|
|
171
195
|
}
|
|
172
|
-
Object.assign(this.popContent.style, {
|
|
173
|
-
left: `${this.lastContentX}px`,
|
|
174
|
-
top: `${this.lastContentY}px`,
|
|
175
|
-
});
|
|
176
196
|
this.dispatchEvent(new CustomEvent("hide"));
|
|
177
197
|
}
|
|
178
198
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
199
|
+
private stopPositionLoop() {
|
|
200
|
+
this.stopPositioning?.();
|
|
201
|
+
this.stopPositioning = undefined;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/** Sans display:none, le contenu masqué par opacité resterait atteignable au clavier. */
|
|
205
|
+
private hideContentAfterTransition() {
|
|
206
|
+
clearTimeout(this.hideDisplayTimeout);
|
|
207
|
+
const duration =
|
|
208
|
+
parseFloat(getComputedStyle(this.popContent).transitionDuration) * 1000;
|
|
209
|
+
this.hideDisplayTimeout = setTimeout(() => {
|
|
210
|
+
if (!this.open) this.popContent.style.display = "none";
|
|
211
|
+
}, duration || 0);
|
|
186
212
|
}
|
|
187
213
|
|
|
188
214
|
/**
|
|
@@ -226,6 +252,7 @@ export class Pop extends LitElement {
|
|
|
226
252
|
const target = path[0] as HTMLElement;
|
|
227
253
|
|
|
228
254
|
Pop.pops.forEach((pop: Pop) => {
|
|
255
|
+
if (!pop.open) return;
|
|
229
256
|
const popContainsTarget = path.includes(pop);
|
|
230
257
|
const popContentContainsTarget = path.includes(
|
|
231
258
|
pop.querySelector('[slot="content"]') as EventTarget,
|
|
@@ -247,7 +274,8 @@ export class Pop extends LitElement {
|
|
|
247
274
|
if (Pop.pops.size == 0) {
|
|
248
275
|
document.addEventListener("pointerdown", this._handleClosePop);
|
|
249
276
|
document.addEventListener("click", this._handleClosePop);
|
|
250
|
-
|
|
277
|
+
// Capture : passer avant les écouteurs Escape des ancêtres (ex. sonic-modal).
|
|
278
|
+
document.addEventListener("keydown", Pop._handleKeyDown, true);
|
|
251
279
|
}
|
|
252
280
|
Pop.pops.add(this);
|
|
253
281
|
}
|
|
@@ -264,24 +292,36 @@ export class Pop extends LitElement {
|
|
|
264
292
|
if (this.popContent) {
|
|
265
293
|
this.resizeObserver.unobserve(this.popContent);
|
|
266
294
|
}
|
|
295
|
+
this.stopPositionLoop();
|
|
296
|
+
clearTimeout(this.hideDisplayTimeout);
|
|
297
|
+
if (this.open) {
|
|
298
|
+
if (!Pop.supportsPopover) this.resetZindexes();
|
|
299
|
+
this.open = false;
|
|
300
|
+
this.triggerElement = null;
|
|
301
|
+
this.popContent?.style.setProperty("display", "none");
|
|
302
|
+
}
|
|
267
303
|
super.disconnectedCallback();
|
|
268
304
|
Pop.pops.delete(this);
|
|
269
305
|
if (Pop.pops.size == 0) {
|
|
270
306
|
document.removeEventListener("pointerdown", this._handleClosePop);
|
|
271
307
|
document.removeEventListener("click", this._handleClosePop);
|
|
272
|
-
document.removeEventListener("keydown", Pop._handleKeyDown);
|
|
308
|
+
document.removeEventListener("keydown", Pop._handleKeyDown, true);
|
|
273
309
|
}
|
|
274
310
|
}
|
|
275
311
|
|
|
276
312
|
computePosition(placement: PopPlacement) {
|
|
277
|
-
const
|
|
313
|
+
const { side, align } = parsePlacement(
|
|
314
|
+
normalizePopPlacement(placement),
|
|
315
|
+
"bottom",
|
|
316
|
+
"start",
|
|
317
|
+
);
|
|
278
318
|
const contentRect = this.popContent.getBoundingClientRect();
|
|
279
319
|
|
|
280
320
|
const { x, y } = computeFloatingPosition({
|
|
281
321
|
anchor: this.getBoundingClientRect(),
|
|
282
322
|
floating: contentRect,
|
|
283
|
-
side
|
|
284
|
-
align
|
|
323
|
+
side,
|
|
324
|
+
align,
|
|
285
325
|
bounds: getFloatingBounds(this.popContent, 5),
|
|
286
326
|
});
|
|
287
327
|
|
|
@@ -11,6 +11,7 @@ import "@supersoniks/concorde/core/components/ui/table/table-tbody";
|
|
|
11
11
|
import "@supersoniks/concorde/core/components/ui/table/table-tfoot";
|
|
12
12
|
import "@supersoniks/concorde/core/components/ui/table/table-caption";
|
|
13
13
|
import { fontSize } from "@supersoniks/concorde/core/components/ui/_css/size";
|
|
14
|
+
import { Size } from "@supersoniks/concorde/core/components/ui/_css/size";
|
|
14
15
|
|
|
15
16
|
const tagName = "sonic-table";
|
|
16
17
|
@customElement(tagName)
|
|
@@ -66,14 +67,7 @@ export class Table extends LitElement {
|
|
|
66
67
|
`,
|
|
67
68
|
];
|
|
68
69
|
|
|
69
|
-
@property({ type: String, reflect: true }) size?:
|
|
70
|
-
| "2xs"
|
|
71
|
-
| "xs"
|
|
72
|
-
| "sm"
|
|
73
|
-
| "md"
|
|
74
|
-
| "lg"
|
|
75
|
-
| "xl"
|
|
76
|
-
| "2xl";
|
|
70
|
+
@property({ type: String, reflect: true }) size?: Size;
|
|
77
71
|
@property({ type: Boolean, reflect: true }) bordered?: boolean;
|
|
78
72
|
@property({ type: Boolean, reflect: true }) rounded?: boolean;
|
|
79
73
|
@property({ type: Boolean, reflect: true }) noCustomScroll?: boolean;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isDismissed,
|
|
3
|
+
markDismissed,
|
|
4
|
+
} from "@supersoniks/concorde/core/utils/dismissed";
|
|
5
|
+
|
|
6
|
+
const storageKey = "sonic-toast-dismissed";
|
|
7
|
+
|
|
8
|
+
export function isToastDismissed(id: string | number): boolean {
|
|
9
|
+
return isDismissed(storageKey, id);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function markToastDismissed(id: string | number): void {
|
|
13
|
+
markDismissed(storageKey, id);
|
|
14
|
+
}
|
|
@@ -10,19 +10,28 @@ import { renderToastContent } from "@supersoniks/concorde/core/components/ui/toa
|
|
|
10
10
|
import { normalizeStyleSheets } from "@supersoniks/concorde/core/components/ui/modal/modal-utils";
|
|
11
11
|
import { customScroll } from "@supersoniks/concorde/core/components/ui/_css/scroll";
|
|
12
12
|
import { HTML } from "@supersoniks/concorde/utils";
|
|
13
|
+
import {
|
|
14
|
+
isToastDismissed,
|
|
15
|
+
markToastDismissed,
|
|
16
|
+
} from "@supersoniks/concorde/core/components/ui/toast/dismissed";
|
|
17
|
+
import { resolveToastCloseLabel } from "@supersoniks/concorde/core/components/ui/_i18n/ui-aria-labels";
|
|
13
18
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
import {
|
|
20
|
+
statusAriaLive,
|
|
21
|
+
statusAriaRole,
|
|
22
|
+
statusColor,
|
|
23
|
+
statusIcon,
|
|
24
|
+
toStatus,
|
|
25
|
+
} from "@supersoniks/concorde/core/components/ui/_css/type";
|
|
26
|
+
|
|
27
|
+
const AUTO_HIDE_DELAY = 6000;
|
|
20
28
|
const tagName = "sonic-toast-item";
|
|
21
29
|
|
|
22
30
|
@customElement(tagName)
|
|
23
31
|
export class SonicToastItem extends LitElement {
|
|
24
32
|
static styles = [
|
|
25
33
|
customScroll,
|
|
34
|
+
statusColor,
|
|
26
35
|
css`
|
|
27
36
|
* {
|
|
28
37
|
box-sizing: border-box;
|
|
@@ -31,7 +40,6 @@ export class SonicToastItem extends LitElement {
|
|
|
31
40
|
display: block;
|
|
32
41
|
pointer-events: auto;
|
|
33
42
|
position: relative;
|
|
34
|
-
--sc-toast-status-color: transparent;
|
|
35
43
|
--sc-toast-color: var(--sc-base-content, #000);
|
|
36
44
|
--sc-toast-bg: var(--sc-base, #fff);
|
|
37
45
|
--sc-toast-rounded: var(--sc-rounded-md);
|
|
@@ -52,14 +60,13 @@ export class SonicToastItem extends LitElement {
|
|
|
52
60
|
pointer-events: auto;
|
|
53
61
|
overflow: hidden;
|
|
54
62
|
line-height: 1.25;
|
|
55
|
-
color: var(--sc-toast-color);
|
|
56
63
|
box-shadow: var(--sc-toast-shadow);
|
|
57
64
|
border-radius: var(--sc-toast-rounded);
|
|
58
65
|
background: var(--sc-toast-bg);
|
|
59
66
|
}
|
|
60
67
|
|
|
61
68
|
.sonic-toast-content {
|
|
62
|
-
padding:
|
|
69
|
+
padding: 0.8em 2.25rem 0.8em 0.8em;
|
|
63
70
|
display: flex;
|
|
64
71
|
gap: 0.5rem;
|
|
65
72
|
overflow: auto;
|
|
@@ -67,6 +74,7 @@ export class SonicToastItem extends LitElement {
|
|
|
67
74
|
}
|
|
68
75
|
|
|
69
76
|
.sonic-toast-text {
|
|
77
|
+
color: var(--sc-toast-color);
|
|
70
78
|
align-self: center;
|
|
71
79
|
margin-top: auto;
|
|
72
80
|
margin-bottom: auto;
|
|
@@ -114,6 +122,7 @@ export class SonicToastItem extends LitElement {
|
|
|
114
122
|
border-radius: 50%;
|
|
115
123
|
text-align: center;
|
|
116
124
|
opacity: 0.5;
|
|
125
|
+
color: var(--sc-toast-color);
|
|
117
126
|
background: rgba(0, 0, 0, 0);
|
|
118
127
|
}
|
|
119
128
|
|
|
@@ -133,39 +142,21 @@ export class SonicToastItem extends LitElement {
|
|
|
133
142
|
/*Title*/
|
|
134
143
|
.sonic-toast-title {
|
|
135
144
|
font-weight: bold;
|
|
136
|
-
font-size: 1.
|
|
137
|
-
margin: 0.15em 0 0.
|
|
145
|
+
font-size: 1.125rem;
|
|
146
|
+
margin: 0.15em 0 0.15em;
|
|
138
147
|
line-height: 1.2;
|
|
139
148
|
}
|
|
140
149
|
|
|
141
|
-
/*STATUS*/
|
|
142
|
-
.
|
|
143
|
-
|
|
144
|
-
--sc-success,
|
|
145
|
-
var(--sc-base-content, #000)
|
|
146
|
-
);
|
|
150
|
+
/*STATUS — accent via statusColor (--sc-_color) */
|
|
151
|
+
:host([status]) .sonic-toast {
|
|
152
|
+
border-top: 3px solid var(--sc-_color);
|
|
147
153
|
}
|
|
148
154
|
|
|
149
|
-
.
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
--sc-toast-status-color: var(
|
|
155
|
-
--sc-warning,
|
|
156
|
-
var(--sc-base-content, #000)
|
|
157
|
-
);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
.info {
|
|
161
|
-
--sc-toast-status-color: var(--sc-info, var(--sc-base-content, #000));
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
.success,
|
|
165
|
-
.error,
|
|
166
|
-
.info,
|
|
167
|
-
.warning {
|
|
168
|
-
border-top: 3px solid var(--sc-toast-status-color, currentColor);
|
|
155
|
+
:host([status="success"]) .sonic-toast:before,
|
|
156
|
+
:host([status="error"]) .sonic-toast:before,
|
|
157
|
+
:host([status="info"]) .sonic-toast:before,
|
|
158
|
+
:host([status="warning"]) .sonic-toast:before {
|
|
159
|
+
background-color: var(--sc-_color);
|
|
169
160
|
}
|
|
170
161
|
|
|
171
162
|
.sonic-toast:before {
|
|
@@ -180,20 +171,12 @@ export class SonicToastItem extends LitElement {
|
|
|
180
171
|
pointer-events: none;
|
|
181
172
|
transition: 0.2s;
|
|
182
173
|
border-radius: var(--sc-toast-rounded);
|
|
183
|
-
background-color: var(--sc-toast-status-color);
|
|
184
174
|
}
|
|
185
175
|
|
|
186
176
|
.sonic-toast:hover:before {
|
|
187
177
|
opacity: 0.025;
|
|
188
178
|
}
|
|
189
179
|
|
|
190
|
-
.info .sonic-toast-icon,
|
|
191
|
-
.error .sonic-toast-icon,
|
|
192
|
-
.success .sonic-toast-icon,
|
|
193
|
-
.warning .sonic-toast-icon {
|
|
194
|
-
color: var(--sc-toast-status-color, currentColor);
|
|
195
|
-
}
|
|
196
|
-
|
|
197
180
|
.sonic-toast-icon {
|
|
198
181
|
position: sticky;
|
|
199
182
|
top: 0;
|
|
@@ -209,7 +192,7 @@ export class SonicToastItem extends LitElement {
|
|
|
209
192
|
@property() label: ToastContent = "";
|
|
210
193
|
@property({ type: String }) id = "";
|
|
211
194
|
@property() text: ToastContent = "";
|
|
212
|
-
@property({ type: String }) status: ToastStatus = "";
|
|
195
|
+
@property({ type: String, reflect: true }) status: ToastStatus = "";
|
|
213
196
|
@property({ type: Boolean }) ghost = false;
|
|
214
197
|
@property({ type: Boolean }) preserve = false;
|
|
215
198
|
@property({ type: Boolean }) dismissForever = false;
|
|
@@ -218,7 +201,42 @@ export class SonicToastItem extends LitElement {
|
|
|
218
201
|
@property({ attribute: false }) styleSheet?: ToastStyleSheetInput;
|
|
219
202
|
@state() visible = true;
|
|
220
203
|
@state() private _titleId: string = "";
|
|
204
|
+
@state() private _dismissed = false;
|
|
221
205
|
private _adoptedStyleSheets: Array<CSSStyleSheet> = [];
|
|
206
|
+
private _hideTimer?: ReturnType<typeof setTimeout>;
|
|
207
|
+
private _hideRemaining = AUTO_HIDE_DELAY;
|
|
208
|
+
private _hideStartedAt = 0;
|
|
209
|
+
private _hovered = false;
|
|
210
|
+
private _focused = false;
|
|
211
|
+
private _hidden = false;
|
|
212
|
+
|
|
213
|
+
connectedCallback(): void {
|
|
214
|
+
super.connectedCallback();
|
|
215
|
+
this.addEventListener("mouseenter", this._onMouseEnter);
|
|
216
|
+
this.addEventListener("mouseleave", this._onMouseLeave);
|
|
217
|
+
this.addEventListener("focusin", this._onFocusIn);
|
|
218
|
+
this.addEventListener("focusout", this._onFocusOut);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
disconnectedCallback(): void {
|
|
222
|
+
this._clearHideTimer();
|
|
223
|
+
this.removeEventListener("mouseenter", this._onMouseEnter);
|
|
224
|
+
this.removeEventListener("mouseleave", this._onMouseLeave);
|
|
225
|
+
this.removeEventListener("focusin", this._onFocusIn);
|
|
226
|
+
this.removeEventListener("focusout", this._onFocusOut);
|
|
227
|
+
super.disconnectedCallback();
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
protected willUpdate(changedProperties: PropertyValues): void {
|
|
231
|
+
if (
|
|
232
|
+
changedProperties.has("dismissForever") ||
|
|
233
|
+
changedProperties.has("id")
|
|
234
|
+
) {
|
|
235
|
+
this._dismissed =
|
|
236
|
+
this.dismissForever && !!this.id && isToastDismissed(this.id);
|
|
237
|
+
}
|
|
238
|
+
super.willUpdate(changedProperties);
|
|
239
|
+
}
|
|
222
240
|
|
|
223
241
|
// @queryAssignedElements({flatten: true, slot: main"})
|
|
224
242
|
// textSlot!: HTMLElement[];
|
|
@@ -229,7 +247,7 @@ export class SonicToastItem extends LitElement {
|
|
|
229
247
|
* - "status" pour les autres (messages informatifs)
|
|
230
248
|
*/
|
|
231
249
|
getAriaRole(): "alert" | "status" {
|
|
232
|
-
return this.status
|
|
250
|
+
return statusAriaRole(toStatus(this.status) ?? "default");
|
|
233
251
|
}
|
|
234
252
|
|
|
235
253
|
/**
|
|
@@ -238,7 +256,7 @@ export class SonicToastItem extends LitElement {
|
|
|
238
256
|
* - "polite" pour les autres (peut attendre)
|
|
239
257
|
*/
|
|
240
258
|
getAriaLive(): "polite" | null {
|
|
241
|
-
return this.status
|
|
259
|
+
return statusAriaLive(toStatus(this.status) ?? "default");
|
|
242
260
|
}
|
|
243
261
|
|
|
244
262
|
/**
|
|
@@ -254,33 +272,8 @@ export class SonicToastItem extends LitElement {
|
|
|
254
272
|
return this._titleId;
|
|
255
273
|
}
|
|
256
274
|
|
|
257
|
-
/**
|
|
258
|
-
* Génère un label ARIA descriptif pour le bouton de fermeture
|
|
259
|
-
*/
|
|
260
|
-
getCloseButtonLabel(): string {
|
|
261
|
-
const statusLabels: Record<string, string> = {
|
|
262
|
-
error: "Fermer le message d'erreur",
|
|
263
|
-
warning: "Fermer l'avertissement",
|
|
264
|
-
success: "Fermer le message de succès",
|
|
265
|
-
info: "Fermer l'information",
|
|
266
|
-
};
|
|
267
|
-
const statusLabel = this.status
|
|
268
|
-
? statusLabels[this.status] || "Fermer la notification"
|
|
269
|
-
: "Fermer la notification";
|
|
270
|
-
return statusLabel;
|
|
271
|
-
}
|
|
272
|
-
|
|
273
275
|
render() {
|
|
274
|
-
|
|
275
|
-
if (this.dismissForever) {
|
|
276
|
-
const dismissed = localStorage.getItem("sonic-toast-dismissed") || "{}";
|
|
277
|
-
const dismissedObj = JSON.parse(dismissed);
|
|
278
|
-
if (dismissedObj[this.id]) {
|
|
279
|
-
return nothing;
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
if (!this.visible) {
|
|
276
|
+
if (this._dismissed || !this.visible) {
|
|
284
277
|
return nothing;
|
|
285
278
|
}
|
|
286
279
|
|
|
@@ -295,14 +288,14 @@ export class SonicToastItem extends LitElement {
|
|
|
295
288
|
|
|
296
289
|
const ariaLive = this.getAriaLive();
|
|
297
290
|
return html`<div
|
|
298
|
-
class="sonic-toast ${this.
|
|
291
|
+
class="sonic-toast ${this.ghost ? "ghost" : ""}"
|
|
299
292
|
role=${this.getAriaRole()}
|
|
300
293
|
aria-live=${ariaLive || nothing}
|
|
301
294
|
aria-atomic="true"
|
|
302
295
|
aria-label=${ariaLabel || nothing}
|
|
303
296
|
>
|
|
304
297
|
<button
|
|
305
|
-
aria-label=${this.
|
|
298
|
+
aria-label=${resolveToastCloseLabel(this.status)}
|
|
306
299
|
class="sonic-toast-close"
|
|
307
300
|
@click=${() => this.hide()}
|
|
308
301
|
>
|
|
@@ -314,9 +307,9 @@ export class SonicToastItem extends LitElement {
|
|
|
314
307
|
>
|
|
315
308
|
${this.status &&
|
|
316
309
|
html`<sonic-icon
|
|
317
|
-
name=${
|
|
310
|
+
name=${statusIcon[toStatus(this.status) ?? "default"]}
|
|
318
311
|
class="sonic-toast-icon"
|
|
319
|
-
size="
|
|
312
|
+
size="xl"
|
|
320
313
|
aria-hidden="true"
|
|
321
314
|
></sonic-icon>`}
|
|
322
315
|
|
|
@@ -329,8 +322,6 @@ export class SonicToastItem extends LitElement {
|
|
|
329
322
|
${this.useSlot ? nothing : renderToastContent(this.text)}
|
|
330
323
|
<slot></slot>
|
|
331
324
|
</div>
|
|
332
|
-
|
|
333
|
-
${!this.preserve ? this.autoHide() : ""}
|
|
334
325
|
</div>
|
|
335
326
|
</div>`;
|
|
336
327
|
}
|
|
@@ -339,6 +330,13 @@ export class SonicToastItem extends LitElement {
|
|
|
339
330
|
if (_changedProperties.has("styleSheet")) {
|
|
340
331
|
this.syncAdoptedStyleSheets();
|
|
341
332
|
}
|
|
333
|
+
if (
|
|
334
|
+
_changedProperties.has("preserve") ||
|
|
335
|
+
_changedProperties.has("visible") ||
|
|
336
|
+
_changedProperties.has("_dismissed")
|
|
337
|
+
) {
|
|
338
|
+
this._syncHideTimer();
|
|
339
|
+
}
|
|
342
340
|
}
|
|
343
341
|
|
|
344
342
|
syncAdoptedStyleSheets() {
|
|
@@ -357,30 +355,80 @@ export class SonicToastItem extends LitElement {
|
|
|
357
355
|
}
|
|
358
356
|
|
|
359
357
|
hide() {
|
|
358
|
+
this._clearHideTimer();
|
|
359
|
+
this._hidden = true;
|
|
360
360
|
if (!HTML.getClosestElement(this, "sonic-toast")) {
|
|
361
361
|
this.visible = false;
|
|
362
362
|
}
|
|
363
363
|
|
|
364
364
|
if (this.dismissForever) {
|
|
365
|
-
|
|
366
|
-
const dismissed = localStorage.getItem("sonic-toast-dismissed") || "{}";
|
|
367
|
-
const dismissedObj = JSON.parse(dismissed);
|
|
368
|
-
dismissedObj[this.id] = true;
|
|
369
|
-
localStorage.setItem(
|
|
370
|
-
"sonic-toast-dismissed",
|
|
371
|
-
JSON.stringify(dismissedObj),
|
|
372
|
-
);
|
|
365
|
+
markToastDismissed(this.id);
|
|
373
366
|
}
|
|
374
367
|
this.dispatchEvent(new CustomEvent("hide", { bubbles: true }));
|
|
375
368
|
}
|
|
376
369
|
|
|
377
370
|
show() {
|
|
371
|
+
this._hidden = false;
|
|
372
|
+
this._hideRemaining = AUTO_HIDE_DELAY;
|
|
378
373
|
this.visible = true;
|
|
374
|
+
this._syncHideTimer();
|
|
379
375
|
}
|
|
380
376
|
|
|
381
|
-
|
|
382
|
-
|
|
377
|
+
private _syncHideTimer() {
|
|
378
|
+
const shouldRun =
|
|
379
|
+
!this.preserve &&
|
|
380
|
+
this.visible &&
|
|
381
|
+
!this._hidden &&
|
|
382
|
+
!this._dismissed &&
|
|
383
|
+
!this._hovered &&
|
|
384
|
+
!this._focused;
|
|
385
|
+
|
|
386
|
+
if (!shouldRun) {
|
|
387
|
+
this._pauseHideTimer();
|
|
388
|
+
return;
|
|
389
|
+
}
|
|
390
|
+
if (this._hideTimer) return;
|
|
391
|
+
|
|
392
|
+
this._hideStartedAt = Date.now();
|
|
393
|
+
this._hideTimer = setTimeout(() => {
|
|
394
|
+
this._hideTimer = undefined;
|
|
383
395
|
this.hide();
|
|
384
|
-
},
|
|
396
|
+
}, this._hideRemaining);
|
|
385
397
|
}
|
|
398
|
+
|
|
399
|
+
private _pauseHideTimer() {
|
|
400
|
+
if (!this._hideTimer) return;
|
|
401
|
+
clearTimeout(this._hideTimer);
|
|
402
|
+
this._hideTimer = undefined;
|
|
403
|
+
this._hideRemaining = Math.max(
|
|
404
|
+
0,
|
|
405
|
+
this._hideRemaining - (Date.now() - this._hideStartedAt),
|
|
406
|
+
);
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
private _clearHideTimer() {
|
|
410
|
+
clearTimeout(this._hideTimer);
|
|
411
|
+
this._hideTimer = undefined;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
private _onMouseEnter = () => {
|
|
415
|
+
this._hovered = true;
|
|
416
|
+
this._syncHideTimer();
|
|
417
|
+
};
|
|
418
|
+
|
|
419
|
+
private _onMouseLeave = () => {
|
|
420
|
+
this._hovered = false;
|
|
421
|
+
this._syncHideTimer();
|
|
422
|
+
};
|
|
423
|
+
|
|
424
|
+
private _onFocusIn = () => {
|
|
425
|
+
this._focused = true;
|
|
426
|
+
this._syncHideTimer();
|
|
427
|
+
};
|
|
428
|
+
|
|
429
|
+
private _onFocusOut = (e: FocusEvent) => {
|
|
430
|
+
if (this.contains(e.relatedTarget as Node | null)) return;
|
|
431
|
+
this._focused = false;
|
|
432
|
+
this._syncHideTimer();
|
|
433
|
+
};
|
|
386
434
|
}
|