@deepfuture/dui-components 1.3.0 → 1.4.1
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/all.d.ts +7 -0
- package/all.js +6 -0
- package/package.json +10 -2
- package/splitter/index.d.ts +8 -0
- package/splitter/index.js +7 -0
- package/splitter/splitter-handle.d.ts +24 -0
- package/splitter/splitter-handle.js +113 -0
- package/splitter/splitter-panel.d.ts +11 -0
- package/splitter/splitter-panel.js +12 -0
- package/splitter/splitter.d.ts +11 -0
- package/splitter/splitter.js +12 -0
- package/toast/default-icons.d.ts +17 -0
- package/toast/default-icons.js +96 -0
- package/toast/index.d.ts +12 -0
- package/toast/index.js +11 -0
- package/toast/toast-action.d.ts +16 -0
- package/toast/toast-action.js +52 -0
- package/toast/toast-close.d.ts +16 -0
- package/toast/toast-close.js +52 -0
- package/toast/toast-region.d.ts +40 -0
- package/toast/toast-region.js +307 -0
- package/toast/toast.d.ts +52 -0
- package/toast/toast.js +448 -0
- package/tokens/tokens-raw.js +1 -1
- package/tokens/tokens.css +18 -0
- package/tokens/tokens.js +1 -1
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
|
|
2
|
+
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
|
|
3
|
+
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
|
|
4
|
+
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
|
|
5
|
+
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
|
|
6
|
+
var _, done = false;
|
|
7
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
8
|
+
var context = {};
|
|
9
|
+
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
|
|
10
|
+
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
|
|
11
|
+
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
|
|
12
|
+
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
|
|
13
|
+
if (kind === "accessor") {
|
|
14
|
+
if (result === void 0) continue;
|
|
15
|
+
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
|
|
16
|
+
if (_ = accept(result.get)) descriptor.get = _;
|
|
17
|
+
if (_ = accept(result.set)) descriptor.set = _;
|
|
18
|
+
if (_ = accept(result.init)) initializers.unshift(_);
|
|
19
|
+
}
|
|
20
|
+
else if (_ = accept(result)) {
|
|
21
|
+
if (kind === "field") initializers.unshift(_);
|
|
22
|
+
else descriptor[key] = _;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (target) Object.defineProperty(target, contextIn.name, descriptor);
|
|
26
|
+
done = true;
|
|
27
|
+
};
|
|
28
|
+
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
|
|
29
|
+
var useValue = arguments.length > 2;
|
|
30
|
+
for (var i = 0; i < initializers.length; i++) {
|
|
31
|
+
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
|
|
32
|
+
}
|
|
33
|
+
return useValue ? value : void 0;
|
|
34
|
+
};
|
|
35
|
+
import { css } from "lit";
|
|
36
|
+
import { property } from "lit/decorators.js";
|
|
37
|
+
import { DuiToastRegionPrimitive } from "@deepfuture/dui-primitives/toast";
|
|
38
|
+
import "../_install.js";
|
|
39
|
+
const styles = css `
|
|
40
|
+
/* ── Region-scoped tokens ──
|
|
41
|
+
*
|
|
42
|
+
* Bump the default region width (primitive ships 22rem; 24rem reads
|
|
43
|
+
* better with action + close affordances).
|
|
44
|
+
*
|
|
45
|
+
* Stack-visual knobs (peek, scale falloff, expanded gap) are exposed for
|
|
46
|
+
* consumer tuning without rewriting the cascade transforms.
|
|
47
|
+
*/
|
|
48
|
+
:host {
|
|
49
|
+
--toast-region-width: 24rem;
|
|
50
|
+
--toast-stack-peek: var(--space-3_5);
|
|
51
|
+
--toast-stack-scale-step: 0.05;
|
|
52
|
+
--toast-expanded-gap: var(--space-2);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/* ── theme="light|dark" overrides ──
|
|
56
|
+
*
|
|
57
|
+
* Re-declare the four Layer-1 primitives AND every Layer-2 derivation on
|
|
58
|
+
* the host. Custom-property var() references resolve at the *declaring*
|
|
59
|
+
* element's scope, so the recipes in tokens.css (declared on :root) bake
|
|
60
|
+
* in :root's --background/--foreground at definition time. Descendants
|
|
61
|
+
* inherit the already-resolved values, not the recipes themselves. To
|
|
62
|
+
* make scoped theme overrides actually work we re-declare the recipes
|
|
63
|
+
* here so they resolve against the host's overridden Layer-1 values.
|
|
64
|
+
*
|
|
65
|
+
* If other components want scoped theme overrides later, we promote this
|
|
66
|
+
* to tokens.css (selectors that match :root[data-theme] AND nested
|
|
67
|
+
* [data-theme]).
|
|
68
|
+
*/
|
|
69
|
+
:host([data-theme="light"]) {
|
|
70
|
+
--background: oklch(0.97 0 0);
|
|
71
|
+
--foreground: oklch(0.15 0 0);
|
|
72
|
+
--accent: oklch(0.55 0.25 260);
|
|
73
|
+
--destructive: oklch(0.55 0.22 25);
|
|
74
|
+
--success: oklch(0.55 0.18 145);
|
|
75
|
+
--warning: oklch(0.65 0.18 70);
|
|
76
|
+
--info: oklch(0.55 0.18 230);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
:host([data-theme="dark"]) {
|
|
80
|
+
--background: oklch(0.15 0.015 260);
|
|
81
|
+
--foreground: oklch(0.93 0 0);
|
|
82
|
+
--accent: oklch(0.75 0.18 260);
|
|
83
|
+
--destructive: oklch(0.70 0.18 25);
|
|
84
|
+
--success: oklch(0.72 0.16 145);
|
|
85
|
+
--warning: oklch(0.78 0.15 70);
|
|
86
|
+
--info: oklch(0.72 0.15 230);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/* Layer-2 derivations re-declared at the host so they pick up the
|
|
90
|
+
overridden Layer-1 values above. */
|
|
91
|
+
:host([data-theme="light"]),
|
|
92
|
+
:host([data-theme="dark"]) {
|
|
93
|
+
--sunken-2: oklch(from var(--background) calc(l - 0.03) c h);
|
|
94
|
+
--sunken-1: oklch(from var(--background) calc(l - 0.01) c h);
|
|
95
|
+
--surface-1: oklch(from var(--background) calc(l + 0.02) c h);
|
|
96
|
+
--surface-2: oklch(from var(--background) calc(l + 0.05) c h);
|
|
97
|
+
--surface-3: oklch(from var(--background) calc(l + 0.09) c h);
|
|
98
|
+
|
|
99
|
+
--border: oklch(from var(--foreground) l c h / 0.15);
|
|
100
|
+
--border-strong: oklch(from var(--foreground) l c h / 0.25);
|
|
101
|
+
|
|
102
|
+
--text-1: oklch(from var(--foreground) l c h / 0.90);
|
|
103
|
+
--text-2: oklch(from var(--foreground) l c h / 0.63);
|
|
104
|
+
--text-3: oklch(from var(--foreground) l c h / 0.45);
|
|
105
|
+
|
|
106
|
+
--accent-subtle: oklch(from var(--accent) l c h / 0.10);
|
|
107
|
+
--accent-text: oklch(from var(--accent) calc(l * 1.1) calc(c * 0.8) h);
|
|
108
|
+
|
|
109
|
+
--destructive-subtle: oklch(from var(--destructive) l c h / 0.10);
|
|
110
|
+
--destructive-text: var(--destructive);
|
|
111
|
+
|
|
112
|
+
--success-subtle: oklch(from var(--success) l c h / 0.10);
|
|
113
|
+
--success-text: oklch(from var(--success) calc(l * 1.05) calc(c * 0.9) h);
|
|
114
|
+
|
|
115
|
+
--warning-subtle: oklch(from var(--warning) l c h / 0.10);
|
|
116
|
+
--warning-text: oklch(from var(--warning) calc(l * 1.05) calc(c * 0.9) h);
|
|
117
|
+
|
|
118
|
+
--info-subtle: oklch(from var(--info) l c h / 0.10);
|
|
119
|
+
--info-text: oklch(from var(--info) calc(l * 1.05) calc(c * 0.9) h);
|
|
120
|
+
|
|
121
|
+
--scrim: oklch(from var(--foreground) l c h / 0.35);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/* ── List layout (cascade stacking on by default) ──
|
|
125
|
+
*
|
|
126
|
+
* Toasts overlap via position: absolute and use the HOST as their
|
|
127
|
+
* containing block, so they pin to the region's anchored edge regardless
|
|
128
|
+
* of stack size. The list itself stays in normal flow with a min-height
|
|
129
|
+
* so the region is a viable hover target when collapsed.
|
|
130
|
+
*
|
|
131
|
+
* IMPORTANT: do NOT make the list position: relative. Doing so would make
|
|
132
|
+
* IT the containing block; since the absolute toasts don't contribute to
|
|
133
|
+
* its height, the list collapses to min-height (60px) and toasts pin to
|
|
134
|
+
* a 60px box instead of the (potentially taller) region. The host's
|
|
135
|
+
* position: fixed (auto-region) or position: relative (declarative,
|
|
136
|
+
* scoped use) is the right containing block.
|
|
137
|
+
*/
|
|
138
|
+
[part="list"] {
|
|
139
|
+
min-height: 60px;
|
|
140
|
+
/* Override primitive's default flex gap — we position absolutely. */
|
|
141
|
+
gap: 0;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/* ── Toast stacking transforms (collapsed) ──
|
|
145
|
+
*
|
|
146
|
+
* Bottom-anchored: each older toast lifts up + scales down a step.
|
|
147
|
+
* Top-anchored: mirror image — older toasts drop down + scale down.
|
|
148
|
+
*/
|
|
149
|
+
::slotted(dui-toast) {
|
|
150
|
+
position: absolute;
|
|
151
|
+
left: 0;
|
|
152
|
+
right: 0;
|
|
153
|
+
bottom: 0;
|
|
154
|
+
pointer-events: none;
|
|
155
|
+
transform-origin: bottom center;
|
|
156
|
+
transform: translateY(
|
|
157
|
+
calc(var(--toast-index, 0) * -1 * var(--toast-stack-peek))
|
|
158
|
+
) scale(calc(1 - var(--toast-index, 0) * var(--toast-stack-scale-step)));
|
|
159
|
+
transition:
|
|
160
|
+
transform var(--duration-normal) var(--ease-out-3),
|
|
161
|
+
opacity var(--duration-normal) var(--ease-out-3);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
:host([data-position^="top-"]) ::slotted(dui-toast) {
|
|
165
|
+
top: 0;
|
|
166
|
+
bottom: auto;
|
|
167
|
+
transform-origin: top center;
|
|
168
|
+
transform: translateY(calc(var(--toast-index, 0) * var(--toast-stack-peek)))
|
|
169
|
+
scale(calc(1 - var(--toast-index, 0) * var(--toast-stack-scale-step)));
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/* Front toast and any toast inside an expanded region are interactive. */
|
|
173
|
+
::slotted(dui-toast[data-front]),
|
|
174
|
+
::slotted(dui-toast[data-region-expanded]) {
|
|
175
|
+
pointer-events: auto;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/* ── Expanded layout: real cumulative-height layout ── */
|
|
179
|
+
::slotted(dui-toast[data-region-expanded]) {
|
|
180
|
+
transform: translateY(
|
|
181
|
+
calc(
|
|
182
|
+
-1 * var(--toasts-before-height, 0px) -
|
|
183
|
+
var(--toast-index, 0) * var(--toast-expanded-gap)
|
|
184
|
+
)
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
:host([data-position^="top-"]) ::slotted(dui-toast[data-region-expanded]) {
|
|
189
|
+
transform: translateY(
|
|
190
|
+
calc(
|
|
191
|
+
var(--toasts-before-height, 0px) +
|
|
192
|
+
var(--toast-index, 0) * var(--toast-expanded-gap)
|
|
193
|
+
)
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/* ── Overflow: hide toasts past max-visible when collapsed ── */
|
|
198
|
+
::slotted(dui-toast[data-overflow]) {
|
|
199
|
+
opacity: 0;
|
|
200
|
+
pointer-events: none;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
::slotted(dui-toast[data-overflow][data-region-expanded]) {
|
|
204
|
+
opacity: 1;
|
|
205
|
+
pointer-events: auto;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/* ── Reduced motion ── */
|
|
209
|
+
@media (prefers-reduced-motion: reduce) {
|
|
210
|
+
::slotted(dui-toast) {
|
|
211
|
+
transition-duration: 0s;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
`;
|
|
215
|
+
/**
|
|
216
|
+
* `<dui-toast-region>` — Styled toast viewport.
|
|
217
|
+
*
|
|
218
|
+
* Extends the primitive with:
|
|
219
|
+
* - Sonner-style cascade-and-expand stacking (default-on)
|
|
220
|
+
* - Wider 24rem default width
|
|
221
|
+
* - Consumer-tunable stack visuals (`--toast-stack-peek`,
|
|
222
|
+
* `--toast-stack-scale-step`, `--toast-expanded-gap`)
|
|
223
|
+
* - Optional `theme="light|dark|inverted"` palette override
|
|
224
|
+
*
|
|
225
|
+
* Default position is the primitive's `bottom-right`; flip via the inherited
|
|
226
|
+
* `position` attribute. Imperative `toast()` calls land here automatically.
|
|
227
|
+
*
|
|
228
|
+
* @attr theme - `"light" | "dark" | "inverted"`. Unset = inherit page theme.
|
|
229
|
+
* `inverted` resolves at runtime to the opposite of the document's
|
|
230
|
+
* `<html data-theme>` attribute.
|
|
231
|
+
*/
|
|
232
|
+
let DuiToastRegion = (() => {
|
|
233
|
+
let _classSuper = DuiToastRegionPrimitive;
|
|
234
|
+
let _theme_decorators;
|
|
235
|
+
let _theme_initializers = [];
|
|
236
|
+
let _theme_extraInitializers = [];
|
|
237
|
+
return class DuiToastRegion extends _classSuper {
|
|
238
|
+
static {
|
|
239
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
240
|
+
_theme_decorators = [property({ type: String, reflect: true })];
|
|
241
|
+
__esDecorate(this, null, _theme_decorators, { kind: "accessor", name: "theme", static: false, private: false, access: { has: obj => "theme" in obj, get: obj => obj.theme, set: (obj, value) => { obj.theme = value; } }, metadata: _metadata }, _theme_initializers, _theme_extraInitializers);
|
|
242
|
+
if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
243
|
+
}
|
|
244
|
+
static styles = [...DuiToastRegionPrimitive.styles, styles];
|
|
245
|
+
#theme_accessor_storage = __runInitializers(this, _theme_initializers, undefined);
|
|
246
|
+
/**
|
|
247
|
+
* Optional palette override. Unset = inherit page theme. `inverted`
|
|
248
|
+
* resolves at runtime to the opposite of `<html>`'s `data-theme`.
|
|
249
|
+
*/
|
|
250
|
+
get theme() { return this.#theme_accessor_storage; }
|
|
251
|
+
set theme(value) { this.#theme_accessor_storage = value; }
|
|
252
|
+
/** Watcher for the document-level theme so `inverted` stays correct. */
|
|
253
|
+
#docThemeObserver = __runInitializers(this, _theme_extraInitializers);
|
|
254
|
+
connectedCallback() {
|
|
255
|
+
super.connectedCallback();
|
|
256
|
+
this.#applyTheme();
|
|
257
|
+
if (this.theme === "inverted")
|
|
258
|
+
this.#observeDocTheme();
|
|
259
|
+
}
|
|
260
|
+
disconnectedCallback() {
|
|
261
|
+
super.disconnectedCallback();
|
|
262
|
+
this.#stopObservingDocTheme();
|
|
263
|
+
}
|
|
264
|
+
willUpdate(changed) {
|
|
265
|
+
super.willUpdate(changed);
|
|
266
|
+
if (changed.has("theme")) {
|
|
267
|
+
this.#applyTheme();
|
|
268
|
+
if (this.theme === "inverted")
|
|
269
|
+
this.#observeDocTheme();
|
|
270
|
+
else
|
|
271
|
+
this.#stopObservingDocTheme();
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Resolve the `theme` property into a `data-theme` attribute on the host.
|
|
276
|
+
* For `inverted`, read `<html>`'s `data-theme` and flip.
|
|
277
|
+
*/
|
|
278
|
+
#applyTheme() {
|
|
279
|
+
if (!this.theme) {
|
|
280
|
+
this.removeAttribute("data-theme");
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
if (this.theme === "inverted") {
|
|
284
|
+
const docTheme = document.documentElement.getAttribute("data-theme");
|
|
285
|
+
const inverted = docTheme === "dark" ? "light" : "dark";
|
|
286
|
+
this.setAttribute("data-theme", inverted);
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
this.setAttribute("data-theme", this.theme);
|
|
290
|
+
}
|
|
291
|
+
#observeDocTheme() {
|
|
292
|
+
if (this.#docThemeObserver)
|
|
293
|
+
return;
|
|
294
|
+
this.#docThemeObserver = new MutationObserver(() => this.#applyTheme());
|
|
295
|
+
this.#docThemeObserver.observe(document.documentElement, {
|
|
296
|
+
attributes: true,
|
|
297
|
+
attributeFilter: ["data-theme"],
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
#stopObservingDocTheme() {
|
|
301
|
+
this.#docThemeObserver?.disconnect();
|
|
302
|
+
this.#docThemeObserver = undefined;
|
|
303
|
+
}
|
|
304
|
+
};
|
|
305
|
+
})();
|
|
306
|
+
export { DuiToastRegion };
|
|
307
|
+
customElements.define(DuiToastRegion.tagName, DuiToastRegion);
|
package/toast/toast.d.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `<dui-toast>` — Styled toast item.
|
|
3
|
+
*
|
|
4
|
+
* NOTE: This is the only DUI component that overrides `render()`. The styled
|
|
5
|
+
* layer's contract is normally "extend with CSS only" — toasts are an
|
|
6
|
+
* exception because we ship built-in default icons keyed off `data-type`,
|
|
7
|
+
* which require a new shadow-DOM slot (`icon`) the primitive doesn't have.
|
|
8
|
+
* The override carefully preserves the primitive's full markup (root, title,
|
|
9
|
+
* description, default slot, action slot, close slot, ARIA wiring,
|
|
10
|
+
* `data-*` state attributes) so consumer-facing parts/slots stay stable.
|
|
11
|
+
*/
|
|
12
|
+
import { type TemplateResult } from "lit";
|
|
13
|
+
import { DuiToastPrimitive } from "@deepfuture/dui-primitives/toast";
|
|
14
|
+
import "../_install.js";
|
|
15
|
+
import "../spinner/index.js";
|
|
16
|
+
/**
|
|
17
|
+
* `<dui-toast>` — Styled toast item.
|
|
18
|
+
*
|
|
19
|
+
* Extends the primitive with:
|
|
20
|
+
* - Sonner-default look (neutral surface, colored icon, title + description)
|
|
21
|
+
* - Built-in default icons per `type` (success/info/warning/error/loading);
|
|
22
|
+
* slot `icon` to override
|
|
23
|
+
* - `appearance="rich"` for tinted-surface mode
|
|
24
|
+
* - CSS Grid layout with full slot/part preservation
|
|
25
|
+
* - Hover-visible close button (always visible on touch)
|
|
26
|
+
*
|
|
27
|
+
* @slot title - Title text (auto-wires aria-labelledby).
|
|
28
|
+
* @slot description - Description text (auto-wires aria-describedby).
|
|
29
|
+
* @slot - Default custom content (Tier-2 escape hatch).
|
|
30
|
+
* @slot icon - Custom icon to replace the type-default. Empty = built-in.
|
|
31
|
+
* @slot action - Action button(s); typically a `<dui-toast-action>` wrapper.
|
|
32
|
+
* @slot close - Close affordance; typically a `<dui-toast-close>` wrapper.
|
|
33
|
+
*
|
|
34
|
+
* @csspart root - The toast container.
|
|
35
|
+
* @csspart icon - The icon container.
|
|
36
|
+
* @csspart title - The title wrapper.
|
|
37
|
+
* @csspart description - The description wrapper.
|
|
38
|
+
* @csspart action-wrapper - The action slot's grid cell.
|
|
39
|
+
* @csspart close-wrapper - The close slot's absolute-positioned container.
|
|
40
|
+
*
|
|
41
|
+
* @attr appearance - `"default" | "rich"`. Rich tints surface + border
|
|
42
|
+
* by type color. Default keeps the surface neutral.
|
|
43
|
+
*/
|
|
44
|
+
export declare class DuiToast extends DuiToastPrimitive {
|
|
45
|
+
#private;
|
|
46
|
+
static styles: import("lit").CSSResult[];
|
|
47
|
+
/**
|
|
48
|
+
* Override the primitive's render to inject an `icon` slot with built-in
|
|
49
|
+
* defaults. Preserves all other parts/slots/ARIA wiring exactly.
|
|
50
|
+
*/
|
|
51
|
+
render(): TemplateResult;
|
|
52
|
+
}
|