@everymatrix/general-input 1.22.0 → 1.22.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,23 +1,1286 @@
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 { i as inputFieldShared, c as InputControlMixin, d as inputFieldShared$1 } from './input-field-shared-styles.js';
4
- import { r as registerStyles, h as html, e as InputController, f as LabelledInputController, g as TooltipController, T as ThemableMixin, E as ElementMixin, P as PolymerElement, i, S as SlotController } from './field-mixin.js';
5
- import { P as PatternMixin } from './pattern-mixin.js';
3
+ import { i as inputFieldShared, a as InputControlMixin, b as inputFieldShared$1 } from './input-field-shared-styles.js';
4
+ import { o, u as usageStatistics, e as InputController, f as LabelledInputController, h as html, P as PolymerElement, i } from './field-mixin.js';
6
5
  import { b as button, B as Button } from './vaadin-button.js';
7
6
 
8
7
  /**
9
8
  * @license
10
- * Copyright (c) 2017 - 2022 Vaadin Ltd.
9
+ * Copyright (c) 2017 - 2023 Vaadin Ltd.
10
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
11
+ */
12
+ /**
13
+ * @polymerMixin
14
+ */
15
+ const ThemePropertyMixin = (superClass) =>
16
+ class VaadinThemePropertyMixin extends superClass {
17
+ static get properties() {
18
+ return {
19
+ /**
20
+ * Helper property with theme attribute value facilitating propagation
21
+ * in shadow DOM.
22
+ *
23
+ * Enables the component implementation to propagate the `theme`
24
+ * attribute value to the sub-components in Shadow DOM by binding
25
+ * the sub-component's "theme" attribute to the `theme` property of
26
+ * the host.
27
+ *
28
+ * **NOTE:** Extending the mixin only provides the property for binding,
29
+ * and does not make the propagation alone.
30
+ *
31
+ * See [Styling Components: Sub-components](https://vaadin.com/docs/latest/styling/styling-components/#sub-components).
32
+ * page for more information.
33
+ *
34
+ * @protected
35
+ */
36
+ _theme: {
37
+ type: String,
38
+ readOnly: true,
39
+ },
40
+ };
41
+ }
42
+
43
+ static get observedAttributes() {
44
+ return [...super.observedAttributes, 'theme'];
45
+ }
46
+
47
+ /** @protected */
48
+ attributeChangedCallback(name, oldValue, newValue) {
49
+ super.attributeChangedCallback(name, oldValue, newValue);
50
+
51
+ if (name === 'theme') {
52
+ this._set_theme(newValue);
53
+ }
54
+ }
55
+ };
56
+
57
+ /**
58
+ * @license
59
+ * Copyright (c) 2017 - 2023 Vaadin Ltd.
60
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
61
+ */
62
+
63
+ /**
64
+ * @typedef {Object} Theme
65
+ * @property {string} themeFor
66
+ * @property {CSSResult[]} styles
67
+ * @property {string | string[]} [include]
68
+ * @property {string} [moduleId]
69
+ *
70
+ * @typedef {CSSResult[] | CSSResult} CSSResultGroup
71
+ */
72
+
73
+ /**
74
+ * @type {Theme[]}
75
+ */
76
+ const themeRegistry = [];
77
+
78
+ /**
79
+ * Check if the custom element type has themes applied.
80
+ * @param {Function} elementClass
81
+ * @returns {boolean}
82
+ */
83
+ function classHasThemes$1(elementClass) {
84
+ return elementClass && Object.prototype.hasOwnProperty.call(elementClass, '__themes');
85
+ }
86
+
87
+ /**
88
+ * Check if the custom element type has themes applied.
89
+ * @param {string} tagName
90
+ * @returns {boolean}
91
+ */
92
+ function hasThemes$1(tagName) {
93
+ return classHasThemes$1(customElements.get(tagName));
94
+ }
95
+
96
+ /**
97
+ * Flattens the styles into a single array of styles.
98
+ * @param {CSSResultGroup} styles
99
+ * @param {CSSResult[]} result
100
+ * @returns {CSSResult[]}
101
+ */
102
+ function flattenStyles$1(styles = []) {
103
+ return [styles].flat(Infinity).filter((style) => {
104
+ if (style instanceof o) {
105
+ return true;
106
+ }
107
+ console.warn('An item in styles is not of type CSSResult. Use `unsafeCSS` or `css`.');
108
+ return false;
109
+ });
110
+ }
111
+
112
+ /**
113
+ * Registers CSS styles for a component type. Make sure to register the styles before
114
+ * the first instance of a component of the type is attached to DOM.
115
+ *
116
+ * @param {string} themeFor The local/tag name of the component type to register the styles for
117
+ * @param {CSSResultGroup} styles The CSS style rules to be registered for the component type
118
+ * matching themeFor and included in the local scope of each component instance
119
+ * @param {{moduleId?: string, include?: string | string[]}} options Additional options
120
+ * @return {void}
121
+ */
122
+ function registerStyles$1(themeFor, styles, options = {}) {
123
+ if (themeFor) {
124
+ if (hasThemes$1(themeFor)) {
125
+ console.warn(`The custom element definition for "${themeFor}"
126
+ was finalized before a style module was registered.
127
+ Make sure to add component specific style modules before
128
+ importing the corresponding custom element.`);
129
+ }
130
+ }
131
+
132
+ styles = flattenStyles$1(styles);
133
+
134
+ if (window.Vaadin && window.Vaadin.styleModules) {
135
+ window.Vaadin.styleModules.registerStyles(themeFor, styles, options);
136
+ } else {
137
+ themeRegistry.push({
138
+ themeFor,
139
+ styles,
140
+ include: options.include,
141
+ moduleId: options.moduleId,
142
+ });
143
+ }
144
+ }
145
+
146
+ /**
147
+ * Returns all registered themes. By default the themeRegistry is returned as is.
148
+ * In case the style-modules adapter is imported, the themes are obtained from there instead
149
+ * @returns {Theme[]}
150
+ */
151
+ function getAllThemes() {
152
+ if (window.Vaadin && window.Vaadin.styleModules) {
153
+ return window.Vaadin.styleModules.getAllThemes();
154
+ }
155
+ return themeRegistry;
156
+ }
157
+
158
+ /**
159
+ * Returns true if the themeFor string matches the tag name
160
+ * @param {string} themeFor
161
+ * @param {string} tagName
162
+ * @returns {boolean}
163
+ */
164
+ function matchesThemeFor(themeFor, tagName) {
165
+ return (themeFor || '').split(' ').some((themeForToken) => {
166
+ return new RegExp(`^${themeForToken.split('*').join('.*')}$`, 'u').test(tagName);
167
+ });
168
+ }
169
+
170
+ /**
171
+ * Maps the moduleName to an include priority number which is used for
172
+ * determining the order in which styles are applied.
173
+ * @param {string} moduleName
174
+ * @returns {number}
175
+ */
176
+ function getIncludePriority(moduleName = '') {
177
+ let includePriority = 0;
178
+ if (moduleName.startsWith('lumo-') || moduleName.startsWith('material-')) {
179
+ includePriority = 1;
180
+ } else if (moduleName.startsWith('vaadin-')) {
181
+ includePriority = 2;
182
+ }
183
+ return includePriority;
184
+ }
185
+
186
+ /**
187
+ * Gets an array of CSSResults matching the include property of the theme.
188
+ * @param {Theme} theme
189
+ * @returns {CSSResult[]}
190
+ */
191
+ function getIncludedStyles(theme) {
192
+ const includedStyles = [];
193
+ if (theme.include) {
194
+ [].concat(theme.include).forEach((includeModuleId) => {
195
+ const includedTheme = getAllThemes().find((s) => s.moduleId === includeModuleId);
196
+ if (includedTheme) {
197
+ includedStyles.push(...getIncludedStyles(includedTheme), ...includedTheme.styles);
198
+ } else {
199
+ console.warn(`Included moduleId ${includeModuleId} not found in style registry`);
200
+ }
201
+ }, theme.styles);
202
+ }
203
+ return includedStyles;
204
+ }
205
+
206
+ /**
207
+ * Includes the styles to the template.
208
+ * @param {CSSResult[]} styles
209
+ * @param {HTMLTemplateElement} template
210
+ */
211
+ function addStylesToTemplate(styles, template) {
212
+ const styleEl = document.createElement('style');
213
+ styleEl.innerHTML = styles.map((style) => style.cssText).join('\n');
214
+ template.content.appendChild(styleEl);
215
+ }
216
+
217
+ /**
218
+ * Returns an array of themes that should be used for styling a component matching
219
+ * the tag name. The array is sorted by the include order.
220
+ * @param {string} tagName
221
+ * @returns {Theme[]}
222
+ */
223
+ function getThemes(tagName) {
224
+ const defaultModuleName = `${tagName}-default-theme`;
225
+
226
+ const themes = getAllThemes()
227
+ // Filter by matching themeFor properties
228
+ .filter((theme) => theme.moduleId !== defaultModuleName && matchesThemeFor(theme.themeFor, tagName))
229
+ .map((theme) => ({
230
+ ...theme,
231
+ // Prepend styles from included themes
232
+ styles: [...getIncludedStyles(theme), ...theme.styles],
233
+ // Map moduleId to includePriority
234
+ includePriority: getIncludePriority(theme.moduleId),
235
+ }))
236
+ // Sort by includePriority
237
+ .sort((themeA, themeB) => themeB.includePriority - themeA.includePriority);
238
+
239
+ if (themes.length > 0) {
240
+ return themes;
241
+ }
242
+ // No theme modules found, return the default module if it exists
243
+ return getAllThemes().filter((theme) => theme.moduleId === defaultModuleName);
244
+ }
245
+
246
+ /**
247
+ * @polymerMixin
248
+ * @mixes ThemePropertyMixin
249
+ */
250
+ const ThemableMixin = (superClass) =>
251
+ class VaadinThemableMixin extends ThemePropertyMixin(superClass) {
252
+ /**
253
+ * Covers PolymerElement based component styling
254
+ * @protected
255
+ */
256
+ static finalize() {
257
+ super.finalize();
258
+
259
+ // Make sure not to run the logic intended for PolymerElement when LitElement is used.
260
+ if (this.elementStyles) {
261
+ return;
262
+ }
263
+
264
+ const template = this.prototype._template;
265
+ if (!template || classHasThemes$1(this)) {
266
+ return;
267
+ }
268
+
269
+ addStylesToTemplate(this.getStylesForThis(), template);
270
+ }
271
+
272
+ /**
273
+ * Covers LitElement based component styling
274
+ *
275
+ * @protected
276
+ */
277
+ static finalizeStyles(styles) {
278
+ // The "styles" object originates from the "static get styles()" function of
279
+ // a LitElement based component. The theme styles are added after it
280
+ // so that they can override the component styles.
281
+ const themeStyles = this.getStylesForThis();
282
+ return styles ? [...super.finalizeStyles(styles), ...themeStyles] : themeStyles;
283
+ }
284
+
285
+ /**
286
+ * Get styles for the component type
287
+ *
288
+ * @private
289
+ */
290
+ static getStylesForThis() {
291
+ const parent = Object.getPrototypeOf(this.prototype);
292
+ const inheritedThemes = (parent ? parent.constructor.__themes : []) || [];
293
+ this.__themes = [...inheritedThemes, ...getThemes(this.is)];
294
+ const themeStyles = this.__themes.flatMap((theme) => theme.styles);
295
+ // Remove duplicates
296
+ return themeStyles.filter((style, index) => index === themeStyles.lastIndexOf(style));
297
+ }
298
+ };
299
+
300
+ /**
301
+ * @license
302
+ * Copyright (c) 2017 - 2023 Vaadin Ltd.
303
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
304
+ */
305
+
306
+ registerStyles$1('vaadin-text-field', inputFieldShared, {
307
+ moduleId: 'lumo-text-field-styles',
308
+ });
309
+
310
+ /**
311
+ * @license
312
+ * Copyright (c) 2021 - 2023 Vaadin Ltd.
313
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
314
+ */
315
+ function defineCustomElement$2(CustomElement) {
316
+ const defined = customElements.get(CustomElement.is);
317
+ if (!defined) {
318
+ customElements.define(CustomElement.is, CustomElement);
319
+ } else {
320
+ const definedVersion = defined.version;
321
+ if (definedVersion && CustomElement.version && definedVersion === CustomElement.version) {
322
+ // Just loading the same thing again
323
+ console.warn(`The component ${CustomElement.is} has been loaded twice`);
324
+ } else {
325
+ console.error(
326
+ `Tried to define ${CustomElement.is} version ${CustomElement.version} when version ${defined.version} is already in use. Something will probably break.`,
327
+ );
328
+ }
329
+ }
330
+ }
331
+
332
+ /**
333
+ * @license
334
+ * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
335
+ * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
336
+ * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
337
+ * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
338
+ * Code distributed by Google as part of the polymer project is also
339
+ * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
340
+ */
341
+
342
+ /**
343
+ * Async interface wrapper around `requestIdleCallback`. Falls back to
344
+ * `setTimeout` on browsers that do not support `requestIdleCallback`.
345
+ *
346
+ * @namespace
347
+ * @summary Async interface wrapper around `requestIdleCallback`.
348
+ */
349
+ const idlePeriod = {
350
+ /**
351
+ * Enqueues a function called at `requestIdleCallback` timing.
352
+ *
353
+ * @memberof idlePeriod
354
+ * @param {function(!IdleDeadline):void} fn Callback to run
355
+ * @return {number} Handle used for canceling task
356
+ */
357
+ run(fn) {
358
+ return window.requestIdleCallback ? window.requestIdleCallback(fn) : window.setTimeout(fn, 16);
359
+ },
360
+ /**
361
+ * Cancels a previously enqueued `idlePeriod` callback.
362
+ *
363
+ * @memberof idlePeriod
364
+ * @param {number} handle Handle returned from `run` of callback to cancel
365
+ * @return {void}
366
+ */
367
+ cancel(handle) {
368
+ if (window.cancelIdleCallback) {
369
+ window.cancelIdleCallback(handle);
370
+ } else {
371
+ window.clearTimeout(handle);
372
+ }
373
+ },
374
+ };
375
+
376
+ /**
377
+ @license
378
+ Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
379
+ This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
380
+ The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
381
+ The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
382
+ Code distributed by Google as part of the polymer project is also
383
+ subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
384
+ */
385
+
386
+ const debouncerQueue = new Set();
387
+
388
+ /**
389
+ * @summary Collapse multiple callbacks into one invocation after a timer.
390
+ */
391
+ class Debouncer {
392
+ /**
393
+ * Creates a debouncer if no debouncer is passed as a parameter
394
+ * or it cancels an active debouncer otherwise. The following
395
+ * example shows how a debouncer can be called multiple times within a
396
+ * microtask and "debounced" such that the provided callback function is
397
+ * called once. Add this method to a custom element:
398
+ *
399
+ * ```js
400
+ * import {microTask} from '@vaadin/component-base/src/async.js';
401
+ * import {Debouncer} from '@vaadin/component-base/src/debounce.js';
402
+ * // ...
403
+ *
404
+ * _debounceWork() {
405
+ * this._debounceJob = Debouncer.debounce(this._debounceJob,
406
+ * microTask, () => this._doWork());
407
+ * }
408
+ * ```
409
+ *
410
+ * If the `_debounceWork` method is called multiple times within the same
411
+ * microtask, the `_doWork` function will be called only once at the next
412
+ * microtask checkpoint.
413
+ *
414
+ * Note: In testing it is often convenient to avoid asynchrony. To accomplish
415
+ * this with a debouncer, you can use `enqueueDebouncer` and
416
+ * `flush`. For example, extend the above example by adding
417
+ * `enqueueDebouncer(this._debounceJob)` at the end of the
418
+ * `_debounceWork` method. Then in a test, call `flush` to ensure
419
+ * the debouncer has completed.
420
+ *
421
+ * @param {Debouncer?} debouncer Debouncer object.
422
+ * @param {!AsyncInterface} asyncModule Object with Async interface
423
+ * @param {function()} callback Callback to run.
424
+ * @return {!Debouncer} Returns a debouncer object.
425
+ */
426
+ static debounce(debouncer, asyncModule, callback) {
427
+ if (debouncer instanceof Debouncer) {
428
+ // Cancel the async callback, but leave in debouncerQueue if it was
429
+ // enqueued, to maintain 1.x flush order
430
+ debouncer._cancelAsync();
431
+ } else {
432
+ debouncer = new Debouncer();
433
+ }
434
+ debouncer.setConfig(asyncModule, callback);
435
+ return debouncer;
436
+ }
437
+
438
+ constructor() {
439
+ this._asyncModule = null;
440
+ this._callback = null;
441
+ this._timer = null;
442
+ }
443
+
444
+ /**
445
+ * Sets the scheduler; that is, a module with the Async interface,
446
+ * a callback and optional arguments to be passed to the run function
447
+ * from the async module.
448
+ *
449
+ * @param {!AsyncInterface} asyncModule Object with Async interface.
450
+ * @param {function()} callback Callback to run.
451
+ * @return {void}
452
+ */
453
+ setConfig(asyncModule, callback) {
454
+ this._asyncModule = asyncModule;
455
+ this._callback = callback;
456
+ this._timer = this._asyncModule.run(() => {
457
+ this._timer = null;
458
+ debouncerQueue.delete(this);
459
+ this._callback();
460
+ });
461
+ }
462
+
463
+ /**
464
+ * Cancels an active debouncer and returns a reference to itself.
465
+ *
466
+ * @return {void}
467
+ */
468
+ cancel() {
469
+ if (this.isActive()) {
470
+ this._cancelAsync();
471
+ // Canceling a debouncer removes its spot from the flush queue,
472
+ // so if a debouncer is manually canceled and re-debounced, it
473
+ // will reset its flush order (this is a very minor difference from 1.x)
474
+ // Re-debouncing via the `debounce` API retains the 1.x FIFO flush order
475
+ debouncerQueue.delete(this);
476
+ }
477
+ }
478
+
479
+ /**
480
+ * Cancels a debouncer's async callback.
481
+ *
482
+ * @return {void}
483
+ */
484
+ _cancelAsync() {
485
+ if (this.isActive()) {
486
+ this._asyncModule.cancel(/** @type {number} */ (this._timer));
487
+ this._timer = null;
488
+ }
489
+ }
490
+
491
+ /**
492
+ * Flushes an active debouncer and returns a reference to itself.
493
+ *
494
+ * @return {void}
495
+ */
496
+ flush() {
497
+ if (this.isActive()) {
498
+ this.cancel();
499
+ this._callback();
500
+ }
501
+ }
502
+
503
+ /**
504
+ * Returns true if the debouncer is active.
505
+ *
506
+ * @return {boolean} True if active.
507
+ */
508
+ isActive() {
509
+ return this._timer != null;
510
+ }
511
+ }
512
+
513
+ /**
514
+ * Adds a `Debouncer` to a list of globally flushable tasks.
515
+ *
516
+ * @param {!Debouncer} debouncer Debouncer to enqueue
517
+ * @return {void}
518
+ */
519
+ function enqueueDebouncer(debouncer) {
520
+ debouncerQueue.add(debouncer);
521
+ }
522
+
523
+ /**
524
+ * @license
525
+ * Copyright (c) 2021 - 2023 Vaadin Ltd.
526
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
527
+ */
528
+
529
+ /**
530
+ * Array of Vaadin custom element classes that have been subscribed to the dir changes.
531
+ */
532
+ const directionSubscribers = [];
533
+
534
+ function alignDirs(element, documentDir, elementDir = element.getAttribute('dir')) {
535
+ if (documentDir) {
536
+ element.setAttribute('dir', documentDir);
537
+ } else if (elementDir != null) {
538
+ element.removeAttribute('dir');
539
+ }
540
+ }
541
+
542
+ function getDocumentDir() {
543
+ return document.documentElement.getAttribute('dir');
544
+ }
545
+
546
+ function directionUpdater() {
547
+ const documentDir = getDocumentDir();
548
+ directionSubscribers.forEach((element) => {
549
+ alignDirs(element, documentDir);
550
+ });
551
+ }
552
+
553
+ const directionObserver = new MutationObserver(directionUpdater);
554
+ directionObserver.observe(document.documentElement, { attributes: true, attributeFilter: ['dir'] });
555
+
556
+ /**
557
+ * A mixin to handle `dir` attribute based on the one set on the `<html>` element.
558
+ *
559
+ * @polymerMixin
560
+ */
561
+ const DirMixin = (superClass) =>
562
+ class VaadinDirMixin extends superClass {
563
+ static get properties() {
564
+ return {
565
+ /**
566
+ * @protected
567
+ */
568
+ dir: {
569
+ type: String,
570
+ value: '',
571
+ reflectToAttribute: true,
572
+ converter: {
573
+ fromAttribute: (attr) => {
574
+ return !attr ? '' : attr;
575
+ },
576
+ toAttribute: (prop) => {
577
+ return prop === '' ? null : prop;
578
+ },
579
+ },
580
+ },
581
+ };
582
+ }
583
+
584
+ /**
585
+ * @return {boolean}
586
+ * @protected
587
+ */
588
+ get __isRTL() {
589
+ return this.getAttribute('dir') === 'rtl';
590
+ }
591
+
592
+ /** @protected */
593
+ connectedCallback() {
594
+ super.connectedCallback();
595
+
596
+ if (!this.hasAttribute('dir') || this.__restoreSubscription) {
597
+ this.__subscribe();
598
+ alignDirs(this, getDocumentDir(), null);
599
+ }
600
+ }
601
+
602
+ /** @protected */
603
+ attributeChangedCallback(name, oldValue, newValue) {
604
+ super.attributeChangedCallback(name, oldValue, newValue);
605
+ if (name !== 'dir') {
606
+ return;
607
+ }
608
+
609
+ const documentDir = getDocumentDir();
610
+
611
+ // New value equals to the document direction and the element is not subscribed to the changes
612
+ const newValueEqlDocDir = newValue === documentDir && directionSubscribers.indexOf(this) === -1;
613
+ // Value was emptied and the element is not subscribed to the changes
614
+ const newValueEmptied = !newValue && oldValue && directionSubscribers.indexOf(this) === -1;
615
+ // New value is different and the old equals to document direction and the element is not subscribed to the changes
616
+ const newDiffValue = newValue !== documentDir && oldValue === documentDir;
617
+
618
+ if (newValueEqlDocDir || newValueEmptied) {
619
+ this.__subscribe();
620
+ alignDirs(this, documentDir, newValue);
621
+ } else if (newDiffValue) {
622
+ this.__unsubscribe();
623
+ }
624
+ }
625
+
626
+ /** @protected */
627
+ disconnectedCallback() {
628
+ super.disconnectedCallback();
629
+ this.__restoreSubscription = directionSubscribers.includes(this);
630
+ this.__unsubscribe();
631
+ }
632
+
633
+ /** @protected */
634
+ _valueToNodeAttribute(node, value, attribute) {
635
+ // Override default Polymer attribute reflection to match native behavior of HTMLElement.dir property
636
+ // If the property contains an empty string then it should not create an empty attribute
637
+ if (attribute === 'dir' && value === '' && !node.hasAttribute('dir')) {
638
+ return;
639
+ }
640
+ super._valueToNodeAttribute(node, value, attribute);
641
+ }
642
+
643
+ /** @protected */
644
+ _attributeToProperty(attribute, value, type) {
645
+ // Override default Polymer attribute reflection to match native behavior of HTMLElement.dir property
646
+ // If the attribute is removed, then the dir property should contain an empty string instead of null
647
+ if (attribute === 'dir' && !value) {
648
+ this.dir = '';
649
+ } else {
650
+ super._attributeToProperty(attribute, value, type);
651
+ }
652
+ }
653
+
654
+ /** @private */
655
+ __subscribe() {
656
+ if (!directionSubscribers.includes(this)) {
657
+ directionSubscribers.push(this);
658
+ }
659
+ }
660
+
661
+ /** @private */
662
+ __unsubscribe() {
663
+ if (directionSubscribers.includes(this)) {
664
+ directionSubscribers.splice(directionSubscribers.indexOf(this), 1);
665
+ }
666
+ }
667
+ };
668
+
669
+ /**
670
+ * @license
671
+ * Copyright (c) 2021 - 2023 Vaadin Ltd.
672
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
673
+ */
674
+
675
+ if (!window.Vaadin) {
676
+ window.Vaadin = {};
677
+ }
678
+
679
+ /**
680
+ * Array of Vaadin custom element classes that have been finalized.
681
+ */
682
+ if (!window.Vaadin.registrations) {
683
+ window.Vaadin.registrations = [];
684
+ }
685
+
686
+ if (!window.Vaadin.developmentModeCallback) {
687
+ window.Vaadin.developmentModeCallback = {};
688
+ }
689
+
690
+ window.Vaadin.developmentModeCallback['vaadin-usage-statistics'] = function () {
691
+ usageStatistics();
692
+ };
693
+
694
+ let statsJob;
695
+
696
+ const registered = new Set();
697
+
698
+ /**
699
+ * @polymerMixin
700
+ * @mixes DirMixin
701
+ */
702
+ const ElementMixin = (superClass) =>
703
+ class VaadinElementMixin extends DirMixin(superClass) {
704
+ static get version() {
705
+ return '24.2.3';
706
+ }
707
+
708
+ /** @protected */
709
+ static finalize() {
710
+ super.finalize();
711
+
712
+ const { is } = this;
713
+
714
+ // Registers a class prototype for telemetry purposes.
715
+ if (is && !registered.has(is)) {
716
+ window.Vaadin.registrations.push(this);
717
+ registered.add(is);
718
+
719
+ if (window.Vaadin.developmentModeCallback) {
720
+ statsJob = Debouncer.debounce(statsJob, idlePeriod, () => {
721
+ window.Vaadin.developmentModeCallback['vaadin-usage-statistics']();
722
+ });
723
+ enqueueDebouncer(statsJob);
724
+ }
725
+ }
726
+ }
727
+
728
+ constructor() {
729
+ super();
730
+
731
+ if (document.doctype === null) {
732
+ console.warn(
733
+ 'Vaadin components require the "standards mode" declaration. Please add <!DOCTYPE html> to the HTML document.',
734
+ );
735
+ }
736
+ }
737
+ };
738
+
739
+ /**
740
+ * @license
741
+ * Copyright (c) 2021 - 2023 Vaadin Ltd.
742
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
743
+ */
744
+
745
+ /**
746
+ * Returns true if the given node is an empty text node, false otherwise.
747
+ *
748
+ * @param {Node} node
749
+ * @return {boolean}
750
+ */
751
+ function isEmptyTextNode$1(node) {
752
+ return node.nodeType === Node.TEXT_NODE && node.textContent.trim() === '';
753
+ }
754
+
755
+ /**
756
+ * @license
757
+ * Copyright (c) 2023 Vaadin Ltd.
758
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
759
+ */
760
+
761
+ /**
762
+ * A helper for observing slot changes.
763
+ */
764
+ class SlotObserver$1 {
765
+ constructor(slot, callback) {
766
+ /** @type HTMLSlotElement */
767
+ this.slot = slot;
768
+
769
+ /** @type Function */
770
+ this.callback = callback;
771
+
772
+ /** @type {Node[]} */
773
+ this._storedNodes = [];
774
+
775
+ this._connected = false;
776
+ this._scheduled = false;
777
+
778
+ this._boundSchedule = () => {
779
+ this._schedule();
780
+ };
781
+
782
+ this.connect();
783
+ this._schedule();
784
+ }
785
+
786
+ /**
787
+ * Activates an observer. This method is automatically called when
788
+ * a `SlotObserver` is created. It should only be called to re-activate
789
+ * an observer that has been deactivated via the `disconnect` method.
790
+ */
791
+ connect() {
792
+ this.slot.addEventListener('slotchange', this._boundSchedule);
793
+ this._connected = true;
794
+ }
795
+
796
+ /**
797
+ * Deactivates the observer. After calling this method the observer callback
798
+ * will not be called when changes to slotted nodes occur. The `connect` method
799
+ * may be subsequently called to reactivate the observer.
800
+ */
801
+ disconnect() {
802
+ this.slot.removeEventListener('slotchange', this._boundSchedule);
803
+ this._connected = false;
804
+ }
805
+
806
+ /** @private */
807
+ _schedule() {
808
+ if (!this._scheduled) {
809
+ this._scheduled = true;
810
+
811
+ queueMicrotask(() => {
812
+ this.flush();
813
+ });
814
+ }
815
+ }
816
+
817
+ /**
818
+ * Run the observer callback synchronously.
819
+ */
820
+ flush() {
821
+ if (!this._connected) {
822
+ return;
823
+ }
824
+
825
+ this._scheduled = false;
826
+
827
+ this._processNodes();
828
+ }
829
+
830
+ /** @private */
831
+ _processNodes() {
832
+ const currentNodes = this.slot.assignedNodes({ flatten: true });
833
+
834
+ let addedNodes = [];
835
+ const removedNodes = [];
836
+ const movedNodes = [];
837
+
838
+ if (currentNodes.length) {
839
+ addedNodes = currentNodes.filter((node) => !this._storedNodes.includes(node));
840
+ }
841
+
842
+ if (this._storedNodes.length) {
843
+ this._storedNodes.forEach((node, index) => {
844
+ const idx = currentNodes.indexOf(node);
845
+ if (idx === -1) {
846
+ removedNodes.push(node);
847
+ } else if (idx !== index) {
848
+ movedNodes.push(node);
849
+ }
850
+ });
851
+ }
852
+
853
+ if (addedNodes.length || removedNodes.length || movedNodes.length) {
854
+ this.callback({ addedNodes, movedNodes, removedNodes });
855
+ }
856
+
857
+ this._storedNodes = currentNodes;
858
+ }
859
+ }
860
+
861
+ /**
862
+ * @license
863
+ * Copyright (c) 2021 - 2023 Vaadin Ltd.
11
864
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
12
865
  */
