@m3e/chips 1.0.0-rc.1 → 1.0.0-rc.2

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.
Files changed (43) hide show
  1. package/README.md +1 -2
  2. package/dist/custom-elements.json +4780 -481
  3. package/dist/html-custom-data.json +10 -10
  4. package/dist/index.js +10 -12
  5. package/dist/index.js.map +1 -1
  6. package/dist/index.min.js +60 -60
  7. package/dist/index.min.js.map +1 -1
  8. package/package.json +5 -5
  9. package/cem.config.mjs +0 -16
  10. package/demo/index.html +0 -183
  11. package/dist/src/AssistChipElement.d.ts +0 -82
  12. package/dist/src/AssistChipElement.d.ts.map +0 -1
  13. package/dist/src/ChipElement.d.ts +0 -86
  14. package/dist/src/ChipElement.d.ts.map +0 -1
  15. package/dist/src/ChipSetElement.d.ts +0 -43
  16. package/dist/src/ChipSetElement.d.ts.map +0 -1
  17. package/dist/src/ChipVariant.d.ts +0 -3
  18. package/dist/src/ChipVariant.d.ts.map +0 -1
  19. package/dist/src/FilterChipElement.d.ts +0 -93
  20. package/dist/src/FilterChipElement.d.ts.map +0 -1
  21. package/dist/src/FilterChipSetElement.d.ts +0 -78
  22. package/dist/src/FilterChipSetElement.d.ts.map +0 -1
  23. package/dist/src/InputChipElement.d.ts +0 -104
  24. package/dist/src/InputChipElement.d.ts.map +0 -1
  25. package/dist/src/InputChipSetElement.d.ts +0 -75
  26. package/dist/src/InputChipSetElement.d.ts.map +0 -1
  27. package/dist/src/SuggestionChipElement.d.ts +0 -83
  28. package/dist/src/SuggestionChipElement.d.ts.map +0 -1
  29. package/dist/src/index.d.ts +0 -10
  30. package/dist/src/index.d.ts.map +0 -1
  31. package/eslint.config.mjs +0 -13
  32. package/rollup.config.js +0 -32
  33. package/src/AssistChipElement.ts +0 -103
  34. package/src/ChipElement.ts +0 -336
  35. package/src/ChipSetElement.ts +0 -60
  36. package/src/ChipVariant.ts +0 -2
  37. package/src/FilterChipElement.ts +0 -254
  38. package/src/FilterChipSetElement.ts +0 -161
  39. package/src/InputChipElement.ts +0 -287
  40. package/src/InputChipSetElement.ts +0 -360
  41. package/src/SuggestionChipElement.ts +0 -104
  42. package/src/index.ts +0 -9
  43. package/tsconfig.json +0 -9
