@crowdstrike/glide-core 0.29.2 → 0.30.1
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/accordion.js +240 -1
- package/dist/accordion.styles.js +13 -7
- package/dist/button-group.button.js +143 -1
- package/dist/button-group.button.styles.js +43 -15
- package/dist/button-group.js +249 -1
- package/dist/button-group.styles.js +10 -5
- package/dist/button.js +206 -1
- package/dist/button.styles.js +12 -7
- package/dist/checkbox-group.js +479 -14
- package/dist/checkbox-group.styles.js +5 -2
- package/dist/checkbox.js +519 -32
- package/dist/checkbox.styles.js +10 -5
- package/dist/drawer.js +168 -1
- package/dist/drawer.styles.js +5 -2
- package/dist/dropdown.js +2423 -123
- package/dist/dropdown.option.js +536 -1
- package/dist/dropdown.option.styles.js +5 -2
- package/dist/dropdown.styles.js +15 -8
- package/dist/form-controls-layout.js +102 -1
- package/dist/form-controls-layout.styles.js +5 -2
- package/dist/icon-button.js +139 -1
- package/dist/icon-button.styles.js +19 -7
- package/dist/icons/checked.js +28 -1
- package/dist/icons/chevron.js +21 -1
- package/dist/icons/magnifying-glass.js +23 -1
- package/dist/icons/pencil.js +21 -1
- package/dist/icons/severity-critical.js +20 -1
- package/dist/icons/severity-informational.js +20 -1
- package/dist/icons/severity-medium.js +20 -1
- package/dist/icons/x.js +21 -1
- package/dist/inline-alert.js +118 -1
- package/dist/inline-alert.styles.js +5 -2
- package/dist/input.d.ts +8 -2
- package/dist/input.js +505 -41
- package/dist/input.styles.js +25 -4
- package/dist/label.js +303 -1
- package/dist/label.styles.js +11 -5
- package/dist/library/assert-slot.js +136 -1
- package/dist/library/expect-unhandled-rejection.js +14 -1
- package/dist/library/expect-window-error.js +26 -1
- package/dist/library/final.js +18 -1
- package/dist/library/form-control.js +1 -1
- package/dist/library/localize.js +10 -1
- package/dist/library/mouse.js +35 -1
- package/dist/library/on-resize.js +24 -1
- package/dist/library/required.js +35 -1
- package/dist/library/shadow-root-mode.js +4 -1
- package/dist/library/unique-id.js +3 -1
- package/dist/link.js +92 -1
- package/dist/link.styles.js +10 -5
- package/dist/menu.d.ts +3 -2
- package/dist/menu.js +1259 -1
- package/dist/menu.styles.js +35 -19
- package/dist/modal.d.ts +4 -0
- package/dist/modal.icon-button.js +60 -1
- package/dist/modal.icon-button.styles.js +5 -2
- package/dist/modal.js +473 -1
- package/dist/modal.styles.js +71 -22
- package/dist/option.d.ts +74 -0
- package/dist/option.js +498 -0
- package/dist/option.styles.js +140 -0
- package/dist/{menu.options.d.ts → options.d.ts} +5 -6
- package/dist/options.js +130 -0
- package/dist/options.styles.js +21 -0
- package/dist/popover.js +620 -1
- package/dist/popover.styles.js +11 -5
- package/dist/radio-group.js +624 -17
- package/dist/radio-group.radio.js +211 -1
- package/dist/radio-group.radio.styles.js +9 -4
- package/dist/radio-group.styles.js +5 -2
- package/dist/slider.js +1040 -61
- package/dist/slider.styles.js +9 -4
- package/dist/spinner.js +60 -1
- package/dist/spinner.styles.js +5 -2
- package/dist/split-button.js +116 -1
- package/dist/split-button.primary-button.js +100 -1
- package/dist/split-button.primary-button.styles.js +13 -6
- package/dist/split-button.primary-link.js +102 -1
- package/dist/split-button.secondary-button.d.ts +2 -3
- package/dist/split-button.secondary-button.js +121 -1
- package/dist/split-button.secondary-button.styles.js +12 -7
- package/dist/split-button.styles.js +9 -4
- package/dist/styles/focus-outline.js +9 -3
- package/dist/styles/fonts.css +6 -1
- package/dist/styles/opacity-and-scale-animation.js +6 -3
- package/dist/styles/skeleton.js +6 -3
- package/dist/styles/variables.css +410 -1
- package/dist/styles/visually-hidden.js +6 -3
- package/dist/tab.group.js +386 -1
- package/dist/tab.group.styles.js +5 -2
- package/dist/tab.js +133 -1
- package/dist/tab.panel.js +93 -1
- package/dist/tab.panel.styles.js +11 -5
- package/dist/tab.styles.js +9 -4
- package/dist/tag.js +207 -1
- package/dist/tag.styles.js +10 -5
- package/dist/textarea.js +353 -19
- package/dist/textarea.styles.js +23 -4
- package/dist/toast.js +130 -1
- package/dist/toast.toasts.js +248 -25
- package/dist/toast.toasts.styles.js +9 -4
- package/dist/toggle.js +178 -1
- package/dist/toggle.styles.js +25 -5
- package/dist/tooltip.container.js +130 -1
- package/dist/tooltip.container.styles.js +5 -2
- package/dist/tooltip.js +484 -1
- package/dist/tooltip.styles.js +21 -5
- package/dist/translations/en.js +36 -1
- package/dist/translations/fr.js +37 -1
- package/dist/translations/ja.js +37 -1
- package/package.json +8 -12
- package/dist/menu.button.d.ts +0 -42
- package/dist/menu.button.js +0 -1
- package/dist/menu.button.styles.js +0 -32
- package/dist/menu.link.d.ts +0 -44
- package/dist/menu.link.js +0 -1
- package/dist/menu.link.styles.js +0 -35
- package/dist/menu.options.js +0 -1
- package/dist/menu.options.styles.d.ts +0 -2
- package/dist/menu.options.styles.js +0 -20
- /package/dist/{menu.button.styles.d.ts → option.styles.d.ts} +0 -0
- /package/dist/{menu.link.styles.d.ts → options.styles.d.ts} +0 -0
package/dist/checkbox-group.js
CHANGED
@@ -1,16 +1,249 @@
|
|
1
|
-
var __decorate
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
4
|
+
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;
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
6
|
+
};
|
7
|
+
import './label.js';
|
8
|
+
import { html, LitElement } from 'lit';
|
9
|
+
import { classMap } from 'lit/directives/class-map.js';
|
10
|
+
import { createRef, ref } from 'lit/directives/ref.js';
|
11
|
+
import { customElement, property, state } from 'lit/decorators.js';
|
12
|
+
import { ifDefined } from 'lit/directives/if-defined.js';
|
13
|
+
import { unsafeHTML } from 'lit/directives/unsafe-html.js';
|
14
|
+
import { when } from 'lit/directives/when.js';
|
15
|
+
import packageJson from '../package.json' with { type: 'json' };
|
16
|
+
import Checkbox from './checkbox.js';
|
17
|
+
import styles from './checkbox-group.styles.js';
|
18
|
+
import assertSlot from './library/assert-slot.js';
|
19
|
+
import shadowRootMode from './library/shadow-root-mode.js';
|
20
|
+
import final from './library/final.js';
|
21
|
+
import required from './library/required.js';
|
22
|
+
/**
|
23
|
+
* @attr {string} label
|
24
|
+
* @attr {boolean} [disabled=false]
|
25
|
+
* @attr {boolean} [hide-label=false]
|
26
|
+
* @attr {string} [name='']
|
27
|
+
* @attr {'horizontal'} [orientation='horizontal']
|
28
|
+
* @attr {boolean} [required=false]
|
29
|
+
* @attr {string} [summary]
|
30
|
+
* @attr {string} [tooltip]
|
31
|
+
* @attr {string[]} [value=[]]
|
32
|
+
*
|
33
|
+
* @readonly
|
34
|
+
* @attr {string} [version]
|
35
|
+
*
|
36
|
+
* @slot {Checkbox}
|
37
|
+
* @slot {Element | string} [description] - Additional information or context
|
38
|
+
*
|
39
|
+
* @fires {Event} invalid
|
40
|
+
*
|
41
|
+
* @readonly
|
42
|
+
* @prop {HTMLFormElement | null} form
|
43
|
+
*
|
44
|
+
* @readonly
|
45
|
+
* @prop {ValidityState} validity
|
46
|
+
*
|
47
|
+
* @method checkValidity
|
48
|
+
* @returns boolean
|
49
|
+
*
|
50
|
+
* @method formAssociatedCallback
|
51
|
+
* @method formResetCallback
|
52
|
+
*
|
53
|
+
* @method reportValidity
|
54
|
+
* @returns boolean
|
55
|
+
*
|
56
|
+
* @method resetValidityFeedback
|
57
|
+
*
|
58
|
+
* @method setCustomValidity
|
59
|
+
* @param {string} message
|
60
|
+
*
|
61
|
+
* @method setValidity
|
62
|
+
* @param {ValidityStateFlags} [flags]
|
63
|
+
* @param {string} [message]
|
64
|
+
*/
|
65
|
+
let CheckboxGroup = class CheckboxGroup extends LitElement {
|
66
|
+
static { this.formAssociated = true; }
|
67
|
+
static { this.shadowRootOptions = {
|
68
|
+
...LitElement.shadowRootOptions,
|
69
|
+
mode: shadowRootMode,
|
70
|
+
}; }
|
71
|
+
static { this.styles = styles; }
|
72
|
+
/**
|
73
|
+
* @default false
|
74
|
+
*/
|
75
|
+
get disabled() {
|
76
|
+
return this.#isDisabled;
|
77
|
+
}
|
78
|
+
set disabled(isDisabled) {
|
79
|
+
this.#isDisabled = isDisabled;
|
80
|
+
for (const checkbox of this.#checkboxElements) {
|
81
|
+
checkbox.disabled = isDisabled;
|
82
|
+
}
|
83
|
+
}
|
84
|
+
/**
|
85
|
+
* @default false
|
86
|
+
*/
|
87
|
+
get required() {
|
88
|
+
return this.#isRequired;
|
89
|
+
}
|
90
|
+
set required(isRequired) {
|
91
|
+
this.#isRequired = isRequired;
|
92
|
+
// Changes to `required` change the validity state. If no checkboxes are
|
93
|
+
// checked and Checkbox Group is `required`, then Checkbox Group is invalid.
|
94
|
+
//
|
95
|
+
// However, if `required` is programmatically removed, then Checkbox Group
|
96
|
+
// is suddenly valid. So we update the validity of every checkbox to match
|
97
|
+
// Checkbox Group. This ensures that any visual feedback shown by Checkbox
|
98
|
+
// based on validity is correct.
|
99
|
+
for (const checkbox of this.#checkboxElements) {
|
100
|
+
if (isRequired) {
|
101
|
+
checkbox.setValidity(this.#internals.validity, ' ');
|
102
|
+
}
|
103
|
+
else {
|
104
|
+
checkbox.setValidity({});
|
105
|
+
}
|
106
|
+
// Checkbox's `this.#internals.validity` isn't reactive.
|
107
|
+
checkbox.requestUpdate();
|
108
|
+
}
|
109
|
+
}
|
110
|
+
// Intentionally not reflected to match native.
|
111
|
+
/**
|
112
|
+
* @default []
|
113
|
+
*/
|
114
|
+
get value() {
|
115
|
+
return this.#value;
|
116
|
+
}
|
117
|
+
set value(value) {
|
118
|
+
this.#value = value;
|
119
|
+
for (const checkbox of this.#checkboxElements) {
|
120
|
+
const isChecked = value.some((value) => value !== '' && value === checkbox.value);
|
121
|
+
// It would be simpler if we just checked and unchecked every Checkbox
|
122
|
+
// based on whether its value is in `value`. But doing so would uncheck
|
123
|
+
// Checkboxes that don't have a value but have nonetheless been checked
|
124
|
+
// by the user. Doing it this way ensures we change as little state as
|
125
|
+
// possible that isn't ours to change.
|
126
|
+
if (isChecked) {
|
127
|
+
checkbox.checked = true;
|
128
|
+
}
|
129
|
+
else if (checkbox.value) {
|
130
|
+
checkbox.checked = false;
|
131
|
+
}
|
132
|
+
// We have a few options if `value` is set programmatically to include
|
133
|
+
// the value of a disabled Checkbox. We can throw, remove the value from
|
134
|
+
// `value`, or enable the Checkbox.
|
135
|
+
//
|
136
|
+
// Throwing is attractive because the inclusion of a disabled Checkbox
|
137
|
+
// in `value` is likely a mistake, either due to bad data or developer
|
138
|
+
// error.
|
139
|
+
//
|
140
|
+
// But we only throw in development. So the form will be submitted with the
|
141
|
+
// new `value` in production regardless if it was by mistake. By enabling
|
142
|
+
// the Checkbox, we at least ensure the user is aware of the fact that it'll
|
143
|
+
// be included in the submission.
|
144
|
+
if (checkbox.checked && checkbox.disabled) {
|
145
|
+
checkbox.disabled = false;
|
146
|
+
}
|
147
|
+
}
|
148
|
+
}
|
149
|
+
checkValidity() {
|
150
|
+
this.isCheckingValidity = true;
|
151
|
+
const isValid = this.#internals.checkValidity();
|
152
|
+
this.isCheckingValidity = false;
|
153
|
+
return isValid;
|
154
|
+
}
|
155
|
+
disconnectedCallback() {
|
156
|
+
super.disconnectedCallback();
|
157
|
+
this.form?.removeEventListener('formdata', this.#onFormdata);
|
158
|
+
}
|
159
|
+
firstUpdated() {
|
160
|
+
if (this.disabled) {
|
161
|
+
for (const checkbox of this.#checkboxElements) {
|
162
|
+
checkbox.disabled = true;
|
163
|
+
}
|
164
|
+
}
|
165
|
+
const hasNoCheckedCheckboxes = this.#checkboxElements.every(({ checked }) => !checked);
|
166
|
+
for (const checkbox of this.#checkboxElements) {
|
167
|
+
checkbox.addEventListener('blur', this.#onCheckboxBlur.bind(this));
|
168
|
+
// When `value` is set on initial render, its setter is called before
|
169
|
+
// `connectedCallback()` and thus before the default slot has any assigned
|
170
|
+
// elements. So we set it again here after the initial render is complete
|
171
|
+
// so `this.#checkboxElements` isn't empty.
|
172
|
+
//
|
173
|
+
// Additionally, `#onDefaultSlotChange()` is called after `firstUpdated()`
|
174
|
+
// and sets `value` based on which checkboxes are checked. And the initial `value`
|
175
|
+
// may conflict with the one derived from which checkboxes are checked.
|
176
|
+
//
|
177
|
+
// So we have a decision to make. On first render, do we defer to the initial
|
178
|
+
// `value` and check and uncheck checkboxes below? Or do we defer to
|
179
|
+
// `#onDefaultSlotChange()` and let that method change `value` from its initial
|
180
|
+
// value based on which checkboxes are checked?
|
181
|
+
//
|
182
|
+
// It's largely a toss-up. But the latter seems like the logical choice given
|
183
|
+
// `#onDefaultSlotChange()` is called after `firstUpdated()`. In other words, we
|
184
|
+
// defer to the lifecycle. `#onDefaultSlotChange()` is called second. So it gets to
|
185
|
+
// override what `value` was initially.
|
186
|
+
//
|
187
|
+
// If no checkboxes are checked, then it's obvious that the consumer's intention is
|
188
|
+
// to check checkboxes based on the initial `value` and that the initial `value` is
|
189
|
+
// the intended one. So we proceed.
|
190
|
+
if (hasNoCheckedCheckboxes) {
|
191
|
+
checkbox.checked = this.value.includes(checkbox.value);
|
192
|
+
if (checkbox.checked && !this.disabled) {
|
193
|
+
checkbox.disabled = false;
|
194
|
+
}
|
195
|
+
}
|
196
|
+
}
|
197
|
+
}
|
198
|
+
get form() {
|
199
|
+
return this.#internals.form;
|
200
|
+
}
|
201
|
+
get validity() {
|
202
|
+
const isChecked = this.#checkboxElements.some(({ checked }) => checked);
|
203
|
+
if (this.required && !isChecked) {
|
204
|
+
// A validation message is required but unused because we disable native
|
205
|
+
// validation feedback. And an empty string isn't allowed. Thus a single space.
|
206
|
+
this.#internals.setValidity({ customError: Boolean(this.validityMessage), valueMissing: true }, ' ', this.#componentElementRef.value);
|
207
|
+
}
|
208
|
+
if (this.required && this.#internals.validity.valueMissing && isChecked) {
|
209
|
+
this.#internals.setValidity({});
|
210
|
+
}
|
211
|
+
if (!this.required && this.#internals.validity.valueMissing && !isChecked) {
|
212
|
+
this.#internals.setValidity({});
|
213
|
+
}
|
214
|
+
for (const checkbox of this.#checkboxElements) {
|
215
|
+
checkbox.setValidity(this.#internals.validity, ' ');
|
216
|
+
// Checkbox's `this.#internals.validity` isn't reactive.
|
217
|
+
checkbox.requestUpdate();
|
218
|
+
}
|
219
|
+
return this.#internals.validity;
|
220
|
+
}
|
221
|
+
focus(options) {
|
222
|
+
const checkbox = this.#checkboxElements.find(({ disabled }) => !disabled);
|
223
|
+
checkbox?.focus(options);
|
224
|
+
}
|
225
|
+
formAssociatedCallback() {
|
226
|
+
this.form?.addEventListener('formdata', this.#onFormdata);
|
227
|
+
}
|
228
|
+
formResetCallback() {
|
229
|
+
for (const checkbox of this.#checkboxElements) {
|
230
|
+
checkbox.formResetCallback();
|
231
|
+
}
|
232
|
+
}
|
233
|
+
render() {
|
234
|
+
return html `<div
|
2
235
|
class="component"
|
3
236
|
data-test="component"
|
4
|
-
${ref(this.#
|
237
|
+
${ref(this.#componentElementRef)}
|
5
238
|
>
|
6
239
|
<glide-core-private-label
|
7
240
|
label=${ifDefined(this.label)}
|
8
241
|
orientation=${this.orientation}
|
9
|
-
split=${ifDefined(this.privateSplit??
|
242
|
+
split=${ifDefined(this.privateSplit ?? undefined)}
|
10
243
|
tooltip=${ifDefined(this.tooltip)}
|
11
244
|
?hide=${this.hideLabel}
|
12
245
|
?disabled=${this.disabled}
|
13
|
-
?error=${this.#
|
246
|
+
?error=${this.#isShowValidationFeedback}
|
14
247
|
?required=${this.required}
|
15
248
|
>
|
16
249
|
<label id="label">${this.label}</label>
|
@@ -20,16 +253,19 @@ var __decorate=this&&this.__decorate||function(e,t,i,s){var o,a=arguments.length
|
|
20
253
|
aria-labelledby="label description"
|
21
254
|
role="group"
|
22
255
|
slot="control"
|
23
|
-
class=${classMap({
|
256
|
+
class=${classMap({
|
257
|
+
'checkbox-container': true,
|
258
|
+
invalid: this.#isShowValidationFeedback,
|
259
|
+
})}
|
24
260
|
>
|
25
261
|
<slot
|
26
262
|
class="default-slot"
|
27
|
-
@private-checked-change=${this.#
|
28
|
-
@private-disabled-change=${this.#
|
29
|
-
@private-value-change=${this.#
|
30
|
-
@slotchange=${this.#
|
263
|
+
@private-checked-change=${this.#onCheckboxCheckedChange}
|
264
|
+
@private-disabled-change=${this.#onCheckboxDisabledChange}
|
265
|
+
@private-value-change=${this.#onCheckboxValueChange}
|
266
|
+
@slotchange=${this.#onDefaultSlotChange}
|
31
267
|
${assertSlot([Checkbox])}
|
32
|
-
${ref(this.#
|
268
|
+
${ref(this.#defaultSlotElementRef)}
|
33
269
|
>
|
34
270
|
<!--
|
35
271
|
@type {Checkbox}
|
@@ -40,7 +276,10 @@ var __decorate=this&&this.__decorate||function(e,t,i,s){var o,a=arguments.length
|
|
40
276
|
|
41
277
|
<div id="description" slot="description">
|
42
278
|
<slot
|
43
|
-
class=${classMap({
|
279
|
+
class=${classMap({
|
280
|
+
description: true,
|
281
|
+
hidden: Boolean(this.#isShowValidationFeedback && this.validityMessage),
|
282
|
+
})}
|
44
283
|
name="description"
|
45
284
|
>
|
46
285
|
<!--
|
@@ -49,9 +288,235 @@ var __decorate=this&&this.__decorate||function(e,t,i,s){var o,a=arguments.length
|
|
49
288
|
-->
|
50
289
|
</slot>
|
51
290
|
|
52
|
-
${when(this.#
|
291
|
+
${when(this.#isShowValidationFeedback && this.validityMessage, () => html `<span class="validity-message" data-test="validity-message"
|
53
292
|
>${unsafeHTML(this.validityMessage)}</span
|
54
|
-
>`)
|
293
|
+
>`)}
|
55
294
|
</div>
|
56
295
|
</glide-core-private-label>
|
57
|
-
</div
|
296
|
+
</div>`;
|
297
|
+
}
|
298
|
+
reportValidity() {
|
299
|
+
this.isReportValidityOrSubmit = true;
|
300
|
+
const isValid = this.#internals.reportValidity();
|
301
|
+
// Ensures that getters referencing `this.validity.valid` are updated.
|
302
|
+
this.requestUpdate();
|
303
|
+
return isValid;
|
304
|
+
}
|
305
|
+
resetValidityFeedback() {
|
306
|
+
this.isReportValidityOrSubmit = false;
|
307
|
+
}
|
308
|
+
setCustomValidity(message) {
|
309
|
+
this.validityMessage = message;
|
310
|
+
if (message === '') {
|
311
|
+
this.#internals.setValidity({ customError: false }, '', this.#componentElementRef.value);
|
312
|
+
}
|
313
|
+
else {
|
314
|
+
// A validation message is required but unused because we disable native validation
|
315
|
+
// feedback. And an empty string isn't allowed. Thus a single space.
|
316
|
+
this.#internals.setValidity({
|
317
|
+
customError: true,
|
318
|
+
valueMissing: this.#internals.validity.valueMissing,
|
319
|
+
}, ' ', this.#componentElementRef.value);
|
320
|
+
}
|
321
|
+
}
|
322
|
+
setValidity(flags, message) {
|
323
|
+
this.validityMessage = message;
|
324
|
+
// A validation message is required but unused because we disable native validation
|
325
|
+
// feedback. And an empty string isn't allowed. Thus a single space.
|
326
|
+
this.#internals.setValidity(flags, ' ', this.#componentElementRef.value);
|
327
|
+
}
|
328
|
+
constructor() {
|
329
|
+
super();
|
330
|
+
this.hideLabel = false;
|
331
|
+
this.name = '';
|
332
|
+
this.orientation = 'horizontal';
|
333
|
+
this.version = packageJson.version;
|
334
|
+
this.isBlurring = false;
|
335
|
+
this.isCheckingValidity = false;
|
336
|
+
this.isReportValidityOrSubmit = false;
|
337
|
+
this.#componentElementRef = createRef();
|
338
|
+
this.#defaultSlotElementRef = createRef();
|
339
|
+
this.#isDisabled = false;
|
340
|
+
this.#isRequired = false;
|
341
|
+
this.#value = [];
|
342
|
+
// An arrow function field instead of a method so `this` is closed over and
|
343
|
+
// set to the component instead of the form.
|
344
|
+
this.#onFormdata = ({ formData }) => {
|
345
|
+
if (this.name && this.value.length > 0 && !this.disabled) {
|
346
|
+
formData.append(this.name, JSON.stringify(this.value));
|
347
|
+
}
|
348
|
+
};
|
349
|
+
this.#internals = this.attachInternals();
|
350
|
+
// Event handlers on the host aren't great because consumers can remove them.
|
351
|
+
// Unfortunately, the host is the only thing on which this event is dispatched
|
352
|
+
// because it's the host that is form-associated.
|
353
|
+
this.addEventListener('invalid', (event) => {
|
354
|
+
event?.preventDefault(); // Canceled so a native validation message isn't shown.
|
355
|
+
// We only want to focus the input if the "invalid" event resulted from either:
|
356
|
+
//
|
357
|
+
// 1. A form submission.
|
358
|
+
// 2. A call of `reportValidity()` that did not result from the input's "blur"
|
359
|
+
// event.
|
360
|
+
if (this.isCheckingValidity || this.isBlurring) {
|
361
|
+
return;
|
362
|
+
}
|
363
|
+
this.isReportValidityOrSubmit = true;
|
364
|
+
const isFirstInvalidFormElement = this.form?.querySelector(':invalid') === this;
|
365
|
+
if (isFirstInvalidFormElement) {
|
366
|
+
// - `this.#internals.delegatesFocus` is preferred because it's declarative. But
|
367
|
+
// it's limited to focusing the first focusable element. That doesn't work for
|
368
|
+
// us because our first focusable element is the tooltip when it's present.
|
369
|
+
//
|
370
|
+
// - Canceling this event means the input won't get focus, even if we were to use
|
371
|
+
// `this.#internals.delegatesFocus`.
|
372
|
+
//
|
373
|
+
// - The browser will ignore this if Checkbox isn't the first invalid form control.
|
374
|
+
//
|
375
|
+
// TODO
|
376
|
+
// Try passing `focusVisible` after browsers support it. It may prevent the issue
|
377
|
+
// where the checkbox itself has a focus outline after this call.
|
378
|
+
//
|
379
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus#focusvisible
|
380
|
+
this.focus();
|
381
|
+
}
|
382
|
+
});
|
383
|
+
}
|
384
|
+
#componentElementRef;
|
385
|
+
#defaultSlotElementRef;
|
386
|
+
#internals;
|
387
|
+
#isDisabled;
|
388
|
+
#isRequired;
|
389
|
+
#value;
|
390
|
+
get #checkboxElements() {
|
391
|
+
return this.#defaultSlotElementRef.value
|
392
|
+
? this.#defaultSlotElementRef.value
|
393
|
+
.assignedElements()
|
394
|
+
.filter((element) => {
|
395
|
+
return element instanceof Checkbox;
|
396
|
+
})
|
397
|
+
: [];
|
398
|
+
}
|
399
|
+
// An arrow function field instead of a method so `this` is closed over and
|
400
|
+
// set to the component instead of the form.
|
401
|
+
#onFormdata;
|
402
|
+
get #isShowValidationFeedback() {
|
403
|
+
return (!this.disabled && !this.validity.valid && this.isReportValidityOrSubmit);
|
404
|
+
}
|
405
|
+
#onBlur() {
|
406
|
+
for (const checkbox of this.#checkboxElements) {
|
407
|
+
checkbox.privateIsReportValidityOrSubmit = true;
|
408
|
+
}
|
409
|
+
}
|
410
|
+
#onCheckboxBlur(event) {
|
411
|
+
const newlyFocusedElement = event.relatedTarget;
|
412
|
+
if (!newlyFocusedElement ||
|
413
|
+
!(newlyFocusedElement instanceof Checkbox) ||
|
414
|
+
!this.#checkboxElements.includes(newlyFocusedElement)) {
|
415
|
+
this.#onBlur();
|
416
|
+
}
|
417
|
+
}
|
418
|
+
#onCheckboxCheckedChange(event) {
|
419
|
+
if (event.target instanceof Checkbox &&
|
420
|
+
event.target.checked &&
|
421
|
+
event.target.value) {
|
422
|
+
this.#value = [...this.value, event.target.value];
|
423
|
+
}
|
424
|
+
else if (event.target instanceof Checkbox && !event.target.checked) {
|
425
|
+
this.#value = this.value.filter((value) => {
|
426
|
+
return event.target instanceof Checkbox && value !== event.target.value;
|
427
|
+
});
|
428
|
+
}
|
429
|
+
}
|
430
|
+
#onCheckboxDisabledChange(event) {
|
431
|
+
if (event.target instanceof Checkbox &&
|
432
|
+
event.target.disabled &&
|
433
|
+
event.target.checked) {
|
434
|
+
// `this.#value` may include multiple of the same value because multiple checkboxes
|
435
|
+
// may have the same value. So we only remove the last.
|
436
|
+
//
|
437
|
+
// Ideally, Checkbox Group wouldn't always remove the last value but would know the
|
438
|
+
// exact index to remove. But Checkbox Group, the way it's built, doesn't know
|
439
|
+
// which value in `this.#value` corresponds to which checkbox. It probably should
|
440
|
+
// if cases like this continue to pile up. For now, though, consumers' needs seem
|
441
|
+
// to be met.
|
442
|
+
const index = this.#value.lastIndexOf(event.target.value);
|
443
|
+
this.#value.splice(index, index + 1);
|
444
|
+
}
|
445
|
+
else if (event.target instanceof Checkbox &&
|
446
|
+
event.target.checked &&
|
447
|
+
event.target.value) {
|
448
|
+
this.#value.push(event.target.value);
|
449
|
+
}
|
450
|
+
}
|
451
|
+
#onCheckboxValueChange(event) {
|
452
|
+
if (event.target instanceof Checkbox &&
|
453
|
+
event.target.checked &&
|
454
|
+
event.detail.new) {
|
455
|
+
this.value = this.#value.map((value) => {
|
456
|
+
return value === event.detail.old ? event.detail.new : value;
|
457
|
+
});
|
458
|
+
}
|
459
|
+
else if (event.target instanceof Checkbox && event.target.checked) {
|
460
|
+
this.value = this.#value.filter((value) => value !== event.detail.old);
|
461
|
+
}
|
462
|
+
}
|
463
|
+
#onDefaultSlotChange() {
|
464
|
+
for (const checkbox of this.#checkboxElements) {
|
465
|
+
checkbox.privateVariant = 'minimal';
|
466
|
+
}
|
467
|
+
this.#value = this.#checkboxElements
|
468
|
+
.filter(({ checked, disabled, value }) => checked && !disabled && value !== '')
|
469
|
+
.map(({ value }) => value);
|
470
|
+
}
|
471
|
+
};
|
472
|
+
__decorate([
|
473
|
+
property({ reflect: true }),
|
474
|
+
required
|
475
|
+
], CheckboxGroup.prototype, "label", void 0);
|
476
|
+
__decorate([
|
477
|
+
property({ reflect: true, type: Boolean })
|
478
|
+
], CheckboxGroup.prototype, "disabled", null);
|
479
|
+
__decorate([
|
480
|
+
property({ attribute: 'hide-label', type: Boolean })
|
481
|
+
], CheckboxGroup.prototype, "hideLabel", void 0);
|
482
|
+
__decorate([
|
483
|
+
property({ reflect: true, useDefault: true })
|
484
|
+
], CheckboxGroup.prototype, "name", void 0);
|
485
|
+
__decorate([
|
486
|
+
property({ reflect: true, useDefault: true })
|
487
|
+
], CheckboxGroup.prototype, "orientation", void 0);
|
488
|
+
__decorate([
|
489
|
+
property()
|
490
|
+
], CheckboxGroup.prototype, "privateSplit", void 0);
|
491
|
+
__decorate([
|
492
|
+
property({ reflect: true, type: Boolean })
|
493
|
+
], CheckboxGroup.prototype, "required", null);
|
494
|
+
__decorate([
|
495
|
+
property({ reflect: true })
|
496
|
+
], CheckboxGroup.prototype, "summary", void 0);
|
497
|
+
__decorate([
|
498
|
+
property({ reflect: true })
|
499
|
+
], CheckboxGroup.prototype, "tooltip", void 0);
|
500
|
+
__decorate([
|
501
|
+
property({ type: Array })
|
502
|
+
], CheckboxGroup.prototype, "value", null);
|
503
|
+
__decorate([
|
504
|
+
property({ reflect: true })
|
505
|
+
], CheckboxGroup.prototype, "version", void 0);
|
506
|
+
__decorate([
|
507
|
+
state()
|
508
|
+
], CheckboxGroup.prototype, "isBlurring", void 0);
|
509
|
+
__decorate([
|
510
|
+
state()
|
511
|
+
], CheckboxGroup.prototype, "isCheckingValidity", void 0);
|
512
|
+
__decorate([
|
513
|
+
state()
|
514
|
+
], CheckboxGroup.prototype, "isReportValidityOrSubmit", void 0);
|
515
|
+
__decorate([
|
516
|
+
state()
|
517
|
+
], CheckboxGroup.prototype, "validityMessage", void 0);
|
518
|
+
CheckboxGroup = __decorate([
|
519
|
+
customElement('glide-core-checkbox-group'),
|
520
|
+
final
|
521
|
+
], CheckboxGroup);
|
522
|
+
export default CheckboxGroup;
|
@@ -1,4 +1,6 @@
|
|
1
|
-
import{css}from
|
1
|
+
import { css } from 'lit';
|
2
|
+
export default [
|
3
|
+
css `
|
2
4
|
:host(:not(:disabled)) .component {
|
3
5
|
&.error {
|
4
6
|
.checkbox {
|
@@ -41,4 +43,5 @@ import{css}from"lit";export default[css`
|
|
41
43
|
.validity-message {
|
42
44
|
display: block;
|
43
45
|
}
|
44
|
-
|
46
|
+
`,
|
47
|
+
];
|