13
866
 
14
- registerStyles('vaadin-text-field', inputFieldShared, {
15
- moduleId: 'lumo-text-field-styles',
16
- });
867
+ let uniqueId$1 = 0;
868
+
869
+ /**
870
+ * Returns a unique integer id.
871
+ *
872
+ * @return {number}
873
+ */
874
+ function generateUniqueId$1() {
875
+ // eslint-disable-next-line no-plusplus
876
+ return uniqueId$1++;
877
+ }
878
+
879
+ /**
880
+ * @license
881
+ * Copyright (c) 2021 - 2023 Vaadin Ltd.
882
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
883
+ */
884
+
885
+ /**
886
+ * A controller for providing content to slot element and observing changes.
887
+ */
888
+ class SlotController$1 extends EventTarget {
889
+ /**
890
+ * Ensure that every instance has unique ID.
891
+ *
892
+ * @param {HTMLElement} host
893
+ * @param {string} slotName
894
+ * @return {string}
895
+ * @protected
896
+ */
897
+ static generateId(host, slotName) {
898
+ const prefix = slotName || 'default';
899
+ return `${prefix}-${host.localName}-${generateUniqueId$1()}`;
900
+ }
901
+
902
+ constructor(host, slotName, tagName, config = {}) {
903
+ super();
904
+
905
+ const { initializer, multiple, observe, useUniqueId } = config;
906
+
907
+ this.host = host;
908
+ this.slotName = slotName;
909
+ this.tagName = tagName;
910
+ this.observe = typeof observe === 'boolean' ? observe : true;
911
+ this.multiple = typeof multiple === 'boolean' ? multiple : false;
912
+ this.slotInitializer = initializer;
913
+
914
+ if (multiple) {
915
+ this.nodes = [];
916
+ }
917
+
918
+ // Only generate the default ID if requested by the controller.
919
+ if (useUniqueId) {
920
+ this.defaultId = this.constructor.generateId(host, slotName);
921
+ }
922
+ }
923
+
924
+ hostConnected() {
925
+ if (!this.initialized) {
926
+ if (this.multiple) {
927
+ this.initMultiple();
928
+ } else {
929
+ this.initSingle();
930
+ }
931
+
932
+ if (this.observe) {
933
+ this.observeSlot();
934
+ }
935
+
936
+ this.initialized = true;
937
+ }
938
+ }
939
+
940
+ /** @protected */
941
+ initSingle() {
942
+ let node = this.getSlotChild();
943
+
944
+ if (!node) {
945
+ node = this.attachDefaultNode();
946
+ this.initNode(node);
947
+ } else {
948
+ this.node = node;
949
+ this.initAddedNode(node);
950
+ }
951
+ }
952
+
953
+ /** @protected */
954
+ initMultiple() {
955
+ const children = this.getSlotChildren();
956
+
957
+ if (children.length === 0) {
958
+ const defaultNode = this.attachDefaultNode();
959
+ if (defaultNode) {
960
+ this.nodes = [defaultNode];
961
+ this.initNode(defaultNode);
962
+ }
963
+ } else {
964
+ this.nodes = children;
965
+ children.forEach((node) => {
966
+ this.initAddedNode(node);
967
+ });
968
+ }
969
+ }
970
+
971
+ /**
972
+ * Create and attach default node using the provided tag name, if any.
973
+ * @return {Node | undefined}
974
+ * @protected
975
+ */
976
+ attachDefaultNode() {
977
+ const { host, slotName, tagName } = this;
978
+
979
+ // Check if the node was created previously and if so, reuse it.
980
+ let node = this.defaultNode;
981
+
982
+ // Tag name is optional, sometimes we don't init default content.
983
+ if (!node && tagName) {
984
+ node = document.createElement(tagName);
985
+ if (node instanceof Element) {
986
+ if (slotName !== '') {
987
+ node.setAttribute('slot', slotName);
988
+ }
989
+ this.node = node;
990
+ this.defaultNode = node;
991
+ }
992
+ }
993
+
994
+ if (node) {
995
+ host.appendChild(node);
996
+ }
997
+
998
+ return node;
999
+ }
1000
+
1001
+ /**
1002
+ * Return the list of nodes matching the slot managed by the controller.
1003
+ * @return {Node}
1004
+ */
1005
+ getSlotChildren() {
1006
+ const { slotName } = this;
1007
+ return Array.from(this.host.childNodes).filter((node) => {
1008
+ // Either an element (any slot) or a text node (only un-named slot).
1009
+ return (
1010
+ (node.nodeType === Node.ELEMENT_NODE && node.slot === slotName) ||
1011
+ (node.nodeType === Node.TEXT_NODE && node.textContent.trim() && slotName === '')
1012
+ );
1013
+ });
1014
+ }
1015
+
1016
+ /**
1017
+ * Return a reference to the node managed by the controller.
1018
+ * @return {Node}
1019
+ */
1020
+ getSlotChild() {
1021
+ return this.getSlotChildren()[0];
1022
+ }
1023
+
1024
+ /**
1025
+ * Run `slotInitializer` for the node managed by the controller.
1026
+ *
1027
+ * @param {Node} node
1028
+ * @protected
1029
+ */
1030
+ initNode(node) {
1031
+ const { slotInitializer } = this;
1032
+ // Don't try to bind `this` to initializer (normally it's arrow function).
1033
+ // Instead, pass the host as a first argument to access component's state.
1034
+ if (slotInitializer) {
1035
+ slotInitializer(node, this.host);
1036
+ }
1037
+ }
1038
+
1039
+ /**
1040
+ * Override to initialize the newly added custom node.
1041
+ *
1042
+ * @param {Node} _node
1043
+ * @protected
1044
+ */
1045
+ initCustomNode(_node) {}
1046
+
1047
+ /**
1048
+ * Override to teardown slotted node when it's removed.
1049
+ *
1050
+ * @param {Node} _node
1051
+ * @protected
1052
+ */
1053
+ teardownNode(_node) {}
1054
+
1055
+ /**
1056
+ * Run both `initCustomNode` and `initNode` for a custom slotted node.
1057
+ *
1058
+ * @param {Node} node
1059
+ * @protected
1060
+ */
1061
+ initAddedNode(node) {
1062
+ if (node !== this.defaultNode) {
1063
+ this.initCustomNode(node);
1064
+ this.initNode(node);
1065
+ }
1066
+ }
1067
+
1068
+ /**
1069
+ * Setup the observer to manage slot content changes.
1070
+ * @protected
1071
+ */
1072
+ observeSlot() {
1073
+ const { slotName } = this;
1074
+ const selector = slotName === '' ? 'slot:not([name])' : `slot[name=${slotName}]`;
1075
+ const slot = this.host.shadowRoot.querySelector(selector);
1076
+
1077
+ this.__slotObserver = new SlotObserver$1(slot, ({ addedNodes, removedNodes }) => {
1078
+ const current = this.multiple ? this.nodes : [this.node];
1079
+
1080
+ // Calling `slot.assignedNodes()` includes whitespace text nodes in case of default slot:
1081
+ // unlike comment nodes, they are not filtered out. So we need to manually ignore them.
1082
+ const newNodes = addedNodes.filter((node) => !isEmptyTextNode$1(node) && !current.includes(node));
1083
+
1084
+ if (removedNodes.length) {
1085
+ this.nodes = current.filter((node) => !removedNodes.includes(node));
1086
+
1087
+ removedNodes.forEach((node) => {
1088
+ this.teardownNode(node);
1089
+ });
1090
+ }
1091
+
1092
+ if (newNodes && newNodes.length > 0) {
1093
+ if (this.multiple) {
1094
+ // Remove default node if exists
1095
+ if (this.defaultNode) {
1096
+ this.defaultNode.remove();
1097
+ }
1098
+ this.nodes = [...current, ...newNodes].filter((node) => node !== this.defaultNode);
1099
+ newNodes.forEach((node) => {
1100
+ this.initAddedNode(node);
1101
+ });
1102
+ } else {
1103
+ // Remove previous node if exists
1104
+ if (this.node) {
1105
+ this.node.remove();
1106
+ }
1107
+ this.node = newNodes[0];
1108
+ this.initAddedNode(this.node);
1109
+ }
1110
+ }
1111
+ });
1112
+ }
1113
+ }
1114
+
1115
+ /**
1116
+ * @license
1117
+ * Copyright (c) 2022 - 2023 Vaadin Ltd.
1118
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
1119
+ */
1120
+
1121
+ /**
1122
+ * A controller that manages the slotted tooltip element.
1123
+ */
1124
+ class TooltipController extends SlotController$1 {
1125
+ constructor(host) {
1126
+ // Do not provide slot factory to create tooltip lazily.
1127
+ super(host, 'tooltip');
1128
+
1129
+ this.setTarget(host);
1130
+ }
1131
+
1132
+ /**
1133
+ * Override to initialize the newly added custom tooltip.
1134
+ *
1135
+ * @param {Node} tooltipNode
1136
+ * @protected
1137
+ * @override
1138
+ */
1139
+ initCustomNode(tooltipNode) {
1140
+ tooltipNode.target = this.target;
1141
+
1142
+ if (this.ariaTarget !== undefined) {
1143
+ tooltipNode.ariaTarget = this.ariaTarget;
1144
+ }
1145
+
1146
+ if (this.context !== undefined) {
1147
+ tooltipNode.context = this.context;
1148
+ }
1149
+
1150
+ if (this.manual !== undefined) {
1151
+ tooltipNode.manual = this.manual;
1152
+ }
1153
+
1154
+ if (this.opened !== undefined) {
1155
+ tooltipNode.opened = this.opened;
1156
+ }
1157
+
1158
+ if (this.position !== undefined) {
1159
+ tooltipNode._position = this.position;
1160
+ }
1161
+
1162
+ if (this.shouldShow !== undefined) {
1163
+ tooltipNode.shouldShow = this.shouldShow;
1164
+ }
1165
+
1166
+ this.__notifyChange();
1167
+ }
1168
+
1169
+ /**
1170
+ * Override to notify the host when the tooltip is removed.
1171
+ *
1172
+ * @param {Node} tooltipNode
1173
+ * @protected
1174
+ * @override
1175
+ */
1176
+ teardownNode() {
1177
+ this.__notifyChange();
1178
+ }
1179
+
1180
+ /**
1181
+ * Set an HTML element for linking with the tooltip overlay
1182
+ * via `aria-describedby` attribute used by screen readers.
1183
+ * @param {HTMLElement} ariaTarget
1184
+ */
1185
+ setAriaTarget(ariaTarget) {
1186
+ this.ariaTarget = ariaTarget;
1187
+
1188
+ const tooltipNode = this.node;
1189
+ if (tooltipNode) {
1190
+ tooltipNode.ariaTarget = ariaTarget;
1191
+ }
1192
+ }
1193
+
1194
+ /**
1195
+ * Set a context object to be used by generator.
1196
+ * @param {object} context
1197
+ */
1198
+ setContext(context) {
1199
+ this.context = context;
1200
+
1201
+ const tooltipNode = this.node;
1202
+ if (tooltipNode) {
1203
+ tooltipNode.context = context;
1204
+ }
1205
+ }
1206
+
1207
+ /**
1208
+ * Toggle manual state on the slotted tooltip.
1209
+ * @param {boolean} manual
1210
+ */
1211
+ setManual(manual) {
1212
+ this.manual = manual;
1213
+
1214
+ const tooltipNode = this.node;
1215
+ if (tooltipNode) {
1216
+ tooltipNode.manual = manual;
1217
+ }
1218
+ }
1219
+
1220
+ /**
1221
+ * Toggle opened state on the slotted tooltip.
1222
+ * @param {boolean} opened
1223
+ */
1224
+ setOpened(opened) {
1225
+ this.opened = opened;
1226
+
1227
+ const tooltipNode = this.node;
1228
+ if (tooltipNode) {
1229
+ tooltipNode.opened = opened;
1230
+ }
1231
+ }
1232
+
1233
+ /**
1234
+ * Set default position for the slotted tooltip.
1235
+ * This can be overridden by setting the position
1236
+ * using corresponding property or attribute.
1237
+ * @param {string} position
1238
+ */
1239
+ setPosition(position) {
1240
+ this.position = position;
1241
+
1242
+ const tooltipNode = this.node;
1243
+ if (tooltipNode) {
1244
+ tooltipNode._position = position;
1245
+ }
1246
+ }
1247
+
1248
+ /**
1249
+ * Set function used to detect whether to show
1250
+ * the tooltip based on a condition.
1251
+ * @param {Function} shouldShow
1252
+ */
1253
+ setShouldShow(shouldShow) {
1254
+ this.shouldShow = shouldShow;
1255
+
1256
+ const tooltipNode = this.node;
1257
+ if (tooltipNode) {
1258
+ tooltipNode.shouldShow = shouldShow;
1259
+ }
1260
+ }
1261
+
1262
+ /**
1263
+ * Set an HTML element to attach the tooltip to.
1264
+ * @param {HTMLElement} target
1265
+ */
1266
+ setTarget(target) {
1267
+ this.target = target;
1268
+
1269
+ const tooltipNode = this.node;
1270
+ if (tooltipNode) {
1271
+ tooltipNode.target = target;
1272
+ }
1273
+ }
1274
+
1275
+ /** @private */
1276
+ __notifyChange() {
1277
+ this.dispatchEvent(new CustomEvent('tooltip-changed', { detail: { node: this.node } }));
1278
+ }
1279
+ }
17
1280
 
