bank20baht-ui 0.8.1 → 0.9.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/dist/components/primitives/baht-bar-chart.js +1 -1
- package/dist/components/primitives/baht-button.d.ts +13 -0
- package/dist/components/primitives/baht-button.js +13 -10
- package/dist/components/primitives/baht-line-chart.d.ts +12 -0
- package/dist/components/primitives/baht-line-chart.js +112 -87
- package/dist/core/i18n.d.ts +4 -0
- package/dist/core/i18n.js +4 -0
- package/dist/core/validators.js +39 -32
- package/dist/css/components.css +18 -7
- package/dist/custom-elements.json +49 -1
- package/dist/tokens.css +18 -7
- package/dist/vscode.html-custom-data.json +6 -1
- package/dist/web-types.json +12 -2
- package/package.json +1 -1
|
@@ -167,7 +167,7 @@ let p = class extends E {
|
|
|
167
167
|
return o`<div class="baht-bar-chart-row">
|
|
168
168
|
<span class="baht-bar-chart-label" title=${y}>${y}</span>
|
|
169
169
|
<div
|
|
170
|
-
class="baht-bar-chart-track${this.stacked ? " baht-bar-chart-track--stacked" : ""}"
|
|
170
|
+
class="baht-bar-chart-track${this.stacked ? " baht-bar-chart-track--stacked" : ""}${this.categoryMarkers(y).length > 0 ? " baht-bar-chart-track--marked" : ""}"
|
|
171
171
|
tabindex="0"
|
|
172
172
|
role="button"
|
|
173
173
|
aria-label=${u}
|
|
@@ -12,6 +12,7 @@ export type ButtonSize = 'sm' | 'md' | 'lg';
|
|
|
12
12
|
* <baht-button label="Save workflow"></baht-button>
|
|
13
13
|
* <baht-button icon="copy" variant="ghost" size="sm">Copy</baht-button>
|
|
14
14
|
* <baht-button icon="close" icon-only label="Close"></baht-button> <!-- label = a11y name -->
|
|
15
|
+
* <baht-button aria-label="Previous month">‹</baht-button> <!-- glyph child, host aria-label wins -->
|
|
15
16
|
*/
|
|
16
17
|
export declare class BahtButton extends BahtElement {
|
|
17
18
|
variant: ButtonVariant;
|
|
@@ -25,6 +26,18 @@ export declare class BahtButton extends BahtElement {
|
|
|
25
26
|
icon: IconName | '';
|
|
26
27
|
/** Square icon-only button. Requires `label` for the accessible name. */
|
|
27
28
|
iconOnly: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* A host `aria-label` never reaches assistive tech on its own — light DOM has no
|
|
31
|
+
* implicit ARIA relationship between a custom element and its rendered children, so an
|
|
32
|
+
* `aria-label` written on `<baht-button>` stays on the host and the inner native
|
|
33
|
+
* `<button>` keeps whatever text (or none) is inside it. Mirroring the attribute into
|
|
34
|
+
* this property forwards it to the inner button's `aria-label`, taking priority over
|
|
35
|
+
* `label`/icon-only fallback — this is how a glyph-only child (e.g. `‹`) gets a real
|
|
36
|
+
* accessible name without `icon-only`. Mapped to the plain `aria-label` attribute so
|
|
37
|
+
* hosts write it the way they naturally would; kept off the `ariaLabel` IDL accessor to
|
|
38
|
+
* avoid shadowing the platform's own ARIAMixin.
|
|
39
|
+
*/
|
|
40
|
+
hostAriaLabel: string;
|
|
28
41
|
private buttonEl;
|
|
29
42
|
protected firstUpdated(): void;
|
|
30
43
|
protected render(): TemplateResult;
|
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
import { nothing as
|
|
1
|
+
import { nothing as p, html as b } from "lit";
|
|
2
2
|
import { property as e, query as c, customElement as y } from "lit/decorators.js";
|
|
3
3
|
import { BahtElement as u, adoptLightChildren as m } from "../base.js";
|
|
4
4
|
import { isIconName as d, renderIcon as f } from "./icons.js";
|
|
5
|
-
var v = Object.defineProperty, O = Object.getOwnPropertyDescriptor, o = (
|
|
6
|
-
for (var i =
|
|
7
|
-
(
|
|
8
|
-
return
|
|
5
|
+
var v = Object.defineProperty, O = Object.getOwnPropertyDescriptor, o = (r, s, a, n) => {
|
|
6
|
+
for (var i = n > 1 ? void 0 : n ? O(s, a) : s, l = r.length - 1, h; l >= 0; l--)
|
|
7
|
+
(h = r[l]) && (i = (n ? h(s, a, i) : h(i)) || i);
|
|
8
|
+
return n && i && v(s, a, i), i;
|
|
9
9
|
};
|
|
10
10
|
let t = class extends u {
|
|
11
11
|
constructor() {
|
|
12
|
-
super(...arguments), this.variant = "primary", this.size = "md", this.disabled = !1, this.type = "button", this.label = "", this.icon = "", this.iconOnly = !1;
|
|
12
|
+
super(...arguments), this.variant = "primary", this.size = "md", this.disabled = !1, this.type = "button", this.label = "", this.icon = "", this.iconOnly = !1, this.hostAriaLabel = "";
|
|
13
13
|
}
|
|
14
14
|
firstUpdated() {
|
|
15
15
|
this.iconOnly || m(this, this.buttonEl);
|
|
16
16
|
}
|
|
17
17
|
render() {
|
|
18
|
-
const
|
|
18
|
+
const r = this.variant === "primary" ? "" : ` baht-button--${this.variant}`, s = this.size === "md" ? "" : ` baht-button--${this.size}`, a = this.iconOnly ? " baht-button--icon" : "", n = this.icon && d(this.icon) ? f(this.icon) : p, i = this.hostAriaLabel || (this.iconOnly && this.label ? this.label : "");
|
|
19
19
|
return b`<button
|
|
20
|
-
class="baht-button${
|
|
20
|
+
class="baht-button${r}${s}${a}"
|
|
21
21
|
type=${this.type}
|
|
22
|
-
aria-label=${
|
|
22
|
+
aria-label=${i || p}
|
|
23
23
|
?disabled=${this.disabled}
|
|
24
|
-
>${
|
|
24
|
+
>${n}${this.iconOnly ? p : this.label}</button>`;
|
|
25
25
|
}
|
|
26
26
|
};
|
|
27
27
|
o([
|
|
@@ -45,6 +45,9 @@ o([
|
|
|
45
45
|
o([
|
|
46
46
|
e({ type: Boolean, attribute: "icon-only" })
|
|
47
47
|
], t.prototype, "iconOnly", 2);
|
|
48
|
+
o([
|
|
49
|
+
e({ attribute: "aria-label" })
|
|
50
|
+
], t.prototype, "hostAriaLabel", 2);
|
|
48
51
|
o([
|
|
49
52
|
c("button")
|
|
50
53
|
], t.prototype, "buttonEl", 2);
|
|
@@ -25,6 +25,18 @@ export declare class BahtLineChart extends BahtChartBase {
|
|
|
25
25
|
labelValues: 'ends' | 'none';
|
|
26
26
|
/** Accessible summary; falls back to a generated sentence. */
|
|
27
27
|
label: string;
|
|
28
|
+
/**
|
|
29
|
+
* Drawing width in SVG units. It follows the host up to `W`, so on a phone
|
|
30
|
+
* one unit is one CSS pixel and tick text keeps its real size instead of
|
|
31
|
+
* shrinking with a 640-wide drawing scaled into a 360px card.
|
|
32
|
+
*/
|
|
33
|
+
private width;
|
|
34
|
+
private resizeObserver;
|
|
35
|
+
connectedCallback(): void;
|
|
36
|
+
disconnectedCallback(): void;
|
|
37
|
+
protected firstUpdated(): void;
|
|
38
|
+
/** Host width → drawing width. Never runs on the server (`hasDom` guard). */
|
|
39
|
+
private measure;
|
|
28
40
|
private get plot();
|
|
29
41
|
protected render(): TemplateResult;
|
|
30
42
|
private crosshairAt;
|
|
@@ -1,151 +1,176 @@
|
|
|
1
|
-
import { html as
|
|
2
|
-
import { property as
|
|
3
|
-
import { arr as
|
|
4
|
-
import { BahtChartBase as
|
|
5
|
-
var U = Object.defineProperty,
|
|
6
|
-
for (var
|
|
7
|
-
(
|
|
8
|
-
return
|
|
1
|
+
import { html as _, nothing as y, svg as l } from "lit";
|
|
2
|
+
import { property as x, state as H, customElement as N } from "lit/decorators.js";
|
|
3
|
+
import { hasDom as k, arr as L } from "../base.js";
|
|
4
|
+
import { BahtChartBase as W, niceTicks as q, linearScale as O, chartColor as g, renderTableTwin as R } from "./charts.js";
|
|
5
|
+
var U = Object.defineProperty, V = Object.getOwnPropertyDescriptor, c = (o, s, $, r) => {
|
|
6
|
+
for (var d = r > 1 ? void 0 : r ? V(s, $) : s, f = o.length - 1, b; f >= 0; f--)
|
|
7
|
+
(b = o[f]) && (d = (r ? b(s, $, d) : b(d)) || d);
|
|
8
|
+
return r && d && U(s, $, d), d;
|
|
9
9
|
};
|
|
10
|
-
const
|
|
11
|
-
let h = class extends
|
|
10
|
+
const T = 640, X = 280, A = 260, I = 56, a = { top: 14, right: 72, bottom: 30, left: 60 };
|
|
11
|
+
let h = class extends W {
|
|
12
12
|
constructor() {
|
|
13
|
-
super(...arguments), this.series = [], this.categories = [], this.area = !1, this.markers = [], this.forecast = 0, this.baseline = null, this.labelValues = "ends", this.label = "", this.crosshairAt = null;
|
|
13
|
+
super(...arguments), this.series = [], this.categories = [], this.area = !1, this.markers = [], this.forecast = 0, this.baseline = null, this.labelValues = "ends", this.label = "", this.width = T, this.crosshairAt = null;
|
|
14
|
+
}
|
|
15
|
+
connectedCallback() {
|
|
16
|
+
super.connectedCallback(), !(!k() || typeof ResizeObserver > "u") && (this.resizeObserver = new ResizeObserver(() => {
|
|
17
|
+
this.measure();
|
|
18
|
+
}), this.resizeObserver.observe(this));
|
|
19
|
+
}
|
|
20
|
+
disconnectedCallback() {
|
|
21
|
+
var o;
|
|
22
|
+
(o = this.resizeObserver) == null || o.disconnect(), this.resizeObserver = void 0, super.disconnectedCallback();
|
|
23
|
+
}
|
|
24
|
+
firstUpdated() {
|
|
25
|
+
k() && queueMicrotask(() => {
|
|
26
|
+
this.measure();
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
/** Host width → drawing width. Never runs on the server (`hasDom` guard). */
|
|
30
|
+
measure() {
|
|
31
|
+
if (!k() || !this.isConnected) return;
|
|
32
|
+
const o = this.clientWidth;
|
|
33
|
+
if (o <= 0) return;
|
|
34
|
+
const s = Math.min(T, Math.max(X, Math.round(o)));
|
|
35
|
+
s !== this.width && (this.width = s);
|
|
14
36
|
}
|
|
15
37
|
get plot() {
|
|
16
|
-
return { w:
|
|
38
|
+
return { w: this.width - a.left - a.right, h: A - a.top - a.bottom };
|
|
17
39
|
}
|
|
18
40
|
render() {
|
|
19
|
-
const
|
|
20
|
-
series:
|
|
21
|
-
categories:
|
|
22
|
-
}), { series:
|
|
23
|
-
if (
|
|
24
|
-
return
|
|
25
|
-
const
|
|
41
|
+
const o = this.hold({
|
|
42
|
+
series: L(this.series).filter((t) => t.values.length > 0),
|
|
43
|
+
categories: L(this.categories)
|
|
44
|
+
}), { series: s, categories: $ } = o;
|
|
45
|
+
if (s.length === 0)
|
|
46
|
+
return _`<div class=${this.rootClass("baht-line-chart")}>${this.renderEmpty()}</div>`;
|
|
47
|
+
const r = Math.max(...s.map((t) => t.values.length)), d = s.flatMap((t) => t.values).filter((t) => Number.isFinite(t)), f = Math.max(0, ...d, ...this.markers.map((t) => t.value)), b = q(f, 4), z = b[b.length - 1] ?? 1, { w: v, h: F } = this.plot, p = O([0, Math.max(1, r - 1)], [a.left, a.left + v]), i = O([0, z], [a.top + F, a.top]), M = Math.max(0, r - 1 - Math.max(0, this.forecast)), w = (t, e, n) => t.slice(e, n + 1).map((u, m) => `${m === 0 ? "M" : "L"}${p(e + m).toFixed(2)},${i(u).toFixed(2)}`).join(" "), P = s.map((t, e) => ({
|
|
26
48
|
i: e,
|
|
27
49
|
name: t.name,
|
|
28
50
|
value: t.values[t.values.length - 1] ?? 0,
|
|
29
|
-
yPos:
|
|
51
|
+
yPos: i(t.values[t.values.length - 1] ?? 0),
|
|
30
52
|
color: g(e, t.color)
|
|
31
|
-
})),
|
|
32
|
-
return
|
|
53
|
+
})), C = [...P].sort((t, e) => t.yPos - e.yPos), B = C.some((t, e) => e > 0 && t.yPos - C[e - 1].yPos < 15), j = this.labelValues === "ends" && !B, D = Math.max(1, Math.ceil(r / Math.max(2, Math.min(8, Math.floor(v / I))))), E = this.label || `Line chart, ${s.length} series over ${r} points. ${s.map((t, e) => `${t.name}: ${this.fmt(P[e].value)} at the end`).join(". ")}`;
|
|
54
|
+
return _`<div class=${this.rootClass("baht-line-chart")}>
|
|
33
55
|
<svg
|
|
34
56
|
class="baht-chart-svg"
|
|
35
|
-
viewBox="0 0 ${
|
|
57
|
+
viewBox="0 0 ${this.width} ${A}"
|
|
36
58
|
preserveAspectRatio="xMidYMid meet"
|
|
37
59
|
role="img"
|
|
38
|
-
aria-label=${
|
|
60
|
+
aria-label=${E}
|
|
39
61
|
>
|
|
40
|
-
${
|
|
62
|
+
${b.map(
|
|
41
63
|
(t) => l`
|
|
42
|
-
<line class="baht-chart-grid-line" x1=${
|
|
43
|
-
y1=${
|
|
44
|
-
<text class="baht-chart-tick" x=${
|
|
64
|
+
<line class="baht-chart-grid-line" x1=${a.left} x2=${a.left + v}
|
|
65
|
+
y1=${i(t).toFixed(2)} y2=${i(t).toFixed(2)}/>
|
|
66
|
+
<text class="baht-chart-tick" x=${a.left - 8} y=${(i(t) + 4).toFixed(2)}
|
|
45
67
|
text-anchor="end">${this.fmt(t)}</text>`
|
|
46
68
|
)}
|
|
47
69
|
${this.baseline != null ? [
|
|
48
|
-
l`<line class="baht-chart-baseline" x1=${
|
|
49
|
-
y1=${
|
|
70
|
+
l`<line class="baht-chart-baseline" x1=${a.left} x2=${a.left + v}
|
|
71
|
+
y1=${i(this.baseline).toFixed(2)} y2=${i(this.baseline).toFixed(2)}/>`
|
|
50
72
|
] : []}
|
|
51
|
-
${
|
|
73
|
+
${L(this.markers).map(
|
|
52
74
|
(t) => l`
|
|
53
|
-
<line class="baht-chart-marker-line" x1=${
|
|
54
|
-
y1=${
|
|
55
|
-
<text class="baht-chart-marker-label" x=${
|
|
75
|
+
<line class="baht-chart-marker-line" x1=${a.left} x2=${a.left + v}
|
|
76
|
+
y1=${i(t.value).toFixed(2)} y2=${i(t.value).toFixed(2)}/>
|
|
77
|
+
<text class="baht-chart-marker-label" x=${a.left + v} y=${(i(t.value) - 5).toFixed(2)}
|
|
56
78
|
text-anchor="end">${t.label ?? this.fmt(t.value)}</text>`
|
|
57
79
|
)}
|
|
58
|
-
${this.area &&
|
|
59
|
-
d=${`${
|
|
60
|
-
${
|
|
61
|
-
const
|
|
62
|
-
l`<path class="baht-chart-line" d=${
|
|
80
|
+
${this.area && s.length === 1 ? l`<path class="baht-chart-area" fill=${g(0, s[0].color)}
|
|
81
|
+
d=${`${w(s[0].values, 0, r - 1)} L${p(r - 1).toFixed(2)},${i(0).toFixed(2)} L${p(0).toFixed(2)},${i(0).toFixed(2)} Z`}/>` : y}
|
|
82
|
+
${s.map((t, e) => {
|
|
83
|
+
const n = g(e, t.color), u = [
|
|
84
|
+
l`<path class="baht-chart-line" d=${w(t.values, 0, M)} stroke=${n} fill="none"/>`
|
|
63
85
|
];
|
|
64
|
-
return M <
|
|
65
|
-
l`<path class="baht-chart-line baht-chart-line--forecast" d=${
|
|
66
|
-
stroke=${
|
|
67
|
-
),
|
|
68
|
-
l`<circle class="baht-chart-end-dot" cx=${
|
|
69
|
-
cy=${
|
|
70
|
-
),
|
|
86
|
+
return M < r - 1 && u.push(
|
|
87
|
+
l`<path class="baht-chart-line baht-chart-line--forecast" d=${w(t.values, M, r - 1)}
|
|
88
|
+
stroke=${n} fill="none"/>`
|
|
89
|
+
), u.push(
|
|
90
|
+
l`<circle class="baht-chart-end-dot" cx=${p(r - 1).toFixed(2)}
|
|
91
|
+
cy=${i(t.values[t.values.length - 1] ?? 0).toFixed(2)} r="4" fill=${n}/>`
|
|
92
|
+
), u;
|
|
71
93
|
})}
|
|
72
|
-
${
|
|
94
|
+
${j ? P.map(
|
|
73
95
|
(t) => l`
|
|
74
|
-
<text class="baht-chart-end-label" x=${
|
|
96
|
+
<text class="baht-chart-end-label" x=${p(r - 1) + 10} y=${(t.yPos + 4).toFixed(2)}
|
|
75
97
|
text-anchor="start">${this.fmt(t.value)}</text>`
|
|
76
98
|
) : y}
|
|
77
|
-
${
|
|
78
|
-
(t, e) => e %
|
|
99
|
+
${$.map(
|
|
100
|
+
(t, e) => e % D === 0 ? l`<text class="baht-chart-tick" x=${p(e).toFixed(2)} y=${A - 10} text-anchor="middle">${t}</text>` : y
|
|
79
101
|
)}
|
|
80
|
-
${Array.from({ length:
|
|
81
|
-
const
|
|
82
|
-
return l`<rect class="baht-chart-hit" x=${(
|
|
83
|
-
width=${Math.max(24,
|
|
84
|
-
aria-label=${
|
|
85
|
-
@pointermove=${(
|
|
86
|
-
this.onHover(
|
|
102
|
+
${Array.from({ length: r }, (t, e) => {
|
|
103
|
+
const n = v / Math.max(1, r - 1), u = `${$[e] ?? `Point ${e + 1}`}: ${s.map((m) => `${m.name} ${this.fmt(m.values[e] ?? 0)}`).join(", ")}`;
|
|
104
|
+
return l`<rect class="baht-chart-hit" x=${(p(e) - n / 2).toFixed(2)} y=${a.top}
|
|
105
|
+
width=${Math.max(24, n).toFixed(2)} height=${F} tabindex="0" role="button"
|
|
106
|
+
aria-label=${u}
|
|
107
|
+
@pointermove=${(m) => {
|
|
108
|
+
this.onHover(m, e, u);
|
|
87
109
|
}}
|
|
88
110
|
@pointerleave=${() => {
|
|
89
111
|
this.onLeave();
|
|
90
112
|
}}
|
|
91
|
-
@focus=${(
|
|
92
|
-
this.onHover(
|
|
113
|
+
@focus=${(m) => {
|
|
114
|
+
this.onHover(m, e, u);
|
|
93
115
|
}}
|
|
94
116
|
@blur=${() => {
|
|
95
117
|
this.onLeave();
|
|
96
118
|
}}/>`;
|
|
97
119
|
})}
|
|
98
|
-
${this.crosshairAt != null ? l`<line class="baht-chart-crosshair" x1=${
|
|
99
|
-
x2=${
|
|
120
|
+
${this.crosshairAt != null ? l`<line class="baht-chart-crosshair" x1=${p(this.crosshairAt).toFixed(2)}
|
|
121
|
+
x2=${p(this.crosshairAt).toFixed(2)} y1=${a.top} y2=${a.top + F}/>` : y}
|
|
100
122
|
</svg>
|
|
101
123
|
${this.renderTooltip()}
|
|
102
124
|
${this.renderLegend(
|
|
103
|
-
|
|
125
|
+
s.map((t, e) => ({ label: t.name, color: g(e, t.color) })),
|
|
104
126
|
"line"
|
|
105
127
|
)}
|
|
106
|
-
${this.showTable ?
|
|
128
|
+
${this.showTable ? R(
|
|
107
129
|
this.label || "Line chart data",
|
|
108
|
-
["Point", ...
|
|
109
|
-
Array.from({ length:
|
|
110
|
-
|
|
111
|
-
...
|
|
130
|
+
["Point", ...s.map((t) => t.name)],
|
|
131
|
+
Array.from({ length: r }, (t, e) => [
|
|
132
|
+
$[e] ?? `Point ${e + 1}`,
|
|
133
|
+
...s.map((n) => this.fmt(n.values[e] ?? 0))
|
|
112
134
|
])
|
|
113
135
|
) : y}
|
|
114
136
|
</div>`;
|
|
115
137
|
}
|
|
116
|
-
onHover(
|
|
117
|
-
this.crosshairAt =
|
|
138
|
+
onHover(o, s, $) {
|
|
139
|
+
this.crosshairAt = s, this.requestUpdate(), this.showTip(o, $);
|
|
118
140
|
}
|
|
119
141
|
onLeave() {
|
|
120
142
|
this.crosshairAt = null, this.requestUpdate(), this.hideTip();
|
|
121
143
|
}
|
|
122
144
|
};
|
|
123
|
-
|
|
124
|
-
|
|
145
|
+
c([
|
|
146
|
+
x({ attribute: !1 })
|
|
125
147
|
], h.prototype, "series", 2);
|
|
126
|
-
|
|
127
|
-
|
|
148
|
+
c([
|
|
149
|
+
x({ attribute: !1 })
|
|
128
150
|
], h.prototype, "categories", 2);
|
|
129
|
-
|
|
130
|
-
|
|
151
|
+
c([
|
|
152
|
+
x({ type: Boolean })
|
|
131
153
|
], h.prototype, "area", 2);
|
|
132
|
-
|
|
133
|
-
|
|
154
|
+
c([
|
|
155
|
+
x({ attribute: !1 })
|
|
134
156
|
], h.prototype, "markers", 2);
|
|
135
|
-
|
|
136
|
-
|
|
157
|
+
c([
|
|
158
|
+
x({ type: Number })
|
|
137
159
|
], h.prototype, "forecast", 2);
|
|
138
|
-
|
|
139
|
-
|
|
160
|
+
c([
|
|
161
|
+
x({ type: Number })
|
|
140
162
|
], h.prototype, "baseline", 2);
|
|
141
|
-
|
|
142
|
-
|
|
163
|
+
c([
|
|
164
|
+
x({ attribute: "label-values" })
|
|
143
165
|
], h.prototype, "labelValues", 2);
|
|
144
|
-
|
|
145
|
-
|
|
166
|
+
c([
|
|
167
|
+
x()
|
|
146
168
|
], h.prototype, "label", 2);
|
|
147
|
-
|
|
148
|
-
|
|
169
|
+
c([
|
|
170
|
+
H()
|
|
171
|
+
], h.prototype, "width", 2);
|
|
172
|
+
h = c([
|
|
173
|
+
N("baht-line-chart")
|
|
149
174
|
], h);
|
|
150
175
|
export {
|
|
151
176
|
h as BahtLineChart
|
package/dist/core/i18n.d.ts
CHANGED
|
@@ -28,6 +28,10 @@ export interface MessageCatalog {
|
|
|
28
28
|
removeRow: string;
|
|
29
29
|
minRows: string;
|
|
30
30
|
maxRows: string;
|
|
31
|
+
/** `min_rows: 1`, where "{n} rows" would read "1 rows". */
|
|
32
|
+
minRowsOne: string;
|
|
33
|
+
/** `max_rows: 1`. */
|
|
34
|
+
maxRowsOne: string;
|
|
31
35
|
next: string;
|
|
32
36
|
submit: string;
|
|
33
37
|
back: string;
|
package/dist/core/i18n.js
CHANGED
|
@@ -28,6 +28,8 @@ const n = {
|
|
|
28
28
|
removeRow: "Remove row",
|
|
29
29
|
minRows: "Add at least {n} rows",
|
|
30
30
|
maxRows: "Add at most {n} rows",
|
|
31
|
+
minRowsOne: "Add at least one row",
|
|
32
|
+
maxRowsOne: "Add at most one row",
|
|
31
33
|
next: "Next",
|
|
32
34
|
submit: "Submit",
|
|
33
35
|
back: "Back",
|
|
@@ -93,6 +95,8 @@ const n = {
|
|
|
93
95
|
removeRow: "ลบแถว",
|
|
94
96
|
minRows: "ต้องมีอย่างน้อย {n} แถว",
|
|
95
97
|
maxRows: "ต้องไม่เกิน {n} แถว",
|
|
98
|
+
minRowsOne: "ต้องมีอย่างน้อย 1 แถว",
|
|
99
|
+
maxRowsOne: "ต้องไม่เกิน 1 แถว",
|
|
96
100
|
next: "ถัดไป",
|
|
97
101
|
submit: "ส่งข้อมูล",
|
|
98
102
|
back: "ย้อนกลับ",
|
package/dist/core/validators.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { defaultValue as
|
|
1
|
+
import { defaultValue as w } from "./defaults.js";
|
|
2
2
|
import { compareValues as k } from "./engine/conditions.js";
|
|
3
|
-
import { isoDaysOf as x, dateModeOf as
|
|
4
|
-
import { t as
|
|
3
|
+
import { isoDaysOf as x, dateModeOf as _, rangeInteriorDays as b, isDateDisabled as A } from "./dates.js";
|
|
4
|
+
import { t as i } from "./i18n.js";
|
|
5
5
|
const L = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
6
|
-
function
|
|
6
|
+
function l(e) {
|
|
7
7
|
return e == null ? !0 : typeof e == "string" ? e === "" : Array.isArray(e) ? e.length === 0 : typeof e == "boolean" ? !e : !1;
|
|
8
8
|
}
|
|
9
9
|
function d(e) {
|
|
@@ -16,14 +16,14 @@ function h(e, t) {
|
|
|
16
16
|
const r = Number(n.value);
|
|
17
17
|
return Number.isNaN(r) ? (console.warn(
|
|
18
18
|
`[bahtui] ${t} validator has non-numeric value ${JSON.stringify(n.value)} — skipped`
|
|
19
|
-
), null) : typeof s != "string" ? null : (e === "minLength" ? s.length < r : s.length > r) ? n.message ??
|
|
19
|
+
), null) : typeof s != "string" ? null : (e === "minLength" ? s.length < r : s.length > r) ? n.message ?? i(e, { n: n.value }) : null;
|
|
20
20
|
};
|
|
21
21
|
}
|
|
22
22
|
function f(e) {
|
|
23
23
|
return (t, n) => E(n).some((r) => {
|
|
24
24
|
const o = k(r, t.value);
|
|
25
25
|
return o !== null && (e === "min" ? o < 0 : o > 0);
|
|
26
|
-
}) ? t.message ??
|
|
26
|
+
}) ? t.message ?? i(e, { n: t.value }) : null;
|
|
27
27
|
}
|
|
28
28
|
const C = {
|
|
29
29
|
eq: (e) => e === 0,
|
|
@@ -32,39 +32,39 @@ const C = {
|
|
|
32
32
|
gte: (e) => e >= 0,
|
|
33
33
|
lt: (e) => e < 0,
|
|
34
34
|
lte: (e) => e <= 0
|
|
35
|
-
},
|
|
35
|
+
}, R = (e, t, n, s) => {
|
|
36
36
|
const r = s == null ? void 0 : s[e.field ?? ""];
|
|
37
|
-
if (r === void 0 ||
|
|
37
|
+
if (r === void 0 || l(r)) return null;
|
|
38
38
|
const o = k(t, r);
|
|
39
39
|
if (o === null) return null;
|
|
40
40
|
const a = e.op ?? "eq";
|
|
41
41
|
if (C[a](o)) return null;
|
|
42
42
|
const m = `compare${a[0].toUpperCase()}${a.slice(1)}`;
|
|
43
|
-
return e.message ??
|
|
44
|
-
},
|
|
43
|
+
return e.message ?? i(m, { other: e.field });
|
|
44
|
+
}, $ = (e, t) => {
|
|
45
45
|
if (typeof t != "string") return null;
|
|
46
46
|
const n = D(String(e.value));
|
|
47
|
-
return n ? n.test(t) ? null : e.message ??
|
|
48
|
-
},
|
|
47
|
+
return n ? n.test(t) ? null : e.message ?? i("pattern") : null;
|
|
48
|
+
}, O = (e, t, n) => {
|
|
49
49
|
var o;
|
|
50
50
|
const s = (o = n == null ? void 0 : n.validators) == null ? void 0 : o[e.fn ?? ""];
|
|
51
51
|
if (!s)
|
|
52
52
|
return console.warn(`[bahtui] unknown custom validator "${e.fn}" — skipped`), null;
|
|
53
53
|
const r = s(t);
|
|
54
54
|
return r === null ? null : e.message ?? r;
|
|
55
|
-
},
|
|
56
|
-
required: (e, t) =>
|
|
55
|
+
}, q = {
|
|
56
|
+
required: (e, t) => l(t) ? e.message ?? i("required") : null,
|
|
57
57
|
minLength: h("minLength", "min_length"),
|
|
58
58
|
maxLength: h("maxLength", "max_length"),
|
|
59
59
|
min: f("min"),
|
|
60
60
|
max: f("max"),
|
|
61
|
-
pattern:
|
|
62
|
-
email: (e, t) => typeof t == "string" && !L.test(t) ? e.message ??
|
|
63
|
-
compare:
|
|
64
|
-
custom:
|
|
61
|
+
pattern: $,
|
|
62
|
+
email: (e, t) => typeof t == "string" && !L.test(t) ? e.message ?? i("email") : null,
|
|
63
|
+
compare: R,
|
|
64
|
+
custom: O
|
|
65
65
|
};
|
|
66
|
-
function
|
|
67
|
-
return
|
|
66
|
+
function N(e, t, n, s) {
|
|
67
|
+
return q[e.type](e, t, n, s);
|
|
68
68
|
}
|
|
69
69
|
const g = /* @__PURE__ */ new Map();
|
|
70
70
|
function D(e) {
|
|
@@ -80,10 +80,10 @@ function D(e) {
|
|
|
80
80
|
return t;
|
|
81
81
|
}
|
|
82
82
|
function S(e, t, n, s) {
|
|
83
|
-
const r = [], o = d(e), a =
|
|
83
|
+
const r = [], o = d(e), a = l(t);
|
|
84
84
|
for (const m of o) {
|
|
85
85
|
if (m.type !== "required" && a) continue;
|
|
86
|
-
const c =
|
|
86
|
+
const c = N(m, t, n, s);
|
|
87
87
|
c !== null && r.push({ key: e.key, message: c });
|
|
88
88
|
}
|
|
89
89
|
return e.type === "repeater" && r.push(...V(e, t, n)), e.type === "file" && r.push(...T(e, t)), e.type === "date" && !a && r.push(...M(e, t)), r;
|
|
@@ -92,7 +92,7 @@ function M(e, t) {
|
|
|
92
92
|
var s, r;
|
|
93
93
|
if (!((s = e.disabled_dates) != null && s.length) && !((r = e.disabled_weekdays) != null && r.length)) return [];
|
|
94
94
|
const n = x(t);
|
|
95
|
-
return
|
|
95
|
+
return _(e) === "range" && n.length === 2 && n.push(...b(n[0], n[1])), n.some((o) => A(e, o)) ? [{ key: e.key, message: i("dateDisabled") }] : [];
|
|
96
96
|
}
|
|
97
97
|
function P(e) {
|
|
98
98
|
return e !== null && typeof e == "object" && typeof e.url == "string" && typeof e.size == "number" && typeof e.name == "string";
|
|
@@ -106,22 +106,29 @@ function z(e, t, n) {
|
|
|
106
106
|
function T(e, t) {
|
|
107
107
|
const n = (Array.isArray(t) ? t : [t]).filter(P), s = [];
|
|
108
108
|
for (const r of n)
|
|
109
|
-
e.max_size !== void 0 && r.size > e.max_size && s.push({ key: e.key, message:
|
|
109
|
+
e.max_size !== void 0 && r.size > e.max_size && s.push({ key: e.key, message: i("fileTooLarge") }), e.accept && !z(e.accept, r.name, r.type ?? "") && s.push({ key: e.key, message: i("fileTypeNotAllowed") });
|
|
110
110
|
return s;
|
|
111
111
|
}
|
|
112
112
|
function V(e, t, n) {
|
|
113
113
|
if (t != null && !Array.isArray(t))
|
|
114
|
-
return [{ key: e.key, message:
|
|
114
|
+
return [{ key: e.key, message: i("pattern") }];
|
|
115
115
|
const s = Array.isArray(t) ? t : [], r = [];
|
|
116
|
-
e.min_rows !== void 0 && s.length < e.min_rows
|
|
116
|
+
if (e.min_rows !== void 0 && s.length < e.min_rows) {
|
|
117
|
+
const a = e.min_rows === 1 ? i("minRowsOne") : i("minRows", { n: e.min_rows });
|
|
118
|
+
r.push({ key: e.key, message: a });
|
|
119
|
+
}
|
|
120
|
+
if (e.max_rows !== void 0 && s.length > e.max_rows) {
|
|
121
|
+
const a = e.max_rows === 1 ? i("maxRowsOne") : i("maxRows", { n: e.max_rows });
|
|
122
|
+
r.push({ key: e.key, message: a });
|
|
123
|
+
}
|
|
117
124
|
const o = [...e.fields ?? []].sort((a, m) => a.order - m.order);
|
|
118
125
|
return s.forEach((a, m) => {
|
|
119
|
-
const c = a !== null && typeof a == "object" && !Array.isArray(a) ? a : {},
|
|
120
|
-
for (const
|
|
121
|
-
|
|
122
|
-
for (const
|
|
123
|
-
if (!(
|
|
124
|
-
for (const y of S(
|
|
126
|
+
const c = a !== null && typeof a == "object" && !Array.isArray(a) ? a : {}, p = {};
|
|
127
|
+
for (const u of o)
|
|
128
|
+
u.type === "label" || u.type === "section" || u.type === "repeater" || (p[u.key] = Object.hasOwn(c, u.key) ? c[u.key] : w(u));
|
|
129
|
+
for (const u of o)
|
|
130
|
+
if (!(u.type === "label" || u.type === "section" || u.type === "repeater"))
|
|
131
|
+
for (const y of S(u, p[u.key], n, p))
|
|
125
132
|
r.push({ key: `${e.key}[${m}].${y.key}`, message: y.message });
|
|
126
133
|
}), r;
|
|
127
134
|
}
|
package/dist/css/components.css
CHANGED
|
@@ -396,6 +396,10 @@
|
|
|
396
396
|
display: flex;
|
|
397
397
|
align-items: center;
|
|
398
398
|
gap: var(--baht-space-2);
|
|
399
|
+
/* A narrow card (a 1/4 option width in a phone-width form) drops the label
|
|
400
|
+
under its icon instead of pushing it past the card edge into the next one. */
|
|
401
|
+
flex-wrap: wrap;
|
|
402
|
+
min-width: 0;
|
|
399
403
|
}
|
|
400
404
|
/* `option.width` — same fractions as `field.width`, against the card row's
|
|
401
405
|
own gap (`--baht-space-3`) instead of the form grid's `--baht-field-gap`,
|
|
@@ -407,6 +411,7 @@
|
|
|
407
411
|
.baht-option-card--w-1-4 {
|
|
408
412
|
flex: 0 0 calc(25% - var(--baht-space-3) * 3 / 4);
|
|
409
413
|
min-width: 0;
|
|
414
|
+
padding-inline: var(--baht-space-3);
|
|
410
415
|
}
|
|
411
416
|
.baht-option-card--w-1-2 {
|
|
412
417
|
flex: 0 0 calc(50% - var(--baht-space-3) / 2);
|
|
@@ -449,6 +454,11 @@
|
|
|
449
454
|
.baht-option-card-title {
|
|
450
455
|
font-weight: 600;
|
|
451
456
|
color: var(--baht-color-text);
|
|
457
|
+
/* Last resort when even its own line is too narrow: clip, never overflow. */
|
|
458
|
+
min-width: 0;
|
|
459
|
+
max-width: 100%;
|
|
460
|
+
overflow: hidden;
|
|
461
|
+
text-overflow: ellipsis;
|
|
452
462
|
}
|
|
453
463
|
.baht-option-card-desc {
|
|
454
464
|
font-size: var(--baht-text-sm);
|
|
@@ -2546,16 +2556,17 @@ code.baht-code {
|
|
|
2546
2556
|
vertical-align: middle;
|
|
2547
2557
|
background: var(--baht-color-text-muted);
|
|
2548
2558
|
}
|
|
2549
|
-
/* A row
|
|
2550
|
-
never
|
|
2559
|
+
/* A row with its own marker (a budget line) gets a caption lane above its
|
|
2560
|
+
bars: the label sits there beside its line and never covers a bar or the
|
|
2561
|
+
bar's value. */
|
|
2562
|
+
.baht-bar-chart-track--marked {
|
|
2563
|
+
padding-top: 1.1rem;
|
|
2564
|
+
}
|
|
2551
2565
|
.baht-bar-chart-marker-label--row {
|
|
2552
|
-
top:
|
|
2566
|
+
top: 0;
|
|
2553
2567
|
bottom: auto;
|
|
2554
2568
|
z-index: 2;
|
|
2555
|
-
|
|
2556
|
-
background: var(--baht-chart-surface);
|
|
2557
|
-
padding: 0 4px;
|
|
2558
|
-
border-radius: var(--baht-radius-xs);
|
|
2569
|
+
padding: 0 2px;
|
|
2559
2570
|
}
|
|
2560
2571
|
.baht-bar-chart-marker-label--row::before {
|
|
2561
2572
|
display: none; /* the line it names is right beside it */
|
|
@@ -4015,7 +4015,7 @@
|
|
|
4015
4015
|
"declarations": [
|
|
4016
4016
|
{
|
|
4017
4017
|
"kind": "class",
|
|
4018
|
-
"description": "Design-system button (20baht: no scale, no shadow change — color does the work).\nStandalone primitive: children become the label, listen for the native `click`.\n(Light DOM has no <slot>, so the initial children are moved into the button.)\n\n <baht-button variant=\"danger\" size=\"sm\">Delete</baht-button>\n <baht-button label=\"Save workflow\"></baht-button>\n <baht-button icon=\"copy\" variant=\"ghost\" size=\"sm\">Copy</baht-button>\n <baht-button icon=\"close\" icon-only label=\"Close\"></baht-button> <!-- label = a11y name -->",
|
|
4018
|
+
"description": "Design-system button (20baht: no scale, no shadow change — color does the work).\nStandalone primitive: children become the label, listen for the native `click`.\n(Light DOM has no <slot>, so the initial children are moved into the button.)\n\n <baht-button variant=\"danger\" size=\"sm\">Delete</baht-button>\n <baht-button label=\"Save workflow\"></baht-button>\n <baht-button icon=\"copy\" variant=\"ghost\" size=\"sm\">Copy</baht-button>\n <baht-button icon=\"close\" icon-only label=\"Close\"></baht-button> <!-- label = a11y name -->\n <baht-button aria-label=\"Previous month\">‹</baht-button> <!-- glyph child, host aria-label wins -->",
|
|
4019
4019
|
"name": "BahtButton",
|
|
4020
4020
|
"members": [
|
|
4021
4021
|
{
|
|
@@ -4085,6 +4085,16 @@
|
|
|
4085
4085
|
"description": "Square icon-only button. Requires `label` for the accessible name.",
|
|
4086
4086
|
"attribute": "icon-only"
|
|
4087
4087
|
},
|
|
4088
|
+
{
|
|
4089
|
+
"kind": "field",
|
|
4090
|
+
"name": "hostAriaLabel",
|
|
4091
|
+
"type": {
|
|
4092
|
+
"text": "string"
|
|
4093
|
+
},
|
|
4094
|
+
"default": "''",
|
|
4095
|
+
"description": "A host `aria-label` never reaches assistive tech on its own — light DOM has no\nimplicit ARIA relationship between a custom element and its rendered children, so an\n`aria-label` written on `<baht-button>` stays on the host and the inner native\n`<button>` keeps whatever text (or none) is inside it. Mirroring the attribute into\nthis property forwards it to the inner button's `aria-label`, taking priority over\n`label`/icon-only fallback — this is how a glyph-only child (e.g. `‹`) gets a real\naccessible name without `icon-only`. Mapped to the plain `aria-label` attribute so\nhosts write it the way they naturally would; kept off the `ariaLabel` IDL accessor to\navoid shadowing the platform's own ARIAMixin.",
|
|
4096
|
+
"attribute": "aria-label"
|
|
4097
|
+
},
|
|
4088
4098
|
{
|
|
4089
4099
|
"kind": "field",
|
|
4090
4100
|
"name": "buttonEl",
|
|
@@ -4199,6 +4209,15 @@
|
|
|
4199
4209
|
"description": "Square icon-only button. Requires `label` for the accessible name.",
|
|
4200
4210
|
"fieldName": "iconOnly"
|
|
4201
4211
|
},
|
|
4212
|
+
{
|
|
4213
|
+
"name": "aria-label",
|
|
4214
|
+
"type": {
|
|
4215
|
+
"text": "string"
|
|
4216
|
+
},
|
|
4217
|
+
"default": "''",
|
|
4218
|
+
"description": "A host `aria-label` never reaches assistive tech on its own — light DOM has no\nimplicit ARIA relationship between a custom element and its rendered children, so an\n`aria-label` written on `<baht-button>` stays on the host and the inner native\n`<button>` keeps whatever text (or none) is inside it. Mirroring the attribute into\nthis property forwards it to the inner button's `aria-label`, taking priority over\n`label`/icon-only fallback — this is how a glyph-only child (e.g. `‹`) gets a real\naccessible name without `icon-only`. Mapped to the plain `aria-label` attribute so\nhosts write it the way they naturally would; kept off the `ariaLabel` IDL accessor to\navoid shadowing the platform's own ARIAMixin.",
|
|
4219
|
+
"fieldName": "hostAriaLabel"
|
|
4220
|
+
},
|
|
4202
4221
|
{
|
|
4203
4222
|
"name": "defer-hydration",
|
|
4204
4223
|
"inheritedFrom": {
|
|
@@ -10081,6 +10100,35 @@
|
|
|
10081
10100
|
"description": "Accessible summary; falls back to a generated sentence.",
|
|
10082
10101
|
"attribute": "label"
|
|
10083
10102
|
},
|
|
10103
|
+
{
|
|
10104
|
+
"kind": "field",
|
|
10105
|
+
"name": "width",
|
|
10106
|
+
"privacy": "private",
|
|
10107
|
+
"default": "640",
|
|
10108
|
+
"description": "Drawing width in SVG units. It follows the host up to `W`, so on a phone\none unit is one CSS pixel and tick text keeps its real size instead of\nshrinking with a 640-wide drawing scaled into a 360px card.",
|
|
10109
|
+
"type": {
|
|
10110
|
+
"text": "number"
|
|
10111
|
+
}
|
|
10112
|
+
},
|
|
10113
|
+
{
|
|
10114
|
+
"kind": "field",
|
|
10115
|
+
"name": "resizeObserver",
|
|
10116
|
+
"type": {
|
|
10117
|
+
"text": "ResizeObserver | undefined"
|
|
10118
|
+
},
|
|
10119
|
+
"privacy": "private"
|
|
10120
|
+
},
|
|
10121
|
+
{
|
|
10122
|
+
"kind": "method",
|
|
10123
|
+
"name": "measure",
|
|
10124
|
+
"privacy": "private",
|
|
10125
|
+
"return": {
|
|
10126
|
+
"type": {
|
|
10127
|
+
"text": "void"
|
|
10128
|
+
}
|
|
10129
|
+
},
|
|
10130
|
+
"description": "Host width → drawing width. Never runs on the server (`hasDom` guard)."
|
|
10131
|
+
},
|
|
10084
10132
|
{
|
|
10085
10133
|
"kind": "field",
|
|
10086
10134
|
"name": "plot",
|
package/dist/tokens.css
CHANGED
|
@@ -830,6 +830,10 @@
|
|
|
830
830
|
display: flex;
|
|
831
831
|
align-items: center;
|
|
832
832
|
gap: var(--baht-space-2);
|
|
833
|
+
/* A narrow card (a 1/4 option width in a phone-width form) drops the label
|
|
834
|
+
under its icon instead of pushing it past the card edge into the next one. */
|
|
835
|
+
flex-wrap: wrap;
|
|
836
|
+
min-width: 0;
|
|
833
837
|
}
|
|
834
838
|
/* `option.width` — same fractions as `field.width`, against the card row's
|
|
835
839
|
own gap (`--baht-space-3`) instead of the form grid's `--baht-field-gap`,
|
|
@@ -841,6 +845,7 @@
|
|
|
841
845
|
.baht-option-card--w-1-4 {
|
|
842
846
|
flex: 0 0 calc(25% - var(--baht-space-3) * 3 / 4);
|
|
843
847
|
min-width: 0;
|
|
848
|
+
padding-inline: var(--baht-space-3);
|
|
844
849
|
}
|
|
845
850
|
.baht-option-card--w-1-2 {
|
|
846
851
|
flex: 0 0 calc(50% - var(--baht-space-3) / 2);
|
|
@@ -883,6 +888,11 @@
|
|
|
883
888
|
.baht-option-card-title {
|
|
884
889
|
font-weight: 600;
|
|
885
890
|
color: var(--baht-color-text);
|
|
891
|
+
/* Last resort when even its own line is too narrow: clip, never overflow. */
|
|
892
|
+
min-width: 0;
|
|
893
|
+
max-width: 100%;
|
|
894
|
+
overflow: hidden;
|
|
895
|
+
text-overflow: ellipsis;
|
|
886
896
|
}
|
|
887
897
|
.baht-option-card-desc {
|
|
888
898
|
font-size: var(--baht-text-sm);
|
|
@@ -2980,16 +2990,17 @@ code.baht-code {
|
|
|
2980
2990
|
vertical-align: middle;
|
|
2981
2991
|
background: var(--baht-color-text-muted);
|
|
2982
2992
|
}
|
|
2983
|
-
/* A row
|
|
2984
|
-
never
|
|
2993
|
+
/* A row with its own marker (a budget line) gets a caption lane above its
|
|
2994
|
+
bars: the label sits there beside its line and never covers a bar or the
|
|
2995
|
+
bar's value. */
|
|
2996
|
+
.baht-bar-chart-track--marked {
|
|
2997
|
+
padding-top: 1.1rem;
|
|
2998
|
+
}
|
|
2985
2999
|
.baht-bar-chart-marker-label--row {
|
|
2986
|
-
top:
|
|
3000
|
+
top: 0;
|
|
2987
3001
|
bottom: auto;
|
|
2988
3002
|
z-index: 2;
|
|
2989
|
-
|
|
2990
|
-
background: var(--baht-chart-surface);
|
|
2991
|
-
padding: 0 4px;
|
|
2992
|
-
border-radius: var(--baht-radius-xs);
|
|
3003
|
+
padding: 0 2px;
|
|
2993
3004
|
}
|
|
2994
3005
|
.baht-bar-chart-marker-label--row::before {
|
|
2995
3006
|
display: none; /* the line it names is right beside it */
|
|
@@ -189,7 +189,7 @@
|
|
|
189
189
|
},
|
|
190
190
|
{
|
|
191
191
|
"name": "baht-button",
|
|
192
|
-
"description": "Design-system button (20baht: no scale, no shadow change — color does the work).\nStandalone primitive: children become the label, listen for the native `click`.\n(Light DOM has no <slot>, so the initial children are moved into the button.)\n\n <baht-button variant=\"danger\" size=\"sm\">Delete</baht-button>\n <baht-button label=\"Save workflow\"></baht-button>\n <baht-button icon=\"copy\" variant=\"ghost\" size=\"sm\">Copy</baht-button>\n <baht-button icon=\"close\" icon-only label=\"Close\"></baht-button> <!-- label = a11y name -->\n---\n\n\n### **Events:**\n - **name**\n\n### **Methods:**\n ",
|
|
192
|
+
"description": "Design-system button (20baht: no scale, no shadow change — color does the work).\nStandalone primitive: children become the label, listen for the native `click`.\n(Light DOM has no <slot>, so the initial children are moved into the button.)\n\n <baht-button variant=\"danger\" size=\"sm\">Delete</baht-button>\n <baht-button label=\"Save workflow\"></baht-button>\n <baht-button icon=\"copy\" variant=\"ghost\" size=\"sm\">Copy</baht-button>\n <baht-button icon=\"close\" icon-only label=\"Close\"></baht-button> <!-- label = a11y name -->\n <baht-button aria-label=\"Previous month\">‹</baht-button> <!-- glyph child, host aria-label wins -->\n---\n\n\n### **Events:**\n - **name**\n\n### **Methods:**\n ",
|
|
193
193
|
"attributes": [
|
|
194
194
|
{ "name": "variant", "values": [{ "name": "ButtonVariant" }] },
|
|
195
195
|
{ "name": "size", "values": [{ "name": "ButtonSize" }] },
|
|
@@ -214,6 +214,11 @@
|
|
|
214
214
|
"description": "Square icon-only button. Requires `label` for the accessible name.",
|
|
215
215
|
"values": []
|
|
216
216
|
},
|
|
217
|
+
{
|
|
218
|
+
"name": "aria-label",
|
|
219
|
+
"description": "A host `aria-label` never reaches assistive tech on its own — light DOM has no\nimplicit ARIA relationship between a custom element and its rendered children, so an\n`aria-label` written on `<baht-button>` stays on the host and the inner native\n`<button>` keeps whatever text (or none) is inside it. Mirroring the attribute into\nthis property forwards it to the inner button's `aria-label`, taking priority over\n`label`/icon-only fallback — this is how a glyph-only child (e.g. `‹`) gets a real\naccessible name without `icon-only`. Mapped to the plain `aria-label` attribute so\nhosts write it the way they naturally would; kept off the `ariaLabel` IDL accessor to\navoid shadowing the platform's own ARIAMixin.",
|
|
220
|
+
"values": []
|
|
221
|
+
},
|
|
217
222
|
{ "name": "defer-hydration", "values": [] }
|
|
218
223
|
],
|
|
219
224
|
"references": []
|
package/dist/web-types.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://raw.githubusercontent.com/JetBrains/web-types/master/schema/web-types.json",
|
|
3
3
|
"name": "bank20baht-ui",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.9.0",
|
|
5
5
|
"description-markup": "markdown",
|
|
6
6
|
"contributions": {
|
|
7
7
|
"html": {
|
|
@@ -454,7 +454,7 @@
|
|
|
454
454
|
},
|
|
455
455
|
{
|
|
456
456
|
"name": "baht-button",
|
|
457
|
-
"description": "Design-system button (20baht: no scale, no shadow change — color does the work).\nStandalone primitive: children become the label, listen for the native `click`.\n(Light DOM has no <slot>, so the initial children are moved into the button.)\n\n <baht-button variant=\"danger\" size=\"sm\">Delete</baht-button>\n <baht-button label=\"Save workflow\"></baht-button>\n <baht-button icon=\"copy\" variant=\"ghost\" size=\"sm\">Copy</baht-button>\n <baht-button icon=\"close\" icon-only label=\"Close\"></baht-button> <!-- label = a11y name -->\n---\n\n\n### **Events:**\n - **name**\n\n### **Methods:**\n ",
|
|
457
|
+
"description": "Design-system button (20baht: no scale, no shadow change — color does the work).\nStandalone primitive: children become the label, listen for the native `click`.\n(Light DOM has no <slot>, so the initial children are moved into the button.)\n\n <baht-button variant=\"danger\" size=\"sm\">Delete</baht-button>\n <baht-button label=\"Save workflow\"></baht-button>\n <baht-button icon=\"copy\" variant=\"ghost\" size=\"sm\">Copy</baht-button>\n <baht-button icon=\"close\" icon-only label=\"Close\"></baht-button> <!-- label = a11y name -->\n <baht-button aria-label=\"Previous month\">‹</baht-button> <!-- glyph child, host aria-label wins -->\n---\n\n\n### **Events:**\n - **name**\n\n### **Methods:**\n ",
|
|
458
458
|
"doc-url": "",
|
|
459
459
|
"attributes": [
|
|
460
460
|
{
|
|
@@ -489,6 +489,11 @@
|
|
|
489
489
|
"description": "Square icon-only button. Requires `label` for the accessible name.",
|
|
490
490
|
"value": { "type": "boolean", "default": "false" }
|
|
491
491
|
},
|
|
492
|
+
{
|
|
493
|
+
"name": "aria-label",
|
|
494
|
+
"description": "A host `aria-label` never reaches assistive tech on its own — light DOM has no\nimplicit ARIA relationship between a custom element and its rendered children, so an\n`aria-label` written on `<baht-button>` stays on the host and the inner native\n`<button>` keeps whatever text (or none) is inside it. Mirroring the attribute into\nthis property forwards it to the inner button's `aria-label`, taking priority over\n`label`/icon-only fallback — this is how a glyph-only child (e.g. `‹`) gets a real\naccessible name without `icon-only`. Mapped to the plain `aria-label` attribute so\nhosts write it the way they naturally would; kept off the `ariaLabel` IDL accessor to\navoid shadowing the platform's own ARIAMixin.",
|
|
495
|
+
"value": { "type": "string", "default": "''" }
|
|
496
|
+
},
|
|
492
497
|
{ "name": "defer-hydration", "value": { "type": "string" } }
|
|
493
498
|
],
|
|
494
499
|
"events": [{ "name": "name", "type": "CustomEvent" }],
|
|
@@ -516,6 +521,11 @@
|
|
|
516
521
|
"name": "iconOnly",
|
|
517
522
|
"description": "Square icon-only button. Requires `label` for the accessible name.",
|
|
518
523
|
"type": "boolean"
|
|
524
|
+
},
|
|
525
|
+
{
|
|
526
|
+
"name": "hostAriaLabel",
|
|
527
|
+
"description": "A host `aria-label` never reaches assistive tech on its own — light DOM has no\nimplicit ARIA relationship between a custom element and its rendered children, so an\n`aria-label` written on `<baht-button>` stays on the host and the inner native\n`<button>` keeps whatever text (or none) is inside it. Mirroring the attribute into\nthis property forwards it to the inner button's `aria-label`, taking priority over\n`label`/icon-only fallback — this is how a glyph-only child (e.g. `‹`) gets a real\naccessible name without `icon-only`. Mapped to the plain `aria-label` attribute so\nhosts write it the way they naturally would; kept off the `ariaLabel` IDL accessor to\navoid shadowing the platform's own ARIAMixin.",
|
|
528
|
+
"type": "string"
|
|
519
529
|
}
|
|
520
530
|
],
|
|
521
531
|
"events": [{ "name": "name", "type": "CustomEvent" }]
|