@exmg/exm-chip-input 1.2.7 → 1.2.9

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 (24) hide show
  1. package/.rollup.cache/root/repo/packages/exm-chip-input/dist/dropdown/dropdown-container.d.ts +1 -1
  2. package/.rollup.cache/root/repo/packages/exm-chip-input/dist/exm-chip-input-dropdown.d.ts +1 -1
  3. package/.rollup.cache/root/repo/packages/exm-chip-input/dist/exm-chip-input.d.ts +22 -8
  4. package/.rollup.cache/root/repo/packages/exm-chip-input/dist/exm-chip-input.js +87 -3
  5. package/.rollup.cache/root/repo/packages/exm-chip-input/dist/exm-chip-input.stories.d.ts +38 -0
  6. package/.rollup.cache/root/repo/packages/exm-chip-input/dist/exm-chip-input.stories.js +139 -0
  7. package/.rollup.cache/root/repo/packages/exm-chip-input/dist/exm-chip-set.d.ts +14 -0
  8. package/.rollup.cache/root/repo/packages/exm-chip-input/dist/exm-chip-set.js +121 -0
  9. package/.rollup.cache/root/repo/packages/exm-chip-input/dist/exm-chip.d.ts +2 -13
  10. package/.rollup.cache/root/repo/packages/exm-chip-input/dist/exm-chip.js +7 -36
  11. package/dist/dropdown/dropdown-container.d.ts +1 -1
  12. package/dist/dropdown/dropdown-container.js +1 -1
  13. package/dist/exm-chip-input-dropdown.d.ts +1 -1
  14. package/dist/exm-chip-input-dropdown.js +1 -1
  15. package/dist/exm-chip-input.d.ts +22 -8
  16. package/dist/exm-chip-input.js +88 -4
  17. package/dist/exm-chip-input.stories.d.ts +38 -0
  18. package/dist/exm-chip-set.d.ts +14 -0
  19. package/dist/exm-chip-set.js +124 -0
  20. package/dist/exm-chip.d.ts +2 -13
  21. package/dist/exm-chip.js +8 -37
  22. package/dist/node_modules/.bun/@rollup_plugin-typescript@12.3.0_8b7a8dd02ef2c96b/node_modules/tslib/tslib.es6.js +31 -0
  23. package/package.json +2 -2
  24. package/dist/validator/chip-validator.js +0 -68
@@ -2,5 +2,5 @@ import { LitElement } from 'lit';
2
2
  export declare class DropdownContainer extends LitElement {
3
3
  dropdownTitle: string;
4
4
  static styles: import("lit").CSSResult[];
5
- render(): import("lit-html").TemplateResult<1>;
5
+ render(): import("lit").TemplateResult<1>;
6
6
  }
@@ -30,6 +30,6 @@ export declare class ExmChipInputDropdown extends ChipSet {
30
30
  private onMenuClosed;
31
31
  private _removeSelected;
32
32
  private onKeydown;
33
- protected render(): import("lit-html").TemplateResult<1>;
33
+ protected render(): import("lit").TemplateResult<1>;
34
34
  private updateTabIndicesOverride;
35
35
  }
@@ -1,19 +1,33 @@
1
- import { ChipSet } from '@material/web/chips/internal/chip-set.js';
2
- declare global {
3
- interface HTMLElementTagNameMap {
4
- 'exm-chip-input': ExmChipInput;
5
- }
6
- }
1
+ import { PropertyValues } from 'lit';
2
+ import { ExmChipSet } from './exm-chip-set.js';
7
3
  /**
8
4
  *
9
5
  * @final
10
6
  * @suppress {visibility}
11
7
  */
