kanto-ds 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +26 -0
- package/README.md +155 -0
- package/dist/assets/fonts/README.md +19 -0
- package/dist/assets/fonts/manrope/OFL.txt +93 -0
- package/dist/assets/fonts/manrope/manrope-cyrillic-ext-wght-normal.woff2 +0 -0
- package/dist/assets/fonts/manrope/manrope-cyrillic-wght-normal.woff2 +0 -0
- package/dist/assets/fonts/manrope/manrope-latin-ext-wght-normal.woff2 +0 -0
- package/dist/assets/fonts/manrope/manrope-latin-wght-normal.woff2 +0 -0
- package/dist/assets/fonts/mulish/OFL.txt +93 -0
- package/dist/assets/fonts/mulish/mulish-cyrillic-ext-wght-italic.woff2 +0 -0
- package/dist/assets/fonts/mulish/mulish-cyrillic-ext-wght-normal.woff2 +0 -0
- package/dist/assets/fonts/mulish/mulish-cyrillic-wght-italic.woff2 +0 -0
- package/dist/assets/fonts/mulish/mulish-cyrillic-wght-normal.woff2 +0 -0
- package/dist/assets/fonts/mulish/mulish-latin-ext-wght-italic.woff2 +0 -0
- package/dist/assets/fonts/mulish/mulish-latin-ext-wght-normal.woff2 +0 -0
- package/dist/assets/fonts/mulish/mulish-latin-wght-italic.woff2 +0 -0
- package/dist/assets/fonts/mulish/mulish-latin-wght-normal.woff2 +0 -0
- package/dist/assets/fonts/source_code_pro/OFL.txt +93 -0
- package/dist/assets/fonts/source_code_pro/SourceCodePro-Regular.woff2 +0 -0
- package/dist/chunks/dialog-CPIfFIlF.js +29 -0
- package/dist/chunks/dialog-CPIfFIlF.js.map +1 -0
- package/dist/chunks/events-Bjl5Zmmq.js +18 -0
- package/dist/chunks/events-Bjl5Zmmq.js.map +1 -0
- package/dist/chunks/form-control-CxjBTt1c.js +17 -0
- package/dist/chunks/form-control-CxjBTt1c.js.map +1 -0
- package/dist/chunks/kt-element-CcMLO5e8.js +28 -0
- package/dist/chunks/kt-element-CcMLO5e8.js.map +1 -0
- package/dist/chunks/listbox-CUXYn_3S.js +101 -0
- package/dist/chunks/listbox-CUXYn_3S.js.map +1 -0
- package/dist/chunks/registry-X4LS9J5K.js +30 -0
- package/dist/chunks/registry-X4LS9J5K.js.map +1 -0
- package/dist/chunks/slots-BPbIdxAJ.js +7 -0
- package/dist/chunks/slots-BPbIdxAJ.js.map +1 -0
- package/dist/chunks/toaster-PmdKSV5x.js +40 -0
- package/dist/chunks/toaster-PmdKSV5x.js.map +1 -0
- package/dist/components/core/kt-avatar/kt-avatar.d.ts +49 -0
- package/dist/components/core/kt-avatar/kt-avatar.js +156 -0
- package/dist/components/core/kt-avatar/kt-avatar.js.map +1 -0
- package/dist/components/core/kt-badge/kt-badge.d.ts +77 -0
- package/dist/components/core/kt-badge/kt-badge.js +254 -0
- package/dist/components/core/kt-badge/kt-badge.js.map +1 -0
- package/dist/components/core/kt-button/kt-button.d.ts +71 -0
- package/dist/components/core/kt-button/kt-button.js +271 -0
- package/dist/components/core/kt-button/kt-button.js.map +1 -0
- package/dist/components/core/kt-card/kt-card.d.ts +62 -0
- package/dist/components/core/kt-card/kt-card.js +230 -0
- package/dist/components/core/kt-card/kt-card.js.map +1 -0
- package/dist/components/core/kt-code/kt-code.d.ts +55 -0
- package/dist/components/core/kt-code/kt-code.js +155 -0
- package/dist/components/core/kt-code/kt-code.js.map +1 -0
- package/dist/components/core/kt-icon/kt-icon.d.ts +44 -0
- package/dist/components/core/kt-icon/kt-icon.js +85 -0
- package/dist/components/core/kt-icon/kt-icon.js.map +1 -0
- package/dist/components/core/kt-kbd/kt-kbd.d.ts +38 -0
- package/dist/components/core/kt-kbd/kt-kbd.js +89 -0
- package/dist/components/core/kt-kbd/kt-kbd.js.map +1 -0
- package/dist/components/data/kt-chart/kt-chart.d.ts +99 -0
- package/dist/components/data/kt-chart/kt-chart.js +406 -0
- package/dist/components/data/kt-chart/kt-chart.js.map +1 -0
- package/dist/components/data/kt-meter/kt-meter.d.ts +63 -0
- package/dist/components/data/kt-meter/kt-meter.js +177 -0
- package/dist/components/data/kt-meter/kt-meter.js.map +1 -0
- package/dist/components/data/kt-pagination/kt-pagination.d.ts +35 -0
- package/dist/components/data/kt-pagination/kt-pagination.js +88 -0
- package/dist/components/data/kt-pagination/kt-pagination.js.map +1 -0
- package/dist/components/data/kt-stat/kt-stat.d.ts +60 -0
- package/dist/components/data/kt-stat/kt-stat.js +137 -0
- package/dist/components/data/kt-stat/kt-stat.js.map +1 -0
- package/dist/components/data/kt-table/kt-table.d.ts +99 -0
- package/dist/components/data/kt-table/kt-table.js +340 -0
- package/dist/components/data/kt-table/kt-table.js.map +1 -0
- package/dist/components/data/kt-timeline/kt-timeline.d.ts +78 -0
- package/dist/components/data/kt-timeline/kt-timeline.js +252 -0
- package/dist/components/data/kt-timeline/kt-timeline.js.map +1 -0
- package/dist/components/feedback/kt-alert/kt-alert.d.ts +46 -0
- package/dist/components/feedback/kt-alert/kt-alert.js +180 -0
- package/dist/components/feedback/kt-alert/kt-alert.js.map +1 -0
- package/dist/components/feedback/kt-empty-state/kt-empty-state.d.ts +40 -0
- package/dist/components/feedback/kt-empty-state/kt-empty-state.js +100 -0
- package/dist/components/feedback/kt-empty-state/kt-empty-state.js.map +1 -0
- package/dist/components/feedback/kt-progress-bar/kt-progress-bar.d.ts +53 -0
- package/dist/components/feedback/kt-progress-bar/kt-progress-bar.js +212 -0
- package/dist/components/feedback/kt-progress-bar/kt-progress-bar.js.map +1 -0
- package/dist/components/feedback/kt-skeleton/kt-skeleton.d.ts +43 -0
- package/dist/components/feedback/kt-skeleton/kt-skeleton.js +117 -0
- package/dist/components/feedback/kt-skeleton/kt-skeleton.js.map +1 -0
- package/dist/components/feedback/kt-toast/kt-toast.d.ts +57 -0
- package/dist/components/feedback/kt-toast/kt-toast.js +231 -0
- package/dist/components/feedback/kt-toast/kt-toast.js.map +1 -0
- package/dist/components/feedback/kt-toast-container/kt-toast-container.d.ts +60 -0
- package/dist/components/feedback/kt-toast-container/kt-toast-container.js +100 -0
- package/dist/components/feedback/kt-toast-container/kt-toast-container.js.map +1 -0
- package/dist/components/feedback/kt-toast-container/toaster.d.ts +37 -0
- package/dist/components/feedback/kt-tooltip/kt-tooltip.d.ts +57 -0
- package/dist/components/feedback/kt-tooltip/kt-tooltip.js +138 -0
- package/dist/components/feedback/kt-tooltip/kt-tooltip.js.map +1 -0
- package/dist/components/forms/kt-drag-drop/kt-drag-drop.d.ts +68 -0
- package/dist/components/forms/kt-drag-drop/kt-drag-drop.js +287 -0
- package/dist/components/forms/kt-drag-drop/kt-drag-drop.js.map +1 -0
- package/dist/components/forms/kt-form/kt-form.d.ts +75 -0
- package/dist/components/forms/kt-form/kt-form.js +187 -0
- package/dist/components/forms/kt-form/kt-form.js.map +1 -0
- package/dist/components/forms/kt-input/kt-input.d.ts +112 -0
- package/dist/components/forms/kt-input/kt-input.js +556 -0
- package/dist/components/forms/kt-input/kt-input.js.map +1 -0
- package/dist/components/forms/kt-input-menu/kt-input-menu.d.ts +60 -0
- package/dist/components/forms/kt-input-menu/kt-input-menu.js +313 -0
- package/dist/components/forms/kt-input-menu/kt-input-menu.js.map +1 -0
- package/dist/components/forms/kt-label-input/kt-label-input.d.ts +42 -0
- package/dist/components/forms/kt-label-input/kt-label-input.js +69 -0
- package/dist/components/forms/kt-label-input/kt-label-input.js.map +1 -0
- package/dist/components/forms/kt-select/kt-select.d.ts +80 -0
- package/dist/components/forms/kt-select/kt-select.js +334 -0
- package/dist/components/forms/kt-select/kt-select.js.map +1 -0
- package/dist/components/forms/kt-textarea/kt-textarea.d.ts +62 -0
- package/dist/components/forms/kt-textarea/kt-textarea.js +239 -0
- package/dist/components/forms/kt-textarea/kt-textarea.js.map +1 -0
- package/dist/components/forms/kt-toggle/kt-toggle.d.ts +53 -0
- package/dist/components/forms/kt-toggle/kt-toggle.js +170 -0
- package/dist/components/forms/kt-toggle/kt-toggle.js.map +1 -0
- package/dist/components/navigation/kt-breadcrumb/kt-breadcrumb.d.ts +45 -0
- package/dist/components/navigation/kt-breadcrumb/kt-breadcrumb.js +93 -0
- package/dist/components/navigation/kt-breadcrumb/kt-breadcrumb.js.map +1 -0
- package/dist/components/navigation/kt-header/kt-header.d.ts +67 -0
- package/dist/components/navigation/kt-header/kt-header.js +195 -0
- package/dist/components/navigation/kt-header/kt-header.js.map +1 -0
- package/dist/components/navigation/kt-page-header/kt-page-header.d.ts +48 -0
- package/dist/components/navigation/kt-page-header/kt-page-header.js +111 -0
- package/dist/components/navigation/kt-page-header/kt-page-header.js.map +1 -0
- package/dist/components/navigation/kt-segmented-control/kt-segmented-control.d.ts +63 -0
- package/dist/components/navigation/kt-segmented-control/kt-segmented-control.js +228 -0
- package/dist/components/navigation/kt-segmented-control/kt-segmented-control.js.map +1 -0
- package/dist/components/navigation/kt-sub-menu-navigation/kt-sub-menu-navigation.d.ts +94 -0
- package/dist/components/navigation/kt-sub-menu-navigation/kt-sub-menu-navigation.js +265 -0
- package/dist/components/navigation/kt-sub-menu-navigation/kt-sub-menu-navigation.js.map +1 -0
- package/dist/components/navigation/kt-tabs/kt-tabs.d.ts +64 -0
- package/dist/components/navigation/kt-tabs/kt-tabs.js +175 -0
- package/dist/components/navigation/kt-tabs/kt-tabs.js.map +1 -0
- package/dist/components/navigation/kt-toggle-button/kt-toggle-button.d.ts +50 -0
- package/dist/components/navigation/kt-toggle-button/kt-toggle-button.js +191 -0
- package/dist/components/navigation/kt-toggle-button/kt-toggle-button.js.map +1 -0
- package/dist/components/navigation/kt-toggle-button-group/kt-toggle-button-group.d.ts +55 -0
- package/dist/components/navigation/kt-toggle-button-group/kt-toggle-button-group.js +128 -0
- package/dist/components/navigation/kt-toggle-button-group/kt-toggle-button-group.js.map +1 -0
- package/dist/components/overlays/kt-collapsible/kt-collapsible.d.ts +42 -0
- package/dist/components/overlays/kt-collapsible/kt-collapsible.js +107 -0
- package/dist/components/overlays/kt-collapsible/kt-collapsible.js.map +1 -0
- package/dist/components/overlays/kt-confirm-dialog/kt-confirm-dialog.d.ts +56 -0
- package/dist/components/overlays/kt-confirm-dialog/kt-confirm-dialog.js +155 -0
- package/dist/components/overlays/kt-confirm-dialog/kt-confirm-dialog.js.map +1 -0
- package/dist/components/overlays/kt-dropdown/kt-dropdown.d.ts +64 -0
- package/dist/components/overlays/kt-dropdown/kt-dropdown.js +212 -0
- package/dist/components/overlays/kt-dropdown/kt-dropdown.js.map +1 -0
- package/dist/components/overlays/kt-modal/kt-modal.d.ts +61 -0
- package/dist/components/overlays/kt-modal/kt-modal.js +207 -0
- package/dist/components/overlays/kt-modal/kt-modal.js.map +1 -0
- package/dist/components/overlays/kt-side-panel/kt-side-panel.d.ts +52 -0
- package/dist/components/overlays/kt-side-panel/kt-side-panel.js +178 -0
- package/dist/components/overlays/kt-side-panel/kt-side-panel.js.map +1 -0
- package/dist/icons/defaults.d.ts +25 -0
- package/dist/icons/index.d.ts +3 -0
- package/dist/icons/index.js +37 -0
- package/dist/icons/index.js.map +1 -0
- package/dist/icons/registry.d.ts +38 -0
- package/dist/index.d.ts +81 -0
- package/dist/index.js +96 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/countries.d.ts +37 -0
- package/dist/internal/dialog.d.ts +22 -0
- package/dist/internal/events.d.ts +14 -0
- package/dist/internal/form-control.d.ts +27 -0
- package/dist/internal/format.d.ts +8 -0
- package/dist/internal/kt-element.d.ts +22 -0
- package/dist/internal/listbox.d.ts +36 -0
- package/dist/internal/slots.d.ts +10 -0
- package/dist/react/index.d.ts +208 -0
- package/dist/react/index.js +314 -0
- package/dist/react/index.js.map +1 -0
- package/dist/styles.css +13 -0
- package/dist/tokens/README.md +63 -0
- package/dist/tokens/base.css +79 -0
- package/dist/tokens/colors.css +125 -0
- package/dist/tokens/fonts.css +136 -0
- package/dist/tokens/index.css +12 -0
- package/dist/tokens/responsive.css +108 -0
- package/dist/tokens/spacing.css +66 -0
- package/dist/tokens/theme-light.css +144 -0
- package/dist/tokens/typography.css +41 -0
- package/dist/vue/index.d.ts +143 -0
- package/dist/vue/index.js +56 -0
- package/dist/vue/index.js.map +1 -0
- package/package.json +296 -0
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import { css as g, nothing as n, html as o } from "lit";
|
|
2
|
+
import { state as u, property as e } from "lit/decorators.js";
|
|
3
|
+
import { K as h, d as v } from "../../../chunks/kt-element-CcMLO5e8.js";
|
|
4
|
+
import { e as m } from "../../../chunks/events-Bjl5Zmmq.js";
|
|
5
|
+
import "../../core/kt-icon/kt-icon.js";
|
|
6
|
+
import "../kt-progress-bar/kt-progress-bar.js";
|
|
7
|
+
var b = Object.defineProperty, i = (c, a, s, w) => {
|
|
8
|
+
for (var r = void 0, d = c.length - 1, l; d >= 0; d--)
|
|
9
|
+
(l = c[d]) && (r = l(a, s, r) || r);
|
|
10
|
+
return r && b(a, s, r), r;
|
|
11
|
+
};
|
|
12
|
+
const f = {
|
|
13
|
+
success: { icon: "circle-check", progress: "success" },
|
|
14
|
+
information: { icon: "info", progress: "info" },
|
|
15
|
+
warning: { icon: "triangle-alert", progress: "warning" },
|
|
16
|
+
error: { icon: "circle-alert", progress: "danger" }
|
|
17
|
+
}, p = 50;
|
|
18
|
+
class t extends h {
|
|
19
|
+
constructor() {
|
|
20
|
+
super(...arguments), this.remaining = 0, this.variant = "information", this.heading = "", this.description = "", this.dismissible = !1, this.duration = 0;
|
|
21
|
+
}
|
|
22
|
+
static {
|
|
23
|
+
this.styles = [
|
|
24
|
+
h.styles,
|
|
25
|
+
g`
|
|
26
|
+
:host {
|
|
27
|
+
display: block;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.toast {
|
|
31
|
+
position: relative;
|
|
32
|
+
display: flex;
|
|
33
|
+
align-items: flex-start;
|
|
34
|
+
justify-content: space-between;
|
|
35
|
+
gap: var(--gap-form);
|
|
36
|
+
max-width: 480px;
|
|
37
|
+
padding: var(--padding-form);
|
|
38
|
+
overflow: hidden;
|
|
39
|
+
color: var(--text-body);
|
|
40
|
+
background: var(--surface-card);
|
|
41
|
+
border: var(--border-width) solid rgba(255, 255, 255, 0.1);
|
|
42
|
+
border-radius: var(--border-radius);
|
|
43
|
+
box-shadow: var(--shadow-toast);
|
|
44
|
+
backdrop-filter: blur(10px);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/* A wash of the variant's hue over the card surface, rather than a
|
|
48
|
+
solid fill: the text stays on a neutral background and keeps its
|
|
49
|
+
contrast. */
|
|
50
|
+
:host([variant='success']) .toast {
|
|
51
|
+
background:
|
|
52
|
+
linear-gradient(135deg, rgba(53, 221, 131, 0.25), rgba(53, 221, 131, 0.15)),
|
|
53
|
+
var(--surface-card);
|
|
54
|
+
}
|
|
55
|
+
:host([variant='information']) .toast {
|
|
56
|
+
background:
|
|
57
|
+
linear-gradient(135deg, rgba(53, 175, 243, 0.25), rgba(53, 175, 243, 0.15)),
|
|
58
|
+
var(--surface-card);
|
|
59
|
+
}
|
|
60
|
+
:host([variant='warning']) .toast {
|
|
61
|
+
background:
|
|
62
|
+
linear-gradient(135deg, rgba(245, 171, 61, 0.25), rgba(245, 171, 61, 0.15)),
|
|
63
|
+
var(--surface-card);
|
|
64
|
+
}
|
|
65
|
+
:host([variant='error']) .toast {
|
|
66
|
+
background:
|
|
67
|
+
linear-gradient(135deg, rgba(245, 61, 92, 0.25), rgba(245, 61, 92, 0.15)),
|
|
68
|
+
var(--surface-card);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
:host([variant='success']) .heading {
|
|
72
|
+
color: var(--color-success-base);
|
|
73
|
+
}
|
|
74
|
+
:host([variant='information']) .heading {
|
|
75
|
+
color: var(--color-info-base);
|
|
76
|
+
}
|
|
77
|
+
:host([variant='warning']) .heading {
|
|
78
|
+
color: var(--color-warning-base);
|
|
79
|
+
}
|
|
80
|
+
:host([variant='error']) .heading {
|
|
81
|
+
color: var(--color-danger-base);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
:host([variant='success']) .icon {
|
|
85
|
+
color: var(--color-success-base);
|
|
86
|
+
}
|
|
87
|
+
:host([variant='information']) .icon {
|
|
88
|
+
color: var(--color-info-base);
|
|
89
|
+
}
|
|
90
|
+
:host([variant='warning']) .icon {
|
|
91
|
+
color: var(--color-warning-base);
|
|
92
|
+
}
|
|
93
|
+
:host([variant='error']) .icon {
|
|
94
|
+
color: var(--color-danger-base);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.body {
|
|
98
|
+
display: flex;
|
|
99
|
+
align-items: center;
|
|
100
|
+
gap: var(--gap-form);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.icon {
|
|
104
|
+
display: flex;
|
|
105
|
+
align-items: center;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.content {
|
|
109
|
+
display: flex;
|
|
110
|
+
flex: 1 1 auto;
|
|
111
|
+
flex-direction: column;
|
|
112
|
+
gap: var(--gap-element);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.heading {
|
|
116
|
+
font: var(--font-normal-medium);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.description {
|
|
120
|
+
font: var(--font-normal-regular);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.close {
|
|
124
|
+
display: flex;
|
|
125
|
+
align-items: center;
|
|
126
|
+
padding: 4px;
|
|
127
|
+
color: currentcolor;
|
|
128
|
+
background: transparent;
|
|
129
|
+
border: none;
|
|
130
|
+
border-radius: 4px;
|
|
131
|
+
cursor: pointer;
|
|
132
|
+
}
|
|
133
|
+
.close:focus-visible {
|
|
134
|
+
outline: var(--outline-width) solid var(--color-primary-base);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.countdown {
|
|
138
|
+
position: absolute;
|
|
139
|
+
bottom: 0;
|
|
140
|
+
left: 0;
|
|
141
|
+
width: 100%;
|
|
142
|
+
}
|
|
143
|
+
`
|
|
144
|
+
];
|
|
145
|
+
}
|
|
146
|
+
connectedCallback() {
|
|
147
|
+
super.connectedCallback(), this.startCountdown();
|
|
148
|
+
}
|
|
149
|
+
disconnectedCallback() {
|
|
150
|
+
super.disconnectedCallback(), this.stopCountdown();
|
|
151
|
+
}
|
|
152
|
+
startCountdown() {
|
|
153
|
+
this.stopCountdown(), !(this.duration <= 0) && (this.remaining = this.duration, this.tick());
|
|
154
|
+
}
|
|
155
|
+
/** Runs the countdown from whatever `remaining` currently is. */
|
|
156
|
+
tick() {
|
|
157
|
+
this.timer = setInterval(() => {
|
|
158
|
+
this.remaining -= p, !(this.remaining > 0) && (this.stopCountdown(), this.close());
|
|
159
|
+
}, p);
|
|
160
|
+
}
|
|
161
|
+
stopCountdown() {
|
|
162
|
+
this.timer !== void 0 && clearInterval(this.timer), this.timer = void 0;
|
|
163
|
+
}
|
|
164
|
+
/** Pauses the countdown. The container calls this while the pointer is over the stack. */
|
|
165
|
+
pause() {
|
|
166
|
+
this.timer !== void 0 && this.stopCountdown();
|
|
167
|
+
}
|
|
168
|
+
/** Resumes a paused countdown from where it stopped. */
|
|
169
|
+
resume() {
|
|
170
|
+
this.duration <= 0 || this.timer !== void 0 || this.remaining <= 0 || this.tick();
|
|
171
|
+
}
|
|
172
|
+
/** Asks to be removed. The container is what actually removes it. */
|
|
173
|
+
close() {
|
|
174
|
+
this.stopCountdown(), m(this, "kt-toast-close");
|
|
175
|
+
}
|
|
176
|
+
render() {
|
|
177
|
+
const a = f[this.variant], s = this.duration > 0;
|
|
178
|
+
return o`<div
|
|
179
|
+
part="base"
|
|
180
|
+
class="toast"
|
|
181
|
+
role=${this.variant === "error" ? "alert" : "status"}
|
|
182
|
+
aria-live=${this.variant === "error" ? "assertive" : "polite"}
|
|
183
|
+
>
|
|
184
|
+
<div class="body">
|
|
185
|
+
<span class="icon"><kt-icon name=${a.icon} size="24"></kt-icon></span>
|
|
186
|
+
<div class="content">
|
|
187
|
+
${this.heading ? o`<div class="heading">${this.heading}</div>` : n}
|
|
188
|
+
${this.description ? o`<div class="description">${this.description}</div>` : n}
|
|
189
|
+
</div>
|
|
190
|
+
</div>
|
|
191
|
+
|
|
192
|
+
${this.dismissible ? o`<button part="close" class="close" aria-label="Close" @click=${this.close}>
|
|
193
|
+
<kt-icon name="x" size="18"></kt-icon>
|
|
194
|
+
</button>` : n}
|
|
195
|
+
${s ? o`<div class="countdown">
|
|
196
|
+
<kt-progress-bar
|
|
197
|
+
size="small"
|
|
198
|
+
variant=${a.progress}
|
|
199
|
+
striped
|
|
200
|
+
animated
|
|
201
|
+
.value=${this.remaining}
|
|
202
|
+
.max=${this.duration}
|
|
203
|
+
label="Time remaining"
|
|
204
|
+
></kt-progress-bar>
|
|
205
|
+
</div>` : n}
|
|
206
|
+
</div>`;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
i([
|
|
210
|
+
u()
|
|
211
|
+
], t.prototype, "remaining");
|
|
212
|
+
i([
|
|
213
|
+
e({ type: String, reflect: !0 })
|
|
214
|
+
], t.prototype, "variant");
|
|
215
|
+
i([
|
|
216
|
+
e({ type: String })
|
|
217
|
+
], t.prototype, "heading");
|
|
218
|
+
i([
|
|
219
|
+
e({ type: String })
|
|
220
|
+
], t.prototype, "description");
|
|
221
|
+
i([
|
|
222
|
+
e({ type: Boolean })
|
|
223
|
+
], t.prototype, "dismissible");
|
|
224
|
+
i([
|
|
225
|
+
e({ type: Number })
|
|
226
|
+
], t.prototype, "duration");
|
|
227
|
+
v("kt-toast", t);
|
|
228
|
+
export {
|
|
229
|
+
t as KtToast
|
|
230
|
+
};
|
|
231
|
+
//# sourceMappingURL=kt-toast.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kt-toast.js","sources":["../../../../src/components/feedback/kt-toast/kt-toast.ts"],"sourcesContent":["import { css, html, nothing, type TemplateResult } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { KtElement, defineElement } from '#internal/kt-element';\nimport { emit } from '#internal/events';\nimport '../../core/kt-icon/kt-icon.js';\nimport '../kt-progress-bar/kt-progress-bar.js';\n\nexport type KtToastVariant = 'success' | 'information' | 'warning' | 'error';\n\ninterface VariantMeta {\n readonly icon: string;\n readonly progress: 'success' | 'info' | 'warning' | 'danger';\n}\n\nconst META: Record<KtToastVariant, VariantMeta> = {\n success: { icon: 'circle-check', progress: 'success' },\n information: { icon: 'info', progress: 'info' },\n warning: { icon: 'triangle-alert', progress: 'warning' },\n error: { icon: 'circle-alert', progress: 'danger' },\n};\n\n/** Countdown refresh interval. 50ms is smooth without being a busy loop. */\nconst TICK_MS = 50;\n\n/**\n * A transient notification.\n *\n * The only element in Kanto with a real shadow, and the only one that blurs\n * what is behind it: a toast floats above the page, so it has to say so.\n *\n * @element kt-toast\n *\n * @csspart base - The toast surface.\n * @csspart close - The dismiss button.\n *\n * @fires kt-toast-close - The toast asked to be removed, by timeout or by the\n * dismiss button. `<kt-toast-container>` listens for this.\n */\nexport class KtToast extends KtElement {\n static override styles = [\n KtElement.styles,\n css`\n :host {\n display: block;\n }\n\n .toast {\n position: relative;\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: var(--gap-form);\n max-width: 480px;\n padding: var(--padding-form);\n overflow: hidden;\n color: var(--text-body);\n background: var(--surface-card);\n border: var(--border-width) solid rgba(255, 255, 255, 0.1);\n border-radius: var(--border-radius);\n box-shadow: var(--shadow-toast);\n backdrop-filter: blur(10px);\n }\n\n /* A wash of the variant's hue over the card surface, rather than a\n solid fill: the text stays on a neutral background and keeps its\n contrast. */\n :host([variant='success']) .toast {\n background:\n linear-gradient(135deg, rgba(53, 221, 131, 0.25), rgba(53, 221, 131, 0.15)),\n var(--surface-card);\n }\n :host([variant='information']) .toast {\n background:\n linear-gradient(135deg, rgba(53, 175, 243, 0.25), rgba(53, 175, 243, 0.15)),\n var(--surface-card);\n }\n :host([variant='warning']) .toast {\n background:\n linear-gradient(135deg, rgba(245, 171, 61, 0.25), rgba(245, 171, 61, 0.15)),\n var(--surface-card);\n }\n :host([variant='error']) .toast {\n background:\n linear-gradient(135deg, rgba(245, 61, 92, 0.25), rgba(245, 61, 92, 0.15)),\n var(--surface-card);\n }\n\n :host([variant='success']) .heading {\n color: var(--color-success-base);\n }\n :host([variant='information']) .heading {\n color: var(--color-info-base);\n }\n :host([variant='warning']) .heading {\n color: var(--color-warning-base);\n }\n :host([variant='error']) .heading {\n color: var(--color-danger-base);\n }\n\n :host([variant='success']) .icon {\n color: var(--color-success-base);\n }\n :host([variant='information']) .icon {\n color: var(--color-info-base);\n }\n :host([variant='warning']) .icon {\n color: var(--color-warning-base);\n }\n :host([variant='error']) .icon {\n color: var(--color-danger-base);\n }\n\n .body {\n display: flex;\n align-items: center;\n gap: var(--gap-form);\n }\n\n .icon {\n display: flex;\n align-items: center;\n }\n\n .content {\n display: flex;\n flex: 1 1 auto;\n flex-direction: column;\n gap: var(--gap-element);\n }\n\n .heading {\n font: var(--font-normal-medium);\n }\n\n .description {\n font: var(--font-normal-regular);\n }\n\n .close {\n display: flex;\n align-items: center;\n padding: 4px;\n color: currentcolor;\n background: transparent;\n border: none;\n border-radius: 4px;\n cursor: pointer;\n }\n .close:focus-visible {\n outline: var(--outline-width) solid var(--color-primary-base);\n }\n\n .countdown {\n position: absolute;\n bottom: 0;\n left: 0;\n width: 100%;\n }\n `,\n ];\n\n private timer: ReturnType<typeof setInterval> | undefined;\n\n @state()\n private remaining = 0;\n\n @property({ type: String, reflect: true })\n variant: KtToastVariant = 'information';\n\n /**\n * The toast's title.\n *\n * Named `heading` because every element already has a `title`, and shadowing\n * it would turn the toast into its own tooltip.\n */\n @property({ type: String })\n heading = '';\n\n @property({ type: String })\n description = '';\n\n @property({ type: Boolean })\n dismissible = false;\n\n /**\n * Auto-dismiss after this many milliseconds, with a countdown bar. Zero\n * keeps the toast until something removes it.\n */\n @property({ type: Number })\n duration = 0;\n\n override connectedCallback(): void {\n super.connectedCallback();\n this.startCountdown();\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.stopCountdown();\n }\n\n private startCountdown(): void {\n this.stopCountdown();\n if (this.duration <= 0) return;\n\n this.remaining = this.duration;\n this.tick();\n }\n\n /** Runs the countdown from whatever `remaining` currently is. */\n private tick(): void {\n this.timer = setInterval(() => {\n this.remaining -= TICK_MS;\n if (this.remaining > 0) return;\n\n this.stopCountdown();\n this.close();\n }, TICK_MS);\n }\n\n private stopCountdown(): void {\n if (this.timer !== undefined) clearInterval(this.timer);\n this.timer = undefined;\n }\n\n /** Pauses the countdown. The container calls this while the pointer is over the stack. */\n pause(): void {\n if (this.timer !== undefined) this.stopCountdown();\n }\n\n /** Resumes a paused countdown from where it stopped. */\n resume(): void {\n if (this.duration <= 0 || this.timer !== undefined || this.remaining <= 0) return;\n this.tick();\n }\n\n /** Asks to be removed. The container is what actually removes it. */\n close(): void {\n this.stopCountdown();\n emit(this, 'kt-toast-close');\n }\n\n override render(): TemplateResult {\n const meta = META[this.variant];\n const showCountdown = this.duration > 0;\n\n return html`<div\n part=\"base\"\n class=\"toast\"\n role=${this.variant === 'error' ? 'alert' : 'status'}\n aria-live=${this.variant === 'error' ? 'assertive' : 'polite'}\n >\n <div class=\"body\">\n <span class=\"icon\"><kt-icon name=${meta.icon} size=\"24\"></kt-icon></span>\n <div class=\"content\">\n ${this.heading ? html`<div class=\"heading\">${this.heading}</div>` : nothing}\n ${this.description ? html`<div class=\"description\">${this.description}</div>` : nothing}\n </div>\n </div>\n\n ${\n this.dismissible\n ? html`<button part=\"close\" class=\"close\" aria-label=\"Close\" @click=${this.close}>\n <kt-icon name=\"x\" size=\"18\"></kt-icon>\n </button>`\n : nothing\n }\n ${\n showCountdown\n ? html`<div class=\"countdown\">\n <kt-progress-bar\n size=\"small\"\n variant=${meta.progress}\n striped\n animated\n .value=${this.remaining}\n .max=${this.duration}\n label=\"Time remaining\"\n ></kt-progress-bar>\n </div>`\n : nothing\n }\n </div>`;\n }\n}\n\ndefineElement('kt-toast', KtToast);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'kt-toast': KtToast;\n }\n}\n"],"names":["META","TICK_MS","KtToast","KtElement","css","emit","meta","showCountdown","html","nothing","__decorateClass","state","property","defineElement"],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { type TemplateResult } from 'lit';
|
|
2
|
+
import { KtElement } from '#internal/kt-element';
|
|
3
|
+
import type { KtToast, KtToastVariant } from '../kt-toast/kt-toast.js';
|
|
4
|
+
import '../kt-toast/kt-toast.js';
|
|
5
|
+
export type KtToastPosition = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
|
|
6
|
+
export interface KtToastOptions {
|
|
7
|
+
readonly variant?: KtToastVariant;
|
|
8
|
+
readonly heading?: string;
|
|
9
|
+
readonly description?: string;
|
|
10
|
+
readonly dismissible?: boolean;
|
|
11
|
+
/** Milliseconds before it dismisses itself. Zero keeps it until closed. */
|
|
12
|
+
readonly duration?: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* A fixed stack that owns the toasts on screen.
|
|
16
|
+
*
|
|
17
|
+
* Toasts are appended and removed by the container, not by the code that
|
|
18
|
+
* raised them — a toast that removes itself from a list it does not own is how
|
|
19
|
+
* you end up with two of them and neither disappearing.
|
|
20
|
+
*
|
|
21
|
+
* @element kt-toast-container
|
|
22
|
+
*
|
|
23
|
+
* @slot - The toasts. Usually filled by `show()` rather than by hand.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```js
|
|
27
|
+
* document.querySelector('kt-toast-container').show({
|
|
28
|
+
* variant: 'success',
|
|
29
|
+
* heading: 'Entity created',
|
|
30
|
+
* duration: 4000,
|
|
31
|
+
* dismissible: true,
|
|
32
|
+
* });
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export declare class KtToastContainer extends KtElement {
|
|
36
|
+
static styles: import("lit").CSSResultGroup[];
|
|
37
|
+
position: KtToastPosition;
|
|
38
|
+
/** Oldest toasts are dropped once the stack reaches this many. */
|
|
39
|
+
limit: number;
|
|
40
|
+
/** The toasts currently on screen, oldest first. */
|
|
41
|
+
get toasts(): KtToast[];
|
|
42
|
+
/** Raises a toast and returns it, so a caller can close it early. */
|
|
43
|
+
show(options?: KtToastOptions): KtToast;
|
|
44
|
+
/** Removes one toast. */
|
|
45
|
+
dismiss(toast: KtToast): void;
|
|
46
|
+
/** Removes every toast. */
|
|
47
|
+
clear(): void;
|
|
48
|
+
private enforceLimit;
|
|
49
|
+
/** Hovering the stack freezes every countdown; leaving it resumes them. */
|
|
50
|
+
private pauseAll;
|
|
51
|
+
private resumeAll;
|
|
52
|
+
connectedCallback(): void;
|
|
53
|
+
disconnectedCallback(): void;
|
|
54
|
+
render(): TemplateResult;
|
|
55
|
+
}
|
|
56
|
+
declare global {
|
|
57
|
+
interface HTMLElementTagNameMap {
|
|
58
|
+
'kt-toast-container': KtToastContainer;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { css as c, html as m } from "lit";
|
|
2
|
+
import { property as p } from "lit/decorators.js";
|
|
3
|
+
import { K as l, d } from "../../../chunks/kt-element-CcMLO5e8.js";
|
|
4
|
+
import "../kt-toast/kt-toast.js";
|
|
5
|
+
var f = Object.defineProperty, h = (i, t, e, n) => {
|
|
6
|
+
for (var s = void 0, o = i.length - 1, a; o >= 0; o--)
|
|
7
|
+
(a = i[o]) && (s = a(t, e, s) || s);
|
|
8
|
+
return s && f(t, e, s), s;
|
|
9
|
+
};
|
|
10
|
+
class r extends l {
|
|
11
|
+
constructor() {
|
|
12
|
+
super(...arguments), this.position = "bottom-right", this.limit = 5, this.pauseAll = () => {
|
|
13
|
+
for (const t of this.toasts) t.pause();
|
|
14
|
+
}, this.resumeAll = () => {
|
|
15
|
+
for (const t of this.toasts) t.resume();
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
static {
|
|
19
|
+
this.styles = [
|
|
20
|
+
l.styles,
|
|
21
|
+
c`
|
|
22
|
+
:host {
|
|
23
|
+
position: fixed;
|
|
24
|
+
z-index: var(--z-toast);
|
|
25
|
+
display: flex;
|
|
26
|
+
flex-direction: column;
|
|
27
|
+
gap: 12px;
|
|
28
|
+
/* The stack only intercepts pointer events over the toasts
|
|
29
|
+
themselves; the rest of the corner stays clickable. */
|
|
30
|
+
pointer-events: none;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
:host([position='bottom-right']) {
|
|
34
|
+
right: 24px;
|
|
35
|
+
bottom: 24px;
|
|
36
|
+
align-items: flex-end;
|
|
37
|
+
}
|
|
38
|
+
:host([position='top-right']) {
|
|
39
|
+
top: 24px;
|
|
40
|
+
right: 24px;
|
|
41
|
+
align-items: flex-end;
|
|
42
|
+
}
|
|
43
|
+
:host([position='bottom-left']) {
|
|
44
|
+
bottom: 24px;
|
|
45
|
+
left: 24px;
|
|
46
|
+
}
|
|
47
|
+
:host([position='top-left']) {
|
|
48
|
+
top: 24px;
|
|
49
|
+
left: 24px;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
::slotted(kt-toast) {
|
|
53
|
+
pointer-events: auto;
|
|
54
|
+
}
|
|
55
|
+
`
|
|
56
|
+
];
|
|
57
|
+
}
|
|
58
|
+
/** The toasts currently on screen, oldest first. */
|
|
59
|
+
get toasts() {
|
|
60
|
+
return [...this.querySelectorAll("kt-toast")];
|
|
61
|
+
}
|
|
62
|
+
/** Raises a toast and returns it, so a caller can close it early. */
|
|
63
|
+
show(t = {}) {
|
|
64
|
+
const e = document.createElement("kt-toast");
|
|
65
|
+
return e.variant = t.variant ?? "information", e.heading = t.heading ?? "", e.description = t.description ?? "", e.dismissible = t.dismissible ?? !0, e.duration = t.duration ?? 0, e.addEventListener("kt-toast-close", () => this.dismiss(e), { once: !0 }), this.position.startsWith("top") ? this.prepend(e) : this.append(e), this.enforceLimit(), e;
|
|
66
|
+
}
|
|
67
|
+
/** Removes one toast. */
|
|
68
|
+
dismiss(t) {
|
|
69
|
+
t.remove();
|
|
70
|
+
}
|
|
71
|
+
/** Removes every toast. */
|
|
72
|
+
clear() {
|
|
73
|
+
for (const t of this.toasts) t.remove();
|
|
74
|
+
}
|
|
75
|
+
enforceLimit() {
|
|
76
|
+
if (this.limit <= 0) return;
|
|
77
|
+
const t = this.toasts, e = t.length - this.limit, n = this.position.startsWith("top") ? [...t].reverse() : t;
|
|
78
|
+
for (let s = 0; s < e; s += 1) n[s]?.remove();
|
|
79
|
+
}
|
|
80
|
+
connectedCallback() {
|
|
81
|
+
super.connectedCallback(), this.addEventListener("pointerenter", this.pauseAll), this.addEventListener("pointerleave", this.resumeAll);
|
|
82
|
+
}
|
|
83
|
+
disconnectedCallback() {
|
|
84
|
+
super.disconnectedCallback(), this.removeEventListener("pointerenter", this.pauseAll), this.removeEventListener("pointerleave", this.resumeAll);
|
|
85
|
+
}
|
|
86
|
+
render() {
|
|
87
|
+
return m`<slot></slot>`;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
h([
|
|
91
|
+
p({ type: String, reflect: !0 })
|
|
92
|
+
], r.prototype, "position");
|
|
93
|
+
h([
|
|
94
|
+
p({ type: Number })
|
|
95
|
+
], r.prototype, "limit");
|
|
96
|
+
d("kt-toast-container", r);
|
|
97
|
+
export {
|
|
98
|
+
r as KtToastContainer
|
|
99
|
+
};
|
|
100
|
+
//# sourceMappingURL=kt-toast-container.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kt-toast-container.js","sources":["../../../../src/components/feedback/kt-toast-container/kt-toast-container.ts"],"sourcesContent":["import { css, html, type TemplateResult } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { KtElement, defineElement } from '#internal/kt-element';\nimport type { KtToast, KtToastVariant } from '../kt-toast/kt-toast.js';\nimport '../kt-toast/kt-toast.js';\n\nexport type KtToastPosition = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';\n\nexport interface KtToastOptions {\n readonly variant?: KtToastVariant;\n readonly heading?: string;\n readonly description?: string;\n readonly dismissible?: boolean;\n /** Milliseconds before it dismisses itself. Zero keeps it until closed. */\n readonly duration?: number;\n}\n\n/**\n * A fixed stack that owns the toasts on screen.\n *\n * Toasts are appended and removed by the container, not by the code that\n * raised them — a toast that removes itself from a list it does not own is how\n * you end up with two of them and neither disappearing.\n *\n * @element kt-toast-container\n *\n * @slot - The toasts. Usually filled by `show()` rather than by hand.\n *\n * @example\n * ```js\n * document.querySelector('kt-toast-container').show({\n * variant: 'success',\n * heading: 'Entity created',\n * duration: 4000,\n * dismissible: true,\n * });\n * ```\n */\nexport class KtToastContainer extends KtElement {\n static override styles = [\n KtElement.styles,\n css`\n :host {\n position: fixed;\n z-index: var(--z-toast);\n display: flex;\n flex-direction: column;\n gap: 12px;\n /* The stack only intercepts pointer events over the toasts\n themselves; the rest of the corner stays clickable. */\n pointer-events: none;\n }\n\n :host([position='bottom-right']) {\n right: 24px;\n bottom: 24px;\n align-items: flex-end;\n }\n :host([position='top-right']) {\n top: 24px;\n right: 24px;\n align-items: flex-end;\n }\n :host([position='bottom-left']) {\n bottom: 24px;\n left: 24px;\n }\n :host([position='top-left']) {\n top: 24px;\n left: 24px;\n }\n\n ::slotted(kt-toast) {\n pointer-events: auto;\n }\n `,\n ];\n\n @property({ type: String, reflect: true })\n position: KtToastPosition = 'bottom-right';\n\n /** Oldest toasts are dropped once the stack reaches this many. */\n @property({ type: Number })\n limit = 5;\n\n /** The toasts currently on screen, oldest first. */\n get toasts(): KtToast[] {\n return [...this.querySelectorAll('kt-toast')];\n }\n\n /** Raises a toast and returns it, so a caller can close it early. */\n show(options: KtToastOptions = {}): KtToast {\n const toast = document.createElement('kt-toast');\n toast.variant = options.variant ?? 'information';\n toast.heading = options.heading ?? '';\n toast.description = options.description ?? '';\n toast.dismissible = options.dismissible ?? true;\n toast.duration = options.duration ?? 0;\n\n toast.addEventListener('kt-toast-close', () => this.dismiss(toast), { once: true });\n\n // Toasts stack towards the screen edge: newest nearest it, which for a\n // bottom-anchored stack means appending and for a top-anchored one means\n // prepending.\n if (this.position.startsWith('top')) this.prepend(toast);\n else this.append(toast);\n\n this.enforceLimit();\n return toast;\n }\n\n /** Removes one toast. */\n dismiss(toast: KtToast): void {\n toast.remove();\n }\n\n /** Removes every toast. */\n clear(): void {\n for (const toast of this.toasts) toast.remove();\n }\n\n private enforceLimit(): void {\n if (this.limit <= 0) return;\n\n const toasts = this.toasts;\n const excess = toasts.length - this.limit;\n const oldestFirst = this.position.startsWith('top') ? [...toasts].reverse() : toasts;\n\n for (let index = 0; index < excess; index += 1) oldestFirst[index]?.remove();\n }\n\n /** Hovering the stack freezes every countdown; leaving it resumes them. */\n private pauseAll = (): void => {\n for (const toast of this.toasts) toast.pause();\n };\n\n private resumeAll = (): void => {\n for (const toast of this.toasts) toast.resume();\n };\n\n override connectedCallback(): void {\n super.connectedCallback();\n this.addEventListener('pointerenter', this.pauseAll);\n this.addEventListener('pointerleave', this.resumeAll);\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.removeEventListener('pointerenter', this.pauseAll);\n this.removeEventListener('pointerleave', this.resumeAll);\n }\n\n override render(): TemplateResult {\n return html`<slot></slot>`;\n }\n}\n\ndefineElement('kt-toast-container', KtToastContainer);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'kt-toast-container': KtToastContainer;\n }\n}\n"],"names":["KtToastContainer","KtElement","toast","css","options","toasts","excess","oldestFirst","index","html","__decorateClass","property","defineElement"],"mappings":";;;;;;;;;AAsCO,MAAMA,UAAyBC,EAAU;AAAA,EAAzC,cAAA;AAAA,UAAA,GAAA,SAAA,GAyCL,KAAA,WAA4B,gBAI5B,KAAA,QAAQ,GAiDR,KAAQ,WAAW,MAAY;AAC7B,iBAAWC,KAAS,KAAK,OAAQ,CAAAA,EAAM,MAAA;AAAA,IACzC,GAEA,KAAQ,YAAY,MAAY;AAC9B,iBAAWA,KAAS,KAAK,OAAQ,CAAAA,EAAM,OAAA;AAAA,IACzC;AAAA,EAAA;AAAA,EAnGA,OAAA;AAAA,SAAgB,SAAS;AAAA,MACvBD,EAAU;AAAA,MACVE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAA;AAAA,EAmCF;AAAA;AAAA,EAUA,IAAI,SAAoB;AACtB,WAAO,CAAC,GAAG,KAAK,iBAAiB,UAAU,CAAC;AAAA,EAC9C;AAAA;AAAA,EAGA,KAAKC,IAA0B,IAAa;AAC1C,UAAMF,IAAQ,SAAS,cAAc,UAAU;AAC/C,WAAAA,EAAM,UAAUE,EAAQ,WAAW,eACnCF,EAAM,UAAUE,EAAQ,WAAW,IACnCF,EAAM,cAAcE,EAAQ,eAAe,IAC3CF,EAAM,cAAcE,EAAQ,eAAe,IAC3CF,EAAM,WAAWE,EAAQ,YAAY,GAErCF,EAAM,iBAAiB,kBAAkB,MAAM,KAAK,QAAQA,CAAK,GAAG,EAAE,MAAM,IAAM,GAK9E,KAAK,SAAS,WAAW,KAAK,IAAG,KAAK,QAAQA,CAAK,IAClD,KAAK,OAAOA,CAAK,GAEtB,KAAK,aAAA,GACEA;AAAA,EACT;AAAA;AAAA,EAGA,QAAQA,GAAsB;AAC5B,IAAAA,EAAM,OAAA;AAAA,EACR;AAAA;AAAA,EAGA,QAAc;AACZ,eAAWA,KAAS,KAAK,OAAQ,CAAAA,EAAM,OAAA;AAAA,EACzC;AAAA,EAEQ,eAAqB;AAC3B,QAAI,KAAK,SAAS,EAAG;AAErB,UAAMG,IAAS,KAAK,QACdC,IAASD,EAAO,SAAS,KAAK,OAC9BE,IAAc,KAAK,SAAS,WAAW,KAAK,IAAI,CAAC,GAAGF,CAAM,EAAE,QAAA,IAAYA;AAE9E,aAASG,IAAQ,GAAGA,IAAQF,GAAQE,KAAS,EAAG,CAAAD,EAAYC,CAAK,GAAG,OAAA;AAAA,EACtE;AAAA,EAWS,oBAA0B;AACjC,UAAM,kBAAA,GACN,KAAK,iBAAiB,gBAAgB,KAAK,QAAQ,GACnD,KAAK,iBAAiB,gBAAgB,KAAK,SAAS;AAAA,EACtD;AAAA,EAES,uBAA6B;AACpC,UAAM,qBAAA,GACN,KAAK,oBAAoB,gBAAgB,KAAK,QAAQ,GACtD,KAAK,oBAAoB,gBAAgB,KAAK,SAAS;AAAA,EACzD;AAAA,EAES,SAAyB;AAChC,WAAOC;AAAA,EACT;AACF;AA5EEC,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,QAAQ,SAAS,IAAM;AAAA,GAxC9BX,EAyCX,WAAA,UAAA;AAIAU,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GA5CfX,EA6CX,WAAA,OAAA;AA0EFY,EAAc,sBAAsBZ,CAAgB;"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { KtToastContainer, type KtToastOptions, type KtToastPosition } from '../kt-toast-container/kt-toast-container.js';
|
|
2
|
+
import type { KtToast } from '../kt-toast/kt-toast.js';
|
|
3
|
+
import '../kt-toast-container/kt-toast-container.js';
|
|
4
|
+
/**
|
|
5
|
+
* The imperative way to raise a toast, for the many places where reaching a
|
|
6
|
+
* container element is inconvenient — an interceptor, a store, a catch block.
|
|
7
|
+
*
|
|
8
|
+
* It lazily creates one `<kt-toast-container>` on `<body>` and reuses it.
|
|
9
|
+
*
|
|
10
|
+
* ```js
|
|
11
|
+
* import { toaster } from 'kanto-ds';
|
|
12
|
+
*
|
|
13
|
+
* toaster.success('Entity created');
|
|
14
|
+
* toaster.error('Could not save', { description: 'Try again in a moment.' });
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* Prefer placing a `<kt-toast-container>` in your own markup when you care
|
|
18
|
+
* where in the DOM it lives — inside a dialog, or scoped to one region.
|
|
19
|
+
*/
|
|
20
|
+
declare class Toaster {
|
|
21
|
+
private container;
|
|
22
|
+
/** Where the auto-created container sits. Changing it moves the stack. */
|
|
23
|
+
position: KtToastPosition;
|
|
24
|
+
/** The container in use, created on first call. */
|
|
25
|
+
getContainer(): KtToastContainer;
|
|
26
|
+
show(options: KtToastOptions): KtToast;
|
|
27
|
+
success(heading: string, options?: Omit<KtToastOptions, 'variant' | 'heading'>): KtToast;
|
|
28
|
+
info(heading: string, options?: Omit<KtToastOptions, 'variant' | 'heading'>): KtToast;
|
|
29
|
+
warning(heading: string, options?: Omit<KtToastOptions, 'variant' | 'heading'>): KtToast;
|
|
30
|
+
/** Errors do not dismiss themselves: the user has to see this one. */
|
|
31
|
+
error(heading: string, options?: Omit<KtToastOptions, 'variant' | 'heading'>): KtToast;
|
|
32
|
+
/** Clears the stack. */
|
|
33
|
+
clear(): void;
|
|
34
|
+
}
|
|
35
|
+
/** The shared toaster. */
|
|
36
|
+
export declare const toaster: Toaster;
|
|
37
|
+
export {};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { type PropertyValues, type TemplateResult } from 'lit';
|
|
2
|
+
import { KtElement } from '#internal/kt-element';
|
|
3
|
+
export type KtTooltipPlacement = 'top' | 'bottom' | 'left' | 'right';
|
|
4
|
+
/**
|
|
5
|
+
* A short label that appears on hover or focus.
|
|
6
|
+
*
|
|
7
|
+
* Wrap the thing it describes:
|
|
8
|
+
*
|
|
9
|
+
* ```html
|
|
10
|
+
* <kt-tooltip text="Refresh the data">
|
|
11
|
+
* <kt-button icon="refresh-cw" label="Refresh"></kt-button>
|
|
12
|
+
* </kt-tooltip>
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* A tooltip is a *description*, never the only name of a control. If the
|
|
16
|
+
* trigger has no visible text, give it its own `label` too — a tooltip that has
|
|
17
|
+
* to be hovered to be read leaves touch and screen-reader users with nothing.
|
|
18
|
+
*
|
|
19
|
+
* @element kt-tooltip
|
|
20
|
+
*
|
|
21
|
+
* @slot - The trigger.
|
|
22
|
+
*
|
|
23
|
+
* @csspart bubble - The tooltip bubble.
|
|
24
|
+
*/
|
|
25
|
+
export declare class KtTooltip extends KtElement {
|
|
26
|
+
static styles: import("lit").CSSResultGroup[];
|
|
27
|
+
private readonly descriptionId;
|
|
28
|
+
private description;
|
|
29
|
+
private visible;
|
|
30
|
+
text: string;
|
|
31
|
+
placement: KtTooltipPlacement;
|
|
32
|
+
/** Suppresses the tooltip without removing it from the markup. */
|
|
33
|
+
disabled: boolean;
|
|
34
|
+
connectedCallback(): void;
|
|
35
|
+
disconnectedCallback(): void;
|
|
36
|
+
willUpdate(changed: PropertyValues<this>): void;
|
|
37
|
+
/**
|
|
38
|
+
* `aria-describedby` cannot reach across a shadow boundary: an id inside this
|
|
39
|
+
* element's shadow root is invisible to a trigger sitting in the light DOM.
|
|
40
|
+
*
|
|
41
|
+
* So the description also exists as a light-DOM node, addressed to a slot
|
|
42
|
+
* that does not exist — which keeps it out of the rendered output while
|
|
43
|
+
* leaving it referenceable, since an explicit aria-describedby target is read
|
|
44
|
+
* even when it is not displayed.
|
|
45
|
+
*/
|
|
46
|
+
private syncDescription;
|
|
47
|
+
private show;
|
|
48
|
+
private hide;
|
|
49
|
+
/** WCAG 1.4.13: a pointer-triggered overlay must be dismissible from the keyboard. */
|
|
50
|
+
private onKeyDown;
|
|
51
|
+
render(): TemplateResult;
|
|
52
|
+
}
|
|
53
|
+
declare global {
|
|
54
|
+
interface HTMLElementTagNameMap {
|
|
55
|
+
'kt-tooltip': KtTooltip;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { css as h, html as l } from "lit";
|
|
2
|
+
import { state as c, property as n } from "lit/decorators.js";
|
|
3
|
+
import { classMap as v } from "lit/directives/class-map.js";
|
|
4
|
+
import { K as d, d as b } from "../../../chunks/kt-element-CcMLO5e8.js";
|
|
5
|
+
import { u as f } from "../../../chunks/events-Bjl5Zmmq.js";
|
|
6
|
+
var u = Object.defineProperty, s = (r, t, a, y) => {
|
|
7
|
+
for (var e = void 0, o = r.length - 1, p; o >= 0; o--)
|
|
8
|
+
(p = r[o]) && (e = p(t, a, e) || e);
|
|
9
|
+
return e && u(t, a, e), e;
|
|
10
|
+
};
|
|
11
|
+
const m = "kt-tooltip-description";
|
|
12
|
+
class i extends d {
|
|
13
|
+
constructor() {
|
|
14
|
+
super(...arguments), this.descriptionId = f("kt-tooltip"), this.visible = !1, this.text = "", this.placement = "top", this.disabled = !1, this.show = () => {
|
|
15
|
+
!this.disabled && this.text && (this.visible = !0);
|
|
16
|
+
}, this.hide = () => {
|
|
17
|
+
this.visible = !1;
|
|
18
|
+
}, this.onKeyDown = (t) => {
|
|
19
|
+
t.key === "Escape" && this.visible && (t.stopPropagation(), this.visible = !1);
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
static {
|
|
23
|
+
this.styles = [
|
|
24
|
+
d.styles,
|
|
25
|
+
h`
|
|
26
|
+
:host {
|
|
27
|
+
position: relative;
|
|
28
|
+
display: inline-flex;
|
|
29
|
+
align-items: center;
|
|
30
|
+
justify-content: center;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.bubble {
|
|
34
|
+
position: absolute;
|
|
35
|
+
z-index: var(--z-tooltip);
|
|
36
|
+
max-width: 260px;
|
|
37
|
+
padding: var(--padding-chip);
|
|
38
|
+
/* Inverted against the page, so the bubble reads as floating in
|
|
39
|
+
both themes — the raw ramp step this used to name is pure white
|
|
40
|
+
under data-theme="light". */
|
|
41
|
+
color: var(--text-inverted);
|
|
42
|
+
font: var(--font-code-regular);
|
|
43
|
+
white-space: nowrap;
|
|
44
|
+
background: var(--surface-inverted);
|
|
45
|
+
border-radius: var(--radius-input);
|
|
46
|
+
opacity: 0;
|
|
47
|
+
pointer-events: none;
|
|
48
|
+
transition: opacity 150ms var(--easing-standard);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.bubble.visible {
|
|
52
|
+
opacity: 1;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.top {
|
|
56
|
+
bottom: calc(100% + 6px);
|
|
57
|
+
left: 50%;
|
|
58
|
+
transform: translateX(-50%);
|
|
59
|
+
}
|
|
60
|
+
.bottom {
|
|
61
|
+
top: calc(100% + 6px);
|
|
62
|
+
left: 50%;
|
|
63
|
+
transform: translateX(-50%);
|
|
64
|
+
}
|
|
65
|
+
.left {
|
|
66
|
+
top: 50%;
|
|
67
|
+
right: calc(100% + 6px);
|
|
68
|
+
transform: translateY(-50%);
|
|
69
|
+
}
|
|
70
|
+
.right {
|
|
71
|
+
top: 50%;
|
|
72
|
+
left: calc(100% + 6px);
|
|
73
|
+
transform: translateY(-50%);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
@media (prefers-reduced-motion: reduce) {
|
|
77
|
+
.bubble {
|
|
78
|
+
transition: none;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
`
|
|
82
|
+
];
|
|
83
|
+
}
|
|
84
|
+
connectedCallback() {
|
|
85
|
+
super.connectedCallback(), this.addEventListener("pointerenter", this.show), this.addEventListener("pointerleave", this.hide), this.addEventListener("focusin", this.show), this.addEventListener("focusout", this.hide), this.addEventListener("keydown", this.onKeyDown);
|
|
86
|
+
}
|
|
87
|
+
disconnectedCallback() {
|
|
88
|
+
super.disconnectedCallback(), this.removeEventListener("pointerenter", this.show), this.removeEventListener("pointerleave", this.hide), this.removeEventListener("focusin", this.show), this.removeEventListener("focusout", this.hide), this.removeEventListener("keydown", this.onKeyDown), this.description?.remove();
|
|
89
|
+
}
|
|
90
|
+
willUpdate(t) {
|
|
91
|
+
t.has("text") && this.syncDescription();
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* `aria-describedby` cannot reach across a shadow boundary: an id inside this
|
|
95
|
+
* element's shadow root is invisible to a trigger sitting in the light DOM.
|
|
96
|
+
*
|
|
97
|
+
* So the description also exists as a light-DOM node, addressed to a slot
|
|
98
|
+
* that does not exist — which keeps it out of the rendered output while
|
|
99
|
+
* leaving it referenceable, since an explicit aria-describedby target is read
|
|
100
|
+
* even when it is not displayed.
|
|
101
|
+
*/
|
|
102
|
+
syncDescription() {
|
|
103
|
+
if (!this.text) {
|
|
104
|
+
this.description?.remove(), this.description = void 0;
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
this.description || (this.description = document.createElement("span"), this.description.id = this.descriptionId, this.description.slot = m, this.append(this.description)), this.description.textContent = this.text;
|
|
108
|
+
for (const t of this.children)
|
|
109
|
+
t !== this.description && t.setAttribute("aria-describedby", this.descriptionId);
|
|
110
|
+
}
|
|
111
|
+
render() {
|
|
112
|
+
return l`<slot @slotchange=${this.syncDescription}></slot>
|
|
113
|
+
<span
|
|
114
|
+
part="bubble"
|
|
115
|
+
class=${v({ bubble: !0, [this.placement]: !0, visible: this.visible })}
|
|
116
|
+
role="tooltip"
|
|
117
|
+
aria-hidden=${this.visible ? "false" : "true"}
|
|
118
|
+
>${this.text}</span
|
|
119
|
+
>`;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
s([
|
|
123
|
+
c()
|
|
124
|
+
], i.prototype, "visible");
|
|
125
|
+
s([
|
|
126
|
+
n({ type: String })
|
|
127
|
+
], i.prototype, "text");
|
|
128
|
+
s([
|
|
129
|
+
n({ type: String, reflect: !0 })
|
|
130
|
+
], i.prototype, "placement");
|
|
131
|
+
s([
|
|
132
|
+
n({ type: Boolean, reflect: !0 })
|
|
133
|
+
], i.prototype, "disabled");
|
|
134
|
+
b("kt-tooltip", i);
|
|
135
|
+
export {
|
|
136
|
+
i as KtTooltip
|
|
137
|
+
};
|
|
138
|
+
//# sourceMappingURL=kt-tooltip.js.map
|