18
1281
  /**
19
1282
  * @license
20
- * Copyright (c) 2021 - 2022 Vaadin Ltd.
1283
+ * Copyright (c) 2021 - 2023 Vaadin Ltd.
21
1284
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
22
1285
  */
23
1286
 
@@ -71,6 +1334,15 @@ const InputFieldMixin = (superclass) =>
71
1334
  return [...super.delegateAttrs, 'autocapitalize', 'autocomplete', 'autocorrect'];
72
1335
  }
73
1336
 
1337
+ // Workaround for https://github.com/Polymer/polymer/issues/5259
1338
+ get __data() {
1339
+ return this.__dataValue || {};
1340
+ }
1341
+
1342
+ set __data(value) {
1343
+ this.__dataValue = value;
1344
+ }
1345
+
74
1346
  /**
75
1347
  * @param {HTMLElement} input
76
1348
  * @protected
@@ -92,15 +1364,6 @@ const InputFieldMixin = (superclass) =>
92
1364
  }
93
1365
  }
94
1366
 
95
- // Workaround for https://github.com/Polymer/polymer/issues/5259
96
- get __data() {
97
- return this.__dataValue || {};
98
- }
99
-
100
- set __data(value) {
101
- this.__dataValue = value;
102
- }
103
-
104
1367
  /**
105
1368
  * Override an event listener from `FocusMixin`.
106
1369
  * @param {boolean} focused
@@ -110,7 +1373,9 @@ const InputFieldMixin = (superclass) =>
110
1373
  _setFocused(focused) {
111
1374
  super._setFocused(focused);
112
1375
 
113
- if (!focused) {
1376
+ // Do not validate when focusout is caused by document
1377
+ // losing focus, which happens on browser tab switch.
1378
+ if (!focused && document.hasFocus()) {
114
1379
  this.validate();
115
1380
  }
116
1381
  }
@@ -130,35 +1395,109 @@ const InputFieldMixin = (superclass) =>
130
1395
  }
131
1396
  }
132
1397
 
133
- /**
134
- * Override an observer from `InputMixin` to validate the field
135
- * when a new value is set programmatically.
136
- *
137
- * @param {string | undefined} newValue
138
- * @param {string | undefined} oldValue
139
- * @protected
140
- * @override
141
- */
142
- _valueChanged(newValue, oldValue) {
143
- super._valueChanged(newValue, oldValue);
1398
+ /**
1399
+ * Override an observer from `InputMixin` to validate the field
1400
+ * when a new value is set programmatically.
1401
+ *
1402
+ * @param {string | undefined} newValue
1403
+ * @param {string | undefined} oldValue
1404
+ * @protected
1405
+ * @override
1406
+ */
1407
+ _valueChanged(newValue, oldValue) {
1408
+ super._valueChanged(newValue, oldValue);
1409
+
1410
+ if (oldValue === undefined) {
1411
+ return;
1412
+ }
1413
+
1414
+ if (this.invalid) {
1415
+ this.validate();
1416
+ }
1417
+ }
1418
+ };
1419
+
1420
+ /**
1421
+ * @license
1422
+ * Copyright (c) 2021 - 2023 Vaadin Ltd.
1423
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
1424
+ */
1425
+
1426
+ /**
1427
+ * A mixin providing common text field functionality.
1428
+ *
1429
+ * @polymerMixin
1430
+ * @mixes InputFieldMixin
1431
+ */
1432
+ const TextFieldMixin = (superClass) =>
1433
+ class TextFieldMixinClass extends InputFieldMixin(superClass) {
1434
+ static get properties() {
1435
+ return {
1436
+ /**
1437
+ * Maximum number of characters (in Unicode code points) that the user can enter.
1438
+ */
1439
+ maxlength: {
1440
+ type: Number,
1441
+ },
1442
+
1443
+ /**
1444
+ * Minimum number of characters (in Unicode code points) that the user can enter.
1445
+ */
1446
+ minlength: {
1447
+ type: Number,
1448
+ },
1449
+
1450
+ /**
1451
+ * A regular expression that the value is checked against.
1452
+ * The pattern must match the entire value, not just some subset.
1453
+ */
1454
+ pattern: {
1455
+ type: String,
1456
+ },
1457
+ };
1458
+ }
1459
+
1460
+ static get delegateAttrs() {
1461
+ return [...super.delegateAttrs, 'maxlength', 'minlength', 'pattern'];
1462
+ }
1463
+
1464
+ static get constraints() {
1465
+ return [...super.constraints, 'maxlength', 'minlength', 'pattern'];
1466
+ }
144
1467
 
145
- if (oldValue === undefined) {
146
- return;
147
- }
1468
+ constructor() {
1469
+ super();
1470
+ this._setType('text');
1471
+ }
148
1472
 
149
- if (this.invalid) {
150
- this.validate();
151
- }
1473
+ /** @protected */
1474
+ get clearElement() {
1475
+ return this.$.clearButton;
1476
+ }
1477
+
1478
+ /** @protected */
1479
+ ready() {
1480
+ super.ready();
1481
+
1482
+ this.addController(
1483
+ new InputController(this, (input) => {
1484
+ this._setInputElement(input);
1485
+ this._setFocusElement(input);
1486
+ this.stateTarget = input;
1487
+ this.ariaTarget = input;
1488
+ }),
1489
+ );
1490
+ this.addController(new LabelledInputController(this.inputElement, this._labelController));
152
1491
  }
153
1492
  };
