bank20baht-ui 0.2.9 → 0.3.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/README.md +43 -14
- package/dist/chunks/baht-toast-CD1WrOYr.js +284 -0
- package/dist/chunks/baht-workflow-Gd0J8mGC.js +3952 -0
- package/dist/chunks/base-CajA2aCO.js +193 -0
- package/dist/chunks/display-DQRcvsn7.js +589 -0
- package/dist/chunks/i18n-BcPL9_Jh.js +138 -0
- package/dist/components/baht-form.d.ts +7 -8
- package/dist/components/baht-workflow.d.ts +4 -4
- package/dist/components/base.d.ts +35 -7
- package/dist/components/primitives/baht-accordion.d.ts +0 -2
- package/dist/components/primitives/baht-datepicker.d.ts +6 -6
- package/dist/components/primitives/baht-file.d.ts +5 -2
- package/dist/components/primitives/baht-keyvalue-editor.d.ts +1 -1
- package/dist/components/primitives/baht-modal.d.ts +1 -2
- package/dist/components/primitives/baht-range.d.ts +0 -2
- package/dist/components/primitives/baht-reference-picker.d.ts +1 -1
- package/dist/components/primitives/baht-repeater.d.ts +5 -6
- package/dist/components/primitives/baht-table.d.ts +1 -2
- package/dist/components/primitives/baht-tooltip.d.ts +0 -2
- package/dist/components/primitives/baht-typeahead.d.ts +0 -1
- package/dist/components/primitives/baht-upload.d.ts +96 -0
- package/dist/components/primitives/index.d.ts +1 -0
- package/dist/core/dates.d.ts +1 -1
- package/dist/core/display.d.ts +1 -1
- package/dist/core/engine/graph.d.ts +1 -1
- package/dist/core/i18n.d.ts +5 -0
- package/dist/core/index.d.ts +1 -0
- package/dist/core/legacy.d.ts +14 -0
- package/dist/core/types.d.ts +27 -27
- package/dist/custom-elements.json +1979 -360
- package/dist/engine.js +65 -22
- package/dist/hydrate.d.ts +9 -0
- package/dist/hydrate.js +46 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +86 -3936
- package/dist/overlay.js +1 -1
- package/dist/ssr.d.ts +16 -0
- package/dist/ssr.js +34 -0
- package/dist/tokens.css +191 -10
- package/dist/vscode.html-custom-data.json +159 -50
- package/dist/web-types.json +259 -52
- package/package.json +21 -1
- package/dist/chunks/index-yULskrKT.js +0 -714
- package/dist/chunks/motion-BRVCzB4Z.js +0 -16
package/README.md
CHANGED
|
@@ -19,9 +19,9 @@ npm i bank20baht-ui
|
|
|
19
19
|
<script>
|
|
20
20
|
const el = document.getElementById('f');
|
|
21
21
|
el.form = {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
form_id: 'f1',
|
|
23
|
+
form_name: 'Person',
|
|
24
|
+
fields: [
|
|
25
25
|
{ order: 1, type: 'text', key: 'firstName', label: 'First name', width: '1/2', required: true, value: '' },
|
|
26
26
|
{ order: 2, type: 'text', key: 'lastName', label: 'Last name', width: '1/2', required: true, value: '' },
|
|
27
27
|
{ order: 3, type: 'number', key: 'age', label: 'Age', width: '1/4', min: 0, value: null }
|
|
@@ -63,7 +63,7 @@ gives you the same formatting for tables.
|
|
|
63
63
|
### Repeater — line items / repeating rows
|
|
64
64
|
|
|
65
65
|
```js
|
|
66
|
-
{ order: 5, type: 'repeater', key: 'items', label: 'Line items',
|
|
66
|
+
{ order: 5, type: 'repeater', key: 'items', label: 'Line items', min_rows: 1,
|
|
67
67
|
fields: [
|
|
68
68
|
{ order: 1, type: 'text', key: 'name', width: '1/2', required: true },
|
|
69
69
|
{ order: 2, type: 'number', key: 'qty', width: '1/4', min: 1 },
|
|
@@ -71,14 +71,14 @@ gives you the same formatting for tables.
|
|
|
71
71
|
```
|
|
72
72
|
|
|
73
73
|
Value is an array of row objects (`getData().items → [{ name, qty }, …]`). Rows add/remove in
|
|
74
|
-
the UI (`
|
|
74
|
+
the UI (`min_rows`/`max_rows` bound the count), each row validates its sub-fields — errors come
|
|
75
75
|
back as `items[0].name`, on both the client and `bank20baht-validator`. One level deep only.
|
|
76
76
|
|
|
77
77
|
### Dependent / async dropdowns
|
|
78
78
|
|
|
79
79
|
```js
|
|
80
80
|
// schema — functions never live in JSON, only registry names:
|
|
81
|
-
{ order: 2, type: 'dropdown', key: 'amphoe',
|
|
81
|
+
{ order: 2, type: 'dropdown', key: 'amphoe', options_from: 'amphoeFor', options_deps: ['province'] }
|
|
82
82
|
|
|
83
83
|
// registry:
|
|
84
84
|
el.registry = {
|
|
@@ -119,7 +119,7 @@ with the same JSON — `bank20baht-validator` re-exports `applyFlags`.
|
|
|
119
119
|
|
|
120
120
|
```js
|
|
121
121
|
// schema:
|
|
122
|
-
{ order: 6, type: 'file', key: 'doc', uploader: 'default', accept: '.pdf,image/*',
|
|
122
|
+
{ order: 6, type: 'file', key: 'doc', uploader: 'default', accept: '.pdf,image/*', max_size: 10_485_760 }
|
|
123
123
|
|
|
124
124
|
// registry — File in, serializable ref out:
|
|
125
125
|
el.registry = {
|
|
@@ -131,9 +131,17 @@ el.registry = {
|
|
|
131
131
|
```
|
|
132
132
|
|
|
133
133
|
Picking a file uploads immediately; the value becomes `{ name, size, type, url }` — plain
|
|
134
|
-
JSON, chips with remove buttons in the UI, `
|
|
134
|
+
JSON, chips with remove buttons in the UI, `max_size`/`accept` validated on both client and
|
|
135
135
|
server. Omit `uploader` for the old capture-only mode.
|
|
136
136
|
|
|
137
|
+
No registry function at all? `<baht-upload>` talks to an endpoint straight from attributes:
|
|
138
|
+
the file is POSTed as multipart on pick, the endpoint returns the stored URL, and that URL is
|
|
139
|
+
the value (`baht-change` → `{ value, files }`; progress and error events included).
|
|
140
|
+
|
|
141
|
+
```html
|
|
142
|
+
<baht-upload url="/api/uploads" accept=".pdf,image/*" max-size="10485760" label="Attachment"></baht-upload>
|
|
143
|
+
```
|
|
144
|
+
|
|
137
145
|
### Drafts / autosave (host pattern)
|
|
138
146
|
|
|
139
147
|
The library is controlled — autosave is three lines in your app:
|
|
@@ -160,7 +168,7 @@ setLocale('th', { required: 'ห้ามว่าง' }); // locale + your own
|
|
|
160
168
|
```
|
|
161
169
|
|
|
162
170
|
Call it once before mounting. Per-field `message` and label attributes
|
|
163
|
-
(`next-label`, `approval.
|
|
171
|
+
(`next-label`, `approval.approve_label`, …) still win over the catalog. The server can
|
|
164
172
|
localize too: `bank20baht-validator` re-exports `setLocale`, so validation issues come
|
|
165
173
|
back in the same language the client shows.
|
|
166
174
|
|
|
@@ -168,8 +176,8 @@ back in the same language the client shows.
|
|
|
168
176
|
|
|
169
177
|
```js
|
|
170
178
|
document.querySelector('baht-workflow').workflow = {
|
|
171
|
-
|
|
172
|
-
forms: [/* {
|
|
179
|
+
workflow_id: 'wf-1',
|
|
180
|
+
forms: [/* {form_id, form_name, order, fields}, ... */],
|
|
173
181
|
rules: [
|
|
174
182
|
{ id: 'skip-person',
|
|
175
183
|
when: { field: 'Intro.kind', op: 'eq', value: 'company' },
|
|
@@ -305,6 +313,27 @@ list of gotchas: [docs/frameworks/angular.md](./docs/frameworks/angular.md#gotch
|
|
|
305
313
|
vue({ template: { compilerOptions: { isCustomElement: (tag) => tag.startsWith('baht-') } } })
|
|
306
314
|
```
|
|
307
315
|
|
|
316
|
+
## Server-side rendering
|
|
317
|
+
|
|
318
|
+
`bank20baht-ui/ssr` (Node) renders any Lit template with `@lit-labs/ssr` and moves each
|
|
319
|
+
`baht-*` element's shadow template into its light DOM, so the HTML string it returns is
|
|
320
|
+
exactly what the client would have rendered. `bank20baht-ui/hydrate` (browser, imported
|
|
321
|
+
**before** `bank20baht-ui`) picks that markup up instead of re-rendering it:
|
|
322
|
+
|
|
323
|
+
```js
|
|
324
|
+
// server
|
|
325
|
+
import { html } from 'lit';
|
|
326
|
+
import { renderToString } from 'bank20baht-ui/ssr';
|
|
327
|
+
const page = await renderToString(html`<baht-button variant="primary" label="Save"></baht-button>`);
|
|
328
|
+
|
|
329
|
+
// client — import order matters
|
|
330
|
+
import 'bank20baht-ui/hydrate';
|
|
331
|
+
import 'bank20baht-ui';
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
`@lit-labs/ssr` is an optional peer dependency (server only). Full guide, limitations
|
|
335
|
+
(light-DOM children, ids, i18n locale) and troubleshooting: [docs/ssr.md](./docs/ssr.md).
|
|
336
|
+
|
|
308
337
|
## Docs, Storybook, examples
|
|
309
338
|
|
|
310
339
|
- **Per-component docs**: [`docs/`](./docs/README.md) — one .md per component + framework
|
|
@@ -319,10 +348,10 @@ vue({ template: { compilerOptions: { isCustomElement: (tag) => tag.startsWith('b
|
|
|
319
348
|
file (capture only, no upload) · label (static)`
|
|
320
349
|
|
|
321
350
|
Each field descriptor: `{ order, type, key, label, placeholder, width: '1/4'|'1/2'|'3/4'|'full',
|
|
322
|
-
value, disabled, required, options,
|
|
351
|
+
value, disabled, required, options, max_length, min, max, validators[], formatter }`.
|
|
323
352
|
|
|
324
353
|
## Visual Builder
|
|
325
354
|
|
|
326
|
-
The
|
|
355
|
+
The docs site ships a two-mode Visual Builder (Form mode: palette/WYSIWYG canvas/properties;
|
|
327
356
|
Workflow mode: sequence + rules with a live preview running the real `<baht-workflow>`), with
|
|
328
|
-
Import/Export JSON. Run it from the monorepo: `
|
|
357
|
+
Import/Export JSON. Run it from the monorepo: `bun run --filter docs dev` → `/builder`.
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
import { svg as c, html as p, nothing as d } from "lit";
|
|
2
|
+
import { property as r, query as $, customElement as f, state as w } from "lit/decorators.js";
|
|
3
|
+
import { B as v, b as C, h as g } from "./base-CajA2aCO.js";
|
|
4
|
+
import { t as E } from "./i18n-BcPL9_Jh.js";
|
|
5
|
+
const O = {
|
|
6
|
+
copy: c`<rect x="6" y="6" width="8" height="8" rx="1.5"/><path d="M10 6V4.5A1.5 1.5 0 0 0 8.5 3H4.5A1.5 1.5 0 0 0 3 4.5v4A1.5 1.5 0 0 0 4.5 10H6"/>`,
|
|
7
|
+
check: c`<path d="M3.5 8.5 6.5 11.5 12.5 4.5"/>`,
|
|
8
|
+
download: c`<path d="M8 3v7m0 0 3-3m-3 3L5 7"/><path d="M3 12h10"/>`,
|
|
9
|
+
upload: c`<path d="M8 12V5m0 0 3 3M8 5 5 8"/><path d="M3 4h10"/>`,
|
|
10
|
+
plus: c`<path d="M8 3.5v9M3.5 8h9"/>`,
|
|
11
|
+
external: c`<path d="M6 3H3.5v9.5h9.5V10"/><path d="M9 3h4v4"/><path d="M13 3 7.5 8.5"/>`,
|
|
12
|
+
close: c`<path d="M4 4l8 8M12 4l-8 8"/>`,
|
|
13
|
+
play: c`<path d="M5 3.5v9l7-4.5z"/>`,
|
|
14
|
+
search: c`<circle cx="7" cy="7" r="4"/><path d="m13 13-3.2-3.2"/>`
|
|
15
|
+
};
|
|
16
|
+
function S(t) {
|
|
17
|
+
return p`<svg
|
|
18
|
+
class="baht-icon"
|
|
19
|
+
width="16"
|
|
20
|
+
height="16"
|
|
21
|
+
viewBox="0 0 16 16"
|
|
22
|
+
fill="none"
|
|
23
|
+
stroke="currentColor"
|
|
24
|
+
stroke-width="1.5"
|
|
25
|
+
stroke-linecap="round"
|
|
26
|
+
stroke-linejoin="round"
|
|
27
|
+
aria-hidden="true"
|
|
28
|
+
>${O[t]}</svg>`;
|
|
29
|
+
}
|
|
30
|
+
function M(t) {
|
|
31
|
+
return t in O;
|
|
32
|
+
}
|
|
33
|
+
var k = Object.defineProperty, x = Object.getOwnPropertyDescriptor, u = (t, s, o, i) => {
|
|
34
|
+
for (var e = i > 1 ? void 0 : i ? x(s, o) : s, a = t.length - 1, l; a >= 0; a--)
|
|
35
|
+
(l = t[a]) && (e = (i ? l(s, o, e) : l(e)) || e);
|
|
36
|
+
return i && e && k(s, o, e), e;
|
|
37
|
+
};
|
|
38
|
+
let h = class extends v {
|
|
39
|
+
constructor() {
|
|
40
|
+
super(...arguments), this.variant = "primary", this.size = "md", this.disabled = !1, this.type = "button", this.label = "", this.icon = "", this.iconOnly = !1;
|
|
41
|
+
}
|
|
42
|
+
firstUpdated() {
|
|
43
|
+
this.iconOnly || C(this, this.buttonEl);
|
|
44
|
+
}
|
|
45
|
+
render() {
|
|
46
|
+
const t = this.variant === "primary" ? "" : ` baht-button--${this.variant}`, s = this.size === "md" ? "" : ` baht-button--${this.size}`, o = this.iconOnly ? " baht-button--icon" : "", i = this.icon && M(this.icon) ? S(this.icon) : d;
|
|
47
|
+
return p`<button
|
|
48
|
+
class="baht-button${t}${s}${o}"
|
|
49
|
+
type=${this.type}
|
|
50
|
+
aria-label=${this.iconOnly && this.label ? this.label : d}
|
|
51
|
+
?disabled=${this.disabled}
|
|
52
|
+
>${i}${this.iconOnly ? d : this.label}</button>`;
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
u([
|
|
56
|
+
r()
|
|
57
|
+
], h.prototype, "variant", 2);
|
|
58
|
+
u([
|
|
59
|
+
r()
|
|
60
|
+
], h.prototype, "size", 2);
|
|
61
|
+
u([
|
|
62
|
+
r({ type: Boolean })
|
|
63
|
+
], h.prototype, "disabled", 2);
|
|
64
|
+
u([
|
|
65
|
+
r()
|
|
66
|
+
], h.prototype, "type", 2);
|
|
67
|
+
u([
|
|
68
|
+
r()
|
|
69
|
+
], h.prototype, "label", 2);
|
|
70
|
+
u([
|
|
71
|
+
r()
|
|
72
|
+
], h.prototype, "icon", 2);
|
|
73
|
+
u([
|
|
74
|
+
r({ type: Boolean, attribute: "icon-only" })
|
|
75
|
+
], h.prototype, "iconOnly", 2);
|
|
76
|
+
u([
|
|
77
|
+
$("button")
|
|
78
|
+
], h.prototype, "buttonEl", 2);
|
|
79
|
+
h = u([
|
|
80
|
+
f("baht-button")
|
|
81
|
+
], h);
|
|
82
|
+
const P = 600;
|
|
83
|
+
function _(t, s) {
|
|
84
|
+
const o = typeof t.getAnimations == "function" ? t.getAnimations({ subtree: !0 }) : [];
|
|
85
|
+
if (o.length === 0) {
|
|
86
|
+
s();
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
let i = !1;
|
|
90
|
+
const e = () => {
|
|
91
|
+
i || (i = !0, s());
|
|
92
|
+
};
|
|
93
|
+
Promise.all(o.map((a) => a.finished.catch(() => {
|
|
94
|
+
}))).then(e, e), setTimeout(e, P);
|
|
95
|
+
}
|
|
96
|
+
var B = Object.defineProperty, T = Object.getOwnPropertyDescriptor, b = (t, s, o, i) => {
|
|
97
|
+
for (var e = i > 1 ? void 0 : i ? T(s, o) : s, a = t.length - 1, l; a >= 0; a--)
|
|
98
|
+
(l = t[a]) && (e = (i ? l(s, o, e) : l(e)) || e);
|
|
99
|
+
return i && e && B(s, o, e), e;
|
|
100
|
+
};
|
|
101
|
+
let n = class extends v {
|
|
102
|
+
constructor() {
|
|
103
|
+
super(...arguments), this.open = !1, this.heading = "", this.showClose = !0, this.closeOnScrim = !0, this.closing = !1, this.closeToken = 0, this.previousFocus = null, this.onKeydown = (t) => {
|
|
104
|
+
!this.open || n.openStack.at(-1) !== this || (t.key === "Escape" ? this.requestClose("escape") : t.key === "Tab" && this.trapFocus(t));
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
get titleId() {
|
|
108
|
+
return `baht-modal-title-${this.uid}`;
|
|
109
|
+
}
|
|
110
|
+
focusables() {
|
|
111
|
+
const t = this.querySelector(".baht-modal");
|
|
112
|
+
return t ? Array.from(
|
|
113
|
+
t.querySelectorAll(
|
|
114
|
+
'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])'
|
|
115
|
+
)
|
|
116
|
+
) : [];
|
|
117
|
+
}
|
|
118
|
+
/** Keep Tab cycling inside the dialog (no keyboard escape to the page behind). */
|
|
119
|
+
trapFocus(t) {
|
|
120
|
+
const s = this.focusables(), o = this.querySelector(".baht-modal");
|
|
121
|
+
if (s.length === 0) {
|
|
122
|
+
o == null || o.focus(), t.preventDefault();
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
const i = s[0], e = s[s.length - 1], a = document.activeElement;
|
|
126
|
+
if (!this.contains(a)) {
|
|
127
|
+
i.focus(), t.preventDefault();
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
t.shiftKey && (a === i || a === o) ? (e.focus(), t.preventDefault()) : !t.shiftKey && a === e && (i.focus(), t.preventDefault());
|
|
131
|
+
}
|
|
132
|
+
connectedCallback() {
|
|
133
|
+
super.connectedCallback(), g() && document.addEventListener("keydown", this.onKeydown);
|
|
134
|
+
}
|
|
135
|
+
disconnectedCallback() {
|
|
136
|
+
g() && document.removeEventListener("keydown", this.onKeydown), n.openStack = n.openStack.filter((t) => t !== this), super.disconnectedCallback();
|
|
137
|
+
}
|
|
138
|
+
firstUpdated() {
|
|
139
|
+
C(this, this.bodyEl);
|
|
140
|
+
}
|
|
141
|
+
willUpdate(t) {
|
|
142
|
+
t.has("open") && (this.open ? this.closing = !1 : t.get("open") === !0 && (this.closing = !0));
|
|
143
|
+
}
|
|
144
|
+
updated(t) {
|
|
145
|
+
var s, o;
|
|
146
|
+
if (t.has("open") && (n.openStack = n.openStack.filter((i) => i !== this), this.open && n.openStack.push(this)), t.has("open") && !this.open && this.closing) {
|
|
147
|
+
const i = ++this.closeToken, e = this.querySelector(".baht-modal-scrim"), a = () => {
|
|
148
|
+
i === this.closeToken && !this.open && (this.closing = !1);
|
|
149
|
+
};
|
|
150
|
+
e ? _(e, a) : a();
|
|
151
|
+
}
|
|
152
|
+
if (t.has("open") && this.open && (this.previousFocus = document.activeElement, (s = this.querySelector(".baht-modal")) == null || s.focus()), t.has("open") && !this.open && t.get("open") === !0) {
|
|
153
|
+
const i = this.previousFocus;
|
|
154
|
+
this.previousFocus = null, i != null && i.isConnected && (!document.activeElement || document.activeElement === document.body || this.contains(document.activeElement)) && ((o = i.focus) == null || o.call(i));
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/** Ask the host to close (the host owns `open`). */
|
|
158
|
+
requestClose(t = "button") {
|
|
159
|
+
this.dispatchEvent(
|
|
160
|
+
new CustomEvent("baht-close", { detail: { reason: t }, bubbles: !0, composed: !0 })
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
render() {
|
|
164
|
+
return p`<div
|
|
165
|
+
class="baht-modal-scrim${this.closing ? " baht-modal-scrim--closing" : ""}"
|
|
166
|
+
style=${this.open || this.closing ? d : "display:none"}
|
|
167
|
+
@click=${(t) => this.closeOnScrim && t.target === t.currentTarget && this.requestClose("scrim")}
|
|
168
|
+
>
|
|
169
|
+
<div
|
|
170
|
+
class="baht-modal"
|
|
171
|
+
role="dialog"
|
|
172
|
+
aria-modal="true"
|
|
173
|
+
aria-labelledby=${this.heading ? this.titleId : d}
|
|
174
|
+
aria-label=${this.heading ? d : "Dialog"}
|
|
175
|
+
tabindex="-1"
|
|
176
|
+
>
|
|
177
|
+
${this.heading || this.showClose ? p`<header class="baht-modal-header">
|
|
178
|
+
<div class="baht-modal-title" id=${this.titleId}>${this.heading}</div>
|
|
179
|
+
${this.showClose ? p`<button type="button" class="baht-modal-close" aria-label=${E("close")} @click=${() => this.requestClose("button")}>×</button>` : d}
|
|
180
|
+
</header>` : d}
|
|
181
|
+
<div class="baht-modal-body"></div>
|
|
182
|
+
</div>
|
|
183
|
+
</div>`;
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
n.openStack = [];
|
|
187
|
+
b([
|
|
188
|
+
r({ type: Boolean, reflect: !0 })
|
|
189
|
+
], n.prototype, "open", 2);
|
|
190
|
+
b([
|
|
191
|
+
r()
|
|
192
|
+
], n.prototype, "heading", 2);
|
|
193
|
+
b([
|
|
194
|
+
r({ type: Boolean, attribute: "show-close" })
|
|
195
|
+
], n.prototype, "showClose", 2);
|
|
196
|
+
b([
|
|
197
|
+
r({ type: Boolean, attribute: "close-on-scrim" })
|
|
198
|
+
], n.prototype, "closeOnScrim", 2);
|
|
199
|
+
b([
|
|
200
|
+
$(".baht-modal-body")
|
|
201
|
+
], n.prototype, "bodyEl", 2);
|
|
202
|
+
b([
|
|
203
|
+
w()
|
|
204
|
+
], n.prototype, "closing", 2);
|
|
205
|
+
n = b([
|
|
206
|
+
f("baht-modal")
|
|
207
|
+
], n);
|
|
208
|
+
var D = Object.defineProperty, q = Object.getOwnPropertyDescriptor, y = (t, s, o, i) => {
|
|
209
|
+
for (var e = i > 1 ? void 0 : i ? q(s, o) : s, a = t.length - 1, l; a >= 0; a--)
|
|
210
|
+
(l = t[a]) && (e = (i ? l(s, o, e) : l(e)) || e);
|
|
211
|
+
return i && e && D(s, o, e), e;
|
|
212
|
+
};
|
|
213
|
+
let m = class extends v {
|
|
214
|
+
constructor() {
|
|
215
|
+
super(...arguments), this.duration = 4e3, this.entries = [], this.timers = /* @__PURE__ */ new Map();
|
|
216
|
+
}
|
|
217
|
+
show(t) {
|
|
218
|
+
const s = {
|
|
219
|
+
id: ++m.counter,
|
|
220
|
+
message: t.message,
|
|
221
|
+
tone: t.tone ?? "neutral",
|
|
222
|
+
duration: t.duration ?? this.duration
|
|
223
|
+
};
|
|
224
|
+
return this.entries = [...this.entries, s], s.duration > 0 && this.timers.set(
|
|
225
|
+
s.id,
|
|
226
|
+
setTimeout(() => this.dismiss(s.id), s.duration)
|
|
227
|
+
), s.id;
|
|
228
|
+
}
|
|
229
|
+
dismiss(t) {
|
|
230
|
+
const s = this.entries.find((e) => e.id === t);
|
|
231
|
+
if (!s || s.leaving) return;
|
|
232
|
+
clearTimeout(this.timers.get(t)), this.timers.delete(t), this.entries = this.entries.map((e) => e.id === t ? { ...e, leaving: !0 } : e), this.dispatchEvent(
|
|
233
|
+
new CustomEvent("baht-dismiss", {
|
|
234
|
+
detail: { id: t, message: s.message },
|
|
235
|
+
bubbles: !0,
|
|
236
|
+
composed: !0
|
|
237
|
+
})
|
|
238
|
+
);
|
|
239
|
+
const o = () => {
|
|
240
|
+
this.entries = this.entries.filter((e) => e.id !== t);
|
|
241
|
+
}, i = this.querySelector(`.baht-toast[data-toast="${t}"]`);
|
|
242
|
+
if (!i) {
|
|
243
|
+
o();
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
i.classList.add("baht-toast--leaving"), _(i, o);
|
|
247
|
+
}
|
|
248
|
+
disconnectedCallback() {
|
|
249
|
+
this.timers.forEach((t) => clearTimeout(t)), this.timers.clear(), super.disconnectedCallback();
|
|
250
|
+
}
|
|
251
|
+
render() {
|
|
252
|
+
return p`<div class="baht-toaster" role="status" aria-live="polite">
|
|
253
|
+
${this.entries.map(
|
|
254
|
+
// Danger/warning interrupt (role=alert); the rest ride the polite container.
|
|
255
|
+
(t) => p`<div
|
|
256
|
+
class="baht-toast ${t.tone === "neutral" ? "" : `baht-toast--${t.tone}`}${t.leaving ? " baht-toast--leaving" : ""}"
|
|
257
|
+
data-toast=${t.id}
|
|
258
|
+
role=${t.tone === "danger" || t.tone === "warning" ? "alert" : d}
|
|
259
|
+
>
|
|
260
|
+
<span class="baht-toast-message">${t.message}</span>
|
|
261
|
+
<button type="button" class="baht-toast-dismiss" aria-label=${E("dismiss")} @click=${() => this.dismiss(t.id)}>×</button>
|
|
262
|
+
</div>`
|
|
263
|
+
)}
|
|
264
|
+
</div>`;
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
m.counter = 0;
|
|
268
|
+
y([
|
|
269
|
+
r({ type: Number })
|
|
270
|
+
], m.prototype, "duration", 2);
|
|
271
|
+
y([
|
|
272
|
+
w()
|
|
273
|
+
], m.prototype, "entries", 2);
|
|
274
|
+
m = y([
|
|
275
|
+
f("baht-toast")
|
|
276
|
+
], m);
|
|
277
|
+
export {
|
|
278
|
+
h as B,
|
|
279
|
+
n as a,
|
|
280
|
+
m as b,
|
|
281
|
+
_ as c,
|
|
282
|
+
M as i,
|
|
283
|
+
S as r
|
|
284
|
+
};
|