@everymatrix/general-input 1.22.1 → 1.22.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.
@@ -1,302 +1,9 @@
1
1
  import { proxyCustomElement, HTMLElement, createEvent, h } from '@stencil/core/internal/client';
2
2
  import { t as translate, a as tooltipIconSvg } from './tooltipIcon.js';
3
- import { o, i, u as usageStatistics, d as dedupingMixin, D as DelegateStateMixin, a as DisabledMixin, I as InputMixin, b as isElementFocused, L as LabelMixin, c as DelegateFocusMixin, e as InputController, f as LabelledInputController, h as html, P as PolymerElement, r as requiredField, g as helper, F as FieldMixin, j as FocusMixin } from './field-mixin.js';
3
+ import { r as registerStyles, i, d as dedupingMixin, D as DelegateStateMixin, a as DisabledMixin, I as InputMixin, b as isElementFocused, L as LabelMixin, c as DelegateFocusMixin, e as InputController, f as LabelledInputController, h as html, T as TooltipController, g as defineCustomElement$1, E as ElementMixin, j as ThemableMixin, P as PolymerElement, k as requiredField, l as helper, F as FieldMixin, m as FocusMixin, S as SlotObserver } from './field-mixin.js';
4
4
  import { A as ActiveMixin } from './active-mixin.js';
5
5
 