12
- export declare class ExmChipInput extends ChipSet {
8
+ export declare class ExmChipInput extends ExmChipSet {
9
+ static formAssociated: boolean;
13
10
  label: string;
14
11
  supportingText: string;
12
+ required: boolean;
13
+ value: string;
14
+ min: number;
15
+ max?: number;
15
16
  chipCount: number;
16
17
  static styles: import("lit").CSSResult[];
17
- protected render(): import("lit-html").TemplateResult<1>;
18
+ checkValidity(): boolean;
19
+ reportValidity(): boolean;
20
+ protected firstUpdated(): void;
21
+ updated(changedProperties: PropertyValues): void;
22
+ private validate;
23
+ protected render(): import("lit").TemplateResult<1>;
24
+ fireChange(name: string): void;
25
+ valuesToString(): string;
26
+ onChanges(): void;
18
27
  private updateTabIndicesOverride;
19
28
  }
29
+ declare global {
30
+ interface HTMLElementTagNameMap {
31
+ 'exm-chip-input': ExmChipInput;
32
+ }
33
+ }
@@ -1,24 +1,76 @@
1
1
  import { __decorate } from "tslib";
2
2
  import { customElement } from 'lit/decorators/custom-element.js';
3
3
  import { style } from './styles/exm-chip-input-css.js';
4
- import { ChipSet } from '@material/web/chips/internal/chip-set.js';
5
4
  import { styles } from '@material/web/chips/internal/chip-set-styles.js';
6
5
  import { html, nothing } from 'lit';
7
6
  import { property, state } from 'lit/decorators.js';
8
7
  import { sharedChipStyle } from './styles/exm-chips-shared-css.js';
9
8
  import { classMap } from 'lit/directives/class-map.js';
9
+ import { ExmChipSet } from './exm-chip-set.js';
10
10
  /**
11
11
  *
12
12
  * @final
13
13
  * @suppress {visibility}
14
14
  */
15
- let ExmChipInput = class ExmChipInput extends ChipSet {
15
+ let ExmChipInput = class ExmChipInput extends ExmChipSet {
16
16
  constructor() {
17
17
  super(...arguments);
18
18
  this.label = '';
19
19
  this.supportingText = '';
20
+ this.required = false;
21
+ this.value = '';
22
+ this.min = 1;
23
+ this.max = undefined;
20
24
  this.chipCount = 0;
21
25
  }
26
+ checkValidity() {
27
+ var _a;
28
+ return (_a = this.internals) === null || _a === void 0 ? void 0 : _a.checkValidity();
29
+ }
30
+ reportValidity() {
31
+ var _a;
32
+ return (_a = this.internals) === null || _a === void 0 ? void 0 : _a.reportValidity();
33
+ }
34
+ firstUpdated() {
35
+ this.validate();
36
+ }
37
+ updated(changedProperties) {
38
+ var _a;
39
+ if (changedProperties.has('value')) {
40
+ (_a = this.internals) === null || _a === void 0 ? void 0 : _a.setFormValue(this.value);
41
+ this.validate();
42
+ }
43
+ if (changedProperties.has('required')) {
44
+ this.validate();
45
+ }
46
+ }
47
+ validate() {
48
+ var _a, _b, _c;
49
+ const { chips } = this;
50
+ this.chipCount = chips.length;
51
+ let selectedCount = 0;
52
+ for (const chip of chips) {
53
+ selectedCount = chip.selected ? selectedCount + 1 : selectedCount;
54
+ }
55
+ const isInvalid = this.min && this.max !== undefined && this.max !== 0
56
+ ? selectedCount < this.min || selectedCount > this.max
57
+ : selectedCount < this.min;
58
+ if (isInvalid) {
59
+ if (this.max && (this.max !== undefined || this.max !== 0) && selectedCount > this.max) {
60
+ (_a = this.internals) === null || _a === void 0 ? void 0 : _a.setValidity({
61
+ rangeOverflow: true,
62
+ }, `Please select a maximum of ${this.max}`);
63
+ }
64
+ else {
65
+ (_b = this.internals) === null || _b === void 0 ? void 0 : _b.setValidity({
66
+ rangeUnderflow: true,
67
+ }, `Please select a minimum of ${this.min}`);
68
+ }
69
+ }
70
+ else {
71
+ (_c = this.internals) === null || _c === void 0 ? void 0 : _c.setValidity({});
72
+ }
73
+ }
22
74
  render() {
23
75
  const containerClasses = { 'has-label': !!this.label };
24
76
  const labelClasses = { 'not-empty': this.chipCount > 0 };
@@ -27,11 +79,30 @@ let ExmChipInput = class ExmChipInput extends ChipSet {
27
79
  <div class="background"></div>
28
80
  <div class="state-layer"></div>
29
81
  <div class="label ${classMap(labelClasses)}">${this.label}</div>
30
- <div class="items"><slot @slotchange=${this.updateTabIndicesOverride}></slot></div>
82
+ <div class="items">
83
+ <slot @slotchange=${this.updateTabIndicesOverride} @change=${this.onChanges}></slot>
84
+ </div>
31
85
  ${this.supportingText ? html `<div class="supporting-text">${this.supportingText}</div>` : nothing}
32
86
  </div>
33
87
  `;
34
88
  }
89
+ fireChange(name) {
90
+ this.dispatchEvent(new CustomEvent(name, {
91
+ detail: this.value,
92
+ bubbles: true,
93
+ composed: true,
94
+ }));
95
+ }
96
+ valuesToString() {
97
+ const values = this.chips.map((value) => (value.selected ? value.value : null));
98
+ return values.filter((value) => value !== null).join();
99
+ }
100
+ onChanges() {
101
+ this.value = this.valuesToString();
102
+ this.required && this.validate();
103
+ this.fireChange('change');
104
+ this.fireChange('input');
105
+ }
35
106
  updateTabIndicesOverride() {
36
107
  // The chip that should be focusable is either the chip that currently has
37
108
  // focus or the first chip that can be focused.
@@ -59,6 +130,7 @@ let ExmChipInput = class ExmChipInput extends ChipSet {
59
130
  }
60
131
  }
61
132
  };
133
+ ExmChipInput.formAssociated = true;
62
134
  ExmChipInput.styles = [styles, sharedChipStyle, style];
63
135
  __decorate([
64
136
  property({ type: String })
@@ -66,6 +138,18 @@ __decorate([
66
138
  __decorate([
67
139
  property({ type: String, attribute: 'supporting-text' })
68
140
  ], ExmChipInput.prototype, "supportingText", void 0);
141
+ __decorate([
142
+ property({ type: Boolean, reflect: true })
143
+ ], ExmChipInput.prototype, "required", void 0);
144
+ __decorate([
145
+ property({ type: String, reflect: true })
146
+ ], ExmChipInput.prototype, "value", void 0);
147
+ __decorate([
148
+ property({ type: Number, reflect: true })
149
+ ], ExmChipInput.prototype, "min", void 0);
150
+ __decorate([
151
+ property({ type: Number, reflect: true })
152
+ ], ExmChipInput.prototype, "max", void 0);
69
153
  __decorate([
70
154
  state()
71
155
  ], ExmChipInput.prototype, "chipCount", void 0);
@@ -0,0 +1,38 @@
1
+ import type { StoryObj } from '@storybook/web-components-vite';
2
+ import { ExmChipInputDropdown } from './exm-chip-input-dropdown.js';
3
+ import { ExmChipInput } from './exm-chip-input.js';
4
+ import { ExmChip } from './exm-chip.js';
5
+ import './exm-chip-input-dropdown.js';
6
+ import './exm-chip-input.js';
7
+ import '@exmg/exm-form';
8
+ import './exm-chip.js';
9
+ declare const meta: {
10
+ title: string;
11
+ tags: string[];
12
+ render: (args: Partial<ExmChip>) => import("lit").TemplateResult<1>;
13
+ argTypes: {
14
+ name: {
15
+ control: string;
16
+ };
17
+ value: {
18
+ control: "text";
19
+ };
20
+ label: {
21
+ control: "text";
22
+ };
23
+ ariaLabel: {
24
+ control: "text";
25
+ };
26
+ required: {
27
+ control: "boolean";
28
+ };
29
+ };
30
+ };
31
+ export default meta;
32
+ export declare const Chip: StoryObj<ExmChip>;
33
+ export declare const ChipInput: StoryObj<ExmChipInput>;
34
+ export declare const ChipInputDropdown: StoryObj<ExmChipInputDropdown>;
35
+ type ExmChipInputExtended = ExmChipInput & {
36
+ formSubmit: (e: any) => void;
37
+ };
38
+ export declare const ChipInputValidation: StoryObj<ExmChipInputExtended>;
@@ -0,0 +1,139 @@
1
+ import { faker } from '@faker-js/faker';
2
+ import { html } from 'lit';
3
+ import './exm-chip-input-dropdown.js';
4
+ import './exm-chip-input.js';
5
+ import '@exmg/exm-form';
6
+ import './exm-chip.js';
7
+ const supportingText = 'Supporting text option';
8
+ const chipTemplate = (args) => html `
9
+ <exm-chip
10
+ name="${args.name || ''}"
11
+ value="${args.value || ''}"
12
+ label="${args.label || ''}"
13
+ aria-label="${args.ariaLabel || ''}"
14
+ ?required="${args.required}"
15
+ ?selected="${args.selected}"
16
+ ></exm-chip>
17
+ `;
18
+ const meta = {
19
+ title: 'Packages/Chip Input',
20
+ tags: ['autodocs'],
21
+ render: chipTemplate,
22
+ argTypes: {
23
+ name: { control: 'text' },
24
+ value: { control: 'text' },
25
+ label: { control: 'text' },
26
+ ariaLabel: { control: 'text' },
27
+ required: { control: 'boolean' },
28
+ },
29
+ };
30
+ export default meta;
31
+ const lorem = faker.lorem.word();
32
+ export const Chip = {
33
+ args: {
34
+ name: lorem,
35
+ value: lorem,
36
+ label: lorem,
37
+ ariaLabel: lorem,
38
+ required: false,
39
+ },
40
+ };
41
+ const weekdays = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'];
42
+ const ChipInputTemplate = (args) => html `
43
+ <exm-chip-input label="${args.label}" supporting-text="${args.supportingText}"> ${args.children} </exm-chip-input>
44
+ `;
45
+ const selectedWeekDay = faker.number.int({ max: weekdays.length - 1 });
46
+ const days = html `${weekdays.map((d, i) => chipTemplate({
47
+ name: d.substring(0, 3),
48
+ value: d.substring(0, 3),
49
+ label: d.substring(0, 3),
50
+ ariaLabel: d,
51
+ selected: i == selectedWeekDay,
52
+ }))}`;
53
+ export const ChipInput = {
54
+ render: ChipInputTemplate,
55
+ argTypes: {
56
+ label: { control: 'text' },
57
+ supportingText: { control: 'text' },
58
+ },
59
+ args: {
60
+ label: 'Dates (Chip input)',
61
+ supportingText,
62
+ children: days,
63
+ },
64
+ };
65
+ // eslint-disable-next-line prefer-spread
66
+ const fruitsArray = Array.apply(null, Array(5)).map((_unused) => faker.food.fruit());
67
+ const fruits = (preSelected) => html `${fruitsArray.map((f, i) => chipTemplate({
68
+ name: `${f}-name`,
69
+ value: f,
70
+ label: f,
71
+ ariaLabel: f,
72
+ selected: i === preSelected,
73
+ }))}`;
74
+ const ChipInputDropdownTemplate = (args) => html `
75
+ <exm-chip-input-dropdown
76
+ label="${args.label}"
77
+ aria-labelledby="fruit-label"
78
+ dropdown-title="${args.dropdownTitle}"
79
+ supporting-text="${args.supportingText}"
80
+ >
81
+ ${args.children}
82
+ </exm-chip-input-dropdown>
83
+ `;
84
+ export const ChipInputDropdown = {
85
+ render: ChipInputDropdownTemplate,
86
+ argTypes: {
87
+ label: { control: 'text' },
88
+ supportingText: { control: 'text' },
89
+ dropdownTitle: { control: 'text' },
90
+ },
91
+ args: {
92
+ label: 'Preferred Fruit (Chip input dropdown)',
93
+ dropdownTitle: 'Select fruits',
94
+ supportingText,
95
+ children: fruits(1),
96
+ },
97
+ };
98
+ const ChipInputTemplateWithForm = (args) => html `
99
+ <exm-form
100
+ hide-cancel-button
101
+ submitBtn="valid-submit"
102
+ @form-success=${args.formSuccess}
103
+ @form-error=${args.formError}
104
+ @form-submit-finished=${args.formSubmitFinished}
105
+ @form-submit=${args.formSubmit}
106
+ @form-cancel=${args.formCancel}
107
+ >
108
+ <form>
109
+ <exm-chip-input
110
+ name="fruit"
111
+ label="${args.label}"
112
+ supporting-text="${args.supportingText}"
113
+ min="${args.min}"
114
+ max="${args.max}"
115
+ required
116
+ >
117
+ ${args.children}
118
+ </exm-chip-input>
119
+ </form>
120
+ </exm-form>
121
+ `;
122
+ export const ChipInputValidation = {
123
+ render: ChipInputTemplateWithForm,
124
+ argTypes: {
125
+ label: { control: 'text' },
126
+ supportingText: { control: 'text' },
127
+ min: { control: 'number' },
128
+ max: { control: 'number' },
129
+ },
130
+ args: {
131
+ min: 2,
132
+ max: undefined,
133
+ label: 'Preferred Fruit (min required)',
134
+ supportingText,
135
+ children: fruits(-1),
136
+ formSubmit: (e) => console.log(e),
137
+ },
138
+ };
139
+ //# sourceMappingURL=exm-chip-input.stories.js.map
@@ -0,0 +1,14 @@
1
+ import { LitElement } from 'lit';
2
+ import { ExmChip } from './exm-chip.js';
3
+ /**
4
+ * A chip set component.
5
+ */
6
+ export declare class ExmChipSet extends LitElement {
7
+ get chips(): ExmChip[];
8
+ private readonly childElements;
9
+ internals: ElementInternals;
10
+ constructor();
11
+ protected render(): import("lit").TemplateResult<1>;
12
+ private handleKeyDown;
13
+ updateTabIndices(): void;
14
+ }
@@ -0,0 +1,121 @@
1
+ import { __decorate } from "tslib";
2
+ import { html, isServer, LitElement } from 'lit';
3
+ import { queryAssignedElements } from 'lit/decorators.js';
4
+ import { ExmChip } from './exm-chip.js';
5
+ /**
6
+ * A chip set component.
7
+ */
8
+ export class ExmChipSet extends LitElement {
9
+ get chips() {
10
+ return this.childElements.filter((child) => child instanceof ExmChip);
11
+ }
12
+ constructor() {
13
+ super();
14
+ this.internals = this.attachInternals();
15
+ if (!isServer) {
16
+ this.addEventListener('focusin', this.updateTabIndices.bind(this));
17
+ this.addEventListener('update-focus', this.updateTabIndices.bind(this));
18
+ this.addEventListener('keydown', this.handleKeyDown.bind(this));
19
+ this.internals.role = 'toolbar';
20
+ }
21
+ }
22
+ render() {
23
+ return html `<slot @slotchange=${this.updateTabIndices}></slot>`;
24
+ }
25
+ handleKeyDown(event) {
26
+ const isLeft = event.key === 'ArrowLeft';
27
+ const isRight = event.key === 'ArrowRight';
28
+ const isHome = event.key === 'Home';
29
+ const isEnd = event.key === 'End';
30
+ // Ignore non-navigation keys
31
+ if (!isLeft && !isRight && !isHome && !isEnd) {
32
+ return;
33
+ }
34
+ const { chips } = this;
35
+ // Don't try to select another chip if there aren't any.
36
+ if (chips.length < 2) {
37
+ return;
38
+ }
39
+ // Prevent default interactions, such as scrolling.
40
+ event.preventDefault();
41
+ if (isHome || isEnd) {
42
+ const index = isHome ? 0 : chips.length - 1;
43
+ chips[index].focus({ trailing: isEnd });
44
+ this.updateTabIndices();
45
+ return;
46
+ }
47
+ // Check if moving forwards or backwards
48
+ const isRtl = getComputedStyle(this).direction === 'rtl';
49
+ const forwards = isRtl ? isLeft : isRight;
50
+ const focusedChip = chips.find((chip) => chip.matches(':focus-within'));
51
+ if (!focusedChip) {
52
+ // If there is not already a chip focused, select the first or last chip
53
+ // based on the direction we're traveling.
54
+ const nextChip = forwards ? chips[0] : chips[chips.length - 1];
55
+ nextChip.focus({ trailing: !forwards });
56
+ this.updateTabIndices();
57
+ return;
58
+ }
59
+ const currentIndex = chips.indexOf(focusedChip);
60
+ let nextIndex = forwards ? currentIndex + 1 : currentIndex - 1;
61
+ // Search for the next sibling that is not disabled to select.
62
+ // If we return to the host index, there is nothing to select.
63
+ while (nextIndex !== currentIndex) {
64
+ if (nextIndex >= chips.length) {
65
+ // Return to start if moving past the last item.
66
+ nextIndex = 0;
67
+ }
68
+ else if (nextIndex < 0) {
69
+ // Go to end if moving before the first item.
70
+ nextIndex = chips.length - 1;
71
+ }
72
+ // Check if the next sibling is disabled. If so,
73
+ // move the index and continue searching.
74
+ //
75
+ // Some toolbar items may be focusable when disabled for increased
76
+ // visibility.
77
+ const nextChip = chips[nextIndex];
78
+ if (nextChip.disabled && !nextChip.alwaysFocusable) {
79
+ if (forwards) {
80
+ nextIndex++;
81
+ }
82
+ else {
83
+ nextIndex--;
84
+ }
85
+ continue;
86
+ }
87
+ nextChip.focus({ trailing: !forwards });
88
+ this.updateTabIndices();
89
+ break;
90
+ }
91
+ }
92
+ updateTabIndices() {
93
+ // The chip that should be focusable is either the chip that currently has
94
+ // focus or the first chip that can be focused.
95
+ const { chips } = this;
96
+ let chipToFocus;
97
+ for (const chip of chips) {
98
+ const isChipFocusable = chip.alwaysFocusable || !chip.disabled;
99
+ const chipIsFocused = chip.matches(':focus-within');
100
+ if (chipIsFocused && isChipFocusable) {
101
+ // Found the first chip that is actively focused. This overrides the
102
+ // first focusable chip found.
103
+ chipToFocus = chip;
104
+ continue;
105
+ }
106
+ if (isChipFocusable && !chipToFocus) {
107
+ chipToFocus = chip;
108
+ }
109
+ // Disable non-focused chips. If we disable all of them, we'll grant focus
110
+ // to the first focusable child that was found.
111
+ chip.tabIndex = -1;
112
+ }
113
+ if (chipToFocus) {
114
+ chipToFocus.tabIndex = 0;
115
+ }
116
+ }
117
+ }
118
+ __decorate([
119
+ queryAssignedElements()
120
+ ], ExmChipSet.prototype, "childElements", void 0);
121
+ //# sourceMappingURL=exm-chip-set.js.map
@@ -1,14 +1,11 @@
1
1
  import { FilterChip } from '@material/web/chips/internal/filter-chip.js';
2
- import { createValidator, getValidityAnchor } from '@material/web/labs/behaviors/constraint-validation.js';
3
- import { getFormState, getFormValue } from '@material/web/labs/behaviors/form-associated.js';
4
- import { ChipValidator } from './validator/chip-validator.js';
5
2
  declare global {
6
3
  interface HTMLElementTagNameMap {
7
4
  'exm-chip': ExmChip;
8
5
  }
9
6
  }
10
7
  declare const CHECKED: unique symbol;
11
- declare const FilterChipBaseClass: import("@material/web/labs/behaviors/mixin.js").MixinReturn<import("@material/web/labs/behaviors/mixin.js").MixinReturn<(abstract new (...args: any[]) => import("@material/web/labs/behaviors/element-internals.js").WithElementInternals) & (abstract new (...args: any[]) => import("@material/web/labs/behaviors/focusable.js").Focusable) & typeof FilterChip & import("@material/web/labs/behaviors/form-associated.js").FormAssociatedConstructor, import("@material/web/labs/behaviors/form-associated.js").FormAssociated>, import("@material/web/labs/behaviors/constraint-validation.js").ConstraintValidation>;
8
+ declare const FilterChipBaseClass: import("@material/web/labs/behaviors/mixin.js").MixinReturn<typeof FilterChip, import("@material/web/labs/behaviors/focusable.js").Focusable>;
12
9
  /**
13
10
  *
14
11
  * @final
@@ -36,16 +33,8 @@ export declare class ExmChip extends FilterChipBaseClass {
36
33
  value: string;
37
34
  private readonly container;
38
35
  disabled: boolean;
39
- name: string;
40
- [getFormValue](): string | null;
41
- [getFormState](): string;
42
36
  constructor();
43
- formResetCallback(): void;
44
- formStateRestoreCallback(state: string): void;
45
- protected updated(): void;
46
- protected renderPrimaryAction(content: unknown): import("lit-html").TemplateResult<1>;
37
+ protected renderPrimaryAction(content: unknown): import("lit").TemplateResult<1>;
47
38
  private _handleClick;
48
- [createValidator](): ChipValidator;
49
- [getValidityAnchor](): HTMLElement;
50
39
  }
51
40
  export {};
@@ -8,17 +8,13 @@ import { styles as selectableStyles } from '@material/web/chips/internal/selecta
8
8
  import { styles as sharedStyles } from '@material/web/chips/internal/shared-styles.js';
9
9
  import { styles as trailingIconStyles } from '@material/web/chips/internal/trailing-icon-styles.js';
10
10
  import { redispatchEvent } from '@material/web/internal/events/redispatch-event.js';
11
- import { createValidator, getValidityAnchor, mixinConstraintValidation, } from '@material/web/labs/behaviors/constraint-validation.js';
12
- import { getFormState, getFormValue, mixinFormAssociated } from '@material/web/labs/behaviors/form-associated.js';
13
- import { internals, mixinElementInternals } from '@material/web/labs/behaviors/element-internals.js';
14
11
  import { mixinFocusable } from '@material/web/labs/behaviors/focusable.js';
15
- import { ChipValidator } from './validator/chip-validator.js';
16
12
  import { observer } from '@exmg/lit-base';
17
13
  import { SelectionController } from './selection-controller.js';
18
14
  import { html, nothing } from 'lit';
19
15
  const CHECKED = Symbol('checked');
20
16
  // Separate variable needed for closure.
21
- const FilterChipBaseClass = mixinConstraintValidation(mixinFormAssociated(mixinElementInternals(mixinFocusable(FilterChip))));
17
+ const FilterChipBaseClass = mixinFocusable(FilterChip);
22
18
  /**
23
19
  *
24
20
  * @final
@@ -39,12 +35,6 @@ let ExmChip = class ExmChip extends FilterChipBaseClass {
39
35
  this[CHECKED] = checked;
40
36
  this.requestUpdate('checked', wasChecked);
41
37
  }
42
- [(_a = CHECKED, getFormValue)]() {
43
- return this.checked ? this.value : null;
44
- }
45
- [getFormState]() {
46
- return String(this.checked);
47
- }
48
38
  constructor() {
49
39
  super();
50
40
  this.removable = false;
@@ -61,18 +51,6 @@ let ExmChip = class ExmChip extends FilterChipBaseClass {
61
51
  */
62
52
  this.value = 'on';
63
53
  this.addController(this.selectionController);
64
- this[internals].role = 'radio';
65
- }
66
- formResetCallback() {
67
- // The checked property does not reflect, so the original attribute set by
68
- // the user is used to determine the default value.
69
- this.checked = this.hasAttribute('checked');
70
- }
71
- formStateRestoreCallback(state) {
72
- this.checked = state === 'true';
73
- }
74
- updated() {
75
- this[internals].ariaChecked = String(this.checked);
76
54
  }
77
55
  renderPrimaryAction(content) {
78
56
  const { ariaLabel } = this;
@@ -97,6 +75,11 @@ let ExmChip = class ExmChip extends FilterChipBaseClass {
97
75
  // event listener.
98
76
  const prevValue = this.selected;
99
77
  this.selected = !this.selected;
78
+ this.dispatchEvent(new CustomEvent('change', {
79
+ detail: this.selected,
80
+ bubbles: true,
81
+ composed: true,
82
+ }));
100
83
  const preventDefault = !redispatchEvent(this, event);
101
84
  if (preventDefault) {
102
85
  // We should not do `this.selected = !this.selected`, since a client
@@ -106,20 +89,8 @@ let ExmChip = class ExmChip extends FilterChipBaseClass {
106
89
  return;
107
90
  }
108
91
  }
109
- [createValidator]() {
110
- return new ChipValidator(() => {
111
- if (!this.selectionController) {
112
- // Validation runs on superclass construction, so selection controller
113
- // might not actually be ready until this class constructs.
114
- return [this];
115
- }
116
- return this.selectionController.controls;
117
- });
118
- }
119
- [getValidityAnchor]() {
120
- return this.container;
121
- }
122
92
  };
93
+ _a = CHECKED;
123
94
  ExmChip.styles = [sharedStyles, elevatedStyles, trailingIconStyles, selectableStyles, styles];
124
95
  __decorate([
125
96
  property({ type: Boolean })
@@ -2,5 +2,5 @@ import { LitElement } from 'lit';
2
2
  export declare class DropdownContainer extends LitElement {
3
3
  dropdownTitle: string;
4
4
  static styles: import("lit").CSSResult[];
5
- render(): import("lit-html").TemplateResult<1>;
5
+ render(): import("lit").TemplateResult<1>;
6
6
  }
@@ -1,4 +1,4 @@
1
- import { __decorate } from 'tslib';
1
+ import { __decorate } from '../node_modules/.bun/@rollup_plugin-typescript@12.3.0_8b7a8dd02ef2c96b/node_modules/tslib/tslib.es6.js';
2
2
  import { css, LitElement, html } from 'lit';
3
3
  import { property, customElement } from 'lit/decorators.js';
4
4
 
@@ -30,6 +30,6 @@ export declare class ExmChipInputDropdown extends ChipSet {
30
30
  private onMenuClosed;
31
31
  private _removeSelected;
32
32
  private onKeydown;
33
- protected render(): import("lit-html").TemplateResult<1>;
33
+ protected render(): import("lit").TemplateResult<1>;
34
34
  private updateTabIndicesOverride;
35
35
  }
@@ -1,4 +1,4 @@
1
- import { __decorate } from 'tslib';
1
+ import { __decorate } from './node_modules/.bun/@rollup_plugin-typescript@12.3.0_8b7a8dd02ef2c96b/node_modules/tslib/tslib.es6.js';
2
2
  import { customElement } from 'lit/decorators/custom-element.js';
3
3
  import '@material/web/iconbutton/icon-button.js';
4
4
  import '@material/web/button/text-button.js';
@@ -1,19 +1,33 @@
1
- import { ChipSet } from '@material/web/chips/internal/chip-set.js';
2
- declare global {
3
- interface HTMLElementTagNameMap {
4
- 'exm-chip-input': ExmChipInput;
5
- }
6
- }
1
+ import { PropertyValues } from 'lit';
2
+ import { ExmChipSet } from './exm-chip-set.js';
7
3
  /**
8
4
  *
9
5
  * @final
10
6
  * @suppress {visibility}
11
7
  */
12
- export declare class ExmChipInput extends ChipSet {
8
+ export declare class ExmChipInput extends ExmChipSet {
9
+ static formAssociated: boolean;
13
10
  label: string;
14
11
  supportingText: string;
12
+ required: boolean;
13
+ value: string;
14
+ min: number;
15
+ max?: number;
15
16
  chipCount: number;
16
17
  static styles: import("lit").CSSResult[];
17
- protected render(): import("lit-html").TemplateResult<1>;
18
+ checkValidity(): boolean;
19
+ reportValidity(): boolean;
20
+ protected firstUpdated(): void;
21
+ updated(changedProperties: PropertyValues): void;
22
+ private validate;
23
+ protected render(): import("lit").TemplateResult<1>;
24
+ fireChange(name: string): void;
25
+ valuesToString(): string;
26
+ onChanges(): void;
18
27
  private updateTabIndicesOverride;
19
28
  }
29
+ declare global {
30
+ interface HTMLElementTagNameMap {
31
+ 'exm-chip-input': ExmChipInput;
32
+ }
33
+ }
@@ -1,25 +1,77 @@
1
- import { __decorate } from 'tslib';
1
+ import { __decorate } from './node_modules/.bun/@rollup_plugin-typescript@12.3.0_8b7a8dd02ef2c96b/node_modules/tslib/tslib.es6.js';
2
2
  import { customElement } from 'lit/decorators/custom-element.js';
3
3
  import { style } from './styles/exm-chip-input-css.js';
4
- import { ChipSet } from '@material/web/chips/internal/chip-set.js';
5
4
  import { styles } from '@material/web/chips/internal/chip-set-styles.js';
6
5
  import { nothing, html } from 'lit';
7
6
  import { property, state } from 'lit/decorators.js';
8
7
  import { sharedChipStyle } from './styles/exm-chips-shared-css.js';
9
8
  import { classMap } from 'lit/directives/class-map.js';
9
+ import { ExmChipSet } from './exm-chip-set.js';
10
10
 
11
11
  /**
12
12
  *
13
13
  * @final
14
14
  * @suppress {visibility}
15
15
  */
16
- let ExmChipInput = class ExmChipInput extends ChipSet {
16
+ let ExmChipInput = class ExmChipInput extends ExmChipSet {
17
17
  constructor() {
18
18
  super(...arguments);
19
19
  this.label = '';
20
20
  this.supportingText = '';
21
+ this.required = false;
22
+ this.value = '';
23
+ this.min = 1;
24
+ this.max = undefined;
21
25
  this.chipCount = 0;
22
26
  }
27
+ checkValidity() {
28
+ var _a;
29
+ return (_a = this.internals) === null || _a === void 0 ? void 0 : _a.checkValidity();
30
+ }
31
+ reportValidity() {
32
+ var _a;
33
+ return (_a = this.internals) === null || _a === void 0 ? void 0 : _a.reportValidity();
34
+ }
35
+ firstUpdated() {
36
+ this.validate();
37
+ }
38
+ updated(changedProperties) {
39
+ var _a;
40
+ if (changedProperties.has('value')) {
41
+ (_a = this.internals) === null || _a === void 0 ? void 0 : _a.setFormValue(this.value);
42
+ this.validate();
43
+ }
44
+ if (changedProperties.has('required')) {
45
+ this.validate();
46
+ }
47
+ }
48
+ validate() {
49
+ var _a, _b, _c;
50
+ const { chips } = this;
51
+ this.chipCount = chips.length;
52
+ let selectedCount = 0;
53
+ for (const chip of chips) {
54
+ selectedCount = chip.selected ? selectedCount + 1 : selectedCount;
55
+ }
56
+ const isInvalid = this.min && this.max !== undefined && this.max !== 0
57
+ ? selectedCount < this.min || selectedCount > this.max
58
+ : selectedCount < this.min;
59
+ if (isInvalid) {
60
+ if (this.max && (this.max !== undefined || this.max !== 0) && selectedCount > this.max) {
61
+ (_a = this.internals) === null || _a === void 0 ? void 0 : _a.setValidity({
62
+ rangeOverflow: true,
63
+ }, `Please select a maximum of ${this.max}`);
64
+ }
65
+ else {
66
+ (_b = this.internals) === null || _b === void 0 ? void 0 : _b.setValidity({
67
+ rangeUnderflow: true,
68
+ }, `Please select a minimum of ${this.min}`);
69
+ }
70
+ }
71
+ else {
72
+ (_c = this.internals) === null || _c === void 0 ? void 0 : _c.setValidity({});
73
+ }
74
+ }
23
75
  render() {
24
76
  const containerClasses = { 'has-label': !!this.label };
25
77
  const labelClasses = { 'not-empty': this.chipCount > 0 };
@@ -28,11 +80,30 @@ let ExmChipInput = class ExmChipInput extends ChipSet {
28
80
  <div class="background"></div>
29
81
  <div class="state-layer"></div>
30
82
  <div class="label ${classMap(labelClasses)}">${this.label}</div>
31
- <div class="items"><slot @slotchange=${this.updateTabIndicesOverride}></slot></div>
83
+ <div class="items">
84
+ <slot @slotchange=${this.updateTabIndicesOverride} @change=${this.onChanges}></slot>
85
+ </div>
32
86
  ${this.supportingText ? html `<div class="supporting-text">${this.supportingText}</div>` : nothing}
33
87
  </div>
34
88
  `;
35
89
  }
90
+ fireChange(name) {
91
+ this.dispatchEvent(new CustomEvent(name, {
92
+ detail: this.value,
93
+ bubbles: true,
94
+ composed: true,
95
+ }));
96
+ }
97
+ valuesToString() {
98
+ const values = this.chips.map((value) => (value.selected ? value.value : null));
99
+ return values.filter((value) => value !== null).join();
100
+ }
101
+ onChanges() {
102
+ this.value = this.valuesToString();
103
+ this.required && this.validate();
104
+ this.fireChange('change');
105
+ this.fireChange('input');
106
+ }
36
107
  updateTabIndicesOverride() {
37
108
  // The chip that should be focusable is either the chip that currently has
38
109
  // focus or the first chip that can be focused.
@@ -60,6 +131,7 @@ let ExmChipInput = class ExmChipInput extends ChipSet {
60
131
  }
61
132
  }
62
133
  };
134
+ ExmChipInput.formAssociated = true;
63
135
  ExmChipInput.styles = [styles, sharedChipStyle, style];
64
136
  __decorate([
65
137
  property({ type: String })
@@ -67,6 +139,18 @@ __decorate([
67
139
  __decorate([
68
140
  property({ type: String, attribute: 'supporting-text' })
69
141
  ], ExmChipInput.prototype, "supportingText", void 0);
142
+ __decorate([
143
+ property({ type: Boolean, reflect: true })
144
+ ], ExmChipInput.prototype, "required", void 0);
145
+ __decorate([
146
+ property({ type: String, reflect: true })
147
+ ], ExmChipInput.prototype, "value", void 0);
148
+ __decorate([
149
+ property({ type: Number, reflect: true })
150
+ ], ExmChipInput.prototype, "min", void 0);
151
+ __decorate([
152
+ property({ type: Number, reflect: true })
153
+ ], ExmChipInput.prototype, "max", void 0);
70
154
  __decorate([
71
155
  state()
72
156
  ], ExmChipInput.prototype, "chipCount", void 0);
@@ -0,0 +1,38 @@
1
+ import type { StoryObj } from '@storybook/web-components-vite';
2
+ import { ExmChipInputDropdown } from './exm-chip-input-dropdown.js';
3
+ import { ExmChipInput } from './exm-chip-input.js';
4
+ import { ExmChip } from './exm-chip.js';
5
+ import './exm-chip-input-dropdown.js';
6
+ import './exm-chip-input.js';
7
+ import '@exmg/exm-form';
8
+ import './exm-chip.js';
9
+ declare const meta: {
10
+ title: string;
11
+ tags: string[];
12
+ render: (args: Partial<ExmChip>) => import("lit").TemplateResult<1>;
13
+ argTypes: {
14
+ name: {
15
+ control: string;
16
+ };
17
+ value: {
18
+ control: "text";
19
+ };
20
+ label: {
21
+ control: "text";
22
+ };
23
+ ariaLabel: {
24
+ control: "text";
25
+ };
26
+ required: {
27
+ control: "boolean";
28
+ };
29
+ };
30
+ };
31
+ export default meta;
32
+ export declare const Chip: StoryObj<ExmChip>;
33
+ export declare const ChipInput: StoryObj<ExmChipInput>;
34
+ export declare const ChipInputDropdown: StoryObj<ExmChipInputDropdown>;
35
+ type ExmChipInputExtended = ExmChipInput & {
36
+ formSubmit: (e: any) => void;
37
+ };
38
+ export declare const ChipInputValidation: StoryObj<ExmChipInputExtended>;
@@ -0,0 +1,14 @@
1
+ import { LitElement } from 'lit';
2
+ import { ExmChip } from './exm-chip.js';
3
+ /**
4
+ * A chip set component.
5
+ */
6
+ export declare class ExmChipSet extends LitElement {
7
+ get chips(): ExmChip[];
8
+ private readonly childElements;
9
+ internals: ElementInternals;
10
+ constructor();
11
+ protected render(): import("lit").TemplateResult<1>;
12
+ private handleKeyDown;
13
+ updateTabIndices(): void;
14
+ }
@@ -0,0 +1,124 @@
1
+ import { __decorate } from './node_modules/.bun/@rollup_plugin-typescript@12.3.0_8b7a8dd02ef2c96b/node_modules/tslib/tslib.es6.js';
2
+ import { LitElement, isServer, html } from 'lit';
3
+ import { queryAssignedElements } from 'lit/decorators.js';
4
+ import { ExmChip } from './exm-chip.js';
5
+
6
+ /**
7
+ * A chip set component.
8
+ */
9
+ class ExmChipSet extends LitElement {
10
+ get chips() {
11
+ return this.childElements.filter((child) => child instanceof ExmChip);
12
+ }
13
+ constructor() {
14
+ super();
15
+ this.internals = this.attachInternals();
16
+ if (!isServer) {
17
+ this.addEventListener('focusin', this.updateTabIndices.bind(this));
18
+ this.addEventListener('update-focus', this.updateTabIndices.bind(this));
19
+ this.addEventListener('keydown', this.handleKeyDown.bind(this));
20
+ this.internals.role = 'toolbar';
21
+ }
22
+ }
23
+ render() {
24
+ return html `<slot @slotchange=${this.updateTabIndices}></slot>`;
25
+ }
26
+ handleKeyDown(event) {
27
+ const isLeft = event.key === 'ArrowLeft';
28
+ const isRight = event.key === 'ArrowRight';
29
+ const isHome = event.key === 'Home';
30
+ const isEnd = event.key === 'End';
31
+ // Ignore non-navigation keys
32
+ if (!isLeft && !isRight && !isHome && !isEnd) {
33
+ return;
34
+ }
35
+ const { chips } = this;
36
+ // Don't try to select another chip if there aren't any.
37
+ if (chips.length < 2) {
38
+ return;
39
+ }
40
+ // Prevent default interactions, such as scrolling.
41
+ event.preventDefault();
42
+ if (isHome || isEnd) {
43
+ const index = isHome ? 0 : chips.length - 1;
44
+ chips[index].focus({ trailing: isEnd });
45
+ this.updateTabIndices();
46
+ return;
47
+ }
48
+ // Check if moving forwards or backwards
49
+ const isRtl = getComputedStyle(this).direction === 'rtl';
50
+ const forwards = isRtl ? isLeft : isRight;
51
+ const focusedChip = chips.find((chip) => chip.matches(':focus-within'));
52
+ if (!focusedChip) {
53
+ // If there is not already a chip focused, select the first or last chip
54
+ // based on the direction we're traveling.
55
+ const nextChip = forwards ? chips[0] : chips[chips.length - 1];
56
+ nextChip.focus({ trailing: !forwards });
57
+ this.updateTabIndices();
58
+ return;
59
+ }
60
+ const currentIndex = chips.indexOf(focusedChip);
61
+ let nextIndex = forwards ? currentIndex + 1 : currentIndex - 1;
62
+ // Search for the next sibling that is not disabled to select.
63
+ // If we return to the host index, there is nothing to select.
64
+ while (nextIndex !== currentIndex) {
65
+ if (nextIndex >= chips.length) {
66
+ // Return to start if moving past the last item.
67
+ nextIndex = 0;
68
+ }
69
+ else if (nextIndex < 0) {
70
+ // Go to end if moving before the first item.
71
+ nextIndex = chips.length - 1;
72
+ }
73
+ // Check if the next sibling is disabled. If so,
74
+ // move the index and continue searching.
75
+ //
76
+ // Some toolbar items may be focusable when disabled for increased
77
+ // visibility.
78
+ const nextChip = chips[nextIndex];
79
+ if (nextChip.disabled && !nextChip.alwaysFocusable) {
80
+ if (forwards) {
81
+ nextIndex++;
82
+ }
83
+ else {
84
+ nextIndex--;
85
+ }
86
+ continue;
87
+ }
88
+ nextChip.focus({ trailing: !forwards });
89
+ this.updateTabIndices();
90
+ break;
91
+ }
92
+ }
93
+ updateTabIndices() {
94
+ // The chip that should be focusable is either the chip that currently has
95
+ // focus or the first chip that can be focused.
96
+ const { chips } = this;
97
+ let chipToFocus;
98
+ for (const chip of chips) {
99
+ const isChipFocusable = chip.alwaysFocusable || !chip.disabled;
100
+ const chipIsFocused = chip.matches(':focus-within');
101
+ if (chipIsFocused && isChipFocusable) {
102
+ // Found the first chip that is actively focused. This overrides the
103
+ // first focusable chip found.
104
+ chipToFocus = chip;
105
+ continue;
106
+ }
107
+ if (isChipFocusable && !chipToFocus) {
108
+ chipToFocus = chip;
109
+ }
110
+ // Disable non-focused chips. If we disable all of them, we'll grant focus
111
+ // to the first focusable child that was found.
112
+ chip.tabIndex = -1;
113
+ }
114
+ if (chipToFocus) {
115
+ chipToFocus.tabIndex = 0;
116
+ }
117
+ }
118
+ }
119
+ __decorate([
120
+ queryAssignedElements()
121
+ ], ExmChipSet.prototype, "childElements", void 0);
122
+
123
+ export { ExmChipSet };
124
+ //# sourceMappingURL=exm-chip-set.js.map
@@ -1,14 +1,11 @@
1
1
  import { FilterChip } from '@material/web/chips/internal/filter-chip.js';
2
- import { createValidator, getValidityAnchor } from '@material/web/labs/behaviors/constraint-validation.js';
3
- import { getFormState, getFormValue } from '@material/web/labs/behaviors/form-associated.js';
4
- import { ChipValidator } from './validator/chip-validator.js';
5
2
  declare global {
6
3
  interface HTMLElementTagNameMap {
7
4
  'exm-chip': ExmChip;
8
5
  }
9
6
  }
10
7
  declare const CHECKED: unique symbol;
11
- declare const FilterChipBaseClass: import("@material/web/labs/behaviors/mixin.js").MixinReturn<import("@material/web/labs/behaviors/mixin.js").MixinReturn<(abstract new (...args: any[]) => import("@material/web/labs/behaviors/element-internals.js").WithElementInternals) & (abstract new (...args: any[]) => import("@material/web/labs/behaviors/focusable.js").Focusable) & typeof FilterChip & import("@material/web/labs/behaviors/form-associated.js").FormAssociatedConstructor, import("@material/web/labs/behaviors/form-associated.js").FormAssociated>, import("@material/web/labs/behaviors/constraint-validation.js").ConstraintValidation>;
8
+ declare const FilterChipBaseClass: import("@material/web/labs/behaviors/mixin.js").MixinReturn<typeof FilterChip, import("@material/web/labs/behaviors/focusable.js").Focusable>;
12
9
  /**
13
10
  *
14
11
  * @final
@@ -36,16 +33,8 @@ export declare class ExmChip extends FilterChipBaseClass {
36
33
  value: string;
37
34
  private readonly container;
38
35
  disabled: boolean;
39
- name: string;
40
- [getFormValue](): string | null;
41
- [getFormState](): string;
42
36
  constructor();
43
- formResetCallback(): void;
44
- formStateRestoreCallback(state: string): void;
45
- protected updated(): void;
46
- protected renderPrimaryAction(content: unknown): import("lit-html").TemplateResult<1>;
37
+ protected renderPrimaryAction(content: unknown): import("lit").TemplateResult<1>;
47
38
  private _handleClick;
48
- [createValidator](): ChipValidator;
49
- [getValidityAnchor](): HTMLElement;
50
39
  }
51
40
  export {};
package/dist/exm-chip.js CHANGED
@@ -1,4 +1,4 @@
1
- import { __decorate } from 'tslib';
1
+ import { __decorate } from './node_modules/.bun/@rollup_plugin-typescript@12.3.0_8b7a8dd02ef2c96b/node_modules/tslib/tslib.es6.js';
2
2
  import { property, query, customElement } from 'lit/decorators.js';
3
3
  import { styles as styles$1 } from '@material/web/chips/internal/elevated-styles.js';
4
4
  import { FilterChip } from '@material/web/chips/internal/filter-chip.js';
@@ -7,11 +7,7 @@ import { styles as styles$3 } from '@material/web/chips/internal/selectable-styl
7
7
  import { styles } from '@material/web/chips/internal/shared-styles.js';
8
8
  import { styles as styles$2 } from '@material/web/chips/internal/trailing-icon-styles.js';
9
9
  import { redispatchEvent } from '@material/web/internal/events/redispatch-event.js';
10
- import { mixinConstraintValidation, createValidator, getValidityAnchor } from '@material/web/labs/behaviors/constraint-validation.js';
11
- import { mixinFormAssociated, getFormValue, getFormState } from '@material/web/labs/behaviors/form-associated.js';
12
- import { mixinElementInternals, internals } from '@material/web/labs/behaviors/element-internals.js';
13
10
  import { mixinFocusable } from '@material/web/labs/behaviors/focusable.js';
14
- import { ChipValidator } from './validator/chip-validator.js';
15
11
  import { observer } from '@exmg/lit-base';
16
12
  import { SelectionController } from './selection-controller.js';
17
13
  import { nothing, html } from 'lit';
@@ -19,7 +15,7 @@ import { nothing, html } from 'lit';
19
15
  var _a;
20
16
  const CHECKED = Symbol('checked');
21
17
  // Separate variable needed for closure.
22
- const FilterChipBaseClass = mixinConstraintValidation(mixinFormAssociated(mixinElementInternals(mixinFocusable(FilterChip))));
18
+ const FilterChipBaseClass = mixinFocusable(FilterChip);
23
19
  /**
24
20
  *
25
21
  * @final
@@ -40,12 +36,6 @@ let ExmChip = class ExmChip extends FilterChipBaseClass {
40
36
  this[CHECKED] = checked;
41
37
  this.requestUpdate('checked', wasChecked);
42
38
  }
43
- [(_a = CHECKED, getFormValue)]() {
44
- return this.checked ? this.value : null;
45
- }
46
- [getFormState]() {
47
- return String(this.checked);
48
- }
49
39
  constructor() {
50
40
  super();
51
41
  this.removable = false;
@@ -62,18 +52,6 @@ let ExmChip = class ExmChip extends FilterChipBaseClass {
62
52
  */
63
53
  this.value = 'on';
64
54
  this.addController(this.selectionController);
65
- this[internals].role = 'radio';
66
- }
67
- formResetCallback() {
68
- // The checked property does not reflect, so the original attribute set by
69
- // the user is used to determine the default value.
70
- this.checked = this.hasAttribute('checked');
71
- }
72
- formStateRestoreCallback(state) {
73
- this.checked = state === 'true';
74
- }
75
- updated() {
76
- this[internals].ariaChecked = String(this.checked);
77
55
  }
78
56
  renderPrimaryAction(content) {
79
57
  const { ariaLabel } = this;
@@ -98,6 +76,11 @@ let ExmChip = class ExmChip extends FilterChipBaseClass {
98
76
  // event listener.
99
77
  const prevValue = this.selected;
100
78
  this.selected = !this.selected;
79
+ this.dispatchEvent(new CustomEvent('change', {
80
+ detail: this.selected,
81
+ bubbles: true,
82
+ composed: true,
83
+ }));
101
84
  const preventDefault = !redispatchEvent(this, event);
102
85
  if (preventDefault) {
103
86
  // We should not do `this.selected = !this.selected`, since a client
@@ -107,20 +90,8 @@ let ExmChip = class ExmChip extends FilterChipBaseClass {
107
90
  return;
108
91
  }
109
92
  }
110
- [createValidator]() {
111
- return new ChipValidator(() => {
112
- if (!this.selectionController) {
113
- // Validation runs on superclass construction, so selection controller
114
- // might not actually be ready until this class constructs.
115
- return [this];
116
- }
117
- return this.selectionController.controls;
118
- });
119
- }
120
- [getValidityAnchor]() {
121
- return this.container;
122
- }
123
93
  };
94
+ _a = CHECKED;
124
95
  ExmChip.styles = [styles, styles$1, styles$2, styles$3, styles$4];
125
96
  __decorate([
126
97
  property({ type: Boolean })
@@ -0,0 +1,31 @@
1
+ /******************************************************************************
2
+ Copyright (c) Microsoft Corporation.
3
+
4
+ Permission to use, copy, modify, and/or distribute this software for any
5
+ purpose with or without fee is hereby granted.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
8
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
9
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
10
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
11
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
12
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
13
+ PERFORMANCE OF THIS SOFTWARE.
14
+ ***************************************************************************** */
15
+ /* global Reflect, Promise, SuppressedError, Symbol, Iterator */
16
+
17
+
18
+ function __decorate(decorators, target, key, desc) {
19
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
20
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
21
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
22
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
23
+ }
24
+
25
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
26
+ var e = new Error(message);
27
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
28
+ };
29
+
30
+ export { __decorate };
31
+ //# sourceMappingURL=tslib.es6.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exmg/exm-chip-input",
3
- "version": "1.2.7",
3
+ "version": "1.2.9",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -39,5 +39,5 @@
39
39
  "publishConfig": {
40
40
  "access": "public"
41
41
  },
42
- "gitHead": "20c45a5fb2f606723218a739897831c27a6f6790"
42
+ "gitHead": "c27c4ffabda0c6a509df58537017af65719d1e57"
43
43
  }
@@ -1,68 +0,0 @@
1
- import { Validator } from '@material/web/labs/behaviors/validators/validator.js';
2
-
3
- /**
4
- * @license
5
- * Copyright 2023 Google LLC
6
- * SPDX-License-Identifier: Apache-2.0
7
- */
8
- /**
9
- * A validator that provides constraint validation that emulates
10
- * `<input type="checkbox">` validation.
11
- */
12
- class ChipValidator extends Validator {
13
- computeValidity(states) {
14
- if (!this.radioElement) {
15
- // Lazily create the radio element
16
- this.radioElement = document.createElement('input');
17
- this.radioElement.type = 'radio';
18
- // A name is required for validation to run
19
- this.radioElement.name = 'group';
20
- }
21
- let isRequired = false;
22
- let isChecked = false;
23
- for (const { checked, required } of states) {
24
- if (required) {
25
- isRequired = true;
26
- }
27
- if (checked) {
28
- isChecked = true;
29
- }
30
- }
31
- // Firefox v119 doesn't compute grouped radio validation correctly while
32
- // they are detached from the DOM, which is why we don't render multiple
33
- // virtual <input>s. Instead, we can check the required/checked states and
34
- // grab the i18n'd validation message if the value is missing.
35
- this.radioElement.checked = isChecked;
36
- this.radioElement.required = isRequired;
37
- return {
38
- validity: {
39
- valueMissing: isRequired && !isChecked,
40
- },
41
- validationMessage: this.radioElement.validationMessage,
42
- };
43
- }
44
- equals(prevGroup, nextGroup) {
45
- if (prevGroup.length !== nextGroup.length) {
46
- return false;
47
- }
48
- for (let i = 0; i < prevGroup.length; i++) {
49
- const prev = prevGroup[i];
50
- const next = nextGroup[i];
51
- if (prev.checked !== next.checked || prev.required !== next.required) {
52
- return false;
53
- }
54
- }
55
- return true;
56
- }
57
- copy(states) {
58
- // Cast as unknown since typescript does not have enough information to
59
- // infer that the array always has at least one element.
60
- return states.map(({ checked, required }) => ({
61
- checked,
62
- required,
63
- }));
64
- }
65
- }
66
-
67
- export { ChipValidator };
68
- //# sourceMappingURL=chip-validator.js.map