@waggylabs/yumekit 0.5.1-beta.4 → 0.5.1-beta.5
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/CHANGELOG.md +22 -0
- package/dist/components/y-appbar.js +328 -81
- package/dist/components/y-banner.js +328 -81
- package/dist/components/y-button/y-button.d.ts +12 -0
- package/dist/components/y-button.d.ts +12 -0
- package/dist/components/y-button.js +328 -81
- package/dist/components/y-code/y-code.d.ts +1 -0
- package/dist/components/y-code.d.ts +1 -0
- package/dist/components/y-code.js +20 -5
- package/dist/components/y-color/y-color.d.ts +6 -0
- package/dist/components/y-color.d.ts +6 -0
- package/dist/components/y-color.js +68 -0
- package/dist/components/y-colorpicker.js +47 -0
- package/dist/components/y-data-grid.js +408 -87
- package/dist/components/y-date/y-date.d.ts +6 -0
- package/dist/components/y-date.d.ts +6 -0
- package/dist/components/y-date.js +381 -87
- package/dist/components/y-datepicker.js +360 -87
- package/dist/components/y-gallery.js +1 -1
- package/dist/components/y-help.js +328 -81
- package/dist/components/y-input/y-input.d.ts +7 -0
- package/dist/components/y-input.d.ts +7 -0
- package/dist/components/y-input.js +24 -0
- package/dist/components/y-paginator.js +354 -81
- package/dist/components/y-select/y-select.d.ts +7 -0
- package/dist/components/y-select.d.ts +7 -0
- package/dist/components/y-select.js +23 -0
- package/dist/components/y-sidebar.js +328 -81
- package/dist/components/y-tabs/y-tabs.d.ts +7 -0
- package/dist/components/y-tabs.d.ts +7 -0
- package/dist/components/y-tabs.js +74 -14
- package/dist/components/y-textarea/y-textarea.d.ts +6 -0
- package/dist/components/y-textarea.d.ts +6 -0
- package/dist/components/y-textarea.js +21 -0
- package/dist/components/y-theme/y-theme.d.ts +1 -0
- package/dist/components/y-theme.d.ts +1 -0
- package/dist/components/y-theme.js +62 -32
- package/dist/index.js +607 -139
- package/dist/react.d.ts +7 -0
- package/dist/styles/blue-dark.css +6 -6
- package/dist/styles/blue-light.css +6 -6
- package/dist/styles/brown-dark.css +6 -6
- package/dist/styles/brown-light.css +6 -6
- package/dist/styles/carbon-dark.css +222 -0
- package/dist/styles/carbon-light.css +222 -0
- package/dist/styles/green-dark.css +6 -6
- package/dist/styles/green-light.css +6 -6
- package/dist/styles/indigo-dark.css +6 -6
- package/dist/styles/indigo-light.css +6 -6
- package/dist/styles/material-blue-dark.css +234 -0
- package/dist/styles/material-blue-light.css +234 -0
- package/dist/styles/olive-dark.css +6 -6
- package/dist/styles/olive-light.css +6 -6
- package/dist/styles/orange-dark.css +6 -6
- package/dist/styles/orange-light.css +6 -6
- package/dist/styles/pink-dark.css +6 -6
- package/dist/styles/pink-light.css +6 -6
- package/dist/styles/purple-dark.css +6 -6
- package/dist/styles/purple-light.css +6 -6
- package/dist/styles/red-dark.css +6 -6
- package/dist/styles/red-light.css +6 -6
- package/dist/styles/teal-dark.css +6 -6
- package/dist/styles/teal-light.css +6 -6
- package/dist/styles/variables.css +10 -8
- package/dist/styles/yellow-dark.css +6 -6
- package/dist/styles/yellow-light.css +6 -6
- package/dist/yumekit.min.js +1 -1
- package/llm.txt +63 -36
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -35,6 +35,14 @@ Delete any empty sections before publishing.
|
|
|
35
35
|
|
|
36
36
|
### Added
|
|
37
37
|
|
|
38
|
+
- Two new built-in themes, `material-blue-light` and `material-blue-dark`, applying Material Design 3 — a Material palette (Blue primary, Material status colors, grey surfaces), Roboto typography, and the M3 shape scale (4/8/12/28px radii, pill buttons, 28px dialogs, 4px text fields, 1px borders) applied across all components. `y-theme` now loads the Roboto webfont automatically when one of these themes is active.
|
|
39
|
+
|
|
40
|
+
- Two new built-in themes, `carbon-light` and `carbon-dark`, applying IBM Carbon — the Carbon palette (Interactive Blue `#0f62fe`, IBM gray surfaces, Carbon status colors), IBM Plex Sans typography, and Carbon's sharp shape language (0px radii, 1px borders). `y-theme` loads the IBM Plex Sans webfont automatically when one of these themes is active.
|
|
41
|
+
|
|
42
|
+
- `y-tabs` — new `variant="accent"` style: minimal tabs where the active tab shows a primary-colored indicator border on its content-facing edge (bottom for top tabs, etc.). The default bordered style is unchanged. Adds `--component-tabs-accent-width` (indicator thickness). The border-width token is normalized to `--component-tabs-border-width` (matching `--component-tabs-border-color`); the legacy `--component-tab-border-width` is still honored as a fallback.
|
|
43
|
+
|
|
44
|
+
- Form fields (`y-input`, `y-textarea`, `y-select`, `y-color`, `y-date`) — new `variant="underline"` style: a bottom-only border with square bottom corners (the Material/Carbon text-field look) instead of the full-border `"default"`. Hover/focus/invalid states still color the underline. Helps match design systems that use underlined fields.
|
|
45
|
+
|
|
38
46
|
- New `y-data-grid` component — interactive grid for large or dynamic datasets with client- or server-side sorting, filtering, and pagination, single/multi row selection, inline cell editing, nested row grouping with aggregates, multi-column header groups, virtual scrolling, an optional per-column header menu (filter, sort, visibility, reorder), and a sticky header.
|
|
39
47
|
|
|
40
48
|
- New `y-popover` component — target-anchored floating panel with rich slotted content, composable triggers (`click` / `hover` / `focus` / `context-menu` / `manual`), flip-on-collision positioning, optional modal mode with focus trap, and an opt-in `portal` mode that renders into `<body>` to escape ancestor stacking contexts.
|
|
@@ -51,6 +59,8 @@ Delete any empty sections before publishing.
|
|
|
51
59
|
|
|
52
60
|
### Changed
|
|
53
61
|
|
|
62
|
+
- `y-button` — padding can now be set per-axis via `--component-button-padding-block-{size}` / `--component-button-padding-inline-{size}` (overriding, and falling back to, the all-sides `--component-button-padding-{size}`), plus a new `padding-mode` attribute (`auto` (default) / `square` / `wide`) controlling whether the inline axis collapses to the block value. `auto` makes icon-only buttons square automatically; `square`/`wide` force it. The Material themes use this for wide pill buttons that stay round when icon-only; `y-paginator` number buttons and `y-datepicker` day / month / year buttons set `padding-mode="square"` so they don't bloat under the wide Material padding.
|
|
63
|
+
|
|
54
64
|
- Custom color support expanded to the browser-native color functions — `hwb()`, `lab()`, `lch()`, `oklab()`, `oklch()`, and `color()` — in addition to `#hex`, `rgb()`/`rgba()`, and `hsl()`/`hsla()`. The shared `isSafeCssColor` gate now also tightens its argument allowlist (rejecting semicolons, braces, angle brackets, and nested functions). Applies anywhere a `color` accepts a custom value, including `y-badge`, `y-select`, `y-popover`, `y-button`, `y-tag`, `y-icon`, and `y-rating`.
|
|
55
65
|
|
|
56
66
|
- `y-rating` — selected icons now swap in the registered `filled` weight variant instead of just thickening the line stroke, falling back to the thick stroke when no filled variant is available.
|
|
@@ -63,6 +73,18 @@ Delete any empty sections before publishing.
|
|
|
63
73
|
|
|
64
74
|
### Fixed
|
|
65
75
|
|
|
76
|
+
- Form field components now share one field background. `y-select` (trigger and dropdown) used `base.background.app` while `y-input` / `y-textarea` / `y-color` / `y-date` used `base.background.component`; `select.background` is now `base.background.component` across all themes, so fields match when placed together on a form (most visible in the Material and Carbon themes). The select dropdown panel now also matches menus/popovers.
|
|
77
|
+
|
|
78
|
+
- `y-avatar` — the three `shape` values are now visually distinct. Added a `--component-avatar-border-radius-rounded` token (medium radius) and changed `square` to a zero radius (sharp corners); `circle` is unchanged.
|
|
79
|
+
|
|
80
|
+
- `y-tag` — Increased the inline padding size for all sizes of `y-tag` component.
|
|
81
|
+
|
|
82
|
+
- `y-tabs` — the tab panel no longer creates a stacking context (`z-index: 0` removed), which was trapping `position: fixed` overlays rendered by slotted components (e.g. `y-gallery`'s lightbox) underneath the tab strip and surrounding page content.
|
|
83
|
+
|
|
84
|
+
- `y-gallery` — the lightbox overlay's default z-index was raised from 1000 to 9000 so it layers above fixed chrome like `y-dock` (8000); override via `--component-gallery-expand-z-index`.
|
|
85
|
+
|
|
86
|
+
- `y-menu` — selected items now use the primary inverse content color for their text, so the label stays readable against the primary-colored selected background across all themes.
|
|
87
|
+
|
|
66
88
|
- `y-button` — no longer throws when `color` is set to an unrecognized value that isn't a valid custom color; it now falls back to the `base` theme instead of crashing while reading the color-token map.
|
|
67
89
|
|
|
68
90
|
- `y-droplist` — touch drag now works reliably on iOS Safari and Chrome Android. `touch-action: none` is applied to the press target at decoration time instead of from inside `pointerdown`, so mobile browsers stop preempting the press as a scroll gesture.
|
|
@@ -3,12 +3,32 @@ import { contrastTextColor, isSafeCssColor, createElement, resolveAnchor, isNavI
|
|
|
3
3
|
class YumeButton extends HTMLElement {
|
|
4
4
|
static get observedAttributes() {
|
|
5
5
|
return [
|
|
6
|
-
"left-icon",
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"
|
|
6
|
+
"left-icon",
|
|
7
|
+
"right-icon",
|
|
8
|
+
"color",
|
|
9
|
+
"size",
|
|
10
|
+
"style-type",
|
|
11
|
+
"type",
|
|
12
|
+
"padding-mode",
|
|
13
|
+
"disabled",
|
|
14
|
+
"name",
|
|
15
|
+
"value",
|
|
16
|
+
"autofocus",
|
|
17
|
+
"form",
|
|
18
|
+
"formaction",
|
|
19
|
+
"formenctype",
|
|
20
|
+
"formmethod",
|
|
21
|
+
"formnovalidate",
|
|
22
|
+
"formtarget",
|
|
23
|
+
"aria-label",
|
|
24
|
+
"aria-pressed",
|
|
25
|
+
"aria-hidden",
|
|
26
|
+
"aria-haspopup",
|
|
27
|
+
"aria-expanded",
|
|
28
|
+
"aria-controls",
|
|
29
|
+
"href",
|
|
30
|
+
"target",
|
|
31
|
+
"rel",
|
|
12
32
|
];
|
|
13
33
|
}
|
|
14
34
|
|
|
@@ -51,65 +71,110 @@ class YumeButton extends HTMLElement {
|
|
|
51
71
|
// -------------------------------------------------------------------------
|
|
52
72
|
|
|
53
73
|
/** URL to navigate to. When set, the internal element renders as an <a> instead of <button>. */
|
|
54
|
-
get href() {
|
|
74
|
+
get href() {
|
|
75
|
+
return this.getAttribute("href");
|
|
76
|
+
}
|
|
55
77
|
set href(val) {
|
|
56
78
|
if (val != null) this.setAttribute("href", val);
|
|
57
79
|
else this.removeAttribute("href");
|
|
58
80
|
}
|
|
59
81
|
|
|
60
82
|
/** Anchor target (e.g. "_blank"). Only applies when href is set. */
|
|
61
|
-
get target() {
|
|
83
|
+
get target() {
|
|
84
|
+
return this.getAttribute("target");
|
|
85
|
+
}
|
|
62
86
|
set target(val) {
|
|
63
87
|
if (val != null) this.setAttribute("target", val);
|
|
64
88
|
else this.removeAttribute("target");
|
|
65
89
|
}
|
|
66
90
|
|
|
67
91
|
/** Anchor rel attribute (e.g. "noopener noreferrer"). Only applies when href is set. */
|
|
68
|
-
get rel() {
|
|
92
|
+
get rel() {
|
|
93
|
+
return this.getAttribute("rel");
|
|
94
|
+
}
|
|
69
95
|
set rel(val) {
|
|
70
96
|
if (val != null) this.setAttribute("rel", val);
|
|
71
97
|
else this.removeAttribute("rel");
|
|
72
98
|
}
|
|
73
99
|
|
|
74
100
|
/** Color theme for the button (default "base"). */
|
|
75
|
-
get color() {
|
|
76
|
-
|
|
101
|
+
get color() {
|
|
102
|
+
return this.getAttribute("color") || "base";
|
|
103
|
+
}
|
|
104
|
+
set color(val) {
|
|
105
|
+
this.setAttribute("color", val);
|
|
106
|
+
}
|
|
77
107
|
|
|
78
108
|
/** Whether the button is disabled. */
|
|
79
|
-
get disabled() {
|
|
109
|
+
get disabled() {
|
|
110
|
+
return this.hasAttribute("disabled");
|
|
111
|
+
}
|
|
80
112
|
set disabled(val) {
|
|
81
113
|
if (val) this.setAttribute("disabled", "");
|
|
82
114
|
else this.removeAttribute("disabled");
|
|
83
115
|
}
|
|
84
116
|
|
|
85
117
|
/** The form name of the button. */
|
|
86
|
-
get name() {
|
|
87
|
-
|
|
118
|
+
get name() {
|
|
119
|
+
return this.getAttribute("name") || "";
|
|
120
|
+
}
|
|
121
|
+
set name(val) {
|
|
122
|
+
this.setAttribute("name", val);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Padding mode: "auto" (default) uses square padding only for icon-only
|
|
127
|
+
* buttons; "square" forces equal block/inline padding (e.g. paginator
|
|
128
|
+
* number buttons); "wide" always uses the inline padding even when icon-only.
|
|
129
|
+
*/
|
|
130
|
+
get paddingMode() {
|
|
131
|
+
const mode = this.getAttribute("padding-mode");
|
|
132
|
+
return ["auto", "square", "wide"].includes(mode) ? mode : "auto";
|
|
133
|
+
}
|
|
134
|
+
set paddingMode(val) {
|
|
135
|
+
this.setAttribute("padding-mode", val);
|
|
136
|
+
}
|
|
88
137
|
|
|
89
138
|
/** Size: "small" | "medium" | "large" (default "medium"). */
|
|
90
|
-
get size() {
|
|
91
|
-
|
|
139
|
+
get size() {
|
|
140
|
+
return this.getAttribute("size") || "medium";
|
|
141
|
+
}
|
|
142
|
+
set size(val) {
|
|
143
|
+
this.setAttribute("size", val);
|
|
144
|
+
}
|
|
92
145
|
|
|
93
146
|
/** Visual style: "filled" | "outlined" | "flat" (default "outlined"). */
|
|
94
|
-
get styleType() {
|
|
95
|
-
|
|
147
|
+
get styleType() {
|
|
148
|
+
return this.getAttribute("style-type") || "outlined";
|
|
149
|
+
}
|
|
150
|
+
set styleType(val) {
|
|
151
|
+
this.setAttribute("style-type", val);
|
|
152
|
+
}
|
|
96
153
|
|
|
97
154
|
/** Button type: "button" | "submit" | "reset" (default "button"). */
|
|
98
|
-
get type() {
|
|
99
|
-
|
|
155
|
+
get type() {
|
|
156
|
+
return this.getAttribute("type") || "button";
|
|
157
|
+
}
|
|
158
|
+
set type(val) {
|
|
159
|
+
this.setAttribute("type", val);
|
|
160
|
+
}
|
|
100
161
|
|
|
101
162
|
/** The current selected value(s), comma-separated when 'multiple' is set. */
|
|
102
163
|
get value() {
|
|
103
164
|
if (this.hasAttribute("multiple")) {
|
|
104
165
|
return Array.from(this.selectedValues).join(",");
|
|
105
166
|
} else {
|
|
106
|
-
return this.selectedValues.size
|
|
167
|
+
return this.selectedValues.size
|
|
168
|
+
? Array.from(this.selectedValues)[0]
|
|
169
|
+
: "";
|
|
107
170
|
}
|
|
108
171
|
}
|
|
109
172
|
set value(newVal) {
|
|
110
173
|
if (this.hasAttribute("multiple")) {
|
|
111
174
|
if (typeof newVal === "string") {
|
|
112
|
-
this.selectedValues = new Set(
|
|
175
|
+
this.selectedValues = new Set(
|
|
176
|
+
newVal.split(",").map((s) => s.trim()),
|
|
177
|
+
);
|
|
113
178
|
} else if (Array.isArray(newVal)) {
|
|
114
179
|
this.selectedValues = new Set(newVal);
|
|
115
180
|
}
|
|
@@ -133,27 +198,35 @@ class YumeButton extends HTMLElement {
|
|
|
133
198
|
|
|
134
199
|
_addEventListeners() {
|
|
135
200
|
this.button.addEventListener("focus", () => {
|
|
136
|
-
this.dispatchEvent(
|
|
201
|
+
this.dispatchEvent(
|
|
202
|
+
new CustomEvent("focus", { bubbles: true, composed: true }),
|
|
203
|
+
);
|
|
137
204
|
});
|
|
138
205
|
|
|
139
206
|
this.button.addEventListener("blur", () => {
|
|
140
|
-
this.dispatchEvent(
|
|
207
|
+
this.dispatchEvent(
|
|
208
|
+
new CustomEvent("blur", { bubbles: true, composed: true }),
|
|
209
|
+
);
|
|
141
210
|
});
|
|
142
211
|
|
|
143
212
|
this.button.addEventListener("keydown", (event) => {
|
|
144
|
-
this.dispatchEvent(
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
213
|
+
this.dispatchEvent(
|
|
214
|
+
new CustomEvent("keydown", {
|
|
215
|
+
detail: { key: event.key, code: event.code },
|
|
216
|
+
bubbles: true,
|
|
217
|
+
composed: true,
|
|
218
|
+
}),
|
|
219
|
+
);
|
|
149
220
|
});
|
|
150
221
|
|
|
151
222
|
this.button.addEventListener("keyup", (event) => {
|
|
152
|
-
this.dispatchEvent(
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
223
|
+
this.dispatchEvent(
|
|
224
|
+
new CustomEvent("keyup", {
|
|
225
|
+
detail: { key: event.key, code: event.code },
|
|
226
|
+
bubbles: true,
|
|
227
|
+
composed: true,
|
|
228
|
+
}),
|
|
229
|
+
);
|
|
157
230
|
});
|
|
158
231
|
|
|
159
232
|
this.button.addEventListener("click", (event) => {
|
|
@@ -228,15 +301,42 @@ class YumeButton extends HTMLElement {
|
|
|
228
301
|
}
|
|
229
302
|
|
|
230
303
|
_applyFilledInteractionStyles(vars) {
|
|
231
|
-
this.button.style.setProperty(
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
this.button.style.setProperty(
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
this.button.style.setProperty(
|
|
304
|
+
this.button.style.setProperty(
|
|
305
|
+
"--hover-background-color",
|
|
306
|
+
`var(${vars[1]}, #292a2b)`,
|
|
307
|
+
);
|
|
308
|
+
this.button.style.setProperty(
|
|
309
|
+
"--hover-text-color",
|
|
310
|
+
`var(${vars[6]}, #0c0c0d)`,
|
|
311
|
+
);
|
|
312
|
+
this.button.style.setProperty(
|
|
313
|
+
"--hover-border-color",
|
|
314
|
+
`var(${vars[1]}, #292a2b)`,
|
|
315
|
+
);
|
|
316
|
+
this.button.style.setProperty(
|
|
317
|
+
"--focus-background-color",
|
|
318
|
+
`var(${vars[2]}, #46474a)`,
|
|
319
|
+
);
|
|
320
|
+
this.button.style.setProperty(
|
|
321
|
+
"--focus-text-color",
|
|
322
|
+
`var(${vars[6]}, #0c0c0d)`,
|
|
323
|
+
);
|
|
324
|
+
this.button.style.setProperty(
|
|
325
|
+
"--focus-border-color",
|
|
326
|
+
`var(${vars[2]}, #46474a)`,
|
|
327
|
+
);
|
|
328
|
+
this.button.style.setProperty(
|
|
329
|
+
"--active-background-color",
|
|
330
|
+
`var(${vars[3]}, #0c0c0d)`,
|
|
331
|
+
);
|
|
332
|
+
this.button.style.setProperty(
|
|
333
|
+
"--active-text-color",
|
|
334
|
+
`var(${vars[0]}, #f7f7fa)`,
|
|
335
|
+
);
|
|
336
|
+
this.button.style.setProperty(
|
|
337
|
+
"--active-border-color",
|
|
338
|
+
`var(${vars[3]}, #0c0c0d)`,
|
|
339
|
+
);
|
|
240
340
|
}
|
|
241
341
|
|
|
242
342
|
_applyInteractionStyles(vars, styleType) {
|
|
@@ -248,22 +348,31 @@ class YumeButton extends HTMLElement {
|
|
|
248
348
|
}
|
|
249
349
|
|
|
250
350
|
_applySizeStyles(size) {
|
|
251
|
-
const
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
this.button.style.setProperty(
|
|
258
|
-
|
|
351
|
+
const s = ["small", "medium", "large"].includes(size) ? size : "medium";
|
|
352
|
+
const shared = `var(--component-button-padding-${s}, var(--component-button-padding-medium))`;
|
|
353
|
+
this.button.style.setProperty(
|
|
354
|
+
"--button-padding-block",
|
|
355
|
+
`var(--component-button-padding-block-${s}, ${shared})`,
|
|
356
|
+
);
|
|
357
|
+
this.button.style.setProperty(
|
|
358
|
+
"--button-padding-inline",
|
|
359
|
+
`var(--component-button-padding-inline-${s}, ${shared})`,
|
|
360
|
+
);
|
|
361
|
+
this.button.style.setProperty("--button-gap", shared);
|
|
259
362
|
|
|
260
363
|
const minSizeMapping = {
|
|
261
364
|
small: "var(--sizing-small, 32px)",
|
|
262
365
|
medium: "var(--sizing-medium, 40px)",
|
|
263
366
|
large: "var(--sizing-large, 56px)",
|
|
264
367
|
};
|
|
265
|
-
this.button.style.setProperty(
|
|
266
|
-
|
|
368
|
+
this.button.style.setProperty(
|
|
369
|
+
"--button-min-height",
|
|
370
|
+
minSizeMapping[size] || "40px",
|
|
371
|
+
);
|
|
372
|
+
this.button.style.setProperty(
|
|
373
|
+
"--button-min-width",
|
|
374
|
+
minSizeMapping[size] || "40px",
|
|
375
|
+
);
|
|
267
376
|
}
|
|
268
377
|
|
|
269
378
|
_applyStyles() {
|
|
@@ -284,7 +393,7 @@ class YumeButton extends HTMLElement {
|
|
|
284
393
|
width: 100%;
|
|
285
394
|
min-height: var(--button-min-height, var(--sizing-medium, 40px));
|
|
286
395
|
min-width: var(--button-min-width, var(--sizing-medium, 40px));
|
|
287
|
-
padding: var(--button-padding, var(--component-button-padding-medium));
|
|
396
|
+
padding: var(--button-padding-block, var(--component-button-padding-medium)) var(--button-padding-inline, var(--component-button-padding-medium));
|
|
288
397
|
gap: var(--button-gap, var(--component-button-padding-medium));
|
|
289
398
|
justify-content: center;
|
|
290
399
|
align-items: center;
|
|
@@ -305,6 +414,13 @@ class YumeButton extends HTMLElement {
|
|
|
305
414
|
text-decoration: none;
|
|
306
415
|
}
|
|
307
416
|
|
|
417
|
+
/* Square padding: the inline axis collapses to the block value, so
|
|
418
|
+
the button stays square instead of inheriting a wide label
|
|
419
|
+
padding. Driven by the padding-mode property (auto tracks icon-only). */
|
|
420
|
+
.button.square-padding {
|
|
421
|
+
padding-inline: var(--button-padding-block, var(--component-button-padding-medium));
|
|
422
|
+
}
|
|
423
|
+
|
|
308
424
|
.button:disabled,
|
|
309
425
|
.button[aria-disabled="true"] {
|
|
310
426
|
opacity: 0.5;
|
|
@@ -349,12 +465,30 @@ class YumeButton extends HTMLElement {
|
|
|
349
465
|
_applyUnfilledInteractionStyles(vars, styleType) {
|
|
350
466
|
const borderColor = `var(${vars[0]}, #f7f7fa)`;
|
|
351
467
|
|
|
352
|
-
this.button.style.setProperty(
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
this.button.style.setProperty(
|
|
357
|
-
|
|
468
|
+
this.button.style.setProperty(
|
|
469
|
+
"--hover-background-color",
|
|
470
|
+
`var(${vars[4]}, #292a2b)`,
|
|
471
|
+
);
|
|
472
|
+
this.button.style.setProperty(
|
|
473
|
+
"--hover-text-color",
|
|
474
|
+
`var(${vars[0]}, #f7f7fa)`,
|
|
475
|
+
);
|
|
476
|
+
this.button.style.setProperty(
|
|
477
|
+
"--focus-background-color",
|
|
478
|
+
`var(${vars[5]}, #46474a)`,
|
|
479
|
+
);
|
|
480
|
+
this.button.style.setProperty(
|
|
481
|
+
"--focus-text-color",
|
|
482
|
+
`var(${vars[0]}, #f7f7fa)`,
|
|
483
|
+
);
|
|
484
|
+
this.button.style.setProperty(
|
|
485
|
+
"--active-background-color",
|
|
486
|
+
`var(${vars[0]}, #f7f7fa)`,
|
|
487
|
+
);
|
|
488
|
+
this.button.style.setProperty(
|
|
489
|
+
"--active-text-color",
|
|
490
|
+
`var(${vars[6]}, #0c0c0d)`,
|
|
491
|
+
);
|
|
358
492
|
|
|
359
493
|
if (styleType === "outlined") {
|
|
360
494
|
// Outlined buttons keep their border color across all states
|
|
@@ -363,21 +497,86 @@ class YumeButton extends HTMLElement {
|
|
|
363
497
|
this.button.style.setProperty("--active-border-color", borderColor);
|
|
364
498
|
} else {
|
|
365
499
|
// Flat buttons match border to background
|
|
366
|
-
this.button.style.setProperty(
|
|
367
|
-
|
|
368
|
-
|
|
500
|
+
this.button.style.setProperty(
|
|
501
|
+
"--hover-border-color",
|
|
502
|
+
`var(${vars[4]}, #292a2b)`,
|
|
503
|
+
);
|
|
504
|
+
this.button.style.setProperty(
|
|
505
|
+
"--focus-border-color",
|
|
506
|
+
`var(${vars[5]}, #46474a)`,
|
|
507
|
+
);
|
|
508
|
+
this.button.style.setProperty(
|
|
509
|
+
"--active-border-color",
|
|
510
|
+
`var(${vars[0]}, #f7f7fa)`,
|
|
511
|
+
);
|
|
369
512
|
}
|
|
370
513
|
}
|
|
371
514
|
|
|
372
515
|
_getColorVarsMap() {
|
|
373
516
|
return {
|
|
374
|
-
primary: [
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
517
|
+
primary: [
|
|
518
|
+
"--primary-content--",
|
|
519
|
+
"--primary-content-hover",
|
|
520
|
+
"--primary-content-active",
|
|
521
|
+
"--primary-background-component",
|
|
522
|
+
"--primary-background-hover",
|
|
523
|
+
"--primary-background-active",
|
|
524
|
+
"--primary-content-inverse",
|
|
525
|
+
],
|
|
526
|
+
secondary: [
|
|
527
|
+
"--secondary-content--",
|
|
528
|
+
"--secondary-content-hover",
|
|
529
|
+
"--secondary-content-active",
|
|
530
|
+
"--secondary-background-component",
|
|
531
|
+
"--secondary-background-hover",
|
|
532
|
+
"--secondary-background-active",
|
|
533
|
+
"--secondary-content-inverse",
|
|
534
|
+
],
|
|
535
|
+
base: [
|
|
536
|
+
"--base-content--",
|
|
537
|
+
"--base-content-lighter",
|
|
538
|
+
"--base-content-lightest",
|
|
539
|
+
"--base-background-component",
|
|
540
|
+
"--base-background-hover",
|
|
541
|
+
"--base-background-active",
|
|
542
|
+
"--base-content-inverse",
|
|
543
|
+
],
|
|
544
|
+
success: [
|
|
545
|
+
"--success-content--",
|
|
546
|
+
"--success-content-hover",
|
|
547
|
+
"--success-content-active",
|
|
548
|
+
"--success-background-component",
|
|
549
|
+
"--success-background-hover",
|
|
550
|
+
"--success-background-active",
|
|
551
|
+
"--success-content-inverse",
|
|
552
|
+
],
|
|
553
|
+
error: [
|
|
554
|
+
"--error-content--",
|
|
555
|
+
"--error-content-hover",
|
|
556
|
+
"--error-content-active",
|
|
557
|
+
"--error-background-component",
|
|
558
|
+
"--error-background-hover",
|
|
559
|
+
"--error-background-active",
|
|
560
|
+
"--error-content-inverse",
|
|
561
|
+
],
|
|
562
|
+
warning: [
|
|
563
|
+
"--warning-content--",
|
|
564
|
+
"--warning-content-hover",
|
|
565
|
+
"--warning-content-active",
|
|
566
|
+
"--warning-background-component",
|
|
567
|
+
"--warning-background-hover",
|
|
568
|
+
"--warning-background-active",
|
|
569
|
+
"--warning-content-inverse",
|
|
570
|
+
],
|
|
571
|
+
help: [
|
|
572
|
+
"--help-content--",
|
|
573
|
+
"--help-content-hover",
|
|
574
|
+
"--help-content-active",
|
|
575
|
+
"--help-background-component",
|
|
576
|
+
"--help-background-hover",
|
|
577
|
+
"--help-background-active",
|
|
578
|
+
"--help-content-inverse",
|
|
579
|
+
],
|
|
381
580
|
};
|
|
382
581
|
}
|
|
383
582
|
|
|
@@ -394,11 +593,13 @@ class YumeButton extends HTMLElement {
|
|
|
394
593
|
detail[key] = attr.value;
|
|
395
594
|
});
|
|
396
595
|
|
|
397
|
-
this.dispatchEvent(
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
596
|
+
this.dispatchEvent(
|
|
597
|
+
new CustomEvent(eventType, {
|
|
598
|
+
detail,
|
|
599
|
+
bubbles: true,
|
|
600
|
+
composed: true,
|
|
601
|
+
}),
|
|
602
|
+
);
|
|
402
603
|
}
|
|
403
604
|
|
|
404
605
|
_init() {
|
|
@@ -408,6 +609,23 @@ class YumeButton extends HTMLElement {
|
|
|
408
609
|
this._addEventListeners();
|
|
409
610
|
}
|
|
410
611
|
|
|
612
|
+
/** Whether a slot (named, or default when slotName is "") has non-empty content. */
|
|
613
|
+
_hasSlotContent(slotName) {
|
|
614
|
+
const slot = slotName
|
|
615
|
+
? this.shadowRoot.querySelector(`slot[name="${slotName}"]`)
|
|
616
|
+
: this.shadowRoot.querySelector("slot:not([name])");
|
|
617
|
+
if (!slot) return false;
|
|
618
|
+
return slot
|
|
619
|
+
.assignedNodes({ flatten: true })
|
|
620
|
+
.some(
|
|
621
|
+
(n) =>
|
|
622
|
+
!(
|
|
623
|
+
n.nodeType === Node.TEXT_NODE &&
|
|
624
|
+
n.textContent.trim() === ""
|
|
625
|
+
),
|
|
626
|
+
);
|
|
627
|
+
}
|
|
628
|
+
|
|
411
629
|
_manageSlotVisibility(slotName, selector) {
|
|
412
630
|
const slot = slotName
|
|
413
631
|
? this.shadowRoot.querySelector(`slot[name="${slotName}"]`)
|
|
@@ -415,21 +633,38 @@ class YumeButton extends HTMLElement {
|
|
|
415
633
|
const container = this.shadowRoot.querySelector(selector);
|
|
416
634
|
|
|
417
635
|
const updateVisibility = () => {
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
636
|
+
container.style.display = this._hasSlotContent(slotName)
|
|
637
|
+
? "inline-flex"
|
|
638
|
+
: "none";
|
|
639
|
+
this._refreshPaddingMode();
|
|
422
640
|
};
|
|
423
641
|
|
|
424
642
|
updateVisibility();
|
|
425
643
|
slot.addEventListener("slotchange", updateVisibility);
|
|
426
644
|
}
|
|
427
645
|
|
|
646
|
+
/** Toggle square padding (inline padding collapses to the block value). In
|
|
647
|
+
* "auto" this tracks icon-only buttons; "square"/"wide" force it on/off. */
|
|
648
|
+
_refreshPaddingMode() {
|
|
649
|
+
if (!this.button) return;
|
|
650
|
+
const mode = this.paddingMode;
|
|
651
|
+
let square = mode === "square";
|
|
652
|
+
if (mode === "auto") {
|
|
653
|
+
const hasIcon =
|
|
654
|
+
this._hasSlotContent("left-icon") ||
|
|
655
|
+
this._hasSlotContent("right-icon");
|
|
656
|
+
square = hasIcon && !this._hasSlotContent("");
|
|
657
|
+
}
|
|
658
|
+
this.button.classList.toggle("square-padding", square);
|
|
659
|
+
}
|
|
660
|
+
|
|
428
661
|
_proxyNativeOnClick() {
|
|
429
662
|
try {
|
|
430
663
|
Object.defineProperty(this, "onclick", {
|
|
431
664
|
get: () => this.button.onclick,
|
|
432
|
-
set: (value) => {
|
|
665
|
+
set: (value) => {
|
|
666
|
+
this.button.onclick = value;
|
|
667
|
+
},
|
|
433
668
|
configurable: true,
|
|
434
669
|
enumerable: true,
|
|
435
670
|
});
|
|
@@ -498,7 +733,19 @@ class YumeButton extends HTMLElement {
|
|
|
498
733
|
_updateButtonAttributes() {
|
|
499
734
|
const isAnchor = this.button?.tagName === "A";
|
|
500
735
|
// These are only meaningful on <button>
|
|
501
|
-
const buttonOnlyAttrs = new Set([
|
|
736
|
+
const buttonOnlyAttrs = new Set([
|
|
737
|
+
"type",
|
|
738
|
+
"disabled",
|
|
739
|
+
"name",
|
|
740
|
+
"value",
|
|
741
|
+
"autofocus",
|
|
742
|
+
"form",
|
|
743
|
+
"formaction",
|
|
744
|
+
"formenctype",
|
|
745
|
+
"formmethod",
|
|
746
|
+
"formnovalidate",
|
|
747
|
+
"formtarget",
|
|
748
|
+
]);
|
|
502
749
|
// These are only meaningful on <a>; href is managed separately in _render
|
|
503
750
|
const anchorOnlyAttrs = new Set(["href", "target", "rel"]);
|
|
504
751
|
|