6
- /**
7
- * @license
8
- * Copyright (c) 2017 - 2023 Vaadin Ltd.
9
- * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
10
- */
11
- /**
12
- * @polymerMixin
13
- */
14
- const ThemePropertyMixin$1 = (superClass) =>
15
- class VaadinThemePropertyMixin extends superClass {
16
- static get properties() {
17
- return {
18
- /**
19
- * Helper property with theme attribute value facilitating propagation
20
- * in shadow DOM.
21
- *
22
- * Enables the component implementation to propagate the `theme`
23
- * attribute value to the sub-components in Shadow DOM by binding
24
- * the sub-component's "theme" attribute to the `theme` property of
25
- * the host.
26
- *
27
- * **NOTE:** Extending the mixin only provides the property for binding,
28
- * and does not make the propagation alone.
29
- *
30
- * See [Styling Components: Sub-components](https://vaadin.com/docs/latest/styling/styling-components/#sub-components).
31
- * page for more information.
32
- *
33
- * @protected
34
- */
35
- _theme: {
36
- type: String,
37
- readOnly: true,
38
- },
39
- };
40
- }
41
-
42
- static get observedAttributes() {
43
- return [...super.observedAttributes, 'theme'];
44
- }
45
-
46
- /** @protected */
47
- attributeChangedCallback(name, oldValue, newValue) {
48
- super.attributeChangedCallback(name, oldValue, newValue);
49
-
50
- if (name === 'theme') {
51
- this._set_theme(newValue);
52
- }
53
- }
54
- };
55
-
56
- /**
57
- * @license
58
- * Copyright (c) 2017 - 2023 Vaadin Ltd.
59
- * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
60
- */
61
-
62
- /**
63
- * @typedef {Object} Theme
64
- * @property {string} themeFor
65
- * @property {CSSResult[]} styles
66
- * @property {string | string[]} [include]
67
- * @property {string} [moduleId]
68
- *
69
- * @typedef {CSSResult[] | CSSResult} CSSResultGroup
70
- */
71
-
72
- /**
73
- * @type {Theme[]}
74
- */
75
- const themeRegistry$1 = [];
76
-
77
- /**
78
- * Check if the custom element type has themes applied.
79
- * @param {Function} elementClass
80
- * @returns {boolean}
81
- */
82
- function classHasThemes$1(elementClass) {
83
- return elementClass && Object.prototype.hasOwnProperty.call(elementClass, '__themes');
84
- }
85
-
86
- /**
87
- * Check if the custom element type has themes applied.
88
- * @param {string} tagName
89
- * @returns {boolean}
90
- */
91
- function hasThemes$1(tagName) {
92
- return classHasThemes$1(customElements.get(tagName));
93
- }
94
-
95
- /**
96
- * Flattens the styles into a single array of styles.
97
- * @param {CSSResultGroup} styles
98
- * @param {CSSResult[]} result
99
- * @returns {CSSResult[]}
100
- */
101
- function flattenStyles$1(styles = []) {
102
- return [styles].flat(Infinity).filter((style) => {
103
- if (style instanceof o) {
104
- return true;
105
- }
106
- console.warn('An item in styles is not of type CSSResult. Use `unsafeCSS` or `css`.');
107
- return false;
108
- });
109
- }
110
-
111
- /**
112
- * Registers CSS styles for a component type. Make sure to register the styles before
113
- * the first instance of a component of the type is attached to DOM.
114
- *
115
- * @param {string} themeFor The local/tag name of the component type to register the styles for
116
- * @param {CSSResultGroup} styles The CSS style rules to be registered for the component type
117
- * matching themeFor and included in the local scope of each component instance
118
- * @param {{moduleId?: string, include?: string | string[]}} options Additional options
119
- * @return {void}
120
- */
121
- function registerStyles$1(themeFor, styles, options = {}) {
122
- if (themeFor) {
123
- if (hasThemes$1(themeFor)) {
124
- console.warn(`The custom element definition for "${themeFor}"
125
- was finalized before a style module was registered.
126
- Make sure to add component specific style modules before
127
- importing the corresponding custom element.`);
128
- }
129
- }
130
-
131
- styles = flattenStyles$1(styles);
132
-
133
- if (window.Vaadin && window.Vaadin.styleModules) {
134
- window.Vaadin.styleModules.registerStyles(themeFor, styles, options);
135
- } else {
136
- themeRegistry$1.push({
137
- themeFor,
138
- styles,
139
- include: options.include,
140
- moduleId: options.moduleId,
141
- });
142
- }
143
- }
144
-
145
- /**
146
- * Returns all registered themes. By default the themeRegistry is returned as is.
147
- * In case the style-modules adapter is imported, the themes are obtained from there instead
148
- * @returns {Theme[]}
149
- */
150
- function getAllThemes$1() {
151
- if (window.Vaadin && window.Vaadin.styleModules) {
152
- return window.Vaadin.styleModules.getAllThemes();
153
- }
154
- return themeRegistry$1;
155
- }
156
-
157
- /**
158
- * Returns true if the themeFor string matches the tag name
159
- * @param {string} themeFor
160
- * @param {string} tagName
161
- * @returns {boolean}
162
- */
163
- function matchesThemeFor$1(themeFor, tagName) {
164
- return (themeFor || '').split(' ').some((themeForToken) => {
165
- return new RegExp(`^${themeForToken.split('*').join('.*')}$`, 'u').test(tagName);
166
- });
167
- }
168
-
169
- /**
170
- * Maps the moduleName to an include priority number which is used for
171
- * determining the order in which styles are applied.
172
- * @param {string} moduleName
173
- * @returns {number}
174
- */
175
- function getIncludePriority$1(moduleName = '') {
176
- let includePriority = 0;
177
- if (moduleName.startsWith('lumo-') || moduleName.startsWith('material-')) {
178
- includePriority = 1;
179
- } else if (moduleName.startsWith('vaadin-')) {
180
- includePriority = 2;
181
- }
182
- return includePriority;
183
- }
184
-
185
- /**
186
- * Gets an array of CSSResults matching the include property of the theme.
187
- * @param {Theme} theme
188
- * @returns {CSSResult[]}
189
- */
190
- function getIncludedStyles$1(theme) {
191
- const includedStyles = [];
192
- if (theme.include) {
193
- [].concat(theme.include).forEach((includeModuleId) => {
194
- const includedTheme = getAllThemes$1().find((s) => s.moduleId === includeModuleId);
195
- if (includedTheme) {
196
- includedStyles.push(...getIncludedStyles$1(includedTheme), ...includedTheme.styles);
197
- } else {
198
- console.warn(`Included moduleId ${includeModuleId} not found in style registry`);
199
- }
200
- }, theme.styles);
201
- }
202
- return includedStyles;
203
- }
204
-
205
- /**
206
- * Includes the styles to the template.
207
- * @param {CSSResult[]} styles
208
- * @param {HTMLTemplateElement} template
209
- */
210
- function addStylesToTemplate$1(styles, template) {
211
- const styleEl = document.createElement('style');
212
- styleEl.innerHTML = styles.map((style) => style.cssText).join('\n');
213
- template.content.appendChild(styleEl);
214
- }
215
-
216
- /**
217
- * Returns an array of themes that should be used for styling a component matching
218
- * the tag name. The array is sorted by the include order.
219
- * @param {string} tagName
220
- * @returns {Theme[]}
221
- */
222
- function getThemes$1(tagName) {
223
- const defaultModuleName = `${tagName}-default-theme`;
224
-
225
- const themes = getAllThemes$1()
226
- // Filter by matching themeFor properties
227
- .filter((theme) => theme.moduleId !== defaultModuleName && matchesThemeFor$1(theme.themeFor, tagName))
228
- .map((theme) => ({
229
- ...theme,
230
- // Prepend styles from included themes
231
- styles: [...getIncludedStyles$1(theme), ...theme.styles],
232
- // Map moduleId to includePriority
233
- includePriority: getIncludePriority$1(theme.moduleId),
234
- }))
235
- // Sort by includePriority
236
- .sort((themeA, themeB) => themeB.includePriority - themeA.includePriority);
237
-
238
- if (themes.length > 0) {
239
- return themes;
240
- }
241
- // No theme modules found, return the default module if it exists
242
- return getAllThemes$1().filter((theme) => theme.moduleId === defaultModuleName);
243
- }
244
-
245
- /**
246
- * @polymerMixin
247
- * @mixes ThemePropertyMixin
248
- */
249
- const ThemableMixin$1 = (superClass) =>
250
- class VaadinThemableMixin extends ThemePropertyMixin$1(superClass) {
251
- /**
252
- * Covers PolymerElement based component styling
253
- * @protected
254
- */
255
- static finalize() {
256
- super.finalize();
257
-
258
- // Make sure not to run the logic intended for PolymerElement when LitElement is used.
259
- if (this.elementStyles) {
260
- return;
261
- }
262
-
263
- const template = this.prototype._template;
264
- if (!template || classHasThemes$1(this)) {
265
- return;
266
- }
267
-
268
- addStylesToTemplate$1(this.getStylesForThis(), template);
269
- }
270
-
271
- /**
272
- * Covers LitElement based component styling
273
- *
274
- * @protected
275
- */
276
- static finalizeStyles(styles) {
277
- // The "styles" object originates from the "static get styles()" function of
278
- // a LitElement based component. The theme styles are added after it
279
- // so that they can override the component styles.
280
- const themeStyles = this.getStylesForThis();
281
- return styles ? [...super.finalizeStyles(styles), ...themeStyles] : themeStyles;
282
- }
283
-
284
- /**
285
- * Get styles for the component type
286
- *
287
- * @private
288
- */
289
- static getStylesForThis() {
290
- const parent = Object.getPrototypeOf(this.prototype);
291
- const inheritedThemes = (parent ? parent.constructor.__themes : []) || [];
292
- this.__themes = [...inheritedThemes, ...getThemes$1(this.is)];
293
- const themeStyles = this.__themes.flatMap((theme) => theme.styles);
294
- // Remove duplicates
295
- return themeStyles.filter((style, index) => index === themeStyles.lastIndexOf(style));
296
- }
297
- };
298
-
299
- registerStyles$1(
6
+ registerStyles(
300
7
  'vaadin-checkbox',
301
8
  i`
302
9
  :host {
@@ -459,2620 +166,385 @@ registerStyles$1(
459
166
  * Copyright (c) 2021 - 2023 Vaadin Ltd.
460
167
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
461
168
  */
462
- function defineCustomElement$2(CustomElement) {
463
- const defined = customElements.get(CustomElement.is);
464
- if (!defined) {
465
- customElements.define(CustomElement.is, CustomElement);
466
- } else {
467
- const definedVersion = defined.version;
468
- if (definedVersion && CustomElement.version && definedVersion === CustomElement.version) {
469
- // Just loading the same thing again
470
- console.warn(`The component ${CustomElement.is} has been loaded twice`);
471
- } else {
472
- console.error(
473
- `Tried to define ${CustomElement.is} version ${CustomElement.version} when version ${defined.version} is already in use. Something will probably break.`,
474
- );
475
- }
476
- }
477
- }
478
-
479
- /**
480
- * @license
481
- * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
482
- * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
483
- * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
484
- * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
485
- * Code distributed by Google as part of the polymer project is also
486
- * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
487
- */
488
169
 
489
170
  /**
490
- * Async interface wrapper around `requestIdleCallback`. Falls back to
491
- * `setTimeout` on browsers that do not support `requestIdleCallback`.
171
+ * A mixin to manage the checked state.
492
172
  *
493
- * @namespace
494
- * @summary Async interface wrapper around `requestIdleCallback`.
495
- */
496
- const idlePeriod$1 = {
497
- /**
498
- * Enqueues a function called at `requestIdleCallback` timing.
499
- *
500
- * @memberof idlePeriod
501
- * @param {function(!IdleDeadline):void} fn Callback to run
502
- * @return {number} Handle used for canceling task
503
- */
504
- run(fn) {
505
- return window.requestIdleCallback ? window.requestIdleCallback(fn) : window.setTimeout(fn, 16);
506
- },
507
- /**
508
- * Cancels a previously enqueued `idlePeriod` callback.
509
- *
510
- * @memberof idlePeriod
511
- * @param {number} handle Handle returned from `run` of callback to cancel
512
- * @return {void}
513
- */
514
- cancel(handle) {
515
- if (window.cancelIdleCallback) {
516
- window.cancelIdleCallback(handle);
517
- } else {
518
- window.clearTimeout(handle);
519
- }
520
- },
521
- };
522
-
523
- /**
524
- @license
525
- Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
526
- This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
527
- The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
528
- The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
529
- Code distributed by Google as part of the polymer project is also
530
- subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
531
- */
532
-
533
- const debouncerQueue$1 = new Set();
534
-
535
- /**
536
- * @summary Collapse multiple callbacks into one invocation after a timer.
173
+ * @polymerMixin
174
+ * @mixes DelegateStateMixin
175
+ * @mixes DisabledMixin
176
+ * @mixes InputMixin
537
177
  */
538
- class Debouncer$1 {
539
- /**
540
- * Creates a debouncer if no debouncer is passed as a parameter
541
- * or it cancels an active debouncer otherwise. The following
542
- * example shows how a debouncer can be called multiple times within a
543
- * microtask and "debounced" such that the provided callback function is
544
- * called once. Add this method to a custom element:
545
- *
546
- * ```js
547
- * import {microTask} from '@vaadin/component-base/src/async.js';
548
- * import {Debouncer} from '@vaadin/component-base/src/debounce.js';
549
- * // ...
550
- *
551
- * _debounceWork() {
552
- * this._debounceJob = Debouncer.debounce(this._debounceJob,
553
- * microTask, () => this._doWork());
554
- * }
555
- * ```
556
- *
557
- * If the `_debounceWork` method is called multiple times within the same
558
- * microtask, the `_doWork` function will be called only once at the next
559
- * microtask checkpoint.
560
- *
561
- * Note: In testing it is often convenient to avoid asynchrony. To accomplish
562
- * this with a debouncer, you can use `enqueueDebouncer` and
563
- * `flush`. For example, extend the above example by adding
564
- * `enqueueDebouncer(this._debounceJob)` at the end of the
565
- * `_debounceWork` method. Then in a test, call `flush` to ensure
566
- * the debouncer has completed.
567
- *
568
- * @param {Debouncer?} debouncer Debouncer object.
569
- * @param {!AsyncInterface} asyncModule Object with Async interface
570
- * @param {function()} callback Callback to run.
571
- * @return {!Debouncer} Returns a debouncer object.
572
- */
573
- static debounce(debouncer, asyncModule, callback) {
574
- if (debouncer instanceof Debouncer$1) {
575
- // Cancel the async callback, but leave in debouncerQueue if it was
576
- // enqueued, to maintain 1.x flush order
577
- debouncer._cancelAsync();
578
- } else {
579
- debouncer = new Debouncer$1();
580
- }
581
- debouncer.setConfig(asyncModule, callback);
582
- return debouncer;
583
- }
584
-
585
- constructor() {
586
- this._asyncModule = null;
587
- this._callback = null;
588
- this._timer = null;
589
- }
590
-
591
- /**
592
- * Sets the scheduler; that is, a module with the Async interface,
593
- * a callback and optional arguments to be passed to the run function
594
- * from the async module.
595
- *
596
- * @param {!AsyncInterface} asyncModule Object with Async interface.
597
- * @param {function()} callback Callback to run.
598
- * @return {void}
599
- */
600
- setConfig(asyncModule, callback) {
601
- this._asyncModule = asyncModule;
602
- this._callback = callback;
603
- this._timer = this._asyncModule.run(() => {
604
- this._timer = null;
605
- debouncerQueue$1.delete(this);
606
- this._callback();
607
- });
608
- }
178
+ const CheckedMixin = dedupingMixin(
179
+ (superclass) =>
180
+ class CheckedMixinClass extends DelegateStateMixin(DisabledMixin(InputMixin(superclass))) {
181
+ static get properties() {
182
+ return {
183
+ /**
184
+ * True if the element is checked.
185
+ * @type {boolean}
186
+ */
187
+ checked: {
188
+ type: Boolean,
189
+ value: false,
190
+ notify: true,
191
+ reflectToAttribute: true,
192
+ },
193
+ };
194
+ }
609
195
 
610
- /**
611
- * Cancels an active debouncer and returns a reference to itself.
612
- *
613
- * @return {void}
614
- */
615
- cancel() {
616
- if (this.isActive()) {
617
- this._cancelAsync();
618
- // Canceling a debouncer removes its spot from the flush queue,
619
- // so if a debouncer is manually canceled and re-debounced, it
620
- // will reset its flush order (this is a very minor difference from 1.x)
621
- // Re-debouncing via the `debounce` API retains the 1.x FIFO flush order
622
- debouncerQueue$1.delete(this);
623
- }
624
- }
196
+ static get delegateProps() {
197
+ return [...super.delegateProps, 'checked'];
198
+ }
625
199
 
626
- /**
627
- * Cancels a debouncer's async callback.
628
- *
629
- * @return {void}
630
- */
631
- _cancelAsync() {
632
- if (this.isActive()) {
633
- this._asyncModule.cancel(/** @type {number} */ (this._timer));
634
- this._timer = null;
635
- }
636
- }
200
+ /**
201
+ * @param {Event} event
202
+ * @protected
203
+ * @override
204
+ */
205
+ _onChange(event) {
206
+ const input = event.target;
637
207
 
638
- /**
639
- * Flushes an active debouncer and returns a reference to itself.
640
- *
641
- * @return {void}
642
- */
643
- flush() {
644
- if (this.isActive()) {
645
- this.cancel();
646
- this._callback();
647
- }
648
- }
208
+ this._toggleChecked(input.checked);
649
209
 
650
- /**
651
- * Returns true if the debouncer is active.
652
- *
653
- * @return {boolean} True if active.
654
- */
655
- isActive() {
656
- return this._timer != null;
657
- }
658
- }
210
+ // Clicking the checkbox or radio-button in Safari
211
+ // does not make it focused, so we do it manually.
212
+ if (!isElementFocused(input)) {
213
+ input.focus();
214
+ }
215
+ }
659
216
 
660
- /**
661
- * Adds a `Debouncer` to a list of globally flushable tasks.
662
- *
663
- * @param {!Debouncer} debouncer Debouncer to enqueue
664
- * @return {void}
665
- */
666
- function enqueueDebouncer$1(debouncer) {
667
- debouncerQueue$1.add(debouncer);
668
- }
217
+ /** @protected */
218
+ _toggleChecked(checked) {
219
+ this.checked = checked;
220
+ }
221
+ },
222
+ );
669
223
 
670
224
  /**
671
225
  * @license
672
- * Copyright (c) 2021 - 2023 Vaadin Ltd.
226
+ * Copyright (c) 2017 - 2023 Vaadin Ltd.
673
227
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
674
228
  */
675
229
 
676
230
  /**
677
- * Array of Vaadin custom element classes that have been subscribed to the dir changes.
678
- */
679
- const directionSubscribers$1 = [];
680
-
681
- function alignDirs$1(element, documentDir, elementDir = element.getAttribute('dir')) {
682
- if (documentDir) {
683
- element.setAttribute('dir', documentDir);
684
- } else if (elementDir != null) {
685
- element.removeAttribute('dir');
686
- }
687
- }
688
-
689
- function getDocumentDir$1() {
690
- return document.documentElement.getAttribute('dir');
691
- }
692
-
693
- function directionUpdater$1() {
694
- const documentDir = getDocumentDir$1();
695
- directionSubscribers$1.forEach((element) => {
696
- alignDirs$1(element, documentDir);
697
- });
698
- }
699
-
700
- const directionObserver$1 = new MutationObserver(directionUpdater$1);
701
- directionObserver$1.observe(document.documentElement, { attributes: true, attributeFilter: ['dir'] });
702
-
703
- /**
704
- * A mixin to handle `dir` attribute based on the one set on the `<html>` element.
231
+ * A mixin providing common checkbox functionality.
705
232
  *
706
233
  * @polymerMixin
234
+ * @mixes ActiveMixin
235
+ * @mixes CheckedMixin
236
+ * @mixes DelegateFocusMixin
237
+ * @mixes LabelMixin
707
238
  */
708
- const DirMixin$1 = (superClass) =>
709
- class VaadinDirMixin extends superClass {
239
+ const CheckboxMixin = (superclass) =>
240
+ class CheckboxMixinClass extends LabelMixin(CheckedMixin(DelegateFocusMixin(ActiveMixin(superclass)))) {
710
241
  static get properties() {
711
242
  return {
712
243
  /**
713
- * @protected
714
- */
715
- dir: {
716
- type: String,
717
- value: '',
718
- reflectToAttribute: true,
719
- converter: {
720
- fromAttribute: (attr) => {
721
- return !attr ? '' : attr;
722
- },
723
- toAttribute: (prop) => {
724
- return prop === '' ? null : prop;
725
- },
726
- },
244
+ * True if the checkbox is in the indeterminate state which means
245
+ * it is not possible to say whether it is checked or unchecked.
246
+ * The state is reset once the user switches the checkbox by hand.
247
+ *
248
+ * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox#Indeterminate_state_checkboxes
249
+ *
250
+ * @type {boolean}
251
+ */
252
+ indeterminate: {
253
+ type: Boolean,
254
+ notify: true,
255
+ value: false,
256
+ reflectToAttribute: true,
257
+ },
258
+
259
+ /**
260
+ * The name of the checkbox.
261
+ *
262
+ * @type {string}
263
+ */
264
+ name: {
265
+ type: String,
266
+ value: '',
727
267
  },
728
268
  };
729
269
  }
730
270
 
731
- /**
732
- * @return {boolean}
733
- * @protected
734
- */
735
- get __isRTL() {
736
- return this.getAttribute('dir') === 'rtl';
271
+ /** @override */
272
+ static get delegateProps() {
273
+ return [...super.delegateProps, 'indeterminate'];
737
274
  }
738
275
 
739
- /** @protected */
740
- connectedCallback() {
741
- super.connectedCallback();
742
-
743
- if (!this.hasAttribute('dir') || this.__restoreSubscription) {
744
- this.__subscribe();
745
- alignDirs$1(this, getDocumentDir$1(), null);
746
- }
276
+ /** @override */
277
+ static get delegateAttrs() {
278
+ return [...super.delegateAttrs, 'name'];
747
279
  }
748
280
 
749
- /** @protected */
750
- attributeChangedCallback(name, oldValue, newValue) {
751
- super.attributeChangedCallback(name, oldValue, newValue);
752
- if (name !== 'dir') {
753
- return;
754
- }
755
-
756
- const documentDir = getDocumentDir$1();
757
-
758
- // New value equals to the document direction and the element is not subscribed to the changes
759
- const newValueEqlDocDir = newValue === documentDir && directionSubscribers$1.indexOf(this) === -1;
760
- // Value was emptied and the element is not subscribed to the changes
761
- const newValueEmptied = !newValue && oldValue && directionSubscribers$1.indexOf(this) === -1;
762
- // New value is different and the old equals to document direction and the element is not subscribed to the changes
763
- const newDiffValue = newValue !== documentDir && oldValue === documentDir;
764
-
765
- if (newValueEqlDocDir || newValueEmptied) {
766
- this.__subscribe();
767
- alignDirs$1(this, documentDir, newValue);
768
- } else if (newDiffValue) {
769
- this.__unsubscribe();
770
- }
771
- }
281
+ constructor() {
282
+ super();
772
283
 
773
- /** @protected */
774
- disconnectedCallback() {
775
- super.disconnectedCallback();
776
- this.__restoreSubscription = directionSubscribers$1.includes(this);
777
- this.__unsubscribe();
778
- }
284
+ this._setType('checkbox');
779
285
 
780
- /** @protected */
781
- _valueToNodeAttribute(node, value, attribute) {
782
- // Override default Polymer attribute reflection to match native behavior of HTMLElement.dir property
783
- // If the property contains an empty string then it should not create an empty attribute
784
- if (attribute === 'dir' && value === '' && !node.hasAttribute('dir')) {
785
- return;
786
- }
787
- super._valueToNodeAttribute(node, value, attribute);
286
+ // Set the string "on" as the default value for the checkbox following the HTML specification:
287
+ // https://html.spec.whatwg.org/multipage/input.html#dom-input-value-default-on
288
+ this.value = 'on';
788
289
  }
789
290
 
790
291
  /** @protected */
791
- _attributeToProperty(attribute, value, type) {
792
- // Override default Polymer attribute reflection to match native behavior of HTMLElement.dir property
793
- // If the attribute is removed, then the dir property should contain an empty string instead of null
794
- if (attribute === 'dir' && !value) {
795
- this.dir = '';
796
- } else {
797
- super._attributeToProperty(attribute, value, type);
798
- }
799
- }
292
+ ready() {
293
+ super.ready();
800
294
 
801
- /** @private */
802
- __subscribe() {
803
- if (!directionSubscribers$1.includes(this)) {
804
- directionSubscribers$1.push(this);
805
- }
295
+ this.addController(
296
+ new InputController(this, (input) => {
297
+ this._setInputElement(input);
298
+ this._setFocusElement(input);
299
+ this.stateTarget = input;
300
+ this.ariaTarget = input;
301
+ }),
302
+ );
303
+ this.addController(new LabelledInputController(this.inputElement, this._labelController));
806
304
  }
807
305
 
808
- /** @private */
809
- __unsubscribe() {
810
- if (directionSubscribers$1.includes(this)) {
811
- directionSubscribers$1.splice(directionSubscribers$1.indexOf(this), 1);
306
+ /**
307
+ * Override method inherited from `ActiveMixin` to prevent setting
308
+ * `active` attribute when clicking a link placed inside the label.
309
+ *
310
+ * @param {Event} event
311
+ * @return {boolean}
312
+ * @protected
313
+ * @override
314
+ */
315
+ _shouldSetActive(event) {
316
+ if (event.target.localName === 'a') {
317
+ return false;
812
318
  }
813
- }
814
- };
815
-
816
- /**
817
- * @license
818
- * Copyright (c) 2021 - 2023 Vaadin Ltd.
819
- * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
820
- */
821
-
822
- if (!window.Vaadin) {
823
- window.Vaadin = {};
824
- }
825
-
826
- /**
827
- * Array of Vaadin custom element classes that have been finalized.
828
- */
829
- if (!window.Vaadin.registrations) {
830
- window.Vaadin.registrations = [];
831
- }
832
-
833
- if (!window.Vaadin.developmentModeCallback) {
834
- window.Vaadin.developmentModeCallback = {};
835
- }
836
-
837
- window.Vaadin.developmentModeCallback['vaadin-usage-statistics'] = function () {
838
- usageStatistics();
839
- };
840
-
841
- let statsJob$1;
842
-
843
- const registered$1 = new Set();
844
319
 
845
- /**
846
- * @polymerMixin
847
- * @mixes DirMixin
848
- */
849
- const ElementMixin$1 = (superClass) =>
850
- class VaadinElementMixin extends DirMixin$1(superClass) {
851
- static get version() {
852
- return '24.2.3';
320
+ return super._shouldSetActive(event);
853
321
  }
854
322
 
855
- /** @protected */
856
- static finalize() {
857
- super.finalize();
858
-
859
- const { is } = this;
860
-
861
- // Registers a class prototype for telemetry purposes.
862
- if (is && !registered$1.has(is)) {
863
- window.Vaadin.registrations.push(this);
864
- registered$1.add(is);
865
-
866
- if (window.Vaadin.developmentModeCallback) {
867
- statsJob$1 = Debouncer$1.debounce(statsJob$1, idlePeriod$1, () => {
868
- window.Vaadin.developmentModeCallback['vaadin-usage-statistics']();
869
- });
870
- enqueueDebouncer$1(statsJob$1);
871
- }
323
+ /**
324
+ * Override method inherited from `CheckedMixin` to reset
325
+ * `indeterminate` state checkbox is toggled by the user.
326
+ *
327
+ * @param {boolean} checked
328
+ * @protected
329
+ * @override
330
+ */
331
+ _toggleChecked(checked) {
332
+ if (this.indeterminate) {
333
+ this.indeterminate = false;
872
334
  }
873
- }
874
-
875
- constructor() {
876
- super();
877
335
 
878
- if (document.doctype === null) {
879
- console.warn(
880
- 'Vaadin components require the "standards mode" declaration. Please add <!DOCTYPE html> to the HTML document.',
881
- );
882
- }
336
+ super._toggleChecked(checked);
883
337
  }
884
338
  };
885
339
 
886
340
  /**
887
341
  * @license
888
- * Copyright (c) 2021 - 2023 Vaadin Ltd.
889
- * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
890
- */
891
-
892
- /**
893
- * Returns true if the given node is an empty text node, false otherwise.
894
- *
895
- * @param {Node} node
896
- * @return {boolean}
897
- */
898
- function isEmptyTextNode$1(node) {
899
- return node.nodeType === Node.TEXT_NODE && node.textContent.trim() === '';
900
- }
901
-
902
- /**
903
- * @license
904
- * Copyright (c) 2023 Vaadin Ltd.
342
+ * Copyright (c) 2017 - 2023 Vaadin Ltd.
905
343
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
906
344
  */
907
345
 
908
- /**
909
- * A helper for observing slot changes.
910
- */
911
- class SlotObserver$1 {
912
- constructor(slot, callback) {
913
- /** @type HTMLSlotElement */
914
- this.slot = slot;
915
-
916
- /** @type Function */
917
- this.callback = callback;
918
-
919
- /** @type {Node[]} */
920
- this._storedNodes = [];
921
-
922
- this._connected = false;
923
- this._scheduled = false;
924
-
925
- this._boundSchedule = () => {
926
- this._schedule();
927
- };
928
-
929
- this.connect();
930
- this._schedule();
346
+ const checkboxStyles = i`
347
+ :host {
348
+ display: inline-block;
931
349
  }
932
350
 
933
- /**
934
- * Activates an observer. This method is automatically called when
935
- * a `SlotObserver` is created. It should only be called to re-activate
936
- * an observer that has been deactivated via the `disconnect` method.
937
- */
938
- connect() {
939
- this.slot.addEventListener('slotchange', this._boundSchedule);
940
- this._connected = true;
351
+ :host([hidden]) {
352
+ display: none !important;
941
353
  }
942
354
 
943
- /**
944
- * Deactivates the observer. After calling this method the observer callback
945
- * will not be called when changes to slotted nodes occur. The `connect` method
946
- * may be subsequently called to reactivate the observer.
947
- */
948
- disconnect() {
949
- this.slot.removeEventListener('slotchange', this._boundSchedule);
950
- this._connected = false;
355
+ :host([disabled]) {
356
+ -webkit-tap-highlight-color: transparent;
951
357
  }
952
358
 
953
- /** @private */
954
- _schedule() {
955
- if (!this._scheduled) {
956
- this._scheduled = true;
957
-
958
- queueMicrotask(() => {
959
- this.flush();
960
- });
961
- }
359
+ .vaadin-checkbox-container {
360
+ display: grid;
361
+ grid-template-columns: auto 1fr;
362
+ align-items: baseline;
962
363
  }
963
364
 
964
- /**
965
- * Run the observer callback synchronously.
966
- */
967
- flush() {
968
- if (!this._connected) {
969
- return;
970
- }
365
+ [part='checkbox'],
366
+ ::slotted(input),
367
+ ::slotted(label) {
368
+ grid-row: 1;
369
+ }
971
370
 
972
- this._scheduled = false;
371
+ [part='checkbox'],
372
+ ::slotted(input) {
373
+ grid-column: 1;
374
+ }
973
375
 
974
- this._processNodes();
376
+ [part='checkbox'] {
377
+ width: var(--vaadin-checkbox-size, 1em);
378
+ height: var(--vaadin-checkbox-size, 1em);
379
+ --_input-border-width: var(--vaadin-input-field-border-width, 0);
380
+ --_input-border-color: var(--vaadin-input-field-border-color, transparent);
381
+ box-shadow: inset 0 0 0 var(--_input-border-width, 0) var(--_input-border-color);
975
382
  }
976
383
 
977
- /** @private */
978
- _processNodes() {
979
- const currentNodes = this.slot.assignedNodes({ flatten: true });
384
+ [part='checkbox']::before {
385
+ display: block;
386
+ content: '\\202F';
387
+ line-height: var(--vaadin-checkbox-size, 1em);
388
+ contain: paint;
389
+ }
980
390
 
981
- let addedNodes = [];
982
- const removedNodes = [];
983
- const movedNodes = [];
391
+ /* visually hidden */
392
+ ::slotted(input) {
393
+ opacity: 0;
394
+ cursor: inherit;
395
+ margin: 0;
396
+ align-self: stretch;
397
+ -webkit-appearance: none;
398
+ width: initial;
399
+ height: initial;
400
+ }
984
401
 
985
- if (currentNodes.length) {
986
- addedNodes = currentNodes.filter((node) => !this._storedNodes.includes(node));
402
+ @media (forced-colors: active) {
403
+ [part='checkbox'] {
404
+ outline: 1px solid;
405
+ outline-offset: -1px;
987
406
  }
988
407
 
989
- if (this._storedNodes.length) {
990
- this._storedNodes.forEach((node, index) => {
991
- const idx = currentNodes.indexOf(node);
992
- if (idx === -1) {
993
- removedNodes.push(node);
994
- } else if (idx !== index) {
995
- movedNodes.push(node);
996
- }
997
- });
408
+ :host([disabled]) [part='checkbox'],
409
+ :host([disabled]) [part='checkbox']::after {
410
+ outline-color: GrayText;
998
411
  }
999
412
 
1000
- if (addedNodes.length || removedNodes.length || movedNodes.length) {
1001
- this.callback({ addedNodes, movedNodes, removedNodes });
413
+ :host(:is([checked], [indeterminate])) [part='checkbox']::after {
414
+ outline: 1px solid;
415
+ outline-offset: -1px;
416
+ border-radius: inherit;
1002
417
  }
1003
418
 
1004
- this._storedNodes = currentNodes;
419
+ :host([focused]) [part='checkbox'],
420
+ :host([focused]) [part='checkbox']::after {
421
+ outline-width: 2px;
422
+ }
1005
423
  }
1006
- }
424
+ `;
1007
425
 
1008
426
  /**
1009
427
  * @license
1010
- * Copyright (c) 2021 - 2023 Vaadin Ltd.
428
+ * Copyright (c) 2017 - 2023 Vaadin Ltd.
1011
429
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
1012
430
  */
1013
431
 
1014
- let uniqueId$1 = 0;
432
+ registerStyles('vaadin-checkbox', checkboxStyles, { moduleId: 'vaadin-checkbox-styles' });
1015
433
 
1016
434
  /**
1017
- * Returns a unique integer id.
435
+ * `<vaadin-checkbox>` is an input field representing a binary choice.
436
+ *
437
+ * ```html
438
+ * <vaadin-checkbox label="I accept the terms and conditions"></vaadin-checkbox>
439
+ * ```
440
+ *
441
+ * ### Styling
442
+ *
443
+ * The following shadow DOM parts are available for styling:
444
+ *
445
+ * Part name | Description
446
+ * ------------|-------------
447
+ * `checkbox` | The element representing a stylable custom checkbox.
448
+ *
449
+ * The following state attributes are available for styling:
450
+ *
451
+ * Attribute | Description
452
+ * ----------------|-------------
453
+ * `active` | Set when the checkbox is activated with mouse, touch or the keyboard.
454
+ * `checked` | Set when the checkbox is checked.
455
+ * `disabled` | Set when the checkbox is disabled.
456
+ * `focus-ring` | Set when the checkbox is focused using the keyboard.
457
+ * `focused` | Set when the checkbox is focused.
458
+ * `indeterminate` | Set when the checkbox is in the indeterminate state.
459
+ * `has-label` | Set when the checkbox has a label.
460
+ *
461
+ * See [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.
462
+ *
463
+ * @fires {CustomEvent} checked-changed - Fired when the `checked` property changes.
464
+ * @fires {CustomEvent} indeterminate-changed - Fired when the `indeterminate` property changes.
1018
465
  *
1019
- * @return {number}
466
+ * @customElement
467
+ * @extends HTMLElement
468
+ * @mixes CheckboxMixin
469
+ * @mixes ThemableMixin
470
+ * @mixes ElementMixin
1020
471
  */
1021
- function generateUniqueId$1() {
1022
- // eslint-disable-next-line no-plusplus
1023
- return uniqueId$1++;
1024
- }
1025
-
1026
- /**
1027
- * @license
1028
- * Copyright (c) 2021 - 2023 Vaadin Ltd.
1029
- * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
1030
- */
1031
-
1032
- /**
1033
- * A controller for providing content to slot element and observing changes.
1034
- */
1035
- class SlotController$1 extends EventTarget {
1036
- /**
1037
- * Ensure that every instance has unique ID.
1038
- *
1039
- * @param {HTMLElement} host
1040
- * @param {string} slotName
1041
- * @return {string}
1042
- * @protected
1043
- */
1044
- static generateId(host, slotName) {
1045
- const prefix = slotName || 'default';
1046
- return `${prefix}-${host.localName}-${generateUniqueId$1()}`;
1047
- }
1048
-
1049
- constructor(host, slotName, tagName, config = {}) {
1050
- super();
1051
-
1052
- const { initializer, multiple, observe, useUniqueId } = config;
1053
-
1054
- this.host = host;
1055
- this.slotName = slotName;
1056
- this.tagName = tagName;
1057
- this.observe = typeof observe === 'boolean' ? observe : true;
1058
- this.multiple = typeof multiple === 'boolean' ? multiple : false;
1059
- this.slotInitializer = initializer;
1060
-
1061
- if (multiple) {
1062
- this.nodes = [];
1063
- }
1064
-
1065
- // Only generate the default ID if requested by the controller.
1066
- if (useUniqueId) {
1067
- this.defaultId = this.constructor.generateId(host, slotName);
1068
- }
1069
- }
1070
-
1071
- hostConnected() {
1072
- if (!this.initialized) {
1073
- if (this.multiple) {
1074
- this.initMultiple();
1075
- } else {
1076
- this.initSingle();
1077
- }
1078
-
1079
- if (this.observe) {
1080
- this.observeSlot();
1081
- }
1082
-
1083
- this.initialized = true;
1084
- }
1085
- }
1086
-
1087
- /** @protected */
1088
- initSingle() {
1089
- let node = this.getSlotChild();
1090
-
1091
- if (!node) {
1092
- node = this.attachDefaultNode();
1093
- this.initNode(node);
1094
- } else {
1095
- this.node = node;
1096
- this.initAddedNode(node);
1097
- }
1098
- }
1099
-
1100
- /** @protected */
1101
- initMultiple() {
1102
- const children = this.getSlotChildren();
1103
-
1104
- if (children.length === 0) {
1105
- const defaultNode = this.attachDefaultNode();
1106
- if (defaultNode) {
1107
- this.nodes = [defaultNode];
1108
- this.initNode(defaultNode);
1109
- }
1110
- } else {
1111
- this.nodes = children;
1112
- children.forEach((node) => {
1113
- this.initAddedNode(node);
1114
- });
1115
- }
1116
- }
1117
-
1118
- /**
1119
- * Create and attach default node using the provided tag name, if any.
1120
- * @return {Node | undefined}
1121
- * @protected
1122
- */
1123
- attachDefaultNode() {
1124
- const { host, slotName, tagName } = this;
1125
-
1126
- // Check if the node was created previously and if so, reuse it.
1127
- let node = this.defaultNode;
1128
-
1129
- // Tag name is optional, sometimes we don't init default content.
1130
- if (!node && tagName) {
1131
- node = document.createElement(tagName);
1132
- if (node instanceof Element) {
1133
- if (slotName !== '') {
1134
- node.setAttribute('slot', slotName);
1135
- }
1136
- this.node = node;
1137
- this.defaultNode = node;
1138
- }
1139
- }
1140
-
1141
- if (node) {
1142
- host.appendChild(node);
1143
- }
1144
-
1145
- return node;
1146
- }
1147
-
1148
- /**
1149
- * Return the list of nodes matching the slot managed by the controller.
1150
- * @return {Node}
1151
- */
1152
- getSlotChildren() {
1153
- const { slotName } = this;
1154
- return Array.from(this.host.childNodes).filter((node) => {
1155
- // Either an element (any slot) or a text node (only un-named slot).
1156
- return (
1157
- (node.nodeType === Node.ELEMENT_NODE && node.slot === slotName) ||
1158
- (node.nodeType === Node.TEXT_NODE && node.textContent.trim() && slotName === '')
1159
- );
1160
- });
1161
- }
1162
-
1163
- /**
1164
- * Return a reference to the node managed by the controller.
1165
- * @return {Node}
1166
- */
1167
- getSlotChild() {
1168
- return this.getSlotChildren()[0];
1169
- }
1170
-
1171
- /**
1172
- * Run `slotInitializer` for the node managed by the controller.
1173
- *
1174
- * @param {Node} node
1175
- * @protected
1176
- */
1177
- initNode(node) {
1178
- const { slotInitializer } = this;
1179
- // Don't try to bind `this` to initializer (normally it's arrow function).
1180
- // Instead, pass the host as a first argument to access component's state.
1181
- if (slotInitializer) {
1182
- slotInitializer(node, this.host);
1183
- }
1184
- }
1185
-
1186
- /**
1187
- * Override to initialize the newly added custom node.
1188
- *
1189
- * @param {Node} _node
1190
- * @protected
1191
- */
1192
- initCustomNode(_node) {}
1193
-
1194
- /**
1195
- * Override to teardown slotted node when it's removed.
1196
- *
1197
- * @param {Node} _node
1198
- * @protected
1199
- */
1200
- teardownNode(_node) {}
1201
-
1202
- /**
1203
- * Run both `initCustomNode` and `initNode` for a custom slotted node.
1204
- *
1205
- * @param {Node} node
1206
- * @protected
1207
- */
1208
- initAddedNode(node) {
1209
- if (node !== this.defaultNode) {
1210
- this.initCustomNode(node);
1211
- this.initNode(node);
1212
- }
1213
- }
1214
-
1215
- /**
1216
- * Setup the observer to manage slot content changes.
1217
- * @protected
1218
- */
1219
- observeSlot() {
1220
- const { slotName } = this;
1221
- const selector = slotName === '' ? 'slot:not([name])' : `slot[name=${slotName}]`;
1222
- const slot = this.host.shadowRoot.querySelector(selector);
1223
-
1224
- this.__slotObserver = new SlotObserver$1(slot, ({ addedNodes, removedNodes }) => {
1225
- const current = this.multiple ? this.nodes : [this.node];
1226
-
1227
- // Calling `slot.assignedNodes()` includes whitespace text nodes in case of default slot:
1228
- // unlike comment nodes, they are not filtered out. So we need to manually ignore them.
1229
- const newNodes = addedNodes.filter((node) => !isEmptyTextNode$1(node) && !current.includes(node));
1230
-
1231
- if (removedNodes.length) {
1232
- this.nodes = current.filter((node) => !removedNodes.includes(node));
1233
-
1234
- removedNodes.forEach((node) => {
1235
- this.teardownNode(node);
1236
- });
1237
- }
1238
-
1239
- if (newNodes && newNodes.length > 0) {
1240
- if (this.multiple) {
1241
- // Remove default node if exists
1242
- if (this.defaultNode) {
1243
- this.defaultNode.remove();
1244
- }
1245
- this.nodes = [...current, ...newNodes].filter((node) => node !== this.defaultNode);
1246
- newNodes.forEach((node) => {
1247
- this.initAddedNode(node);
1248
- });
1249
- } else {
1250
- // Remove previous node if exists
1251
- if (this.node) {
1252
- this.node.remove();
1253
- }
1254
- this.node = newNodes[0];
1255
- this.initAddedNode(this.node);
1256
- }
1257
- }
1258
- });
1259
- }
1260
- }
1261
-
1262
- /**
1263
- * @license
1264
- * Copyright (c) 2022 - 2023 Vaadin Ltd.
1265
- * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
1266
- */
1267
-
1268
- /**
1269
- * A controller that manages the slotted tooltip element.
1270
- */
1271
- class TooltipController$1 extends SlotController$1 {
1272
- constructor(host) {
1273
- // Do not provide slot factory to create tooltip lazily.
1274
- super(host, 'tooltip');
1275
-
1276
- this.setTarget(host);
1277
- }
1278
-
1279
- /**
1280
- * Override to initialize the newly added custom tooltip.
1281
- *
1282
- * @param {Node} tooltipNode
1283
- * @protected
1284
- * @override
1285
- */
1286
- initCustomNode(tooltipNode) {
1287
- tooltipNode.target = this.target;
1288
-
1289
- if (this.ariaTarget !== undefined) {
1290
- tooltipNode.ariaTarget = this.ariaTarget;
1291
- }
1292
-
1293
- if (this.context !== undefined) {
1294
- tooltipNode.context = this.context;
1295
- }
1296
-
1297
- if (this.manual !== undefined) {
1298
- tooltipNode.manual = this.manual;
1299
- }
1300
-
1301
- if (this.opened !== undefined) {
1302
- tooltipNode.opened = this.opened;
1303
- }
1304
-
1305
- if (this.position !== undefined) {
1306
- tooltipNode._position = this.position;
1307
- }
1308
-
1309
- if (this.shouldShow !== undefined) {
1310
- tooltipNode.shouldShow = this.shouldShow;
1311
- }
1312
-
1313
- this.__notifyChange();
1314
- }
1315
-
1316
- /**
1317
- * Override to notify the host when the tooltip is removed.
1318
- *
1319
- * @param {Node} tooltipNode
1320
- * @protected
1321
- * @override
1322
- */
1323
- teardownNode() {
1324
- this.__notifyChange();
1325
- }
1326
-
1327
- /**
1328
- * Set an HTML element for linking with the tooltip overlay
1329
- * via `aria-describedby` attribute used by screen readers.
1330
- * @param {HTMLElement} ariaTarget
1331
- */
1332
- setAriaTarget(ariaTarget) {
1333
- this.ariaTarget = ariaTarget;
1334
-
1335
- const tooltipNode = this.node;
1336
- if (tooltipNode) {
1337
- tooltipNode.ariaTarget = ariaTarget;
1338
- }
1339
- }
1340
-
1341
- /**
1342
- * Set a context object to be used by generator.
1343
- * @param {object} context
1344
- */
1345
- setContext(context) {
1346
- this.context = context;
1347
-
1348
- const tooltipNode = this.node;
1349
- if (tooltipNode) {
1350
- tooltipNode.context = context;
1351
- }
1352
- }
1353
-
1354
- /**
1355
- * Toggle manual state on the slotted tooltip.
1356
- * @param {boolean} manual
1357
- */
1358
- setManual(manual) {
1359
- this.manual = manual;
1360
-
1361
- const tooltipNode = this.node;
1362
- if (tooltipNode) {
1363
- tooltipNode.manual = manual;
1364
- }
1365
- }
1366
-
1367
- /**
1368
- * Toggle opened state on the slotted tooltip.
1369
- * @param {boolean} opened
1370
- */
1371
- setOpened(opened) {
1372
- this.opened = opened;
1373
-
1374
- const tooltipNode = this.node;
1375
- if (tooltipNode) {
1376
- tooltipNode.opened = opened;
1377
- }
1378
- }
1379
-
1380
- /**
1381
- * Set default position for the slotted tooltip.
1382
- * This can be overridden by setting the position
1383
- * using corresponding property or attribute.
1384
- * @param {string} position
1385
- */
1386
- setPosition(position) {
1387
- this.position = position;
1388
-
1389
- const tooltipNode = this.node;
1390
- if (tooltipNode) {
1391
- tooltipNode._position = position;
1392
- }
1393
- }
1394
-
1395
- /**
1396
- * Set function used to detect whether to show
1397
- * the tooltip based on a condition.
1398
- * @param {Function} shouldShow
1399
- */
1400
- setShouldShow(shouldShow) {
1401
- this.shouldShow = shouldShow;
1402
-
1403
- const tooltipNode = this.node;
1404
- if (tooltipNode) {
1405
- tooltipNode.shouldShow = shouldShow;
1406
- }
1407
- }
1408
-
1409
- /**
1410
- * Set an HTML element to attach the tooltip to.
1411
- * @param {HTMLElement} target
1412
- */
1413
- setTarget(target) {
1414
- this.target = target;
1415
-
1416
- const tooltipNode = this.node;
1417
- if (tooltipNode) {
1418
- tooltipNode.target = target;
1419
- }
1420
- }
1421
-
1422
- /** @private */
1423
- __notifyChange() {
1424
- this.dispatchEvent(new CustomEvent('tooltip-changed', { detail: { node: this.node } }));
1425
- }
1426
- }
1427
-
1428
- /**
1429
- * @license
1430
- * Copyright (c) 2021 - 2023 Vaadin Ltd.
1431
- * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
1432
- */
1433
-
1434
- /**
1435
- * A mixin to manage the checked state.
1436
- *
1437
- * @polymerMixin
1438
- * @mixes DelegateStateMixin
1439
- * @mixes DisabledMixin
1440
- * @mixes InputMixin
1441
- */
1442
- const CheckedMixin = dedupingMixin(
1443
- (superclass) =>
1444
- class CheckedMixinClass extends DelegateStateMixin(DisabledMixin(InputMixin(superclass))) {
1445
- static get properties() {
1446
- return {
1447
- /**
1448
- * True if the element is checked.
1449
- * @type {boolean}
1450
- */
1451
- checked: {
1452
- type: Boolean,
1453
- value: false,
1454
- notify: true,
1455
- reflectToAttribute: true,
1456
- },
1457
- };
1458
- }
1459
-
1460
- static get delegateProps() {
1461
- return [...super.delegateProps, 'checked'];
1462
- }
1463
-
1464
- /**
1465
- * @param {Event} event
1466
- * @protected
1467
- * @override
1468
- */
1469
- _onChange(event) {
1470
- const input = event.target;
1471
-
1472
- this._toggleChecked(input.checked);
1473
-
1474
- // Clicking the checkbox or radio-button in Safari
1475
- // does not make it focused, so we do it manually.
1476
- if (!isElementFocused(input)) {
1477
- input.focus();
1478
- }
1479
- }
1480
-
1481
- /** @protected */
1482
- _toggleChecked(checked) {
1483
- this.checked = checked;
1484
- }
1485
- },
1486
- );
1487
-
1488
- /**
1489
- * @license
1490
- * Copyright (c) 2017 - 2023 Vaadin Ltd.
1491
- * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
1492
- */
1493
-
1494
- /**
1495
- * A mixin providing common checkbox functionality.
1496
- *
1497
- * @polymerMixin
1498
- * @mixes ActiveMixin
1499
- * @mixes CheckedMixin
1500
- * @mixes DelegateFocusMixin
1501
- * @mixes LabelMixin
1502
- */
1503
- const CheckboxMixin = (superclass) =>
1504
- class CheckboxMixinClass extends LabelMixin(CheckedMixin(DelegateFocusMixin(ActiveMixin(superclass)))) {
1505
- static get properties() {
1506
- return {
1507
- /**
1508
- * True if the checkbox is in the indeterminate state which means
1509
- * it is not possible to say whether it is checked or unchecked.
1510
- * The state is reset once the user switches the checkbox by hand.
1511
- *
1512
- * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox#Indeterminate_state_checkboxes
1513
- *
1514
- * @type {boolean}
1515
- */
1516
- indeterminate: {
1517
- type: Boolean,
1518
- notify: true,
1519
- value: false,
1520
- reflectToAttribute: true,
1521
- },
1522
-
1523
- /**
1524
- * The name of the checkbox.
1525
- *
1526
- * @type {string}
1527
- */
1528
- name: {
1529
- type: String,
1530
- value: '',
1531
- },
1532
- };
1533
- }
1534
-
1535
- /** @override */
1536
- static get delegateProps() {
1537
- return [...super.delegateProps, 'indeterminate'];
1538
- }
1539
-
1540
- /** @override */
1541
- static get delegateAttrs() {
1542
- return [...super.delegateAttrs, 'name'];
1543
- }
1544
-
1545
- constructor() {
1546
- super();
1547
-
1548
- this._setType('checkbox');
1549
-
1550
- // Set the string "on" as the default value for the checkbox following the HTML specification:
1551
- // https://html.spec.whatwg.org/multipage/input.html#dom-input-value-default-on
1552
- this.value = 'on';
1553
- }
1554
-
1555
- /** @protected */
1556
- ready() {
1557
- super.ready();
1558
-
1559
- this.addController(
1560
- new InputController(this, (input) => {
1561
- this._setInputElement(input);
1562
- this._setFocusElement(input);
1563
- this.stateTarget = input;
1564
- this.ariaTarget = input;
1565
- }),
1566
- );
1567
- this.addController(new LabelledInputController(this.inputElement, this._labelController));
1568
- }
1569
-
1570
- /**
1571
- * Override method inherited from `ActiveMixin` to prevent setting
1572
- * `active` attribute when clicking a link placed inside the label.
1573
- *
1574
- * @param {Event} event
1575
- * @return {boolean}
1576
- * @protected
1577
- * @override
1578
- */
1579
- _shouldSetActive(event) {
1580
- if (event.target.localName === 'a') {
1581
- return false;
1582
- }
1583
-
1584
- return super._shouldSetActive(event);
1585
- }
1586
-
1587
- /**
1588
- * Override method inherited from `CheckedMixin` to reset
1589
- * `indeterminate` state checkbox is toggled by the user.
1590
- *
1591
- * @param {boolean} checked
1592
- * @protected
1593
- * @override
1594
- */
1595
- _toggleChecked(checked) {
1596
- if (this.indeterminate) {
1597
- this.indeterminate = false;
1598
- }
1599
-
1600
- super._toggleChecked(checked);
1601
- }
1602
- };
1603
-
1604
- /**
1605
- * @license
1606
- * Copyright (c) 2017 - 2023 Vaadin Ltd.
1607
- * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
1608
- */
1609
-
1610
- const checkboxStyles = i`
1611
- :host {
1612
- display: inline-block;
1613
- }
1614
-
1615
- :host([hidden]) {
1616
- display: none !important;
1617
- }
1618
-
1619
- :host([disabled]) {
1620
- -webkit-tap-highlight-color: transparent;
1621
- }
1622
-
1623
- .vaadin-checkbox-container {
1624
- display: grid;
1625
- grid-template-columns: auto 1fr;
1626
- align-items: baseline;
1627
- }
1628
-
1629
- [part='checkbox'],
1630
- ::slotted(input),
1631
- ::slotted(label) {
1632
- grid-row: 1;
1633
- }
1634
-
1635
- [part='checkbox'],
1636
- ::slotted(input) {
1637
- grid-column: 1;
1638
- }
1639
-
1640
- [part='checkbox'] {
1641
- width: var(--vaadin-checkbox-size, 1em);
1642
- height: var(--vaadin-checkbox-size, 1em);
1643
- --_input-border-width: var(--vaadin-input-field-border-width, 0);
1644
- --_input-border-color: var(--vaadin-input-field-border-color, transparent);
1645
- box-shadow: inset 0 0 0 var(--_input-border-width, 0) var(--_input-border-color);
1646
- }
1647
-
1648
- [part='checkbox']::before {
1649
- display: block;
1650
- content: '\\202F';
1651
- line-height: var(--vaadin-checkbox-size, 1em);
1652
- contain: paint;
1653
- }
1654
-
1655
- /* visually hidden */
1656
- ::slotted(input) {
1657
- opacity: 0;
1658
- cursor: inherit;
1659
- margin: 0;
1660
- align-self: stretch;
1661
- -webkit-appearance: none;
1662
- width: initial;
1663
- height: initial;
1664
- }
1665
-
1666
- @media (forced-colors: active) {
1667
- [part='checkbox'] {
1668
- outline: 1px solid;
1669
- outline-offset: -1px;
1670
- }
1671
-
1672
- :host([disabled]) [part='checkbox'],
1673
- :host([disabled]) [part='checkbox']::after {
1674
- outline-color: GrayText;
1675
- }
1676
-
1677
- :host(:is([checked], [indeterminate])) [part='checkbox']::after {
1678
- outline: 1px solid;
1679
- outline-offset: -1px;
1680
- border-radius: inherit;
1681
- }
1682
-
1683
- :host([focused]) [part='checkbox'],
1684
- :host([focused]) [part='checkbox']::after {
1685
- outline-width: 2px;
1686
- }
1687
- }
1688
- `;
1689
-
1690
- /**
1691
- * @license
1692
- * Copyright (c) 2017 - 2023 Vaadin Ltd.
1693
- * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
1694
- */
1695
-
1696
- registerStyles$1('vaadin-checkbox', checkboxStyles, { moduleId: 'vaadin-checkbox-styles' });
1697
-
1698
- /**
1699
- * `<vaadin-checkbox>` is an input field representing a binary choice.
1700
- *
1701
- * ```html
1702
- * <vaadin-checkbox label="I accept the terms and conditions"></vaadin-checkbox>
1703
- * ```
1704
- *
1705
- * ### Styling
1706
- *
1707
- * The following shadow DOM parts are available for styling:
1708
- *
1709
- * Part name | Description
1710
- * ------------|-------------
1711
- * `checkbox` | The element representing a stylable custom checkbox.
1712
- *
1713
- * The following state attributes are available for styling:
1714
- *
1715
- * Attribute | Description
1716
- * ----------------|-------------
1717
- * `active` | Set when the checkbox is activated with mouse, touch or the keyboard.
1718
- * `checked` | Set when the checkbox is checked.
1719
- * `disabled` | Set when the checkbox is disabled.
1720
- * `focus-ring` | Set when the checkbox is focused using the keyboard.
1721
- * `focused` | Set when the checkbox is focused.
1722
- * `indeterminate` | Set when the checkbox is in the indeterminate state.
1723
- * `has-label` | Set when the checkbox has a label.
1724
- *
1725
- * See [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.
1726
- *
1727
- * @fires {CustomEvent} checked-changed - Fired when the `checked` property changes.
1728
- * @fires {CustomEvent} indeterminate-changed - Fired when the `indeterminate` property changes.
1729
- *
1730
- * @customElement
1731
- * @extends HTMLElement
1732
- * @mixes CheckboxMixin
1733
- * @mixes ThemableMixin
1734
- * @mixes ElementMixin
1735
- */
1736
- class Checkbox extends CheckboxMixin(ElementMixin$1(ThemableMixin$1(PolymerElement))) {
1737
- static get is() {
1738
- return 'vaadin-checkbox';
1739
- }
1740
-
1741
- static get template() {
1742
- return html`
1743
- <div class="vaadin-checkbox-container">
1744
- <div part="checkbox" aria-hidden="true"></div>
1745
- <slot name="input"></slot>
1746
- <slot name="label"></slot>
1747
- </div>
1748
- <slot name="tooltip"></slot>
1749
- `;
1750
- }
1751
-
1752
- /** @protected */
1753
- ready() {
1754
- super.ready();
1755
-
1756
- this._tooltipController = new TooltipController$1(this);
1757
- this._tooltipController.setAriaTarget(this.inputElement);
1758
- this.addController(this._tooltipController);
1759
- }
1760
- }
1761
-
1762
- defineCustomElement$2(Checkbox);
1763
-
1764
- /**
1765
- * @license
1766
- * Copyright (c) 2017 - 2023 Vaadin Ltd.
1767
- * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
1768
- */
1769
- /**
1770
- * @polymerMixin
1771
- */
1772
- const ThemePropertyMixin = (superClass) =>
1773
- class VaadinThemePropertyMixin extends superClass {
1774
- static get properties() {
1775
- return {
1776
- /**
1777
- * Helper property with theme attribute value facilitating propagation
1778
- * in shadow DOM.
1779
- *
1780
- * Enables the component implementation to propagate the `theme`
1781
- * attribute value to the sub-components in Shadow DOM by binding
1782
- * the sub-component's "theme" attribute to the `theme` property of
1783
- * the host.
1784
- *
1785
- * **NOTE:** Extending the mixin only provides the property for binding,
1786
- * and does not make the propagation alone.
1787
- *
1788
- * See [Styling Components: Sub-components](https://vaadin.com/docs/latest/styling/styling-components/#sub-components).
1789
- * page for more information.
1790
- *
1791
- * @protected
1792
- */
1793
- _theme: {
1794
- type: String,
1795
- readOnly: true,
1796
- },
1797
- };
1798
- }
1799
-
1800
- static get observedAttributes() {
1801
- return [...super.observedAttributes, 'theme'];
1802
- }
1803
-
1804
- /** @protected */
1805
- attributeChangedCallback(name, oldValue, newValue) {
1806
- super.attributeChangedCallback(name, oldValue, newValue);
1807
-
1808
- if (name === 'theme') {
1809
- this._set_theme(newValue);
1810
- }
1811
- }
1812
- };
1813
-
1814
- /**
1815
- * @license
1816
- * Copyright (c) 2017 - 2023 Vaadin Ltd.
1817
- * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
1818
- */
1819
-
1820
- /**
1821
- * @typedef {Object} Theme
1822
- * @property {string} themeFor
1823
- * @property {CSSResult[]} styles
1824
- * @property {string | string[]} [include]
1825
- * @property {string} [moduleId]
1826
- *
1827
- * @typedef {CSSResult[] | CSSResult} CSSResultGroup
1828
- */
1829
-
1830
- /**
1831
- * @type {Theme[]}
1832
- */
1833
- const themeRegistry = [];
1834
-
1835
- /**
1836
- * Check if the custom element type has themes applied.
1837
- * @param {Function} elementClass
1838
- * @returns {boolean}
1839
- */
1840
- function classHasThemes(elementClass) {
1841
- return elementClass && Object.prototype.hasOwnProperty.call(elementClass, '__themes');
1842
- }
1843
-
1844
- /**
1845
- * Check if the custom element type has themes applied.
1846
- * @param {string} tagName
1847
- * @returns {boolean}
1848
- */
1849
- function hasThemes(tagName) {
1850
- return classHasThemes(customElements.get(tagName));
1851
- }
1852
-
1853
- /**
1854
- * Flattens the styles into a single array of styles.
1855
- * @param {CSSResultGroup} styles
1856
- * @param {CSSResult[]} result
1857
- * @returns {CSSResult[]}
1858
- */
1859
- function flattenStyles(styles = []) {
1860
- return [styles].flat(Infinity).filter((style) => {
1861
- if (style instanceof o) {
1862
- return true;
1863
- }
1864
- console.warn('An item in styles is not of type CSSResult. Use `unsafeCSS` or `css`.');
1865
- return false;
1866
- });
1867
- }
1868
-
1869
- /**
1870
- * Registers CSS styles for a component type. Make sure to register the styles before
1871
- * the first instance of a component of the type is attached to DOM.
1872
- *
1873
- * @param {string} themeFor The local/tag name of the component type to register the styles for
1874
- * @param {CSSResultGroup} styles The CSS style rules to be registered for the component type
1875
- * matching themeFor and included in the local scope of each component instance
1876
- * @param {{moduleId?: string, include?: string | string[]}} options Additional options
1877
- * @return {void}
1878
- */
1879
- function registerStyles(themeFor, styles, options = {}) {
1880
- if (themeFor) {
1881
- if (hasThemes(themeFor)) {
1882
- console.warn(`The custom element definition for "${themeFor}"
1883
- was finalized before a style module was registered.
1884
- Make sure to add component specific style modules before
1885
- importing the corresponding custom element.`);
1886
- }
1887
- }
1888
-
1889
- styles = flattenStyles(styles);
1890
-
1891
- if (window.Vaadin && window.Vaadin.styleModules) {
1892
- window.Vaadin.styleModules.registerStyles(themeFor, styles, options);
1893
- } else {
1894
- themeRegistry.push({
1895
- themeFor,
1896
- styles,
1897
- include: options.include,
1898
- moduleId: options.moduleId,
1899
- });
1900
- }
1901
- }
1902
-
1903
- /**
1904
- * Returns all registered themes. By default the themeRegistry is returned as is.
1905
- * In case the style-modules adapter is imported, the themes are obtained from there instead
1906
- * @returns {Theme[]}
1907
- */
1908
- function getAllThemes() {
1909
- if (window.Vaadin && window.Vaadin.styleModules) {
1910
- return window.Vaadin.styleModules.getAllThemes();
1911
- }
1912
- return themeRegistry;
1913
- }
1914
-
1915
- /**
1916
- * Returns true if the themeFor string matches the tag name
1917
- * @param {string} themeFor
1918
- * @param {string} tagName
1919
- * @returns {boolean}
1920
- */
1921
- function matchesThemeFor(themeFor, tagName) {
1922
- return (themeFor || '').split(' ').some((themeForToken) => {
1923
- return new RegExp(`^${themeForToken.split('*').join('.*')}$`, 'u').test(tagName);
1924
- });
1925
- }
1926
-
1927
- /**
1928
- * Maps the moduleName to an include priority number which is used for
1929
- * determining the order in which styles are applied.
1930
- * @param {string} moduleName
1931
- * @returns {number}
1932
- */
1933
- function getIncludePriority(moduleName = '') {
1934
- let includePriority = 0;
1935
- if (moduleName.startsWith('lumo-') || moduleName.startsWith('material-')) {
1936
- includePriority = 1;
1937
- } else if (moduleName.startsWith('vaadin-')) {
1938
- includePriority = 2;
1939
- }
1940
- return includePriority;
1941
- }
1942
-
1943
- /**
1944
- * Gets an array of CSSResults matching the include property of the theme.
1945
- * @param {Theme} theme
1946
- * @returns {CSSResult[]}
1947
- */
1948
- function getIncludedStyles(theme) {
1949
- const includedStyles = [];
1950
- if (theme.include) {
1951
- [].concat(theme.include).forEach((includeModuleId) => {
1952
- const includedTheme = getAllThemes().find((s) => s.moduleId === includeModuleId);
1953
- if (includedTheme) {
1954
- includedStyles.push(...getIncludedStyles(includedTheme), ...includedTheme.styles);
1955
- } else {
1956
- console.warn(`Included moduleId ${includeModuleId} not found in style registry`);
1957
- }
1958
- }, theme.styles);
1959
- }
1960
- return includedStyles;
1961
- }
1962
-
1963
- /**
1964
- * Includes the styles to the template.
1965
- * @param {CSSResult[]} styles
1966
- * @param {HTMLTemplateElement} template
1967
- */
1968
- function addStylesToTemplate(styles, template) {
1969
- const styleEl = document.createElement('style');
1970
- styleEl.innerHTML = styles.map((style) => style.cssText).join('\n');
1971
- template.content.appendChild(styleEl);
1972
- }
1973
-
1974
- /**
1975
- * Returns an array of themes that should be used for styling a component matching
1976
- * the tag name. The array is sorted by the include order.
1977
- * @param {string} tagName
1978
- * @returns {Theme[]}
1979
- */
1980
- function getThemes(tagName) {
1981
- const defaultModuleName = `${tagName}-default-theme`;
1982
-
1983
- const themes = getAllThemes()
1984
- // Filter by matching themeFor properties
1985
- .filter((theme) => theme.moduleId !== defaultModuleName && matchesThemeFor(theme.themeFor, tagName))
1986
- .map((theme) => ({
1987
- ...theme,
1988
- // Prepend styles from included themes
1989
- styles: [...getIncludedStyles(theme), ...theme.styles],
1990
- // Map moduleId to includePriority
1991
- includePriority: getIncludePriority(theme.moduleId),
1992
- }))
1993
- // Sort by includePriority
1994
- .sort((themeA, themeB) => themeB.includePriority - themeA.includePriority);
1995
-
1996
- if (themes.length > 0) {
1997
- return themes;
1998
- }
1999
- // No theme modules found, return the default module if it exists
2000
- return getAllThemes().filter((theme) => theme.moduleId === defaultModuleName);
2001
- }
2002
-
2003
- /**
2004
- * @polymerMixin
2005
- * @mixes ThemePropertyMixin
2006
- */
2007
- const ThemableMixin = (superClass) =>
2008
- class VaadinThemableMixin extends ThemePropertyMixin(superClass) {
2009
- /**
2010
- * Covers PolymerElement based component styling
2011
- * @protected
2012
- */
2013
- static finalize() {
2014
- super.finalize();
2015
-
2016
- // Make sure not to run the logic intended for PolymerElement when LitElement is used.
2017
- if (this.elementStyles) {
2018
- return;
2019
- }
2020
-
2021
- const template = this.prototype._template;
2022
- if (!template || classHasThemes(this)) {
2023
- return;
2024
- }
2025
-
2026
- addStylesToTemplate(this.getStylesForThis(), template);
2027
- }
2028
-
2029
- /**
2030
- * Covers LitElement based component styling
2031
- *
2032
- * @protected
2033
- */
2034
- static finalizeStyles(styles) {
2035
- // The "styles" object originates from the "static get styles()" function of
2036
- // a LitElement based component. The theme styles are added after it
2037
- // so that they can override the component styles.
2038
- const themeStyles = this.getStylesForThis();
2039
- return styles ? [...super.finalizeStyles(styles), ...themeStyles] : themeStyles;
2040
- }
2041
-
2042
- /**
2043
- * Get styles for the component type
2044
- *
2045
- * @private
2046
- */
2047
- static getStylesForThis() {
2048
- const parent = Object.getPrototypeOf(this.prototype);
2049
- const inheritedThemes = (parent ? parent.constructor.__themes : []) || [];
2050
- this.__themes = [...inheritedThemes, ...getThemes(this.is)];
2051
- const themeStyles = this.__themes.flatMap((theme) => theme.styles);
2052
- // Remove duplicates
2053
- return themeStyles.filter((style, index) => index === themeStyles.lastIndexOf(style));
2054
- }
2055
- };
2056
-
2057
- const checkboxGroup = i`
2058
- :host {
2059
- color: var(--lumo-body-text-color);
2060
- font-size: var(--lumo-font-size-m);
2061
- font-family: var(--lumo-font-family);
2062
- -webkit-font-smoothing: antialiased;
2063
- -moz-osx-font-smoothing: grayscale;
2064
- -webkit-tap-highlight-color: transparent;
2065
- padding: var(--lumo-space-xs) 0;
2066
- }
2067
-
2068
- :host::before {
2069
- /* Effective height of vaadin-checkbox */
2070
- height: var(--lumo-size-s);
2071
- box-sizing: border-box;
2072
- display: inline-flex;
2073
- align-items: center;
2074
- }
2075
-
2076
- :host([theme~='vertical']) [part='group-field'] {
2077
- flex-direction: column;
2078
- }
2079
-
2080
- :host([disabled]) [part='label'] {
2081
- color: var(--lumo-disabled-text-color);
2082
- -webkit-text-fill-color: var(--lumo-disabled-text-color);
2083
- }
2084
-
2085
- :host([focused]:not([disabled])) [part='label'] {
2086
- color: var(--lumo-primary-text-color);
2087
- }
2088
-
2089
- :host(:hover:not([disabled]):not([focused])) [part='label'],
2090
- :host(:hover:not([disabled]):not([focused])) [part='helper-text'] {
2091
- color: var(--lumo-body-text-color);
2092
- }
2093
-
2094
- /* Touch device adjustment */
2095
- @media (pointer: coarse) {
2096
- :host(:hover:not([disabled]):not([focused])) [part='label'] {
2097
- color: var(--lumo-secondary-text-color);
2098
- }
2099
- }
2100
- `;
2101
-
2102
- registerStyles('vaadin-checkbox-group', [requiredField, helper, checkboxGroup], {
2103
- moduleId: 'lumo-checkbox-group',
2104
- });
2105
-
2106
- /**
2107
- * @license
2108
- * Copyright (c) 2021 - 2023 Vaadin Ltd.
2109
- * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
2110
- */
2111
- function defineCustomElement$1(CustomElement) {
2112
- const defined = customElements.get(CustomElement.is);
2113
- if (!defined) {
2114
- customElements.define(CustomElement.is, CustomElement);
2115
- } else {
2116
- const definedVersion = defined.version;
2117
- if (definedVersion && CustomElement.version && definedVersion === CustomElement.version) {
2118
- // Just loading the same thing again
2119
- console.warn(`The component ${CustomElement.is} has been loaded twice`);
2120
- } else {
2121
- console.error(
2122
- `Tried to define ${CustomElement.is} version ${CustomElement.version} when version ${defined.version} is already in use. Something will probably break.`,
2123
- );
2124
- }
2125
- }
2126
- }
2127
-
2128
- /**
2129
- * @license
2130
- * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
2131
- * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
2132
- * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
2133
- * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
2134
- * Code distributed by Google as part of the polymer project is also
2135
- * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
2136
- */
2137
-
2138
- /**
2139
- * Async interface wrapper around `requestIdleCallback`. Falls back to
2140
- * `setTimeout` on browsers that do not support `requestIdleCallback`.
2141
- *
2142
- * @namespace
2143
- * @summary Async interface wrapper around `requestIdleCallback`.
2144
- */
2145
- const idlePeriod = {
2146
- /**
2147
- * Enqueues a function called at `requestIdleCallback` timing.
2148
- *
2149
- * @memberof idlePeriod
2150
- * @param {function(!IdleDeadline):void} fn Callback to run
2151
- * @return {number} Handle used for canceling task
2152
- */
2153
- run(fn) {
2154
- return window.requestIdleCallback ? window.requestIdleCallback(fn) : window.setTimeout(fn, 16);
2155
- },
2156
- /**
2157
- * Cancels a previously enqueued `idlePeriod` callback.
2158
- *
2159
- * @memberof idlePeriod
2160
- * @param {number} handle Handle returned from `run` of callback to cancel
2161
- * @return {void}
2162
- */
2163
- cancel(handle) {
2164
- if (window.cancelIdleCallback) {
2165
- window.cancelIdleCallback(handle);
2166
- } else {
2167
- window.clearTimeout(handle);
2168
- }
2169
- },
2170
- };
2171
-
2172
- /**
2173
- @license
2174
- Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
2175
- This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
2176
- The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
2177
- The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
2178
- Code distributed by Google as part of the polymer project is also
2179
- subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
2180
- */
2181
-
2182
- const debouncerQueue = new Set();
2183
-
2184
- /**
2185
- * @summary Collapse multiple callbacks into one invocation after a timer.
2186
- */
2187
- class Debouncer {
2188
- /**
2189
- * Creates a debouncer if no debouncer is passed as a parameter
2190
- * or it cancels an active debouncer otherwise. The following
2191
- * example shows how a debouncer can be called multiple times within a
2192
- * microtask and "debounced" such that the provided callback function is
2193
- * called once. Add this method to a custom element:
2194
- *
2195
- * ```js
2196
- * import {microTask} from '@vaadin/component-base/src/async.js';
2197
- * import {Debouncer} from '@vaadin/component-base/src/debounce.js';
2198
- * // ...
2199
- *
2200
- * _debounceWork() {
2201
- * this._debounceJob = Debouncer.debounce(this._debounceJob,
2202
- * microTask, () => this._doWork());
2203
- * }
2204
- * ```
2205
- *
2206
- * If the `_debounceWork` method is called multiple times within the same
2207
- * microtask, the `_doWork` function will be called only once at the next
2208
- * microtask checkpoint.
2209
- *
2210
- * Note: In testing it is often convenient to avoid asynchrony. To accomplish
2211
- * this with a debouncer, you can use `enqueueDebouncer` and
2212
- * `flush`. For example, extend the above example by adding
2213
- * `enqueueDebouncer(this._debounceJob)` at the end of the
2214
- * `_debounceWork` method. Then in a test, call `flush` to ensure
2215
- * the debouncer has completed.
2216
- *
2217
- * @param {Debouncer?} debouncer Debouncer object.
2218
- * @param {!AsyncInterface} asyncModule Object with Async interface
2219
- * @param {function()} callback Callback to run.
2220
- * @return {!Debouncer} Returns a debouncer object.
2221
- */
2222
- static debounce(debouncer, asyncModule, callback) {
2223
- if (debouncer instanceof Debouncer) {
2224
- // Cancel the async callback, but leave in debouncerQueue if it was
2225
- // enqueued, to maintain 1.x flush order
2226
- debouncer._cancelAsync();
2227
- } else {
2228
- debouncer = new Debouncer();
2229
- }
2230
- debouncer.setConfig(asyncModule, callback);
2231
- return debouncer;
2232
- }
2233
-
2234
- constructor() {
2235
- this._asyncModule = null;
2236
- this._callback = null;
2237
- this._timer = null;
2238
- }
2239
-
2240
- /**
2241
- * Sets the scheduler; that is, a module with the Async interface,
2242
- * a callback and optional arguments to be passed to the run function
2243
- * from the async module.
2244
- *
2245
- * @param {!AsyncInterface} asyncModule Object with Async interface.
2246
- * @param {function()} callback Callback to run.
2247
- * @return {void}
2248
- */
2249
- setConfig(asyncModule, callback) {
2250
- this._asyncModule = asyncModule;
2251
- this._callback = callback;
2252
- this._timer = this._asyncModule.run(() => {
2253
- this._timer = null;
2254
- debouncerQueue.delete(this);
2255
- this._callback();
2256
- });
2257
- }
2258
-
2259
- /**
2260
- * Cancels an active debouncer and returns a reference to itself.
2261
- *
2262
- * @return {void}
2263
- */
2264
- cancel() {
2265
- if (this.isActive()) {
2266
- this._cancelAsync();
2267
- // Canceling a debouncer removes its spot from the flush queue,
2268
- // so if a debouncer is manually canceled and re-debounced, it
2269
- // will reset its flush order (this is a very minor difference from 1.x)
2270
- // Re-debouncing via the `debounce` API retains the 1.x FIFO flush order
2271
- debouncerQueue.delete(this);
2272
- }
2273
- }
2274
-
2275
- /**
2276
- * Cancels a debouncer's async callback.
2277
- *
2278
- * @return {void}
2279
- */
2280
- _cancelAsync() {
2281
- if (this.isActive()) {
2282
- this._asyncModule.cancel(/** @type {number} */ (this._timer));
2283
- this._timer = null;
2284
- }
2285
- }
2286
-
2287
- /**
2288
- * Flushes an active debouncer and returns a reference to itself.
2289
- *
2290
- * @return {void}
2291
- */
2292
- flush() {
2293
- if (this.isActive()) {
2294
- this.cancel();
2295
- this._callback();
2296
- }
2297
- }
2298
-
2299
- /**
2300
- * Returns true if the debouncer is active.
2301
- *
2302
- * @return {boolean} True if active.
2303
- */
2304
- isActive() {
2305
- return this._timer != null;
2306
- }
2307
- }
2308
-
2309
- /**
2310
- * Adds a `Debouncer` to a list of globally flushable tasks.
2311
- *
2312
- * @param {!Debouncer} debouncer Debouncer to enqueue
2313
- * @return {void}
2314
- */
2315
- function enqueueDebouncer(debouncer) {
2316
- debouncerQueue.add(debouncer);
2317
- }
2318
-
2319
- /**
2320
- * @license
2321
- * Copyright (c) 2021 - 2023 Vaadin Ltd.
2322
- * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
2323
- */
2324
-
2325
- /**
2326
- * Array of Vaadin custom element classes that have been subscribed to the dir changes.
2327
- */
2328
- const directionSubscribers = [];
2329
-
2330
- function alignDirs(element, documentDir, elementDir = element.getAttribute('dir')) {
2331
- if (documentDir) {
2332
- element.setAttribute('dir', documentDir);
2333
- } else if (elementDir != null) {
2334
- element.removeAttribute('dir');
2335
- }
2336
- }
2337
-
2338
- function getDocumentDir() {
2339
- return document.documentElement.getAttribute('dir');
2340
- }
2341
-
2342
- function directionUpdater() {
2343
- const documentDir = getDocumentDir();
2344
- directionSubscribers.forEach((element) => {
2345
- alignDirs(element, documentDir);
2346
- });
2347
- }
2348
-
2349
- const directionObserver = new MutationObserver(directionUpdater);
2350
- directionObserver.observe(document.documentElement, { attributes: true, attributeFilter: ['dir'] });
2351
-
2352
- /**
2353
- * A mixin to handle `dir` attribute based on the one set on the `<html>` element.
2354
- *
2355
- * @polymerMixin
2356
- */
2357
- const DirMixin = (superClass) =>
2358
- class VaadinDirMixin extends superClass {
2359
- static get properties() {
2360
- return {
2361
- /**
2362
- * @protected
2363
- */
2364
- dir: {
2365
- type: String,
2366
- value: '',
2367
- reflectToAttribute: true,
2368
- converter: {
2369
- fromAttribute: (attr) => {
2370
- return !attr ? '' : attr;
2371
- },
2372
- toAttribute: (prop) => {
2373
- return prop === '' ? null : prop;
2374
- },
2375
- },
2376
- },
2377
- };
2378
- }
2379
-
2380
- /**
2381
- * @return {boolean}
2382
- * @protected
2383
- */
2384
- get __isRTL() {
2385
- return this.getAttribute('dir') === 'rtl';
2386
- }
2387
-
2388
- /** @protected */
2389
- connectedCallback() {
2390
- super.connectedCallback();
2391
-
2392
- if (!this.hasAttribute('dir') || this.__restoreSubscription) {
2393
- this.__subscribe();
2394
- alignDirs(this, getDocumentDir(), null);
2395
- }
2396
- }
2397
-
2398
- /** @protected */
2399
- attributeChangedCallback(name, oldValue, newValue) {
2400
- super.attributeChangedCallback(name, oldValue, newValue);
2401
- if (name !== 'dir') {
2402
- return;
2403
- }
2404
-
2405
- const documentDir = getDocumentDir();
2406
-
2407
- // New value equals to the document direction and the element is not subscribed to the changes
2408
- const newValueEqlDocDir = newValue === documentDir && directionSubscribers.indexOf(this) === -1;
2409
- // Value was emptied and the element is not subscribed to the changes
2410
- const newValueEmptied = !newValue && oldValue && directionSubscribers.indexOf(this) === -1;
2411
- // New value is different and the old equals to document direction and the element is not subscribed to the changes
2412
- const newDiffValue = newValue !== documentDir && oldValue === documentDir;
2413
-
2414
- if (newValueEqlDocDir || newValueEmptied) {
2415
- this.__subscribe();
2416
- alignDirs(this, documentDir, newValue);
2417
- } else if (newDiffValue) {
2418
- this.__unsubscribe();
2419
- }
2420
- }
2421
-
2422
- /** @protected */
2423
- disconnectedCallback() {
2424
- super.disconnectedCallback();
2425
- this.__restoreSubscription = directionSubscribers.includes(this);
2426
- this.__unsubscribe();
2427
- }
2428
-
2429
- /** @protected */
2430
- _valueToNodeAttribute(node, value, attribute) {
2431
- // Override default Polymer attribute reflection to match native behavior of HTMLElement.dir property
2432
- // If the property contains an empty string then it should not create an empty attribute
2433
- if (attribute === 'dir' && value === '' && !node.hasAttribute('dir')) {
2434
- return;
2435
- }
2436
- super._valueToNodeAttribute(node, value, attribute);
2437
- }
2438
-
2439
- /** @protected */
2440
- _attributeToProperty(attribute, value, type) {
2441
- // Override default Polymer attribute reflection to match native behavior of HTMLElement.dir property
2442
- // If the attribute is removed, then the dir property should contain an empty string instead of null
2443
- if (attribute === 'dir' && !value) {
2444
- this.dir = '';
2445
- } else {
2446
- super._attributeToProperty(attribute, value, type);
2447
- }
2448
- }
2449
-
2450
- /** @private */
2451
- __subscribe() {
2452
- if (!directionSubscribers.includes(this)) {
2453
- directionSubscribers.push(this);
2454
- }
2455
- }
2456
-
2457
- /** @private */
2458
- __unsubscribe() {
2459
- if (directionSubscribers.includes(this)) {
2460
- directionSubscribers.splice(directionSubscribers.indexOf(this), 1);
2461
- }
2462
- }
2463
- };
2464
-
2465
- /**
2466
- * @license
2467
- * Copyright (c) 2021 - 2023 Vaadin Ltd.
2468
- * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
2469
- */
2470
-
2471
- if (!window.Vaadin) {
2472
- window.Vaadin = {};
2473
- }
2474
-
2475
- /**
2476
- * Array of Vaadin custom element classes that have been finalized.
2477
- */
2478
- if (!window.Vaadin.registrations) {
2479
- window.Vaadin.registrations = [];
2480
- }
2481
-
2482
- if (!window.Vaadin.developmentModeCallback) {
2483
- window.Vaadin.developmentModeCallback = {};
2484
- }
2485
-
2486
- window.Vaadin.developmentModeCallback['vaadin-usage-statistics'] = function () {
2487
- usageStatistics();
2488
- };
2489
-
2490
- let statsJob;
2491
-
2492
- const registered = new Set();
2493
-
2494
- /**
2495
- * @polymerMixin
2496
- * @mixes DirMixin
2497
- */
2498
- const ElementMixin = (superClass) =>
2499
- class VaadinElementMixin extends DirMixin(superClass) {
2500
- static get version() {
2501
- return '24.2.3';
2502
- }
2503
-
2504
- /** @protected */
2505
- static finalize() {
2506
- super.finalize();
2507
-
2508
- const { is } = this;
2509
-
2510
- // Registers a class prototype for telemetry purposes.
2511
- if (is && !registered.has(is)) {
2512
- window.Vaadin.registrations.push(this);
2513
- registered.add(is);
2514
-
2515
- if (window.Vaadin.developmentModeCallback) {
2516
- statsJob = Debouncer.debounce(statsJob, idlePeriod, () => {
2517
- window.Vaadin.developmentModeCallback['vaadin-usage-statistics']();
2518
- });
2519
- enqueueDebouncer(statsJob);
2520
- }
2521
- }
2522
- }
2523
-
2524
- constructor() {
2525
- super();
2526
-
2527
- if (document.doctype === null) {
2528
- console.warn(
2529
- 'Vaadin components require the "standards mode" declaration. Please add <!DOCTYPE html> to the HTML document.',
2530
- );
2531
- }
2532
- }
2533
- };
2534
-
2535
- /**
2536
- * @license
2537
- * Copyright (c) 2023 Vaadin Ltd.
2538
- * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
2539
- */
2540
-
2541
- /**
2542
- * A helper for observing slot changes.
2543
- */
2544
- class SlotObserver {
2545
- constructor(slot, callback) {
2546
- /** @type HTMLSlotElement */
2547
- this.slot = slot;
2548
-
2549
- /** @type Function */
2550
- this.callback = callback;
2551
-
2552
- /** @type {Node[]} */
2553
- this._storedNodes = [];
2554
-
2555
- this._connected = false;
2556
- this._scheduled = false;
2557
-
2558
- this._boundSchedule = () => {
2559
- this._schedule();
2560
- };
2561
-
2562
- this.connect();
2563
- this._schedule();
2564
- }
2565
-
2566
- /**
2567
- * Activates an observer. This method is automatically called when
2568
- * a `SlotObserver` is created. It should only be called to re-activate
2569
- * an observer that has been deactivated via the `disconnect` method.
2570
- */
2571
- connect() {
2572
- this.slot.addEventListener('slotchange', this._boundSchedule);
2573
- this._connected = true;
2574
- }
2575
-
2576
- /**
2577
- * Deactivates the observer. After calling this method the observer callback
2578
- * will not be called when changes to slotted nodes occur. The `connect` method
2579
- * may be subsequently called to reactivate the observer.
2580
- */
2581
- disconnect() {
2582
- this.slot.removeEventListener('slotchange', this._boundSchedule);
2583
- this._connected = false;
2584
- }
2585
-
2586
- /** @private */
2587
- _schedule() {
2588
- if (!this._scheduled) {
2589
- this._scheduled = true;
2590
-
2591
- queueMicrotask(() => {
2592
- this.flush();
2593
- });
2594
- }
2595
- }
2596
-
2597
- /**
2598
- * Run the observer callback synchronously.
2599
- */
2600
- flush() {
2601
- if (!this._connected) {
2602
- return;
2603
- }
2604
-
2605
- this._scheduled = false;
2606
-
2607
- this._processNodes();
2608
- }
2609
-
2610
- /** @private */
2611
- _processNodes() {
2612
- const currentNodes = this.slot.assignedNodes({ flatten: true });
2613
-
2614
- let addedNodes = [];
2615
- const removedNodes = [];
2616
- const movedNodes = [];
2617
-
2618
- if (currentNodes.length) {
2619
- addedNodes = currentNodes.filter((node) => !this._storedNodes.includes(node));
2620
- }
2621
-
2622
- if (this._storedNodes.length) {
2623
- this._storedNodes.forEach((node, index) => {
2624
- const idx = currentNodes.indexOf(node);
2625
- if (idx === -1) {
2626
- removedNodes.push(node);
2627
- } else if (idx !== index) {
2628
- movedNodes.push(node);
2629
- }
2630
- });
2631
- }
2632
-
2633
- if (addedNodes.length || removedNodes.length || movedNodes.length) {
2634
- this.callback({ addedNodes, movedNodes, removedNodes });
2635
- }
2636
-
2637
- this._storedNodes = currentNodes;
2638
- }
2639
- }
2640
-
2641
- /**
2642
- * @license
2643
- * Copyright (c) 2021 - 2023 Vaadin Ltd.
2644
- * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
2645
- */
2646
-
2647
- /**
2648
- * Returns true if the given node is an empty text node, false otherwise.
2649
- *
2650
- * @param {Node} node
2651
- * @return {boolean}
2652
- */
2653
- function isEmptyTextNode(node) {
2654
- return node.nodeType === Node.TEXT_NODE && node.textContent.trim() === '';
2655
- }
2656
-
2657
- /**
2658
- * @license
2659
- * Copyright (c) 2021 - 2023 Vaadin Ltd.
2660
- * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
2661
- */
2662
-
2663
- let uniqueId = 0;
2664
-
2665
- /**
2666
- * Returns a unique integer id.
2667
- *
2668
- * @return {number}
2669
- */
2670
- function generateUniqueId() {
2671
- // eslint-disable-next-line no-plusplus
2672
- return uniqueId++;
2673
- }
2674
-
2675
- /**
2676
- * @license
2677
- * Copyright (c) 2021 - 2023 Vaadin Ltd.
2678
- * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
2679
- */
2680
-
2681
- /**
2682
- * A controller for providing content to slot element and observing changes.
2683
- */
2684
- class SlotController extends EventTarget {
2685
- /**
2686
- * Ensure that every instance has unique ID.
2687
- *
2688
- * @param {HTMLElement} host
2689
- * @param {string} slotName
2690
- * @return {string}
2691
- * @protected
2692
- */
2693
- static generateId(host, slotName) {
2694
- const prefix = slotName || 'default';
2695
- return `${prefix}-${host.localName}-${generateUniqueId()}`;
2696
- }
2697
-
2698
- constructor(host, slotName, tagName, config = {}) {
2699
- super();
2700
-
2701
- const { initializer, multiple, observe, useUniqueId } = config;
2702
-
2703
- this.host = host;
2704
- this.slotName = slotName;
2705
- this.tagName = tagName;
2706
- this.observe = typeof observe === 'boolean' ? observe : true;
2707
- this.multiple = typeof multiple === 'boolean' ? multiple : false;
2708
- this.slotInitializer = initializer;
2709
-
2710
- if (multiple) {
2711
- this.nodes = [];
2712
- }
2713
-
2714
- // Only generate the default ID if requested by the controller.
2715
- if (useUniqueId) {
2716
- this.defaultId = this.constructor.generateId(host, slotName);
2717
- }
2718
- }
2719
-
2720
- hostConnected() {
2721
- if (!this.initialized) {
2722
- if (this.multiple) {
2723
- this.initMultiple();
2724
- } else {
2725
- this.initSingle();
2726
- }
2727
-
2728
- if (this.observe) {
2729
- this.observeSlot();
2730
- }
2731
-
2732
- this.initialized = true;
2733
- }
472
+ class Checkbox extends CheckboxMixin(ElementMixin(ThemableMixin(PolymerElement))) {
473
+ static get is() {
474
+ return 'vaadin-checkbox';
2734
475
  }
2735
476
 
2736
- /** @protected */
2737
- initSingle() {
2738
- let node = this.getSlotChild();
2739
-
2740
- if (!node) {
2741
- node = this.attachDefaultNode();
2742
- this.initNode(node);
2743
- } else {
2744
- this.node = node;
2745
- this.initAddedNode(node);
2746
- }
477
+ static get template() {
478
+ return html`
479
+ <div class="vaadin-checkbox-container">
480
+ <div part="checkbox" aria-hidden="true"></div>
481
+ <slot name="input"></slot>
482
+ <slot name="label"></slot>
483
+ </div>
484
+ <slot name="tooltip"></slot>
485
+ `;
2747
486
  }
2748
487
 
2749
488
  /** @protected */
2750
- initMultiple() {
2751
- const children = this.getSlotChildren();
2752
-
2753
- if (children.length === 0) {
2754
- const defaultNode = this.attachDefaultNode();
2755
- if (defaultNode) {
2756
- this.nodes = [defaultNode];
2757
- this.initNode(defaultNode);
2758
- }
2759
- } else {
2760
- this.nodes = children;
2761
- children.forEach((node) => {
2762
- this.initAddedNode(node);
2763
- });
2764
- }
2765
- }
2766
-
2767
- /**
2768
- * Create and attach default node using the provided tag name, if any.
2769
- * @return {Node | undefined}
2770
- * @protected
2771
- */
2772
- attachDefaultNode() {
2773
- const { host, slotName, tagName } = this;
2774
-
2775
- // Check if the node was created previously and if so, reuse it.
2776
- let node = this.defaultNode;
2777
-
2778
- // Tag name is optional, sometimes we don't init default content.
2779
- if (!node && tagName) {
2780
- node = document.createElement(tagName);
2781
- if (node instanceof Element) {
2782
- if (slotName !== '') {
2783
- node.setAttribute('slot', slotName);
2784
- }
2785
- this.node = node;
2786
- this.defaultNode = node;
2787
- }
2788
- }
2789
-
2790
- if (node) {
2791
- host.appendChild(node);
2792
- }
2793
-
2794
- return node;
2795
- }
2796
-
2797
- /**
2798
- * Return the list of nodes matching the slot managed by the controller.
2799
- * @return {Node}
2800
- */
2801
- getSlotChildren() {
2802
- const { slotName } = this;
2803
- return Array.from(this.host.childNodes).filter((node) => {
2804
- // Either an element (any slot) or a text node (only un-named slot).
2805
- return (
2806
- (node.nodeType === Node.ELEMENT_NODE && node.slot === slotName) ||
2807
- (node.nodeType === Node.TEXT_NODE && node.textContent.trim() && slotName === '')
2808
- );
2809
- });
2810
- }
2811
-
2812
- /**
2813
- * Return a reference to the node managed by the controller.
2814
- * @return {Node}
2815
- */
2816
- getSlotChild() {
2817
- return this.getSlotChildren()[0];
2818
- }
2819
-
2820
- /**
2821
- * Run `slotInitializer` for the node managed by the controller.
2822
- *
2823
- * @param {Node} node
2824
- * @protected
2825
- */
2826
- initNode(node) {
2827
- const { slotInitializer } = this;
2828
- // Don't try to bind `this` to initializer (normally it's arrow function).
2829
- // Instead, pass the host as a first argument to access component's state.
2830
- if (slotInitializer) {
2831
- slotInitializer(node, this.host);
2832
- }
2833
- }
2834
-
2835
- /**
2836
- * Override to initialize the newly added custom node.
2837
- *
2838
- * @param {Node} _node
2839
- * @protected
2840
- */
2841
- initCustomNode(_node) {}
2842
-
2843
- /**
2844
- * Override to teardown slotted node when it's removed.
2845
- *
2846
- * @param {Node} _node
2847
- * @protected
2848
- */
2849
- teardownNode(_node) {}
2850
-
2851
- /**
2852
- * Run both `initCustomNode` and `initNode` for a custom slotted node.
2853
- *
2854
- * @param {Node} node
2855
- * @protected
2856
- */
2857
- initAddedNode(node) {
2858
- if (node !== this.defaultNode) {
2859
- this.initCustomNode(node);
2860
- this.initNode(node);
2861
- }
2862
- }
2863
-
2864
- /**
2865
- * Setup the observer to manage slot content changes.
2866
- * @protected
2867
- */
2868
- observeSlot() {
2869
- const { slotName } = this;
2870
- const selector = slotName === '' ? 'slot:not([name])' : `slot[name=${slotName}]`;
2871
- const slot = this.host.shadowRoot.querySelector(selector);
2872
-
2873
- this.__slotObserver = new SlotObserver(slot, ({ addedNodes, removedNodes }) => {
2874
- const current = this.multiple ? this.nodes : [this.node];
2875
-
2876
- // Calling `slot.assignedNodes()` includes whitespace text nodes in case of default slot:
2877
- // unlike comment nodes, they are not filtered out. So we need to manually ignore them.
2878
- const newNodes = addedNodes.filter((node) => !isEmptyTextNode(node) && !current.includes(node));
2879
-
2880
- if (removedNodes.length) {
2881
- this.nodes = current.filter((node) => !removedNodes.includes(node));
2882
-
2883
- removedNodes.forEach((node) => {
2884
- this.teardownNode(node);
2885
- });
2886
- }
489
+ ready() {
490
+ super.ready();
2887
491
 
2888
- if (newNodes && newNodes.length > 0) {
2889
- if (this.multiple) {
2890
- // Remove default node if exists
2891
- if (this.defaultNode) {
2892
- this.defaultNode.remove();
2893
- }
2894
- this.nodes = [...current, ...newNodes].filter((node) => node !== this.defaultNode);
2895
- newNodes.forEach((node) => {
2896
- this.initAddedNode(node);
2897
- });
2898
- } else {
2899
- // Remove previous node if exists
2900
- if (this.node) {
2901
- this.node.remove();
2902
- }
2903
- this.node = newNodes[0];
2904
- this.initAddedNode(this.node);
2905
- }
2906
- }
2907
- });
492
+ this._tooltipController = new TooltipController(this);
493
+ this._tooltipController.setAriaTarget(this.inputElement);
494
+ this.addController(this._tooltipController);
2908
495
  }
2909
496
  }
2910
497
 
2911
- /**
2912
- * @license
2913
- * Copyright (c) 2022 - 2023 Vaadin Ltd.
2914
- * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
2915
- */
2916
-
2917
- /**
2918
- * A controller that manages the slotted tooltip element.
2919
- */
2920
- class TooltipController extends SlotController {
2921
- constructor(host) {
2922
- // Do not provide slot factory to create tooltip lazily.
2923
- super(host, 'tooltip');
2924
-
2925
- this.setTarget(host);
2926
- }
2927
-
2928
- /**
2929
- * Override to initialize the newly added custom tooltip.
2930
- *
2931
- * @param {Node} tooltipNode
2932
- * @protected
2933
- * @override
2934
- */
2935
- initCustomNode(tooltipNode) {
2936
- tooltipNode.target = this.target;
2937
-
2938
- if (this.ariaTarget !== undefined) {
2939
- tooltipNode.ariaTarget = this.ariaTarget;
2940
- }
2941
-
2942
- if (this.context !== undefined) {
2943
- tooltipNode.context = this.context;
2944
- }
2945
-
2946
- if (this.manual !== undefined) {
2947
- tooltipNode.manual = this.manual;
2948
- }
2949
-
2950
- if (this.opened !== undefined) {
2951
- tooltipNode.opened = this.opened;
2952
- }
2953
-
2954
- if (this.position !== undefined) {
2955
- tooltipNode._position = this.position;
2956
- }
2957
-
2958
- if (this.shouldShow !== undefined) {
2959
- tooltipNode.shouldShow = this.shouldShow;
2960
- }
2961
-
2962
- this.__notifyChange();
2963
- }
2964
-
2965
- /**
2966
- * Override to notify the host when the tooltip is removed.
2967
- *
2968
- * @param {Node} tooltipNode
2969
- * @protected
2970
- * @override
2971
- */
2972
- teardownNode() {
2973
- this.__notifyChange();
2974
- }
2975
-
2976
- /**
2977
- * Set an HTML element for linking with the tooltip overlay
2978
- * via `aria-describedby` attribute used by screen readers.
2979
- * @param {HTMLElement} ariaTarget
2980
- */
2981
- setAriaTarget(ariaTarget) {
2982
- this.ariaTarget = ariaTarget;
498
+ defineCustomElement$1(Checkbox);
2983
499
 
2984
- const tooltipNode = this.node;
2985
- if (tooltipNode) {
2986
- tooltipNode.ariaTarget = ariaTarget;
2987
- }
500
+ const checkboxGroup = i`
501
+ :host {
502
+ color: var(--lumo-body-text-color);
503
+ font-size: var(--lumo-font-size-m);
504
+ font-family: var(--lumo-font-family);
505
+ -webkit-font-smoothing: antialiased;
506
+ -moz-osx-font-smoothing: grayscale;
507
+ -webkit-tap-highlight-color: transparent;
508
+ padding: var(--lumo-space-xs) 0;
2988
509
  }
2989
510
 
2990
- /**
2991
- * Set a context object to be used by generator.
2992
- * @param {object} context
2993
- */
2994
- setContext(context) {
2995
- this.context = context;
2996
-
2997
- const tooltipNode = this.node;
2998
- if (tooltipNode) {
2999
- tooltipNode.context = context;
3000
- }
511
+ :host::before {
512
+ /* Effective height of vaadin-checkbox */
513
+ height: var(--lumo-size-s);
514
+ box-sizing: border-box;
515
+ display: inline-flex;
516
+ align-items: center;
3001
517
  }
3002
518
 
3003
- /**
3004
- * Toggle manual state on the slotted tooltip.
3005
- * @param {boolean} manual
3006
- */
3007
- setManual(manual) {
3008
- this.manual = manual;
3009
-
3010
- const tooltipNode = this.node;
3011
- if (tooltipNode) {
3012
- tooltipNode.manual = manual;
3013
- }
519
+ :host([theme~='vertical']) [part='group-field'] {
520
+ flex-direction: column;
3014
521
  }
3015
522
 
3016
- /**
3017
- * Toggle opened state on the slotted tooltip.
3018
- * @param {boolean} opened
3019
- */
3020
- setOpened(opened) {
3021
- this.opened = opened;
3022
-
3023
- const tooltipNode = this.node;
3024
- if (tooltipNode) {
3025
- tooltipNode.opened = opened;
3026
- }
523
+ :host([disabled]) [part='label'] {
524
+ color: var(--lumo-disabled-text-color);
525
+ -webkit-text-fill-color: var(--lumo-disabled-text-color);
3027
526
  }
3028
527
 
3029
- /**
3030
- * Set default position for the slotted tooltip.
3031
- * This can be overridden by setting the position
3032
- * using corresponding property or attribute.
3033
- * @param {string} position
3034
- */
3035
- setPosition(position) {
3036
- this.position = position;
3037
-
3038
- const tooltipNode = this.node;
3039
- if (tooltipNode) {
3040
- tooltipNode._position = position;
3041
- }
528
+ :host([focused]:not([disabled])) [part='label'] {
529
+ color: var(--lumo-primary-text-color);
3042
530
  }
3043
531
 
3044
- /**
3045
- * Set function used to detect whether to show
3046
- * the tooltip based on a condition.
3047
- * @param {Function} shouldShow
3048
- */
3049
- setShouldShow(shouldShow) {
3050
- this.shouldShow = shouldShow;
3051
-
3052
- const tooltipNode = this.node;
3053
- if (tooltipNode) {
3054
- tooltipNode.shouldShow = shouldShow;
3055
- }
532
+ :host(:hover:not([disabled]):not([focused])) [part='label'],
533
+ :host(:hover:not([disabled]):not([focused])) [part='helper-text'] {
534
+ color: var(--lumo-body-text-color);
3056
535
  }
3057
536
 
3058
- /**
3059
- * Set an HTML element to attach the tooltip to.
3060
- * @param {HTMLElement} target
3061
- */
3062
- setTarget(target) {
3063
- this.target = target;
3064
-
3065
- const tooltipNode = this.node;
3066
- if (tooltipNode) {
3067
- tooltipNode.target = target;
537
+ /* Touch device adjustment */
538
+ @media (pointer: coarse) {
539
+ :host(:hover:not([disabled]):not([focused])) [part='label'] {
540
+ color: var(--lumo-secondary-text-color);
3068
541
  }
3069
542
  }
543
+ `;
3070
544
 
3071
- /** @private */
3072
- __notifyChange() {
3073
- this.dispatchEvent(new CustomEvent('tooltip-changed', { detail: { node: this.node } }));
3074
- }
3075
- }
545
+ registerStyles('vaadin-checkbox-group', [requiredField, helper, checkboxGroup], {
546
+ moduleId: 'lumo-checkbox-group',
547
+ });
3076
548
 
3077
549
  /**
3078
550
  * @license