154
1493
 
155
1494
  /**
156
1495
  * @license
157
- * Copyright (c) 2017 - 2022 Vaadin Ltd.
1496
+ * Copyright (c) 2017 - 2023 Vaadin Ltd.
158
1497
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
159
1498
  */
160
1499
 
161
- registerStyles('vaadin-text-field', inputFieldShared$1, { moduleId: 'vaadin-text-field-styles' });
1500
+ registerStyles$1('vaadin-text-field', inputFieldShared$1, { moduleId: 'vaadin-text-field-styles' });
162
1501
 
163
1502
  /**
164
1503
  * `<vaadin-text-field>` is a web component that allows the user to input and edit text.
@@ -215,7 +1554,7 @@ registerStyles('vaadin-text-field', inputFieldShared$1, { moduleId: 'vaadin-text
215
1554
  * `focus-ring` | Set when the element is keyboard focused | :host
216
1555
  * `readonly` | Set to a readonly text field | :host
217
1556
  *
218
- * See [Styling Components](https://vaadin.com/docs/latest/styling/custom-theme/styling-components) documentation.
1557
+ * See [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.
219
1558
  *
220
1559
  * @fires {Event} input - Fired when the value is changed by the user: on every typing keystroke, and the value is cleared using the clear button.
221
1560
  * @fires {Event} change - Fired when the user commits a value change.
@@ -223,13 +1562,13 @@ registerStyles('vaadin-text-field', inputFieldShared$1, { moduleId: 'vaadin-text
223
1562
  * @fires {CustomEvent} value-changed - Fired when the `value` property changes.
224
1563
  * @fires {CustomEvent} validated - Fired whenever the field is validated.
225
1564
  *
1565
+ * @customElement
226
1566
  * @extends HTMLElement
227
1567
  * @mixes ElementMixin
228
1568
  * @mixes ThemableMixin
229
- * @mixes PatternMixin
230
- * @mixes InputFieldMixin
1569
+ * @mixes TextFieldMixin
231
1570
  */
