@m3e/badge 1.0.0-rc.1 → 1.0.0-rc.3
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 +1 -2
- package/dist/custom-elements.json +2632 -7
- package/dist/html-custom-data.json +6 -1
- package/dist/index.js +4 -5
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +17 -17
- package/dist/index.min.js.map +1 -1
- package/dist/src/BadgeElement.d.ts +1 -2
- package/dist/src/BadgeElement.d.ts.map +1 -1
- package/package.json +4 -4
- package/cem.config.mjs +0 -16
- package/demo/index.html +0 -60
- package/eslint.config.mjs +0 -13
- package/rollup.config.js +0 -32
- package/src/BadgeElement.ts +0 -247
- package/src/BadgePosition.ts +0 -10
- package/src/BadgeSize.ts +0 -2
- package/src/index.ts +0 -2
- package/tsconfig.json +0 -9
package/src/BadgeElement.ts
DELETED
|
@@ -1,247 +0,0 @@
|
|
|
1
|
-
import { css, CSSResultGroup, html, LitElement, PropertyValues } from "lit";
|
|
2
|
-
import { customElement, property } from "lit/decorators.js";
|
|
3
|
-
|
|
4
|
-
import { DesignToken, HtmlFor, Role } from "@m3e/core";
|
|
5
|
-
import { M3eDirectionality } from "@m3e/core/bidi";
|
|
6
|
-
import { AnchorPosition, positionAnchor } from "@m3e/core/anchoring";
|
|
7
|
-
|
|
8
|
-
import { BadgeSize } from "./BadgeSize";
|
|
9
|
-
import { BadgePosition } from "./BadgePosition";
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* @summary
|
|
13
|
-
* A visual indicator used to label content.
|
|
14
|
-
*
|
|
15
|
-
* @description
|
|
16
|
-
* The `m3e-badge` component is a compact visual indicator used to label content. Designed
|
|
17
|
-
* according to Material Design 3 guidelines, it can display counts, presence, or semantic
|
|
18
|
-
* emphasis, and is attachable to icons, buttons, or other components. Badges support dynamic
|
|
19
|
-
* sizing, color, and shape, ensuring clarity and accessibility while maintaining a consistent,
|
|
20
|
-
* expressive appearance across surfaces.
|
|
21
|
-
*
|
|
22
|
-
* @example
|
|
23
|
-
* The following example illustrates attaching a `m3e-badge` to another element using the `for` attribute.
|
|
24
|
-
* ```html
|
|
25
|
-
* <m3e-button id="button">Button</m3e-button>
|
|
26
|
-
* <m3e-badge for="button">10</m3e-badge>
|
|
27
|
-
* ```
|
|
28
|
-
*
|
|
29
|
-
* @tag m3e-badge
|
|
30
|
-
*
|
|
31
|
-
* @slot - Renders the content of the badge.
|
|
32
|
-
*
|
|
33
|
-
* @attr size - The size of the badge.
|
|
34
|
-
*
|
|
35
|
-
* @cssprop --m3e-badge-shape - Corner radius of the badge.
|
|
36
|
-
* @cssprop --m3e-badge-color - Foreground color of badge content.
|
|
37
|
-
* @cssprop --m3e-badge-container-color - Background color of the badge.
|
|
38
|
-
* @cssprop --m3e-badge-small-size - Fixed dimensions for small badge. Used for minimal indicators (e.g. dot).
|
|
39
|
-
* @cssprop --m3e-badge-medium-size - Height and min-width for medium badge.
|
|
40
|
-
* @cssprop --m3e-badge-medium-font-size - Font size for medium badge label.
|
|
41
|
-
* @cssprop --m3e-badge-medium-font-weight - Font weight for medium badge label.
|
|
42
|
-
* @cssprop --m3e-badge-medium-line-height - Line height for medium badge label.
|
|
43
|
-
* @cssprop --m3e-badge-medium-tracking - Letter spacing for medium badge label.
|
|
44
|
-
* @cssprop --m3e-badge-large-size - Height and min-width for large badge.
|
|
45
|
-
* @cssprop --m3e-badge-large-font-size - Font size for large badge label.
|
|
46
|
-
* @cssprop --m3e-badge-large-font-weight - Font weight for large badge label.
|
|
47
|
-
* @cssprop --m3e-badge-large-line-height - Line height for large badge label.
|
|
48
|
-
* @cssprop --m3e-badge-large-tracking - Letter spacing for large badge label.
|
|
49
|
-
*/
|
|
50
|
-
@customElement("m3e-badge")
|
|
51
|
-
export class M3eBadgeElement extends HtmlFor(Role(LitElement, "status")) {
|
|
52
|
-
/** The styles of the element. */
|
|
53
|
-
static override styles: CSSResultGroup = css`
|
|
54
|
-
:host {
|
|
55
|
-
display: inline-flex;
|
|
56
|
-
align-items: center;
|
|
57
|
-
justify-content: center;
|
|
58
|
-
text-align: center;
|
|
59
|
-
white-space: nowrap;
|
|
60
|
-
vertical-align: baseline;
|
|
61
|
-
box-sizing: border-box;
|
|
62
|
-
user-select: none;
|
|
63
|
-
padding: var(--_badge-padding);
|
|
64
|
-
border-radius: var(--m3e-badge-shape, ${DesignToken.shape.corner.full});
|
|
65
|
-
color: var(--m3e-badge-color, ${DesignToken.color.onError});
|
|
66
|
-
background-color: var(--m3e-badge-container-color, ${DesignToken.color.error});
|
|
67
|
-
}
|
|
68
|
-
:host([for]) {
|
|
69
|
-
position: absolute;
|
|
70
|
-
z-index: 1;
|
|
71
|
-
}
|
|
72
|
-
:host([for]:not([dir])) {
|
|
73
|
-
visibility: hidden;
|
|
74
|
-
}
|
|
75
|
-
:host([for][position^="above"]) {
|
|
76
|
-
margin-block-start: var(--_badge-offset, 0px);
|
|
77
|
-
}
|
|
78
|
-
:host([for][position^="below"]) {
|
|
79
|
-
margin-block-start: calc(0px - var(--_badge-offset, 0px));
|
|
80
|
-
}
|
|
81
|
-
:host([for][position$="before"][dir="ltr"]),
|
|
82
|
-
:host([for][position$="after"][dir="rtl"]) {
|
|
83
|
-
margin-left: var(--_badge-offset, 0px);
|
|
84
|
-
}
|
|
85
|
-
:host([for][position$="before"][dir="rtl"]),
|
|
86
|
-
:host([for][position$="after"][dir="ltr"]) {
|
|
87
|
-
margin-left: calc(0px - var(--_badge-offset, 0px));
|
|
88
|
-
}
|
|
89
|
-
:host([size="small"]) {
|
|
90
|
-
height: var(--m3e-badge-small-size, 0.375rem);
|
|
91
|
-
max-height: var(--m3e-badge-small-size, 0.375rem);
|
|
92
|
-
width: var(--m3e-badge-small-size, 0.375rem);
|
|
93
|
-
min-width: var(--m3e-badge-small-size, 0.375rem);
|
|
94
|
-
font-size: 0;
|
|
95
|
-
--_badge-offset: var(--m3e-badge-small-offset, 0.375rem);
|
|
96
|
-
}
|
|
97
|
-
:host([size="medium"]) {
|
|
98
|
-
height: var(--m3e-badge-medium-size, 1.375rem);
|
|
99
|
-
min-width: var(--m3e-badge-medium-size, 1.375rem);
|
|
100
|
-
font-size: var(--m3e-badge-medium-font-size, ${DesignToken.typescale.standard.label.small.fontSize});
|
|
101
|
-
font-weight: var(--m3e-badge-medium-font-weight, ${DesignToken.typescale.standard.label.small.fontWeight});
|
|
102
|
-
line-height: var(--m3e-badge-medium-line-height, ${DesignToken.typescale.standard.label.small.lineHeight});
|
|
103
|
-
letter-spacing: var(--m3e-badge-medium-tracking, ${DesignToken.typescale.standard.label.small.tracking});
|
|
104
|
-
--_badge-offset: var(--m3e-badge-small-offset, 0.75rem);
|
|
105
|
-
}
|
|
106
|
-
:host([size="large"]) {
|
|
107
|
-
height: var(--m3e-badge-large-size, 1.75rem);
|
|
108
|
-
min-width: var(--m3e-badge-large-size, 1.75rem);
|
|
109
|
-
font-size: var(--m3e-badge-large-font-size, ${DesignToken.typescale.standard.label.large.fontSize});
|
|
110
|
-
font-weight: var(--m3e-badge-large-font-weight, ${DesignToken.typescale.standard.label.large.fontWeight});
|
|
111
|
-
line-height: var(--m3e-badge-large-line-height, ${DesignToken.typescale.standard.label.large.lineHeight});
|
|
112
|
-
letter-spacing: var(--m3e-badge-large-tracking, ${DesignToken.typescale.standard.label.large.tracking});
|
|
113
|
-
--_badge-offset: var(--m3e-badge-small-offset, 1rem);
|
|
114
|
-
}
|
|
115
|
-
@media (forced-colors: active) {
|
|
116
|
-
:host {
|
|
117
|
-
background-color: ButtonFace;
|
|
118
|
-
color: ButtonText;
|
|
119
|
-
outline: 1px solid ButtonText;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
`;
|
|
123
|
-
|
|
124
|
-
/** @private */ #directionalitySubscription?: () => void;
|
|
125
|
-
/** @private */ #anchorCleanup?: () => void;
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* The size of the badge.
|
|
129
|
-
* @default "medium"
|
|
130
|
-
*/
|
|
131
|
-
@property({ reflect: true }) size: BadgeSize = "medium";
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* The position of the badge, when attached to another element.
|
|
135
|
-
* @default "above-after"
|
|
136
|
-
*/
|
|
137
|
-
@property({ reflect: true }) position: BadgePosition = "above-after";
|
|
138
|
-
|
|
139
|
-
/** @inheritdoc */
|
|
140
|
-
override detach(): void {
|
|
141
|
-
super.detach();
|
|
142
|
-
this.#detach();
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/** @inheritdoc */
|
|
146
|
-
override connectedCallback(): void {
|
|
147
|
-
super.connectedCallback();
|
|
148
|
-
this.#directionalitySubscription = M3eDirectionality.observe(() => this.#attach());
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
/** @inheritdoc */
|
|
152
|
-
override disconnectedCallback(): void {
|
|
153
|
-
super.disconnectedCallback();
|
|
154
|
-
this.#directionalitySubscription?.();
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
/** @inheritdoc */
|
|
158
|
-
protected override update(changedProperties: PropertyValues<this>): void {
|
|
159
|
-
super.update(changedProperties);
|
|
160
|
-
|
|
161
|
-
if (changedProperties.has("position") || changedProperties.has("size") || changedProperties.has("htmlFor")) {
|
|
162
|
-
this.#attach();
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
/** @inheritdoc */
|
|
167
|
-
protected override render(): unknown {
|
|
168
|
-
return html`<slot @slotchange="${this.#handleSlotChange}"> <span aria-hidden="true"> </span></slot>`;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
/** @internal */
|
|
172
|
-
#handleSlotChange() {
|
|
173
|
-
if (!this.isConnected) return;
|
|
174
|
-
this.style.setProperty(
|
|
175
|
-
"--_badge-padding",
|
|
176
|
-
this.textContent && this.textContent.length > 2
|
|
177
|
-
? `0 ${this.size === "medium" ? "0.25rem" : this.size === "large" ? "0.5rem" : "0"}`
|
|
178
|
-
: ""
|
|
179
|
-
);
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
/** @private */
|
|
183
|
-
#detach(): void {
|
|
184
|
-
this.#anchorCleanup?.();
|
|
185
|
-
this.#anchorCleanup = undefined;
|
|
186
|
-
this.dir = "";
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
/** @private */
|
|
190
|
-
async #attach(): Promise<void> {
|
|
191
|
-
this.#detach();
|
|
192
|
-
|
|
193
|
-
if (!this.control) return;
|
|
194
|
-
|
|
195
|
-
let position: AnchorPosition = "top-end";
|
|
196
|
-
switch (this.position) {
|
|
197
|
-
case "above":
|
|
198
|
-
position = "top";
|
|
199
|
-
break;
|
|
200
|
-
case "above-before":
|
|
201
|
-
position = "top-start";
|
|
202
|
-
break;
|
|
203
|
-
case "after":
|
|
204
|
-
position = "right";
|
|
205
|
-
break;
|
|
206
|
-
case "before":
|
|
207
|
-
position = "left";
|
|
208
|
-
break;
|
|
209
|
-
case "below":
|
|
210
|
-
position = "bottom";
|
|
211
|
-
break;
|
|
212
|
-
case "below-after":
|
|
213
|
-
position = "bottom-end";
|
|
214
|
-
break;
|
|
215
|
-
case "below-before":
|
|
216
|
-
position = "bottom-start";
|
|
217
|
-
break;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
this.#anchorCleanup = await positionAnchor(this, this.control, { position }, (x, y) => {
|
|
221
|
-
this.dir = M3eDirectionality.current;
|
|
222
|
-
if (this.position.includes("before")) {
|
|
223
|
-
if (this.dir == "rtl") {
|
|
224
|
-
x += this.clientWidth;
|
|
225
|
-
} else {
|
|
226
|
-
x -= this.clientWidth;
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
if (this.position.includes("after")) {
|
|
230
|
-
if (this.dir == "rtl") {
|
|
231
|
-
x -= this.clientWidth;
|
|
232
|
-
} else {
|
|
233
|
-
x += this.clientWidth;
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
this.style.left = `${x}px`;
|
|
238
|
-
this.style.top = `${y}px`;
|
|
239
|
-
});
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
declare global {
|
|
244
|
-
interface HTMLElementTagNameMap {
|
|
245
|
-
"m3e-badge": M3eBadgeElement;
|
|
246
|
-
}
|
|
247
|
-
}
|
package/src/BadgePosition.ts
DELETED
package/src/BadgeSize.ts
DELETED
package/src/index.ts
DELETED