@justeattakeaway/pie-chip 0.12.11 → 0.14.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/README.md +79 -28
- package/custom-elements.json +56 -26
- package/dist/index.d.ts +32 -23
- package/dist/index.js +167 -98
- package/dist/react.d.ts +34 -24
- package/dist/react.js +13 -11
- package/package.json +5 -5
- package/src/chip.scss +32 -0
- package/src/defs.ts +9 -8
- package/src/index.ts +147 -51
- package/src/react.ts +4 -2
package/src/index.ts
CHANGED
|
@@ -7,12 +7,16 @@ import { ifDefined } from 'lit/directives/if-defined.js';
|
|
|
7
7
|
import { classMap } from 'lit/directives/class-map.js';
|
|
8
8
|
|
|
9
9
|
import {
|
|
10
|
-
validPropertyValues,
|
|
10
|
+
validPropertyValues,
|
|
11
11
|
safeCustomElement,
|
|
12
|
+
DelegatesFocusMixin,
|
|
12
13
|
} from '@justeattakeaway/pie-webc-core';
|
|
13
14
|
import styles from './chip.scss?inline';
|
|
14
15
|
import {
|
|
15
|
-
type ChipProps,
|
|
16
|
+
type ChipProps,
|
|
17
|
+
variants,
|
|
18
|
+
types,
|
|
19
|
+
defaultProps,
|
|
16
20
|
} from './defs';
|
|
17
21
|
import '@justeattakeaway/pie-icons-webc/dist/IconCloseCircleFilled.js';
|
|
18
22
|
import '@justeattakeaway/pie-spinner';
|
|
@@ -26,21 +30,26 @@ const componentSelector = 'pie-chip';
|
|
|
26
30
|
* @tagname pie-chip
|
|
27
31
|
* @slot icon - The icon slot
|
|
28
32
|
* @slot - Default slot
|
|
29
|
-
* @event {
|
|
33
|
+
* @event {Event} close - when a user clicks the close button.
|
|
34
|
+
* @event {Event} change - when a user interacts with the chip of type checkbox.
|
|
30
35
|
*/
|
|
31
36
|
@safeCustomElement('pie-chip')
|
|
32
|
-
export class PieChip extends PieElement implements ChipProps {
|
|
37
|
+
export class PieChip extends DelegatesFocusMixin(PieElement) implements ChipProps {
|
|
33
38
|
@property({ type: String })
|
|
34
39
|
@validPropertyValues(componentSelector, variants, defaultProps.variant)
|
|
35
40
|
public variant = defaultProps.variant;
|
|
36
41
|
|
|
37
|
-
@property({ type:
|
|
42
|
+
@property({ type: String })
|
|
43
|
+
@validPropertyValues(componentSelector, types, defaultProps.type)
|
|
44
|
+
public type = defaultProps.type;
|
|
45
|
+
|
|
46
|
+
@property({ type: Boolean, reflect: true })
|
|
38
47
|
public disabled = defaultProps.disabled;
|
|
39
48
|
|
|
40
|
-
@property({ type: Boolean })
|
|
49
|
+
@property({ type: Boolean, reflect: true })
|
|
41
50
|
public isSelected = defaultProps.isSelected;
|
|
42
51
|
|
|
43
|
-
@property({ type: Boolean })
|
|
52
|
+
@property({ type: Boolean, reflect: true })
|
|
44
53
|
public isLoading = defaultProps.isLoading;
|
|
45
54
|
|
|
46
55
|
@property({ type: Boolean })
|
|
@@ -50,62 +59,123 @@ export class PieChip extends PieElement implements ChipProps {
|
|
|
50
59
|
public aria: ChipProps['aria'];
|
|
51
60
|
|
|
52
61
|
/**
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
62
|
+
* Handles the change event for the native checkbox.
|
|
63
|
+
* This component is controlled, so it does not set its own state.
|
|
64
|
+
* It simply forwards the native change event.
|
|
56
65
|
* @private
|
|
57
66
|
*/
|
|
58
|
-
private
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
67
|
+
private _onCheckboxChange () {
|
|
68
|
+
// The original event from the input does not bubble past the shadow DOM boundary.
|
|
69
|
+
// We create and dispatch a new 'change' event to ensure it bubbles and is composed,
|
|
70
|
+
// allowing consumers to respond to the interaction.
|
|
71
|
+
const changeEvent = new Event('change', { bubbles: true, composed: true });
|
|
72
|
+
this.dispatchEvent(changeEvent);
|
|
63
73
|
}
|
|
64
74
|
|
|
65
75
|
/**
|
|
66
|
-
* Template for the loading state
|
|
67
|
-
*
|
|
76
|
+
* Template for the loading state spinner.
|
|
68
77
|
* @private
|
|
69
78
|
*/
|
|
70
|
-
private
|
|
71
|
-
const
|
|
72
|
-
const spinnerVariant = isSelected ? 'inverse' : 'secondary';
|
|
79
|
+
private _renderSpinner (): TemplateResult {
|
|
80
|
+
const spinnerVariant = this.isSelected ? 'inverse' : 'secondary';
|
|
73
81
|
|
|
74
82
|
return html`
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
83
|
+
<pie-spinner
|
|
84
|
+
class="c-chip-spinner"
|
|
85
|
+
size="small"
|
|
86
|
+
variant="${spinnerVariant}">
|
|
87
|
+
</pie-spinner>`;
|
|
80
88
|
}
|
|
81
89
|
|
|
82
90
|
/**
|
|
83
|
-
*
|
|
84
|
-
*
|
|
91
|
+
* Renders the core content of the chip (icon, text, spinner).
|
|
85
92
|
* @private
|
|
86
93
|
*/
|
|
87
|
-
private
|
|
88
|
-
|
|
94
|
+
private _renderContent (): TemplateResult {
|
|
95
|
+
return html`
|
|
96
|
+
<slot name="icon"></slot>
|
|
97
|
+
${this.isLoading ? this._renderSpinner() : nothing}
|
|
98
|
+
<slot></slot>
|
|
99
|
+
`;
|
|
89
100
|
}
|
|
90
101
|
|
|
91
102
|
/**
|
|
92
|
-
* Template for the
|
|
93
|
-
*
|
|
103
|
+
* Template for the checkbox variant.
|
|
104
|
+
* This uses a visually hidden native checkbox for accessibility and form integration.
|
|
94
105
|
* @private
|
|
95
106
|
*/
|
|
96
|
-
private
|
|
107
|
+
private _renderCheckbox (): TemplateResult {
|
|
108
|
+
const {
|
|
109
|
+
aria,
|
|
110
|
+
variant,
|
|
111
|
+
disabled,
|
|
112
|
+
isSelected,
|
|
113
|
+
isLoading,
|
|
114
|
+
} = this;
|
|
115
|
+
|
|
116
|
+
const classes = {
|
|
117
|
+
'c-chip': true,
|
|
118
|
+
[`c-chip--${variant}`]: true,
|
|
119
|
+
'c-chip--selected': isSelected,
|
|
120
|
+
'is-disabled': disabled,
|
|
121
|
+
'is-loading': isLoading,
|
|
122
|
+
};
|
|
123
|
+
|
|
97
124
|
return html`
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
125
|
+
<input
|
|
126
|
+
data-test-id="chip-checkbox-input"
|
|
127
|
+
type="checkbox"
|
|
128
|
+
id="pie-chip"
|
|
129
|
+
aria-label="${ifDefined(aria?.label)}"
|
|
130
|
+
?checked=${isSelected}
|
|
131
|
+
?disabled=${disabled}
|
|
132
|
+
@change="${this._onCheckboxChange}"/>
|
|
133
|
+
<label
|
|
134
|
+
for="pie-chip"
|
|
135
|
+
class=${classMap(classes)}
|
|
136
|
+
data-test-id="pie-chip">
|
|
137
|
+
${this._renderContent()}
|
|
138
|
+
</label>`;
|
|
106
139
|
}
|
|
107
140
|
|
|
108
|
-
|
|
141
|
+
private _renderButton (): TemplateResult {
|
|
142
|
+
const {
|
|
143
|
+
aria,
|
|
144
|
+
variant,
|
|
145
|
+
disabled,
|
|
146
|
+
isSelected,
|
|
147
|
+
isLoading,
|
|
148
|
+
} = this;
|
|
149
|
+
|
|
150
|
+
const classes = {
|
|
151
|
+
'c-chip': true,
|
|
152
|
+
[`c-chip--${variant}`]: true,
|
|
153
|
+
'c-chip--selected': isSelected,
|
|
154
|
+
'is-disabled': disabled,
|
|
155
|
+
'is-loading': isLoading,
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
return html`
|
|
159
|
+
<button
|
|
160
|
+
id="pie-chip"
|
|
161
|
+
type="button"
|
|
162
|
+
class=${classMap(classes)}
|
|
163
|
+
aria-busy="${ifDefined(isLoading)}"
|
|
164
|
+
aria-haspopup="${ifDefined(aria?.haspopup)}"
|
|
165
|
+
aria-expanded="${ifDefined(aria?.expanded)}"
|
|
166
|
+
aria-pressed="${isSelected}"
|
|
167
|
+
aria-label="${ifDefined(aria?.label)}"
|
|
168
|
+
?disabled=${disabled}
|
|
169
|
+
data-test-id="pie-chip">
|
|
170
|
+
${this._renderContent()}
|
|
171
|
+
</button>`;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Template for the dismissible variant.
|
|
176
|
+
* @private
|
|
177
|
+
*/
|
|
178
|
+
private _renderDismissible (): TemplateResult {
|
|
109
179
|
const {
|
|
110
180
|
variant,
|
|
111
181
|
disabled,
|
|
@@ -113,6 +183,7 @@ export class PieChip extends PieElement implements ChipProps {
|
|
|
113
183
|
isLoading,
|
|
114
184
|
isDismissible,
|
|
115
185
|
} = this;
|
|
186
|
+
|
|
116
187
|
const showCloseButton = isDismissible && isSelected;
|
|
117
188
|
|
|
118
189
|
const classes = {
|
|
@@ -124,26 +195,51 @@ export class PieChip extends PieElement implements ChipProps {
|
|
|
124
195
|
'is-loading': isLoading,
|
|
125
196
|
};
|
|
126
197
|
|
|
198
|
+
const handleClick = (event: Event) => {
|
|
199
|
+
if (disabled || isDismissible) {
|
|
200
|
+
event.preventDefault();
|
|
201
|
+
event.stopPropagation();
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
const handleCloseButtonClick = (event: Event) : void => {
|
|
206
|
+
event.stopPropagation();
|
|
207
|
+
const closeEvent = new Event('close', { bubbles: true, composed: true });
|
|
208
|
+
this.dispatchEvent(closeEvent);
|
|
209
|
+
};
|
|
210
|
+
|
|
127
211
|
return html`
|
|
128
212
|
<div
|
|
129
|
-
role="${ifDefined(showCloseButton ? undefined : 'button')}"
|
|
130
|
-
tabindex="${ifDefined(showCloseButton ? undefined : '0')}"
|
|
131
|
-
aria-atomic="true"
|
|
132
213
|
aria-busy="${isLoading}"
|
|
133
214
|
aria-current="${isSelected}"
|
|
134
215
|
aria-label="${ifDefined(this.aria?.label)}"
|
|
135
|
-
aria-live="polite"
|
|
136
216
|
class=${classMap(classes)}
|
|
137
217
|
data-test-id="pie-chip"
|
|
138
|
-
@click
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
218
|
+
@click=${handleClick}>
|
|
219
|
+
${this._renderContent()}
|
|
220
|
+
${showCloseButton ? html`<button
|
|
221
|
+
@click="${handleCloseButtonClick}"
|
|
222
|
+
?disabled=${this.disabled}
|
|
223
|
+
aria-label="${ifDefined(this.aria?.close)}"
|
|
224
|
+
class="c-chip-closeBtn"
|
|
225
|
+
data-test-id="chip-close-button">
|
|
226
|
+
<icon-close-circle-filled size="m"></icon-close-circle-filled>
|
|
227
|
+
</button>` : nothing}
|
|
143
228
|
</div>`;
|
|
144
229
|
}
|
|
145
230
|
|
|
146
|
-
|
|
231
|
+
render () {
|
|
232
|
+
if (this.isDismissible) {
|
|
233
|
+
return this._renderDismissible();
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
if (this.type === 'checkbox') {
|
|
237
|
+
return this._renderCheckbox();
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
return this._renderButton();
|
|
241
|
+
}
|
|
242
|
+
|
|
147
243
|
static styles = unsafeCSS(styles);
|
|
148
244
|
}
|
|
149
245
|
|
package/src/react.ts
CHANGED
|
@@ -11,14 +11,16 @@ const PieChipReact = createComponent({
|
|
|
11
11
|
react: React,
|
|
12
12
|
tagName: 'pie-chip',
|
|
13
13
|
events: {
|
|
14
|
-
|
|
14
|
+
onClose: 'close' as EventName<Event>, // when a user clicks the close button.
|
|
15
|
+
onChange: 'change' as EventName<Event>, // when a user interacts with the chip of type checkbox.
|
|
15
16
|
},
|
|
16
17
|
});
|
|
17
18
|
|
|
18
19
|
type ReactBaseType = React.HTMLAttributes<HTMLElement>
|
|
19
20
|
|
|
20
21
|
type PieChipEvents = {
|
|
21
|
-
|
|
22
|
+
onClose?: (event: Event) => void;
|
|
23
|
+
onChange?: (event: Event) => void;
|
|
22
24
|
};
|
|
23
25
|
|
|
24
26
|
export const PieChip = PieChipReact as React.ForwardRefExoticComponent<React.PropsWithoutRef<ChipProps>
|