232
- class TextField extends PatternMixin(InputFieldMixin(ThemableMixin(ElementMixin(PolymerElement)))) {
1571
+ class TextField extends TextFieldMixin(ThemableMixin(ElementMixin(PolymerElement))) {
233
1572
  static get is() {
234
1573
  return 'vaadin-text-field';
235
1574
  }
@@ -291,49 +1630,89 @@ class TextField extends PatternMixin(InputFieldMixin(ThemableMixin(ElementMixin(
291
1630
  };
292
1631
  }
293
1632
 
294
- static get delegateAttrs() {
295
- return [...super.delegateAttrs, 'maxlength', 'minlength'];
296
- }
297
-
298
- static get constraints() {
299
- return [...super.constraints, 'maxlength', 'minlength'];
300
- }
301
-
302
- constructor() {
303
- super();
304
- this._setType('text');
305
- }
306
-
307
- /** @protected */
308
- get clearElement() {
309
- return this.$.clearButton;
310
- }
311
-
312
1633
  /** @protected */
313
1634
  ready() {
314
1635
  super.ready();
315
1636
 
316
- this.addController(
317
- new InputController(this, (input) => {
318
- this._setInputElement(input);
319
- this._setFocusElement(input);
320
- this.stateTarget = input;
321
- this.ariaTarget = input;
322
- }),
323
- );
324
- this.addController(new LabelledInputController(this.inputElement, this._labelController));
325
-
326
1637
  this._tooltipController = new TooltipController(this);
327
1638
  this._tooltipController.setPosition('top');
1639
+ this._tooltipController.setAriaTarget(this.inputElement);
328
1640
  this.addController(this._tooltipController);
329
1641
  }
330
1642
  }
331
1643
 
332
- customElements.define(TextField.is, TextField);
1644
+ defineCustomElement$2(TextField);
1645
+
1646
+ /**
1647
+ * @license
1648
+ * Copyright (c) 2017 - 2023 Vaadin Ltd.
1649
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
1650
+ */
1651
+
1652
+ /**
1653
+ * Check if the custom element type has themes applied.
1654
+ * @param {Function} elementClass
1655
+ * @returns {boolean}
1656
+ */
1657
+ function classHasThemes(elementClass) {
1658
+ return elementClass && Object.prototype.hasOwnProperty.call(elementClass, '__themes');
1659
+ }
1660
+
1661
+ /**
1662
+ * Check if the custom element type has themes applied.
1663
+ * @param {string} tagName
1664
+ * @returns {boolean}
1665
+ */
1666
+ function hasThemes(tagName) {
1667
+ return classHasThemes(customElements.get(tagName));
1668
+ }
1669
+
1670
+ /**
1671
+ * Flattens the styles into a single array of styles.
1672
+ * @param {CSSResultGroup} styles
1673
+ * @param {CSSResult[]} result
1674
+ * @returns {CSSResult[]}
1675
+ */
1676
+ function flattenStyles(styles = []) {
1677
+ return [styles].flat(Infinity).filter((style) => {
1678
+ if (style instanceof o) {
1679
+ return true;
1680
+ }
1681
+ console.warn('An item in styles is not of type CSSResult. Use `unsafeCSS` or `css`.');
1682
+ return false;
1683
+ });
1684
+ }
1685
+
1686
+ /**
1687
+ * Registers CSS styles for a component type. Make sure to register the styles before
1688
+ * the first instance of a component of the type is attached to DOM.
1689
+ *
1690
+ * @param {string} themeFor The local/tag name of the component type to register the styles for
1691
+ * @param {CSSResultGroup} styles The CSS style rules to be registered for the component type
1692
+ * matching themeFor and included in the local scope of each component instance
1693
+ * @param {{moduleId?: string, include?: string | string[]}} options Additional options
1694
+ * @return {void}
1695
+ */
1696
+ function registerStyles(themeFor, styles, options = {}) {
1697
+ if (themeFor) {
1698
+ if (hasThemes(themeFor)) {
1699
+ console.warn(`The custom element definition for "${themeFor}"
1700
+ was finalized before a style module was registered.
1701
+ Make sure to add component specific style modules before
1702
+ importing the corresponding custom element.`);
1703
+ }
1704
+ }
1705
+
1706
+ styles = flattenStyles(styles);
1707
+
1708
+ if (window.Vaadin && window.Vaadin.styleModules) {
1709
+ window.Vaadin.styleModules.registerStyles(themeFor, styles, options);
1710
+ }
1711
+ }
333
1712
 
334
1713
  /**
335
1714
  * @license
336
- * Copyright (c) 2021 - 2022 Vaadin Ltd.
1715
+ * Copyright (c) 2021 - 2023 Vaadin Ltd.
337
1716
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
338
1717
  */
339
1718
 
@@ -358,7 +1737,7 @@ registerStyles('vaadin-password-field-button', [button, passwordFieldButton], {
358
1737
 
359
1738
  /**
360
1739
  * @license
361
- * Copyright (c) 2021 - 2022 Vaadin Ltd.
1740
+ * Copyright (c) 2021 - 2023 Vaadin Ltd.
362
1741
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
363
1742
  */
364
1743
 
@@ -386,13 +1765,36 @@ registerStyles('vaadin-password-field', [inputFieldShared, passwordField], { mod
386
1765
 
387
1766
  /**
388
1767
  * @license
389
- * Copyright (c) 2021 - 2022 Vaadin Ltd.
1768
+ * Copyright (c) 2021 - 2023 Vaadin Ltd.
1769
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
1770
+ */
1771
+ function defineCustomElement$1(CustomElement) {
1772
+ const defined = customElements.get(CustomElement.is);
1773
+ if (!defined) {
1774
+ customElements.define(CustomElement.is, CustomElement);
1775
+ } else {
1776
+ const definedVersion = defined.version;
1777
+ if (definedVersion && CustomElement.version && definedVersion === CustomElement.version) {
1778
+ // Just loading the same thing again
1779
+ console.warn(`The component ${CustomElement.is} has been loaded twice`);
1780
+ } else {
1781
+ console.error(
1782
+ `Tried to define ${CustomElement.is} version ${CustomElement.version} when version ${defined.version} is already in use. Something will probably break.`,
1783
+ );
1784
+ }
1785
+ }
1786
+ }
1787
+
1788
+ /**
1789
+ * @license
1790
+ * Copyright (c) 2021 - 2023 Vaadin Ltd.
390
1791
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
391
1792
  */
392
1793
 
393
1794
  /**
394
1795
  * An element used internally by `<vaadin-password-field>`. Not intended to be used separately.
395
1796
  *
1797
+ * @customElement
396
1798
  * @extends Button
397
1799
  * @private
398
1800
  */
@@ -417,11 +1819,387 @@ class PasswordFieldButton extends Button {
417
1819
  }
418
1820
  }
419
1821
 
420
- customElements.define(PasswordFieldButton.is, PasswordFieldButton);
1822
+ defineCustomElement$1(PasswordFieldButton);
1823
+
1824
+ /**
1825
+ * @license
1826
+ * Copyright (c) 2021 - 2023 Vaadin Ltd.
1827
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
1828
+ */
1829
+
1830
+ /**
1831
+ * Returns true if the given node is an empty text node, false otherwise.
1832
+ *
1833
+ * @param {Node} node
1834
+ * @return {boolean}
1835
+ */
1836
+ function isEmptyTextNode(node) {
1837
+ return node.nodeType === Node.TEXT_NODE && node.textContent.trim() === '';
1838
+ }
1839
+
1840
+ /**
1841
+ * @license
1842
+ * Copyright (c) 2023 Vaadin Ltd.
1843
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
1844
+ */
1845
+
1846
+ /**
1847
+ * A helper for observing slot changes.
1848
+ */
1849
+ class SlotObserver {
1850
+ constructor(slot, callback) {
1851
+ /** @type HTMLSlotElement */
1852
+ this.slot = slot;
1853
+
1854
+ /** @type Function */
1855
+ this.callback = callback;
1856
+
1857
+ /** @type {Node[]} */
1858
+ this._storedNodes = [];
1859
+
1860
+ this._connected = false;
1861
+ this._scheduled = false;
1862
+
1863
+ this._boundSchedule = () => {
1864
+ this._schedule();
1865
+ };
1866
+
1867
+ this.connect();
1868
+ this._schedule();
1869
+ }
1870
+
1871
+ /**
1872
+ * Activates an observer. This method is automatically called when
1873
+ * a `SlotObserver` is created. It should only be called to re-activate
1874
+ * an observer that has been deactivated via the `disconnect` method.
1875
+ */
1876
+ connect() {
1877
+ this.slot.addEventListener('slotchange', this._boundSchedule);
1878
+ this._connected = true;
1879
+ }
1880
+
1881
+ /**
1882
+ * Deactivates the observer. After calling this method the observer callback
1883
+ * will not be called when changes to slotted nodes occur. The `connect` method
1884
+ * may be subsequently called to reactivate the observer.
1885
+ */
1886
+ disconnect() {
1887
+ this.slot.removeEventListener('slotchange', this._boundSchedule);
1888
+ this._connected = false;
1889
+ }
1890
+
1891
+ /** @private */
1892
+ _schedule() {
1893
+ if (!this._scheduled) {
1894
+ this._scheduled = true;
1895
+
1896
+ queueMicrotask(() => {
1897
+ this.flush();
1898
+ });
1899
+ }
1900
+ }
1901
+
1902
+ /**
1903
+ * Run the observer callback synchronously.
1904
+ */
1905
+ flush() {
1906
+ if (!this._connected) {
1907
+ return;
1908
+ }
1909
+
1910
+ this._scheduled = false;
1911
+
1912
+ this._processNodes();
1913
+ }
1914
+
1915
+ /** @private */
1916
+ _processNodes() {
1917
+ const currentNodes = this.slot.assignedNodes({ flatten: true });
1918
+
1919
+ let addedNodes = [];
1920
+ const removedNodes = [];
1921
+ const movedNodes = [];
1922
+
1923
+ if (currentNodes.length) {
1924
+ addedNodes = currentNodes.filter((node) => !this._storedNodes.includes(node));
1925
+ }
1926
+
1927
+ if (this._storedNodes.length) {
1928
+ this._storedNodes.forEach((node, index) => {
1929
+ const idx = currentNodes.indexOf(node);
1930
+ if (idx === -1) {
1931
+ removedNodes.push(node);
1932
+ } else if (idx !== index) {
1933
+ movedNodes.push(node);
1934
+ }
1935
+ });
1936
+ }
1937
+
1938
+ if (addedNodes.length || removedNodes.length || movedNodes.length) {
1939
+ this.callback({ addedNodes, movedNodes, removedNodes });
1940
+ }
1941
+
1942
+ this._storedNodes = currentNodes;
1943
+ }
1944
+ }
1945
+
1946
+ /**
1947
+ * @license
1948
+ * Copyright (c) 2021 - 2023 Vaadin Ltd.
1949
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
1950
+ */
1951
+
1952
+ let uniqueId = 0;
1953
+
1954
+ /**
1955
+ * Returns a unique integer id.
1956
+ *
1957
+ * @return {number}
1958
+ */
1959
+ function generateUniqueId() {
1960
+ // eslint-disable-next-line no-plusplus
1961
+ return uniqueId++;
1962
+ }
1963
+
1964
+ /**
1965
+ * @license
1966
+ * Copyright (c) 2021 - 2023 Vaadin Ltd.
1967
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
1968
+ */
1969
+
1970
+ /**
1971
+ * A controller for providing content to slot element and observing changes.
1972
+ */
1973
+ class SlotController extends EventTarget {
1974
+ /**
1975
+ * Ensure that every instance has unique ID.
1976
+ *
1977
+ * @param {HTMLElement} host
1978
+ * @param {string} slotName
1979
+ * @return {string}
1980
+ * @protected
1981
+ */
1982
+ static generateId(host, slotName) {
1983
+ const prefix = slotName || 'default';
1984
+ return `${prefix}-${host.localName}-${generateUniqueId()}`;
1985
+ }
1986
+
1987
+ constructor(host, slotName, tagName, config = {}) {
1988
+ super();
1989
+
1990
+ const { initializer, multiple, observe, useUniqueId } = config;
1991
+
1992
+ this.host = host;
1993
+ this.slotName = slotName;
1994
+ this.tagName = tagName;
1995
+ this.observe = typeof observe === 'boolean' ? observe : true;
1996
+ this.multiple = typeof multiple === 'boolean' ? multiple : false;
1997
+ this.slotInitializer = initializer;
1998
+
1999
+ if (multiple) {
2000
+ this.nodes = [];
2001
+ }
2002
+
2003
+ // Only generate the default ID if requested by the controller.
2004
+ if (useUniqueId) {
2005
+ this.defaultId = this.constructor.generateId(host, slotName);
2006
+ }
2007
+ }
2008
+
2009
+ hostConnected() {
2010
+ if (!this.initialized) {
2011
+ if (this.multiple) {
2012
+ this.initMultiple();
2013
+ } else {
2014
+ this.initSingle();
2015
+ }
2016
+
2017
+ if (this.observe) {
2018
+ this.observeSlot();
2019
+ }
2020
+
2021
+ this.initialized = true;
2022
+ }
2023
+ }
2024
+
2025
+ /** @protected */
2026
+ initSingle() {
2027
+ let node = this.getSlotChild();
2028
+
2029
+ if (!node) {
2030
+ node = this.attachDefaultNode();
2031
+ this.initNode(node);
2032
+ } else {
2033
+ this.node = node;
2034
+ this.initAddedNode(node);
2035
+ }
2036
+ }
2037
+
2038
+ /** @protected */
2039
+ initMultiple() {
2040
+ const children = this.getSlotChildren();
2041
+
2042
+ if (children.length === 0) {
2043
+ const defaultNode = this.attachDefaultNode();
2044
+ if (defaultNode) {
2045
+ this.nodes = [defaultNode];
2046
+ this.initNode(defaultNode);
2047
+ }
2048
+ } else {
2049
+ this.nodes = children;
2050
+ children.forEach((node) => {
2051
+ this.initAddedNode(node);
2052
+ });
2053
+ }
2054
+ }
2055
+
2056
+ /**
2057
+ * Create and attach default node using the provided tag name, if any.
2058
+ * @return {Node | undefined}
2059
+ * @protected
2060
+ */
2061
+ attachDefaultNode() {
2062
+ const { host, slotName, tagName } = this;
2063
+
2064
+ // Check if the node was created previously and if so, reuse it.
2065
+ let node = this.defaultNode;
2066
+
2067
+ // Tag name is optional, sometimes we don't init default content.
2068
+ if (!node && tagName) {
2069
+ node = document.createElement(tagName);
2070
+ if (node instanceof Element) {
2071
+ if (slotName !== '') {
2072
+ node.setAttribute('slot', slotName);
2073
+ }
2074
+ this.node = node;
2075
+ this.defaultNode = node;
2076
+ }
2077
+ }
2078
+
2079
+ if (node) {
2080
+ host.appendChild(node);
2081
+ }
2082
+
2083
+ return node;
2084
+ }
2085
+
2086
+ /**
2087
+ * Return the list of nodes matching the slot managed by the controller.
2088
+ * @return {Node}
2089
+ */
2090
+ getSlotChildren() {
2091
+ const { slotName } = this;
2092
+ return Array.from(this.host.childNodes).filter((node) => {
2093
+ // Either an element (any slot) or a text node (only un-named slot).
2094
+ return (
2095
+ (node.nodeType === Node.ELEMENT_NODE && node.slot === slotName) ||
2096
+ (node.nodeType === Node.TEXT_NODE && node.textContent.trim() && slotName === '')
2097
+ );
2098
+ });
2099
+ }
2100
+
2101
+ /**
2102
+ * Return a reference to the node managed by the controller.
2103
+ * @return {Node}
2104
+ */
2105
+ getSlotChild() {
2106
+ return this.getSlotChildren()[0];
2107
+ }
2108
+
2109
+ /**
2110
+ * Run `slotInitializer` for the node managed by the controller.
2111
+ *
2112
+ * @param {Node} node
2113
+ * @protected
2114
+ */
2115
+ initNode(node) {
2116
+ const { slotInitializer } = this;
2117
+ // Don't try to bind `this` to initializer (normally it's arrow function).
2118
+ // Instead, pass the host as a first argument to access component's state.
2119
+ if (slotInitializer) {
2120
+ slotInitializer(node, this.host);
2121
+ }
2122
+ }
2123
+
2124
+ /**
2125
+ * Override to initialize the newly added custom node.
2126
+ *
2127
+ * @param {Node} _node
2128
+ * @protected
2129
+ */
2130
+ initCustomNode(_node) {}
2131
+
2132
+ /**
2133
+ * Override to teardown slotted node when it's removed.
2134
+ *
2135
+ * @param {Node} _node
2136
+ * @protected
2137
+ */
2138
+ teardownNode(_node) {}
2139
+
2140
+ /**
2141
+ * Run both `initCustomNode` and `initNode` for a custom slotted node.
2142
+ *
2143
+ * @param {Node} node
2144
+ * @protected
2145
+ */
2146
+ initAddedNode(node) {
2147
+ if (node !== this.defaultNode) {
2148
+ this.initCustomNode(node);
2149
+ this.initNode(node);
2150
+ }
2151
+ }
2152
+
2153
+ /**
2154
+ * Setup the observer to manage slot content changes.
2155
+ * @protected
2156
+ */
2157
+ observeSlot() {
2158
+ const { slotName } = this;
2159
+ const selector = slotName === '' ? 'slot:not([name])' : `slot[name=${slotName}]`;
2160
+ const slot = this.host.shadowRoot.querySelector(selector);
2161
+
2162
+ this.__slotObserver = new SlotObserver(slot, ({ addedNodes, removedNodes }) => {
2163
+ const current = this.multiple ? this.nodes : [this.node];
2164
+
2165
+ // Calling `slot.assignedNodes()` includes whitespace text nodes in case of default slot:
2166
+ // unlike comment nodes, they are not filtered out. So we need to manually ignore them.
2167
+ const newNodes = addedNodes.filter((node) => !isEmptyTextNode(node) && !current.includes(node));
2168
+
2169
+ if (removedNodes.length) {
2170
+ this.nodes = current.filter((node) => !removedNodes.includes(node));
2171
+
2172
+ removedNodes.forEach((node) => {
2173
+ this.teardownNode(node);
2174
+ });
2175
+ }
2176
+
2177
+ if (newNodes && newNodes.length > 0) {
2178
+ if (this.multiple) {
2179
+ // Remove default node if exists
2180
+ if (this.defaultNode) {
2181
+ this.defaultNode.remove();
2182
+ }
2183
+ this.nodes = [...current, ...newNodes].filter((node) => node !== this.defaultNode);
2184
+ newNodes.forEach((node) => {
2185
+ this.initAddedNode(node);
2186
+ });
2187
+ } else {
2188
+ // Remove previous node if exists
2189
+ if (this.node) {
2190
+ this.node.remove();
2191
+ }
2192
+ this.node = newNodes[0];
2193
+ this.initAddedNode(this.node);
2194
+ }
2195
+ }
2196
+ });
2197
+ }
2198
+ }
421
2199
 
422
2200
  /**
423
2201
  * @license
424
- * Copyright (c) 2021 - 2022 Vaadin Ltd.
2202
+ * Copyright (c) 2021 - 2023 Vaadin Ltd.
425
2203
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
426
2204
  */
427
2205
 
@@ -457,7 +2235,7 @@ let memoizedTemplate;
457
2235
  * -------------------|---------------------------------
458
2236
  * `password-visible` | Set when the password is visible
459
2237
  *
460
- * See [Styling Components](https://vaadin.com/docs/latest/styling/custom-theme/styling-components) documentation.
2238
+ * See [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.
461
2239
  *
462
2240
  * @fires {Event} input - Fired when the value is changed by the user: on every typing keystroke, and the value is cleared using the clear button.
463
2241
  * @fires {Event} change - Fired when the user commits a value change.
@@ -465,6 +2243,7 @@ let memoizedTemplate;
465
2243
  * @fires {CustomEvent} value-changed - Fired when the `value` property changes.
466
2244
  * @fires {CustomEvent} validated - Fired whenever the field is validated.
467
2245
  *
2246
+ * @customElement
468
2247
  * @extends TextField
469
2248
  */
470
2249
  class PasswordField extends TextField {
@@ -538,6 +2317,14 @@ class PasswordField extends TextField {
538
2317
  return ['__i18nChanged(i18n.*)'];
539
2318
  }
540
2319
 
2320
+ constructor() {
2321
+ super();
2322
+ this._setType('password');
2323
+ this.__boundRevealButtonClick = this._onRevealButtonClick.bind(this);
2324
+ this.__boundRevealButtonMouseDown = this._onRevealButtonMouseDown.bind(this);
2325
+ this.__lastChange = '';
2326
+ }
2327
+
541
2328
  /** @protected */
542
2329
  get slotStyles() {
543
2330
  const tag = this.localName;
@@ -556,31 +2343,20 @@ class PasswordField extends TextField {
556
2343
  return this._revealButtonController && this._revealButtonController.node;
557
2344
  }
558
2345
 
559
- constructor() {
560
- super();
561
- this._setType('password');
562
- this.__boundRevealButtonClick = this._onRevealButtonClick.bind(this);
563
- this.__boundRevealButtonMouseDown = this._onRevealButtonMouseDown.bind(this);
564
- this.__lastChange = '';
565
- }
566
-
567
2346
  /** @protected */
568
2347
  ready() {
569
2348
  super.ready();
570
2349
 
571
2350
  this._revealPart = this.shadowRoot.querySelector('[part="reveal-button"]');
572
2351
 
573
- this._revealButtonController = new SlotController(
574
- this,
575
- 'reveal',
576
- () => document.createElement('vaadin-password-field-button'),
577
- (host, btn) => {
578
- btn.disabled = host.disabled;
2352
+ this._revealButtonController = new SlotController(this, 'reveal', 'vaadin-password-field-button', {
2353
+ initializer: (btn) => {
2354
+ btn.disabled = this.disabled;
579
2355
 
580
- btn.addEventListener('click', host.__boundRevealButtonClick);
581
- btn.addEventListener('mousedown', host.__boundRevealButtonMouseDown);
2356
+ btn.addEventListener('click', this.__boundRevealButtonClick);
2357
+ btn.addEventListener('mousedown', this.__boundRevealButtonMouseDown);
582
2358
  },
583
- );
2359
+ });
584
2360
  this.addController(this._revealButtonController);
585
2361
 
586
2362
  this.__updateAriaLabel(this.i18n);
@@ -737,7 +2513,7 @@ class PasswordField extends TextField {
737
2513
  }
738
2514
  }
739
2515
 
740
- customElements.define(PasswordField.is, PasswordField);
2516
+ defineCustomElement$1(PasswordField);
741
2517
 
742
2518
  const passwordInputCss = "*,*::before,*::after{padding:0;margin:0;box-sizing:border-box}.password{font-family:\"Roboto\";font-style:normal}.password__wrapper{position:relative;width:100%}.password__wrapper--autofilled{pointer-events:none}.password__wrapper--autofilled .password__label{color:#979797}.password__wrapper--autofilled .password__input::part(input-field){color:#979797}.password__wrapper--flex{display:flex;gap:5px}.password__wrapper--relative{position:relative}.password__label{font-family:inherit;font-style:normal;font-weight:500;font-size:16px;line-height:20px;color:#2A3841}.password__label--required::after{content:\"*\";font-family:inherit;color:#2A3841;margin-left:2px}.password__input{width:inherit;border:none;margin-bottom:5px}.password__input[focused]::part(input-field){border-color:#3E3E3E}.password__input[invalid]::part(input-field){border-color:#cc0000b3}.password__input::part(input-field){border-radius:4px;background-color:transparent;font-family:inherit;font-style:normal;font-weight:300;font-size:16px;line-height:19px;color:#2A2E3F;width:100%;position:relative;border:2px solid #DEE1EE}.password__input>input:placeholder-shown{color:#979797}.password__error-message{position:absolute;top:calc(100% + 5px);left:0;color:#cc0000b3}.password__complexity{position:relative;padding:10px;display:flex;flex-direction:column;gap:20px;justify-content:center;margin-top:20px;font-weight:300;background:#FFFFFF;-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px;height:150px;border:1px solid #B0B0B0}.password__complexity--strength{display:flex;justify-content:space-evenly}.password__complexity--strength meter::-webkit-meter-optimum-value{background:#1F1F1F}.password__complexity--strength meter::-moz-meter-bar{background:#B0B0B0}.password__complexity--hidden{display:none}.password__complexity--text-bold{font-weight:500}.password__complexity--checkbox{margin-right:5px}.password__complexity:after{content:\"\";position:absolute;width:25px;height:25px;border-top:1px solid #B0B0B0;border-right:0 solid #B0B0B0;border-left:1px solid #B0B0B0;border-bottom:0 solid #B0B0B0;bottom:92%;left:50%;margin-left:-25px;transform:rotate(45deg);margin-top:-25px;background-color:#FFFFFF}.password__tooltip-icon{width:16px;height:auto}.password__tooltip{position:absolute;top:0;left:20px;background-color:#FFFFFF;border:1px solid #B0B0B0;color:#2B2D3F;padding:10px;border-radius:5px;opacity:0;transition:opacity 0.3s ease-in-out;z-index:10}.password__tooltip.visible{opacity:1}";
743
2519