@reliability-design/web 1.2.0 → 1.3.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/rel-accordion/rel-accordion.ts +289 -135
- package/dist/components/rel-avatar/README.md +15 -4
- package/dist/components/rel-avatar/rel-avatar.ts +138 -96
- package/dist/components/rel-badge/README.md +7 -0
- package/dist/components/rel-badge/rel-badge.ts +38 -2
- package/dist/components/rel-button/rel-button.ts +29 -7
- package/dist/components/rel-chip/README.md +7 -0
- package/dist/components/rel-chip/rel-chip.ts +250 -130
- package/dist/components/rel-drawer/rel-drawer.ts +5 -2
- package/dist/components/rel-menubar/rel-menubar.ts +1 -0
- package/dist/components/rel-pagination/rel-pagination.ts +442 -425
- package/dist/components/rel-radio/rel-radio.ts +16 -16
- package/dist/components/rel-range-picker/rel-range-picker.css +349 -349
- package/dist/components/rel-range-picker/rel-range-picker.ts +1080 -1079
- package/dist/components/rel-select/README.md +34 -28
- package/dist/components/rel-select/rel-select.ts +1015 -346
- package/dist/components/rel-sheet/rel-sheet.ts +6 -3
- package/dist/components/rel-skeleton/rel-skeleton.ts +139 -0
- package/dist/components/rel-textfield/rel-textfield.ts +49 -1
- package/dist/components/rel-toast/rel-toast.ts +1 -6
- package/dist/index.d.mts +164 -22
- package/dist/index.d.ts +164 -22
- package/dist/index.js +2127 -927
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2139 -940
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -1,96 +1,138 @@
|
|
|
1
|
-
import "../../styles/vars-v2.css";
|
|
2
|
-
import { LitElement, html, css } from "lit";
|
|
3
|
-
import { customElement, property } from "lit/decorators.js";
|
|
4
|
-
|
|
5
|
-
@customElement("rel-avatar")
|
|
6
|
-
export class RelAvatar extends LitElement {
|
|
7
|
-
@property({ type: String, reflect: true })
|
|
8
|
-
size: "lg" | "md" | "sm" | "xs" = "md";
|
|
9
|
-
|
|
10
|
-
@property({ type: String, reflect: true })
|
|
11
|
-
type: "image" | "text" | "icon" = "image";
|
|
12
|
-
|
|
13
|
-
@property({ type: String })
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
@property({ type: String })
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
.
|
|
80
|
-
width:
|
|
81
|
-
height:
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
1
|
+
import "../../styles/vars-v2.css";
|
|
2
|
+
import { LitElement, html, css } from "lit";
|
|
3
|
+
import { customElement, property } from "lit/decorators.js";
|
|
4
|
+
|
|
5
|
+
@customElement("rel-avatar")
|
|
6
|
+
export class RelAvatar extends LitElement {
|
|
7
|
+
@property({ type: String, reflect: true })
|
|
8
|
+
size: "lg" | "md" | "sm" | "xs" = "md";
|
|
9
|
+
|
|
10
|
+
@property({ type: String, reflect: true })
|
|
11
|
+
type: "image" | "text" | "icon" = "image";
|
|
12
|
+
|
|
13
|
+
@property({ type: String, reflect: true })
|
|
14
|
+
variant: "fill" | "subtle" | "outline" = "fill";
|
|
15
|
+
|
|
16
|
+
@property({ type: String }) src = "";
|
|
17
|
+
@property({ type: String }) text = "";
|
|
18
|
+
@property({ type: String }) alt = "Avatar";
|
|
19
|
+
@property({ type: String }) bg: string = "";
|
|
20
|
+
@property({ type: String }) color: string = "";
|
|
21
|
+
|
|
22
|
+
static styles = css`
|
|
23
|
+
:host {
|
|
24
|
+
display: inline-flex;
|
|
25
|
+
font-family: var(--rel-fontFamilies-primary);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.avatar {
|
|
29
|
+
display: inline-flex;
|
|
30
|
+
align-items: center;
|
|
31
|
+
justify-content: center;
|
|
32
|
+
border-radius: 50%;
|
|
33
|
+
overflow: hidden;
|
|
34
|
+
box-sizing: border-box;
|
|
35
|
+
border: var(--rel-borders-width-stroke-100, 1px) solid transparent;
|
|
36
|
+
font-weight: var(--rel-fontWeights-semibold);
|
|
37
|
+
user-select: none;
|
|
38
|
+
text-transform: uppercase;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/* ── Variants ─────────────────────────────────────────────── */
|
|
42
|
+
|
|
43
|
+
:host([variant="fill"]) .avatar {
|
|
44
|
+
background-color: var(--rel-avatar-bg-fill, #0b0b0b);
|
|
45
|
+
color: var(--rel-avatar-color-fill, #ffffff);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
:host([variant="subtle"]) .avatar {
|
|
49
|
+
background-color: var(--rel-avatar-bg-subtle, #f5f5f5);
|
|
50
|
+
color: var(--rel-avatar-color-subtle, #0b0b0b);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
:host([variant="outline"]) .avatar {
|
|
54
|
+
background-color: transparent;
|
|
55
|
+
border-color: var(--rel-avatar-border-outline, var(--rel-color-border-default));
|
|
56
|
+
color: var(--rel-avatar-color-outline, #0b0b0b);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/* ── Sizes ────────────────────────────────────────────────── */
|
|
60
|
+
|
|
61
|
+
.avatar-lg {
|
|
62
|
+
width: 40px;
|
|
63
|
+
height: 40px;
|
|
64
|
+
font-size: var(--rel-fontSizes-lg); /* 20px */
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.avatar-md {
|
|
68
|
+
width: 32px;
|
|
69
|
+
height: 32px;
|
|
70
|
+
font-size: 16px;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.avatar-sm {
|
|
74
|
+
width: 24px;
|
|
75
|
+
height: 24px;
|
|
76
|
+
font-size: var(--rel-fontSizes-sm); /* 12px */
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.avatar-xs {
|
|
80
|
+
width: 20px;
|
|
81
|
+
height: 20px;
|
|
82
|
+
font-size: var(--rel-fontSizes-xs); /* 10px */
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/* ── Image ────────────────────────────────────────────────── */
|
|
86
|
+
|
|
87
|
+
img {
|
|
88
|
+
width: 100%;
|
|
89
|
+
height: 100%;
|
|
90
|
+
object-fit: cover;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/* ── Icon slot ────────────────────────────────────────────── */
|
|
94
|
+
|
|
95
|
+
.icon-slot {
|
|
96
|
+
width: 100%;
|
|
97
|
+
height: 100%;
|
|
98
|
+
display: inline-flex;
|
|
99
|
+
align-items: center;
|
|
100
|
+
justify-content: center;
|
|
101
|
+
color: inherit;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.icon-slot ::slotted(svg) {
|
|
105
|
+
width: 50%;
|
|
106
|
+
height: 50%;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/* ── Dark mode ────────────────────────────────────────────────
|
|
110
|
+
:host() can never be preceded by a combinator inside a shadow-tree
|
|
111
|
+
stylesheet, so ":host-context(dark) :host([variant=...]) .avatar"
|
|
112
|
+
(the previous approach) is invalid and silently matches nothing.
|
|
113
|
+
Instead, redefine the same custom properties the variant rules
|
|
114
|
+
above already read via var(--token, fallback) — a plain
|
|
115
|
+
:host-context() selector with no compounding, guaranteed valid. ── */
|
|
116
|
+
|
|
117
|
+
:host-context([data-theme="dark"]) {
|
|
118
|
+
--rel-avatar-bg-fill: #ffffff;
|
|
119
|
+
--rel-avatar-color-fill: #0b0b0b;
|
|
120
|
+
--rel-avatar-bg-subtle: #2b2b2b;
|
|
121
|
+
--rel-avatar-color-subtle: #f5f5f5;
|
|
122
|
+
--rel-avatar-border-outline: #525252;
|
|
123
|
+
--rel-avatar-color-outline: #f5f5f5;
|
|
124
|
+
}
|
|
125
|
+
`;
|
|
126
|
+
|
|
127
|
+
render() {
|
|
128
|
+
return html`
|
|
129
|
+
<div class="avatar avatar-${this.size}" style=${[this.bg ? `background-color:${this.bg}` : "", this.color ? `color:${this.color}` : ""].filter(Boolean).join(";")}>
|
|
130
|
+
${this.type === "image" && this.src
|
|
131
|
+
? html`<img src=${this.src} alt=${this.alt} />`
|
|
132
|
+
: this.type === "text"
|
|
133
|
+
? html`<span>${this.text}</span>`
|
|
134
|
+
: html`<span class="icon-slot"><slot></slot></span>`}
|
|
135
|
+
</div>
|
|
136
|
+
`;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
@@ -25,6 +25,11 @@ A simple notification badge component displaying numeric counts or dot indicator
|
|
|
25
25
|
<rel-badge number="1" size="sm"></rel-badge>
|
|
26
26
|
<rel-badge number="2" size="md"></rel-badge>
|
|
27
27
|
<rel-badge number="3" size="lg"></rel-badge>
|
|
28
|
+
|
|
29
|
+
<!-- Custom colors -->
|
|
30
|
+
<rel-badge number="3" color="#7d7d7d"></rel-badge>
|
|
31
|
+
<rel-badge number="3" color="teal" text-color="#1a1a1a"></rel-badge>
|
|
32
|
+
<rel-badge variant="dot" color="lavender"></rel-badge>
|
|
28
33
|
```
|
|
29
34
|
|
|
30
35
|
## API
|
|
@@ -35,6 +40,8 @@ A simple notification badge component displaying numeric counts or dot indicator
|
|
|
35
40
|
| `number` | `string` | `""` | Text to display in number variant (can be numeric or text like "99+") |
|
|
36
41
|
| `size` | `"sm" \| "md" \| "lg"` (reflected) | `"md"` | Size variant |
|
|
37
42
|
| `variant` | `"dot" \| "number"` (reflected) | `"number"` | Display mode (number shows text, dot shows indicator only) |
|
|
43
|
+
| `color` | `string` (reflected) | `""` | Direct CSS color override for the badge background. Accepts any valid CSS color (hex, rgb, hsl, named, `var(...)`). Falls back to the default token when empty |
|
|
44
|
+
| `text-color` | `string` (reflected) | `""` | Direct CSS color override for the badge text/icon color. Accepts any valid CSS color. Falls back to white when empty |
|
|
38
45
|
|
|
39
46
|
## Events
|
|
40
47
|
None.
|
|
@@ -16,6 +16,24 @@ export class RelBadge extends LitElement {
|
|
|
16
16
|
@property({ type: String, reflect: true })
|
|
17
17
|
variant: "dot" | "number" = "number";
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Direct CSS color override for the badge background. Accepts any valid
|
|
21
|
+
* CSS color value: hex, rgb(...), hsl(...), named color, or var(--token).
|
|
22
|
+
*
|
|
23
|
+
* Clear it (set to `''`) to fall back to the default token.
|
|
24
|
+
*/
|
|
25
|
+
@property({ type: String, reflect: true })
|
|
26
|
+
color = "";
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Direct CSS color override for the badge text/icon color. Accepts any
|
|
30
|
+
* valid CSS color value: hex, rgb(...), hsl(...), named color, or var(--token).
|
|
31
|
+
*
|
|
32
|
+
* Clear it (set to `''`) to fall back to the default (white).
|
|
33
|
+
*/
|
|
34
|
+
@property({ type: String, reflect: true, attribute: "text-color" })
|
|
35
|
+
textColor = "";
|
|
36
|
+
|
|
19
37
|
static styles = css`
|
|
20
38
|
:host {
|
|
21
39
|
display: inline-flex;
|
|
@@ -27,8 +45,8 @@ export class RelBadge extends LitElement {
|
|
|
27
45
|
justify-content: center;
|
|
28
46
|
font-family: var(--rel-fontFamilies-primary, sans-serif);
|
|
29
47
|
font-weight: var(--rel-fontWeights-semibold, 600);
|
|
30
|
-
background-color: var(--rel-error-surface-default);
|
|
31
|
-
color: #ffffff;
|
|
48
|
+
background-color: var(--rel-badge-bg, var(--rel-error-surface-default));
|
|
49
|
+
color: var(--rel-badge-color, #ffffff);
|
|
32
50
|
border-radius: 50%;
|
|
33
51
|
}
|
|
34
52
|
|
|
@@ -72,6 +90,24 @@ export class RelBadge extends LitElement {
|
|
|
72
90
|
return ["badge", `badge-${this.size}`, `badge-${this.variant}`].join(" ");
|
|
73
91
|
}
|
|
74
92
|
|
|
93
|
+
override updated(changedProperties: Map<PropertyKey, unknown>): void {
|
|
94
|
+
if (changedProperties.has("color")) {
|
|
95
|
+
if (this.color) {
|
|
96
|
+
this.style.setProperty("--rel-badge-bg", this.color);
|
|
97
|
+
} else {
|
|
98
|
+
this.style.removeProperty("--rel-badge-bg");
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (changedProperties.has("textColor")) {
|
|
103
|
+
if (this.textColor) {
|
|
104
|
+
this.style.setProperty("--rel-badge-color", this.textColor);
|
|
105
|
+
} else {
|
|
106
|
+
this.style.removeProperty("--rel-badge-color");
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
75
111
|
render() {
|
|
76
112
|
return html`
|
|
77
113
|
<span class="${this.classes}" aria-label=${this.ariaLabel || `${this.number} ${this.suffix}`}>
|
|
@@ -76,6 +76,10 @@ export class RelButton extends LitElement {
|
|
|
76
76
|
/* Disabled */
|
|
77
77
|
:host([disabled]) {
|
|
78
78
|
cursor: not-allowed;
|
|
79
|
+
/* Without this, clicks on a disabled button hit-test fall through the
|
|
80
|
+
inner button's pointer-events:none straight onto the host, which still
|
|
81
|
+
dispatches a normal click to any externally-attached listener. */
|
|
82
|
+
pointer-events: none;
|
|
79
83
|
}
|
|
80
84
|
|
|
81
85
|
:host([disabled]) button {
|
|
@@ -245,6 +249,27 @@ export class RelButton extends LitElement {
|
|
|
245
249
|
/* btn-link: blue in both modes — no dark override */
|
|
246
250
|
`;
|
|
247
251
|
|
|
252
|
+
connectedCallback() {
|
|
253
|
+
super.connectedCallback();
|
|
254
|
+
// Capture-phase, on the host itself: blocks programmatic el.click() calls
|
|
255
|
+
// and any other path that bypasses the inner button's pointer-events:none
|
|
256
|
+
// (e.g. CSS pointer-events doesn't stop .click(), which targets the host
|
|
257
|
+
// directly regardless of hit-testing).
|
|
258
|
+
this.addEventListener("click", this.handleHostClick, { capture: true });
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
disconnectedCallback() {
|
|
262
|
+
this.removeEventListener("click", this.handleHostClick, { capture: true });
|
|
263
|
+
super.disconnectedCallback();
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
private handleHostClick = (e: MouseEvent) => {
|
|
267
|
+
if (this.disabled) {
|
|
268
|
+
e.preventDefault();
|
|
269
|
+
e.stopImmediatePropagation();
|
|
270
|
+
}
|
|
271
|
+
};
|
|
272
|
+
|
|
248
273
|
private get classes() {
|
|
249
274
|
return [
|
|
250
275
|
`btn-${this.variant}`,
|
|
@@ -261,13 +286,10 @@ export class RelButton extends LitElement {
|
|
|
261
286
|
return;
|
|
262
287
|
}
|
|
263
288
|
|
|
264
|
-
//
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
composed: true,
|
|
269
|
-
})
|
|
270
|
-
);
|
|
289
|
+
// Native click events are already composed: true, so this bubbles
|
|
290
|
+
// through the shadow boundary to the host on its own — no re-dispatch
|
|
291
|
+
// needed. (A manual re-dispatch here previously caused every @click
|
|
292
|
+
// listener on <rel-button> to fire twice per real click.)
|
|
271
293
|
}
|
|
272
294
|
|
|
273
295
|
render() {
|
|
@@ -17,6 +17,9 @@ A compact chip component for displaying tags, labels, or selected options. Suppo
|
|
|
17
17
|
<!-- Outline variant -->
|
|
18
18
|
<rel-chip label="Outline Style" tone="blue" outline></rel-chip>
|
|
19
19
|
|
|
20
|
+
<!-- Small size variant -->
|
|
21
|
+
<rel-chip label="Small" size="sm" tone="blue"></rel-chip>
|
|
22
|
+
|
|
20
23
|
<!-- With avatar -->
|
|
21
24
|
<rel-chip id="avatarChip" label="John Doe" avatar="./user.jpg"></rel-chip>
|
|
22
25
|
|
|
@@ -43,6 +46,7 @@ A compact chip component for displaying tags, labels, or selected options. Suppo
|
|
|
43
46
|
| Name | Type | Default | Description |
|
|
44
47
|
|------|------|---------|-------------|
|
|
45
48
|
| `label` | `string` | `"Label"` | Text displayed on the chip |
|
|
49
|
+
| `size` (reflected) | `"sm" \| "md"` | `"md"` | Chip size variant |
|
|
46
50
|
| `tone` | `"default" \| "blue" \| "yellow" \| "red" \| "green"` | `"default"` | Color tone variant |
|
|
47
51
|
| `leadingIcon` | `string` | - | SVG or HTML string for leading icon |
|
|
48
52
|
| `trailingIcon` | `string` | - | SVG or HTML string for trailing icon |
|
|
@@ -103,6 +107,9 @@ None exposed.
|
|
|
103
107
|
- Remove button focus: 2px white outline with 1px offset
|
|
104
108
|
|
|
105
109
|
## Notes / Edge Cases
|
|
110
|
+
- **Size variants**:
|
|
111
|
+
- **md** (default): `--rel-fontSizes-md` text, `--rel-spacing-space-2xs`/`--rel-spacing-space-xs` padding, 20px × 20px avatar, 16px × 16px icons
|
|
112
|
+
- **sm**: `--rel-fontSizes-sm` text, `--rel-spacing-space-3xs`/`--rel-spacing-space-2xs` padding, 16px × 16px avatar, 12px × 12px icons
|
|
106
113
|
- Icons (`leadingIcon`, `trailingIcon`) must be passed as raw HTML/SVG strings via JavaScript (see examples)
|
|
107
114
|
- Icons are injected using `renderIcon()` which creates a template element and clones the content
|
|
108
115
|
- Avatar images are 20px × 20px circular (`border-radius: 50%`, `object-fit: cover`)
|