@@ -1,161 +0,0 @@
1
- import { html, PropertyValues } from "lit";
2
- import { customElement, property } from "lit/decorators.js";
3
-
4
- import { AttachInternals, Labelled, Dirty, Disabled, FormAssociated, formValue, Touched, Role } from "@m3e/core";
5
- import { SelectionManager, selectionManager } from "@m3e/core/a11y";
6
-
7
- import { M3eChipSetElement } from "./ChipSetElement";
8
- import { M3eFilterChipElement } from "./FilterChipElement";
9
-
10
- /**
11
- * @summary
12
- * A container that organizes filter chips into a cohesive group, enabling selection and
13
- * deselection of values used to refine content or trigger contextual behavior.
14
- *
15
- * @description
16
- * The `m3e-filter-chip-set` component presents a group of filter chips, enabling users to select
17
- * one or more options to filter content or data sets. It supports single and multi-selection,
18
- * keyboard navigation, accessibility, and seamless form association, providing expressive and
19
- * interactive filtering experiences in line with Material 3 guidelines.
20
- *
21
- * @example
22
- * The following example illustrates a single-select `m3e-filter-chip-set` containing multiple `m3e-filter-chip` components that
23
- * allow a user to choose an option. You can use the `multi` attribute to enable multiselect.
24
- * ```html
25
- * <m3e-filter-chip-set aria-label="Filter by topic">
26
- * <m3e-filter-chip><m3e-icon slot="icon" name="palette"></m3e-icon>Design</m3e-filter-chip>
27
- * <m3e-filter-chip><m3e-icon slot="icon" name="accessibility_new"></m3e-icon>Accessibility</m3e-filter-chip>
28
- * <m3e-filter-chip><m3e-icon slot="icon" name="motion_photos_on"></m3e-icon>Motion</m3e-filter-chip>
29
- * <m3e-filter-chip><m3e-icon slot="icon" name="description"></m3e-icon>Documentation</m3e-filter-chip>
30
- * </m3e-filter-chip-set>
31
- * ```
32
- *
33
- * @tag m3e-filter-chip-set
34
- *
35
- * @slot - Renders the chips of the set.
36
- *
37
- * @attr disabled - Whether the element is disabled.
38
- * @attr hide-selection-indicator - Whether to hide the selection indicator.
39
- * @attr multi - Whether multiple chips can be selected.
40
- * @attr name - The name that identifies the element when submitting the associated form.
41
- * @attr vertical - Whether the element is oriented vertically.
42
- *
43
- * @fires input - Emitted when the selected state of a chip changes.
44
- * @fires change - Emitted when the selected state of a chip changes.
45
- *
46
- * @cssprop --m3e-chip-set-spacing - The spacing (gap) between chips in the set.
47
- */
48
- @customElement("m3e-filter-chip-set")
49
- export class M3eFilterChipSetElement extends Labelled(
50
- Dirty(Touched(FormAssociated(Disabled(AttachInternals(Role(M3eChipSetElement, "listbox"))))))
51
- ) {
52
- /** @internal */
53
- readonly [selectionManager] = new SelectionManager<M3eFilterChipElement>()
54
- .onActiveItemChange(() => this[selectionManager].activeItem?.focus())
55
- .withWrap();
56
-
57
- /**
58
- * Whether multiple chips can be selected.
59
- * @default false
60
- */
61
- @property({ type: Boolean }) multi = false;
62
-
63
- /**
64
- * Whether to hide the selection indicator.
65
- * @default false
66
- */
67
- @property({ attribute: "hide-selection-indicator", type: Boolean }) hideSelectionIndicator = false;
68
-
69
- /** The chips of the set. */
70
- get chips(): readonly M3eFilterChipElement[] {
71
- return this[selectionManager]?.items ?? [];
72
- }
73
-
74
- /** The selected chip(s) of the set. */
75
- get selected(): readonly M3eFilterChipElement[] {
76
- return this[selectionManager]?.selectedItems ?? [];
77
- }
78
-
79
- /** The selected value(s) of the set. */
80
- get value(): string | readonly string[] | null {
81
- const values = this.selected.map((x) => x.value);
82
- switch (values.length) {
83
- case 0:
84
- return null;
85
- case 1:
86
- return values[0];
87
- default:
88
- return values;
89
- }
90
- }
91
-
92
- /** @inheritdoc @internal */
93
- override get [formValue]() {
94
- const values = this.value;
95
- if (Array.isArray(values)) {
96
- const data = new FormData();
97
- for (const value of values) {
98
- data.append(this.name, value);
99
- }
100
- return data;
101
- }
102
- return <string | null>values;
103
- }
104
-
105
- /** @inheritdoc */
106
- protected override update(changedProperties: PropertyValues<this>): void {
107
- super.update(changedProperties);
108
-
109
- if (changedProperties.has("vertical")) {
110
- this[selectionManager].vertical = this.vertical;
111
- }
112
-
113
- if (changedProperties.has("disabled") && (changedProperties.get("disabled") !== undefined || this.disabled)) {
114
- this[selectionManager].disabled = this.disabled;
115
- }
116
-
117
- if (changedProperties.has("multi")) {
118
- this.ariaMultiSelectable = `${this.multi}`;
119
- this[selectionManager].multi = this.multi;
120
- this[selectionManager].disableRovingTabIndex(this.multi);
121
- }
122
-
123
- if (changedProperties.has("hideSelectionIndicator")) {
124
- this.chips.forEach((x) => x.classList.toggle("-hide-selection", this.hideSelectionIndicator));
125
- }
126
- }
127
-
128
- /** @inheritdoc */
129
- protected override render(): unknown {
130
- return html`<slot
131
- @slotchange="${this.#handleSlotChange}"
132
- @keydown="${this.#handleKeyDown}"
133
- @change="${this.#handleChange}"
134
- ></slot>`;
135
- }
136
-
137
- /** @internal */
138
- #handleSlotChange() {
139
- const { added } = this[selectionManager].setItems([...this.querySelectorAll("m3e-filter-chip")]);
140
- added.forEach((x) => x.classList.toggle("-hide-selection", this.hideSelectionIndicator));
141
- }
142
-
143
- /** @internal */
144
- #handleKeyDown(e: KeyboardEvent): void {
145
- if (!this.multi) {
146
- this[selectionManager].onKeyDown(e);
147
- }
148
- }
149
-
150
- /** @internal */
151
- #handleChange(e: Event): void {
152
- e.stopPropagation();
153
- this.dispatchEvent(new Event("change", { bubbles: true }));
154
- }
155
- }
156
-
157
- declare global {
158
- interface HTMLElementTagNameMap {
159
- "m3e-filter-chip-set": M3eFilterChipSetElement;
160
- }
161
- }
@@ -1,287 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */
2
- import { css, CSSResultGroup, html, nothing, PropertyValues } from "lit";
3
- import { customElement, property, query } from "lit/decorators.js";
4
- import { ifDefined } from "lit/directives/if-defined.js";
5
-
6
- import {
7
- DisabledInteractive,
8
- Disabled,
9
- EventAttribute,
10
- Role,
11
- AttachInternals,
12
- DesignToken,
13
- hasAssignedNodes,
14
- } from "@m3e/core";
15
-
16
- import { M3eIconButtonElement } from "@m3e/icon-button";
17
-
18
- import { M3eChipElement } from "./ChipElement";
19
-
20
- /**
21
- * @summary
22
- * A chip which represents a discrete piece of information entered by a user.
23
- *
24
- * @description
25
- * The `m3e-input-chip` component represents an input chip, allowing users to enter, display,
26
- * and manage discrete values such as tags or keywords. It supports expressive styling, accessibility,
27
- * keyboard interaction, and appearance variants including `elevated` and `outlined`.
28
- *
29
- * @tag m3e-input-chip
30
- *
31
- * @slot - Renders the label of the chip.
32
- * @slot avatar - Renders an avatar before the chip's label.
33
- * @slot icon - Renders an icon before the chip's label.
34
- * @slot remove-icon - Renders the icon for the button used to remove the chip.
35
- *
36
- * @attr disabled - Whether the element is disabled.
37
- * @attr disabled-interactive - Whether the element is disabled and interactive.
38
- * @attr removable - Whether the chip is removable.
39
- * @attr remove-label - The accessible label given to the button used to remove the chip.
40
- * @attr value - A string representing the value of the chip.
41
- * @attr variant - The appearance variant of the chip.
42
- *
43
- * @fires remove - Emitted when the remove button is clicked or DELETE or BACKSPACE key is pressed.
44
- *
45
- * @cssprop --m3e-chip-container-shape - Border radius of the chip container.
46
- * @cssprop --m3e-chip-container-height - Base height of the chip container before density adjustment.
47
- * @cssprop --m3e-chip-label-text-font-size - Font size of the chip label text.
48
- * @cssprop --m3e-chip-label-text-font-weight - Font weight of the chip label text.
49
- * @cssprop --m3e-chip-label-text-line-height - Line height of the chip label text.
50
- * @cssprop --m3e-chip-label-text-tracking - Letter spacing of the chip label text.
51
- * @cssprop --m3e-chip-label-text-color - Label text color in default state.
52
- * @cssprop --m3e-chip-icon-color - Icon color in default state.
53
- * @cssprop --m3e-chip-icon-size - Font size of leading/trailing icons.
54
- * @cssprop --m3e-chip-spacing - Horizontal gap between chip content elements.
55
- * @cssprop --m3e-chip-padding-start - Default start padding when no icon is present.
56
- * @cssprop --m3e-chip-padding-end - Default end padding when no trailing icon is present.
57
- * @cssprop --m3e-chip-with-icon-padding-start - Start padding when leading icon is present.
58
- * @cssprop --m3e-chip-with-icon-padding-end - End padding when trailing icon is present.
59
- * @cssprop --m3e-chip-disabled-label-text-color - Base color for disabled label text.
60
- * @cssprop --m3e-chip-disabled-label-text-opacity - Opacity applied to disabled label text.
61
- * @cssprop --m3e-chip-disabled-icon-color - Base color for disabled icons.
62
- * @cssprop --m3e-chip-disabled-icon-opacity - Opacity applied to disabled icons.
63
- * @cssprop --m3e-elevated-chip-container-color - Background color for elevated variant.
64
- * @cssprop --m3e-elevated-chip-elevation - Elevation level for elevated variant.
65
- * @cssprop --m3e-elevated-chip-hover-elevation - Elevation level on hover.
66
- * @cssprop --m3e-elevated-chip-disabled-container-color - Background color for disabled elevated variant.
67
- * @cssprop --m3e-elevated-chip-disabled-container-opacity - Opacity applied to disabled elevated background.
68
- * @cssprop --m3e-elevated-chip-disabled-elevation - Elevation level for disabled elevated variant.
69
- * @cssprop --m3e-outlined-chip-outline-thickness - Outline thickness for outlined variant.
70
- * @cssprop --m3e-outlined-chip-outline-color - Outline color for outlined variant.
71
- * @cssprop --m3e-outlined-chip-disabled-outline-color - Outline color for disabled outlined variant.
72
- * @cssprop --m3e-outlined-chip-disabled-outline-opacity - Opacity applied to disabled outline.
73
- * @cssprop --m3e-chip-avatar-size - Font size of the avatar slot content.
74
- * @cssprop --m3e-chip-disabled-avatar-opacity - Opacity applied to the avatar when disabled.
75
- * @cssprop --m3e-chip-with-avatar-padding-start - Start padding when an avatar is present.
76
- */
77
- @customElement("m3e-input-chip")
78
- export class M3eInputChipElement extends EventAttribute(
79
- DisabledInteractive(Disabled(AttachInternals(Role(M3eChipElement, "row"), true))),
80
- "remove"
81
- ) {
82
- /** The styles of the element. */
83
- static override styles: CSSResultGroup = [
84
- M3eChipElement.styles,
85
- css`
86
- .cell {
87
- display: inline-flex;
88
- align-items: center;
89
- outline: none;
90
- column-gap: var(--m3e-chip-spacing, 0.5rem);
91
- min-width: 0;
92
- }
93
- .remove-button {
94
- --m3e-icon-button-extra-small-container-height: 1.5rem;
95
- --m3e-icon-button-extra-small-icon-size: var(--m3e-chip-icon-size, 1.125rem);
96
- width: 1.5rem;
97
- }
98
- .remove-icon {
99
- flex: none;
100
- width: var(--m3e-chip-icon-size, 1.125rem);
101
- height: var(--m3e-chip-icon-size, 1.125rem);
102
- }
103
- .touch {
104
- top: calc(
105
- 0px - calc(calc(3rem - calc(var(--m3e-chip-container-height, 2rem) + ${DesignToken.density.calc(-2)})) / 2)
106
- );
107
- }
108
- .wrapper {
109
- height: 100%;
110
- overflow: visible;
111
- min-width: 0;
112
- }
113
- ::slotted([slot="avatar"]) {
114
- flex: none;
115
- font-size: var(--m3e-chip-avatar-size, 1.5rem);
116
- }
117
- :host(:disabled) ::slotted([slot="avatar"]),
118
- :host([disabled-interactive]) ::slotted([slot="avatar"]) {
119
- opacity: var(--m3e-chip-disabled-avatar-opacity, 38%);
120
- color: var(--m3e-chip-disabled-icon-color, ${DesignToken.color.onSurface});
121
- }
122
- :host(.-with-avatar) ::slotted([slot="icon"]) {
123
- display: none;
124
- }
125
- :host(.-with-avatar) .wrapper {
126
- padding-inline-start: var(--m3e-chip-with-avatar-padding-start, 0.25rem);
127
- }
128
- @media (forced-colors: active) {
129
- :host(:disabled) ::slotted([slot="avatar"]),
130
- :host([disabled-interactive]) ::slotted([slot="avatar"]) {
131
- color: CanvasText;
132
- }
133
- }
134
- `,
135
- ];
136
-
137
- /** A reference to the grid cell of the chip. */
138
- @query(".cell") readonly cell!: HTMLSpanElement;
139
-
140
- /** A reference to the button used to remove the chip. */
141
- @query(".remove-button") readonly removeButton!: M3eIconButtonElement | null;
142
-
143
- /**
144
- * Whether the chip is removable.
145
- * @default false
146
- */
147
- @property({ type: Boolean }) removable = false;
148
-
149
- /**
150
- * The accessible label given to the button used to remove the chip.
151
- * @default "Remove"
152
- */
153
- @property({ attribute: "remove-label" }) removeLabel = "Remove";
154
-
155
- /** @inheritdoc */
156
- override connectedCallback(): void {
157
- super.connectedCallback();
158
- this.removeAttribute("tabindex");
159
- }
160
-
161
- /** @inheritdoc */
162
- protected override update(changedProperties: PropertyValues<this>): void {
163
- super.update(changedProperties);
164
- this.removeAttribute("tabindex");
165
-
166
- if (changedProperties.has("removable")) {
167
- this.classList.toggle("-with-trailing-icon", this.removable);
168
- }
169
- }
170
-
171
- /** @inheritdoc */
172
- protected override render(): unknown {
173
- return html`<div class="base">
174
- <m3e-elevation
175
- class="elevation"
176
- for="cell"
177
- ?disabled="${this.disabled || this.disabledInteractive}"
178
- ></m3e-elevation>
179
- <m3e-state-layer
180
- class="state-layer"
181
- for="cell"
182
- ?disabled="${this.disabled || this.disabledInteractive}"
183
- ></m3e-state-layer>
184
- <m3e-focus-ring class="focus-ring" for="cell" ?disabled="${this.disabled}"></m3e-focus-ring>
185
- <m3e-ripple class="ripple" for="cell" ?disabled="${this.disabled || this.disabledInteractive}"></m3e-ripple>
186
- <div class="wrapper">
187
- <div
188
- id="cell"
189
- class="cell"
190
- role="gridcell"
191
- tabindex="${ifDefined(this.disabled ? undefined : "-1")}"
192
- @keydown="${this.#handleKeyDown}"
193
- >
194
- <slot name="avatar" @slotchange="${this.#handleAvatarSlotChange}"></slot>
195
- ${this._renderIcon()}
196
- <div class="label">${this._renderSlot()}</div>
197
- <div class="touch" aria-hidden="true"></div>
198
- </div>
199
- ${this._renderTrailingIcon()}
200
- </div>
201
- </div>`;
202
- }
203
-
204
- /** @internal @inheritdoc */
205
- protected override _renderTrailingIcon(): unknown {
206
- return this.removable
207
- ? html`<span role="gridcell" class="remove">
208
- <m3e-icon-button
209
- class="remove-button"
210
- aria-label="${this.removeLabel}"
211
- size="extra-small"
212
- tabindex="-1"
213
- ?disabled="${this.disabled}"
214
- ?disabled-interactive="${this.disabledInteractive}"
215
- @click="${this.#handleRemoveButtonClick}"
216
- >
217
- <slot name="remove-icon">
218
- <svg class="remove-icon" viewBox="0 -960 960 960" fill="currentColor">
219
- <path
220
- d="m256-200-56-56 224-224-224-224 56-56 224 224 224-224 56 56-224 224 224 224-56 56-224-224-224 224Z"
221
- />
222
- </svg>
223
- </slot>
224
- </m3e-icon-button>
225
- </span>`
226
- : nothing;
227
- }
228
-
229
- /** @private */
230
- #handleAvatarSlotChange(e: Event): void {
231
- this.classList.toggle("-with-avatar", hasAssignedNodes(<HTMLSlotElement>e.target));
232
- }
233
-
234
- /** @private */
235
- #handleRemoveButtonClick(e: Event): void {
236
- e.stopPropagation();
237
- this.dispatchEvent(new Event("remove"));
238
- }
239
-
240
- /** @private */
241
- #handleKeyDown(e: KeyboardEvent): void {
242
- if (this.removable) {
243
- switch (e.key) {
244
- case "Backspace":
245
- case "Delete":
246
- this.dispatchEvent(new Event("remove"));
247
- break;
248
- }
249
- }
250
- }
251
- }
252
-
253
- interface M3eInputChipElementEventMap extends HTMLElementEventMap {
254
- remove: Event;
255
- }
256
-
257
- export interface M3eInputChipElement {
258
- addEventListener<K extends keyof M3eInputChipElementEventMap>(
259
- type: K,
260
- listener: (this: M3eInputChipElement, ev: M3eInputChipElementEventMap[K]) => void,
261
- options?: boolean | AddEventListenerOptions
262
- ): void;
263
-
264
- addEventListener(
265
- type: string,
266
- listener: EventListenerOrEventListenerObject,
267
- options?: boolean | AddEventListenerOptions
268
- ): void;
269
-
270
- removeEventListener<K extends keyof M3eInputChipElementEventMap>(
271
- type: K,
272
- listener: (this: M3eInputChipElement, ev: M3eInputChipElementEventMap[K]) => void,
273
- options?: boolean | EventListenerOptions
274
- ): void;
275
-
276
- removeEventListener(
277
- type: string,
278
- listener: EventListenerOrEventListenerObject,
279
- options?: boolean | EventListenerOptions
280
- ): void;
281
- }
282
-
283
- declare global {
284
- interface HTMLElementTagNameMap {
285
- "m3e-input-chip": M3eInputChipElement;
286
- }
287
- }