fancy-ui-ts 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,1233 @@
1
+ var styles = `\n\t:host {\n\t\tdisplay: block;\n\t\tposition: relative;\n\t\twidth: 100%;\n\t\tbox-sizing: border-box;\n \tfont-family: var(--fc-font-family);\n\t\tmax-width: var(--fc-combobox-max-width);\n\t}\n\n\t/* only show invalid style if the user has touched the field (blurred). the :invalid pseudo-class comes from \n\tinternals.setValidity() logic. */\n\n\t:host([touched]:invalid) .fc-input {\n background-color: var(--fc-combobox-error-bg);\n border-color: var(--fc-combobox-error-color);\n }\n\n :host([touched]:invalid) .fc-input:focus {\n box-shadow: 0 0 0 2px var(--fc-combobox-error-focus-ring);\n }\n\n\t.fc-input {\n\t\twidth: 100%;\n\t\tbox-sizing: border-box;\n\n\t\tpadding: var(--fc-combobox-padding);\n\t\tborder-radius: var(--fc-combobox-radius);\n\t\tbackground: var(--fc-combobox-bg);\n\t\tcolor: var(--fc-combobox-fg);\n\n\t\tborder: var(--fc-combobox-border-width) solid var(--fc-combobox-border);\n\t\tfont-size: var(--fc-font-size-md);\n\n\t\tbox-shadow: var(--fc-combobox-shadow);\n\t\ttransition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n\t}\n\n\t.fc-input::placeholder {\n\t\tcolor: var(--fc-combobox-placeholder);\n\t}\n\n\t.fc-input:hover {\n\t\tborder-color: var(--fc-combobox-border-hover);\n\t}\n\n\t.fc-input:focus {\n\t\tborder-color: var(--fc-combobox-border-focus);\n\t\toutline: none;\n\t\tbox-shadow: var(--fc-combobox-focus-ring);\n\t}\n\n\t.fc-options {\n\t\tposition: absolute;\n\t\ttop: calc(100% + 6px);\n\t\tleft: 0;\n\t\tright: 0;\n\t\tz-index: 1000;\n\t\tbackground: var(--fc-combobox-dropdown-bg, var(--fc-combobox-bg));\n\t\tborder: var(--fc-combobox-border-width) solid var(--fc-combobox-border);\n\t\tborder-radius: var(--fc-combobox-dropdown-radius, var(--fc-combobox-radius));\n\t\tpadding: var(--fc-combobox-dropdown-padding, calc(var(--fc-combobox-padding) - 5px));\n\t\tbox-shadow: var(--fc-combobox-dropdown-shadow);\n\t\tmax-height: var(--fc-combobox-dropdown-max-height, 240px);\n\t\toverflow-y: auto;\n\t\tbox-sizing: border-box;\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\tgap: 4px;\n\t}\n\t\n\t.fc-options[hidden] {\n display: none !important;\n }\n\n\t:host([disabled]) {\n cursor: not-allowed;\n }\n\n\t.fc-input:disabled {\n\t\tbackground: var(--fc-combobox-disabled-bg);\n cursor: not-allowed;\n\t\tbox-shadow: none;\n }\n\n\t.fc-input:disabled::placeholder {\n\t\tcolor: var(--fc-combobox-disabled-placeholder);\n }\n\n\t.fc-input:disabled:hover {\n\t\tborder-color: var(--fc-combobox-border);\n\t}\n\n\t.fc-input:disabled:focus {\n\t\tborder-color: var(--fc-combobox-border);\n\t}\n`;
2
+
3
+ var template = document.createElement("template");
4
+
5
+ template.innerHTML = `\n\t<style>${styles}</style>\n\n\t<input \n\t\tid="fc-input" \n\t\tclass="fc-input"\n\t\ttype="text" \n\t\trole="combobox"\n\t\taria-autocomplete="list"\n\t\taria-expanded="false"\n\t\taria-haspopup="listbox"\n\t\taria-controls="fc-options"\n\t\tpart="input"\n\t\tautocomplete="off"\n\t/>\n\n\t<div \n\t\tid="fc-options" \n\t\tpart="options" \n\t\tclass="fc-options" \n\t\trole="listbox"\n\t\thidden\n\t>\n\t\t<slot></slot>\n\t</div>\n\t\n`;
6
+
7
+ var FcCombobox = class extends HTMLElement {
8
+ constructor() {
9
+ super();
10
+ this._value = "";
11
+ this.activeIndex = -1;
12
+ this._validatorFunction = null;
13
+ const shadow = this.attachShadow({
14
+ mode: "open",
15
+ delegatesFocus: true
16
+ });
17
+ shadow.appendChild(template.content.cloneNode(true));
18
+ this.internals = this.attachInternals();
19
+ this.onInput = this.onInput.bind(this);
20
+ this.onChange = this.onChange.bind(this);
21
+ this.onOptionSelect = this.onOptionSelect.bind(this);
22
+ this.onOutsideClick = this.onOutsideClick.bind(this);
23
+ this.onFocusOut = this.onFocusOut.bind(this);
24
+ this.onFocus = this.onFocus.bind(this);
25
+ this.onDropdownClick = this.onDropdownClick.bind(this);
26
+ this.onSlotChange = this.onSlotChange.bind(this);
27
+ this.onKeyDown = this.onKeyDown.bind(this);
28
+ this.onBlur = this.onBlur.bind(this);
29
+ this.onInvalid = this.onInvalid.bind(this);
30
+ }
31
+ static get observedAttributes() {
32
+ return [ "placeholder", "name", "value", "disabled", "required", "readonly", "strict" ];
33
+ }
34
+ get validity() {
35
+ return this.internals.validity;
36
+ }
37
+ get validationMessage() {
38
+ return this.internals.validationMessage;
39
+ }
40
+ get willValidate() {
41
+ return this.internals.willValidate;
42
+ }
43
+ checkValidity() {
44
+ return this.internals.checkValidity();
45
+ }
46
+ reportValidity() {
47
+ return this.internals.reportValidity();
48
+ }
49
+ get placeholder() {
50
+ var _a;
51
+ return (_a = this.getAttribute("placeholder")) != null ? _a : "";
52
+ }
53
+ set placeholder(val) {
54
+ this.setAttribute("placeholder", val);
55
+ }
56
+ get name() {
57
+ var _a;
58
+ return (_a = this.getAttribute("name")) != null ? _a : "";
59
+ }
60
+ set name(val) {
61
+ this.setAttribute("name", val);
62
+ }
63
+ get disabled() {
64
+ return this.hasAttribute("disabled");
65
+ }
66
+ set disabled(val) {
67
+ if (val) {
68
+ this.setAttribute("disabled", "true");
69
+ return;
70
+ }
71
+ this.removeAttribute("disabled");
72
+ }
73
+ get value() {
74
+ return this._value;
75
+ }
76
+ set value(newValue) {
77
+ if (this._value === newValue) {
78
+ return;
79
+ }
80
+ this._value = newValue;
81
+ this.internals.setFormValue(newValue);
82
+ if (!this.inputEl) {
83
+ return;
84
+ }
85
+ const options = Array.from(this.querySelectorAll("fc-option"));
86
+ options.forEach(option => {
87
+ const selected = option.value === newValue;
88
+ option.selected = selected;
89
+ option.hidden = !selected;
90
+ option.active = false;
91
+ if (selected) {
92
+ this.inputEl.value = option.label;
93
+ }
94
+ });
95
+ if (this.inputEl.value === "") {
96
+ this.inputEl.value = newValue;
97
+ }
98
+ this.syncValidity();
99
+ }
100
+ get label() {
101
+ var _a, _b;
102
+ return (_b = (_a = this.inputEl) == null ? void 0 : _a.value) != null ? _b : "";
103
+ }
104
+ get options() {
105
+ const slot = this.shadowRoot.querySelector("slot");
106
+ const optionElements = slot.assignedElements().filter(el => el.tagName === "FC-OPTION");
107
+ return optionElements.map(opt => ({
108
+ label: opt.label,
109
+ value: opt.value
110
+ }));
111
+ }
112
+ set options(data) {
113
+ const oldOptions = this.querySelectorAll("fc-option");
114
+ oldOptions.forEach(opt => opt.remove());
115
+ data.forEach(element => {
116
+ const optEl = document.createElement("fc-option");
117
+ optEl.setAttribute("value", element.value);
118
+ optEl.setAttribute("label", element.label);
119
+ optEl.textContent = element.label;
120
+ if (element.disabled) {
121
+ optEl.setAttribute("disabled", "");
122
+ }
123
+ this.appendChild(optEl);
124
+ });
125
+ this.syncValidity();
126
+ }
127
+ get required() {
128
+ return this.hasAttribute("required");
129
+ }
130
+ set required(val) {
131
+ if (val) {
132
+ this.setAttribute("required", "true");
133
+ return;
134
+ }
135
+ this.removeAttribute("required");
136
+ }
137
+ get readonly() {
138
+ return this.hasAttribute("readonly");
139
+ }
140
+ set readonly(val) {
141
+ if (val) {
142
+ this.setAttribute("readonly", "true");
143
+ return;
144
+ }
145
+ this.removeAttribute("readonly");
146
+ }
147
+ get strict() {
148
+ return this.hasAttribute("strict");
149
+ }
150
+ set strict(val) {
151
+ if (val) {
152
+ this.setAttribute("strict", "");
153
+ return;
154
+ }
155
+ this.removeAttribute("strict");
156
+ }
157
+ get validator() {
158
+ return this._validatorFunction;
159
+ }
160
+ set validator(func) {
161
+ this._validatorFunction = func;
162
+ this.syncValidity();
163
+ }
164
+ connectedCallback() {
165
+ this.inputEl = this.shadowRoot.getElementById("fc-input");
166
+ this.dropdownEl = this.shadowRoot.getElementById("fc-options");
167
+ if (this.hasAttribute("placeholder")) {
168
+ this.inputEl.placeholder = this.getAttribute("placeholder");
169
+ }
170
+ this.internals.setFormValue(this.value);
171
+ if (this.hasAttribute("disabled")) {
172
+ this.inputEl.disabled = true;
173
+ this.internals.ariaDisabled = "true";
174
+ }
175
+ if (this.hasAttribute("readonly")) {
176
+ this.inputEl.readOnly = true;
177
+ }
178
+ if (this.hasAttribute("required")) {
179
+ this.internals.ariaRequired = "true";
180
+ this.inputEl.required = true;
181
+ }
182
+ this.inputEl.addEventListener("input", this.onInput);
183
+ this.inputEl.addEventListener("change", this.onChange);
184
+ this.addEventListener("fc-option-select", this.onOptionSelect);
185
+ document.addEventListener("click", this.onOutsideClick);
186
+ this.addEventListener("focusout", this.onFocusOut);
187
+ this.inputEl.addEventListener("focus", this.onFocus);
188
+ this.dropdownEl.addEventListener("mousedown", this.onDropdownClick);
189
+ this.inputEl.addEventListener("blur", this.onBlur);
190
+ this.addEventListener("invalid", this.onInvalid);
191
+ const slot = this.shadowRoot.querySelector("slot");
192
+ slot == null ? void 0 : slot.addEventListener("slotchange", this.onSlotChange);
193
+ this.inputEl.addEventListener("keydown", this.onKeyDown);
194
+ this.syncValidity();
195
+ }
196
+ attributeChangedCallback(name, _old, newVal) {
197
+ if (name === "placeholder" && this.inputEl) {
198
+ this.inputEl.placeholder = newVal;
199
+ }
200
+ if (name === "name") {
201
+ this.internals.setFormValue(this.value);
202
+ }
203
+ if (name === "value") {
204
+ this.value = newVal;
205
+ }
206
+ if (name === "disabled" && this.inputEl) {
207
+ const isDisabled = this.hasAttribute("disabled");
208
+ this.inputEl.disabled = isDisabled;
209
+ this.internals.ariaDisabled = isDisabled ? "true" : "false";
210
+ if (isDisabled) {
211
+ this.toggleDropdown(false);
212
+ }
213
+ }
214
+ if (name === "required" && this.inputEl) {
215
+ const isRequired = this.hasAttribute("required");
216
+ this.internals.ariaRequired = isRequired ? "true" : "false";
217
+ this.inputEl.required = isRequired;
218
+ this.syncValidity();
219
+ }
220
+ if (name === "readonly" && this.inputEl) {
221
+ this.inputEl.readOnly = this.hasAttribute("readonly");
222
+ }
223
+ if (name === "strict" && this.inputEl) {
224
+ this.syncValidity();
225
+ }
226
+ }
227
+ disconnectedCallback() {
228
+ document.removeEventListener("click", this.onOutsideClick);
229
+ }
230
+ formResetCallback() {
231
+ this._value = "";
232
+ if (this.inputEl) {
233
+ this.inputEl.value = "";
234
+ }
235
+ this.internals.setFormValue("");
236
+ const options = Array.from(this.querySelectorAll("fc-option"));
237
+ options.forEach(option => {
238
+ option.selected = false;
239
+ option.hidden = false;
240
+ });
241
+ this.toggleDropdown(false);
242
+ this.removeAttribute("touched");
243
+ this.syncValidity();
244
+ this.dispatchEvent(new CustomEvent("fc-reset", {
245
+ bubbles: true,
246
+ composed: true
247
+ }));
248
+ }
249
+ formStateRestoreCallback(state, mode) {
250
+ const restoredValue = state;
251
+ if (restoredValue) {
252
+ this._value = restoredValue;
253
+ this.internals.setFormValue(restoredValue);
254
+ const options = Array.from(this.querySelectorAll("fc-option"));
255
+ const match = options.find(opt => opt.value === restoredValue);
256
+ if (match && this.inputEl) {
257
+ this.inputEl.value = match.label;
258
+ match.selected = true;
259
+ }
260
+ this.syncValidity();
261
+ }
262
+ }
263
+ onInput(e) {
264
+ const rawQuery = e.target.value;
265
+ const query = rawQuery.toLowerCase().trim();
266
+ const options = Array.from(this.querySelectorAll("fc-option"));
267
+ if (query.length === 0) {
268
+ options.forEach(opt => {
269
+ opt.hidden = false;
270
+ opt.selected = false;
271
+ opt.active = false;
272
+ });
273
+ this._value = "";
274
+ this.internals.setFormValue("");
275
+ this.inputEl.removeAttribute("aria-activedescendant");
276
+ this.toggleDropdown(true);
277
+ this.syncValidity();
278
+ this.dispatchEvent(new CustomEvent("fc-input", {
279
+ detail: {
280
+ value: rawQuery,
281
+ label: rawQuery
282
+ },
283
+ bubbles: true,
284
+ composed: true
285
+ }));
286
+ return;
287
+ }
288
+ let hasMatch = false;
289
+ let finalValue = "";
290
+ options.forEach(option => {
291
+ const rawLabel = option.getAttribute("label") || option.textContent || "";
292
+ const label = rawLabel.toLowerCase();
293
+ const match = label.includes(query);
294
+ option.hidden = !match;
295
+ if (match) {
296
+ hasMatch = true;
297
+ }
298
+ const matchExactly = rawQuery === rawLabel && query.length > 0;
299
+ if (matchExactly && !option.disabled) {
300
+ finalValue = option.value;
301
+ option.selected = true;
302
+ return;
303
+ }
304
+ option.selected = false;
305
+ });
306
+ if (finalValue == "") {
307
+ finalValue = rawQuery;
308
+ }
309
+ this._value = finalValue;
310
+ this.internals.setFormValue(finalValue);
311
+ this.syncValidity();
312
+ this.dispatchEvent(new CustomEvent("fc-input", {
313
+ detail: {
314
+ value: finalValue,
315
+ label: rawQuery
316
+ },
317
+ bubbles: true,
318
+ composed: true
319
+ }));
320
+ this.toggleDropdown(hasMatch);
321
+ }
322
+ onChange(e) {
323
+ e.stopPropagation();
324
+ this.dispatchEvent(new CustomEvent("fc-change", {
325
+ detail: {
326
+ value: this._value,
327
+ label: this.inputEl.value
328
+ },
329
+ bubbles: true,
330
+ composed: true
331
+ }));
332
+ }
333
+ onOptionSelect(e) {
334
+ const {value: value, label: label} = e.detail;
335
+ if (this.disabled) {
336
+ return;
337
+ }
338
+ this.inputEl.value = label;
339
+ this._value = value;
340
+ this.internals.setFormValue(value);
341
+ const options = Array.from(this.querySelectorAll("fc-option"));
342
+ options.forEach(option => {
343
+ const selected = option.value === value;
344
+ option.selected = selected;
345
+ option.hidden = !selected;
346
+ option.active = false;
347
+ });
348
+ this.toggleDropdown(false);
349
+ this.syncValidity();
350
+ this.dispatchEvent(new CustomEvent("fc-change", {
351
+ detail: {
352
+ value: value,
353
+ label: label
354
+ },
355
+ bubbles: true,
356
+ composed: true
357
+ }));
358
+ }
359
+ onOutsideClick(e) {
360
+ if (!this.contains(e.target)) {
361
+ this.toggleDropdown(false);
362
+ }
363
+ }
364
+ onFocusOut(e) {
365
+ if (!this.contains(e.relatedTarget)) {
366
+ this.toggleDropdown(false);
367
+ }
368
+ }
369
+ onDropdownClick(e) {
370
+ e.preventDefault();
371
+ }
372
+ onFocus(e) {
373
+ if (this.disabled) {
374
+ return;
375
+ }
376
+ const query = this.inputEl.value.toLowerCase().trim();
377
+ const options = Array.from(this.querySelectorAll("fc-option"));
378
+ const match = options.some(option => {
379
+ const label = (option.getAttribute("label") || option.textContent || "").toLowerCase();
380
+ return label.includes(query);
381
+ });
382
+ this.toggleDropdown(match);
383
+ }
384
+ onSlotChange() {
385
+ if (!this._value) {
386
+ return;
387
+ }
388
+ const options = Array.from(this.querySelectorAll("fc-option"));
389
+ let foundMatch = false;
390
+ options.forEach(option => {
391
+ const selected = option.value === this._value;
392
+ option.selected = selected;
393
+ option.hidden = !selected;
394
+ option.active = false;
395
+ if (selected) {
396
+ this.inputEl.value = option.label;
397
+ foundMatch = true;
398
+ }
399
+ });
400
+ if (!foundMatch && this.inputEl.value === "") {
401
+ this.inputEl.value = this._value;
402
+ }
403
+ this.syncValidity();
404
+ }
405
+ onKeyDown(e) {
406
+ if (this.disabled) {
407
+ return;
408
+ }
409
+ const options = this.getVisibleOptions();
410
+ if (options.length === 0) {
411
+ return;
412
+ }
413
+ if (e.key === "ArrowDown") {
414
+ e.preventDefault();
415
+ this.toggleDropdown(true);
416
+ const nextIndex = this.activeIndex >= options.length - 1 ? 0 : this.activeIndex + 1;
417
+ this.setActiveOption(nextIndex, options);
418
+ } else if (e.key === "ArrowUp") {
419
+ e.preventDefault();
420
+ this.toggleDropdown(true);
421
+ const prevIndex = this.activeIndex <= 0 ? options.length - 1 : this.activeIndex - 1;
422
+ this.setActiveOption(prevIndex, options);
423
+ } else if (e.key === "Enter") {
424
+ e.preventDefault();
425
+ if (this.activeIndex > -1 && options[this.activeIndex]) {
426
+ const target = options[this.activeIndex];
427
+ this.selectOption(target);
428
+ }
429
+ } else if (e.key === "Escape") {
430
+ e.preventDefault();
431
+ this.toggleDropdown(false);
432
+ } else if (e.key === "Tab") {
433
+ this.toggleDropdown(false);
434
+ }
435
+ }
436
+ onBlur() {
437
+ this.setAttribute("touched", "");
438
+ }
439
+ onInvalid(e) {
440
+ this.setAttribute("touched", "");
441
+ }
442
+ setActiveOption(index, visibleOptions) {
443
+ this.querySelectorAll("fc-option").forEach(opt => opt.active = false);
444
+ this.activeIndex = index;
445
+ const target = visibleOptions[index];
446
+ if (target) {
447
+ target.active = true;
448
+ this.inputEl.setAttribute("aria-activedescendant", target.id);
449
+ target.scrollIntoView({
450
+ block: "nearest",
451
+ behavior: "smooth"
452
+ });
453
+ return;
454
+ }
455
+ this.inputEl.removeAttribute("aria-activedescendant");
456
+ }
457
+ getVisibleOptions() {
458
+ return Array.from(this.querySelectorAll("fc-option")).filter(opt => !opt.hidden && !opt.disabled);
459
+ }
460
+ selectOption(option) {
461
+ const value = option.value;
462
+ const label = option.label;
463
+ this.inputEl.value = label;
464
+ this._value = value;
465
+ this.internals.setFormValue(value);
466
+ const allOptions = Array.from(this.querySelectorAll("fc-option"));
467
+ allOptions.forEach(opt => {
468
+ const selected = opt.value === value;
469
+ opt.selected = selected;
470
+ opt.hidden = !selected;
471
+ opt.active = false;
472
+ });
473
+ this.toggleDropdown(false);
474
+ this.syncValidity();
475
+ this.dispatchEvent(new CustomEvent("fc-change", {
476
+ detail: {
477
+ value: value,
478
+ label: label
479
+ },
480
+ bubbles: true,
481
+ composed: true
482
+ }));
483
+ }
484
+ toggleDropdown(show) {
485
+ if (!this.dropdownEl) {
486
+ return;
487
+ }
488
+ if (this.disabled && show) {
489
+ return;
490
+ }
491
+ const dropdown = this.dropdownEl;
492
+ if (show) {
493
+ dropdown.hidden = false;
494
+ this.setAttribute("open", "true");
495
+ this.inputEl.setAttribute("aria-expanded", "true");
496
+ return;
497
+ }
498
+ this.dropdownEl.hidden = true;
499
+ this.removeAttribute("open");
500
+ this.inputEl.setAttribute("aria-expanded", "false");
501
+ this.activeIndex = -1;
502
+ this.querySelectorAll("fc-option").forEach(opt => opt.active = false);
503
+ this.inputEl.removeAttribute("aria-activedescendant");
504
+ }
505
+ syncValidity() {
506
+ if (!this.inputEl) {
507
+ return;
508
+ }
509
+ if (!this.inputEl.validity.valid) {
510
+ this.internals.setValidity(this.inputEl.validity, this.inputEl.validationMessage, this.inputEl);
511
+ return;
512
+ }
513
+ if (this.strict && this._value) {
514
+ const options = Array.from(this.querySelectorAll("fc-option"));
515
+ const match = options.some(opt => opt.value === this._value);
516
+ if (!match) {
517
+ this.internals.setValidity({
518
+ customError: true
519
+ }, "Please select a valid option from the list.", this.inputEl);
520
+ return;
521
+ }
522
+ }
523
+ if (this._validatorFunction) {
524
+ const customErrorMessage = this._validatorFunction(this._value);
525
+ if (customErrorMessage) {
526
+ this.internals.setValidity({
527
+ customError: true
528
+ }, customErrorMessage, this.inputEl);
529
+ return;
530
+ }
531
+ }
532
+ this.internals.setValidity({});
533
+ }
534
+ setProps(props) {
535
+ for (const property in props) {
536
+ const value = props[property];
537
+ if (property in this) {
538
+ this[property] = value;
539
+ continue;
540
+ }
541
+ if ([ "string", "number", "boolean" ].includes(typeof value)) {
542
+ this.setAttribute(property, String(value));
543
+ }
544
+ }
545
+ }
546
+ };
547
+
548
+ FcCombobox.formAssociated = true;
549
+
550
+ var defineCombobox = () => {
551
+ if (!customElements.get("fc-combobox")) {
552
+ customElements.define("fc-combobox", FcCombobox);
553
+ }
554
+ return FcCombobox;
555
+ };
556
+
557
+ var styles2 = `\n\t:host {\n\t\tdisplay: block;\n\t\twidth: 100%;\n\t\tbox-sizing: border-box;\n \tfont-family: var(--fc-font-family);\n\t}\n\n\t:host([hidden]) {\n display: none !important;\n }\n\n\t:host([disabled]) {\n cursor: not-allowed;\n }\n\t\t\n\t\t\n\tbutton.fc-option {\n\t\twidth: 100%;\n\t\tbox-sizing: border-box;\n\t\ttext-align: left;\n\t\tbackground: var(--fc-option-bg);\n\t\tcolor: var(--fc-option-fg);\n\t\tpadding: var(--fc-option-padding);\n\t\tborder-radius: var(--fc-option-radius);\n\t\tborder: none;\n\t\tfont: inherit;\n\t\tcursor: pointer;\n\t\toverflow: hidden;\n\t\ttext-overflow: ellipsis;\n\t}\n\n\tbutton.fc-option:hover {\n\t\tbackground: var(--fc-option-bg-hover);\n\t\ttransition: background 0.15s ease-in-out, color 0.15s ease-in-out;\n\t}\n\n\tbutton.fc-option[data-active="true"] { \n background: var(--fc-option-bg-active);\n }\n\n\tbutton.fc-option:disabled {\n\t\tcolor: var(--fc-option-disabled-fg);\n\t\tbackground: var(--fc-option-disabled-bg);\n\t\tpointer-events: none; // this prevents disabled attribute on button to move focus out of the fc-combobox\n\t\tbox-shadow: none;\n\t}\n\n button.fc-option:disabled:hover {\n\t\tbackground: var(--fc-option-disabled-bg);\n\t}\n\n\tbutton.fc-option[aria-selected="true"] {\n\t\tbackground: var(--fc-option-bg-selected);\n\t\tcolor: var(--fc-option-fg-selected);\n\t}\n\n`;
558
+
559
+ var template2 = document.createElement("template");
560
+
561
+ template2.innerHTML = `\n\t<style>${styles2}</style>\n\t<button part="base" class="fc-option" role="option">\n\t\t<slot></slot>\n\t</button>\n`;
562
+
563
+ var FcOption = class extends HTMLElement {
564
+ static get observedAttributes() {
565
+ return [ "value", "label", "selected", "disabled", "active" ];
566
+ }
567
+ constructor() {
568
+ super();
569
+ const shadow = this.attachShadow({
570
+ mode: "open"
571
+ });
572
+ shadow.appendChild(template2.content.cloneNode(true));
573
+ this.onClick = this.onClick.bind(this);
574
+ }
575
+ get value() {
576
+ var _a;
577
+ return (_a = this.getAttribute("value")) != null ? _a : "";
578
+ }
579
+ set value(data) {
580
+ this.setAttribute("value", data);
581
+ }
582
+ get label() {
583
+ var _a, _b;
584
+ return (_b = (_a = this.getAttribute("label")) != null ? _a : this.textContent) != null ? _b : "";
585
+ }
586
+ set label(val) {
587
+ this.setAttribute("label", val);
588
+ this.textContent = val;
589
+ }
590
+ get selected() {
591
+ return this.hasAttribute("selected");
592
+ }
593
+ set selected(isSelected) {
594
+ if (isSelected) {
595
+ this.setAttribute("selected", "true");
596
+ return;
597
+ }
598
+ this.removeAttribute("selected");
599
+ }
600
+ get disabled() {
601
+ return this.hasAttribute("disabled");
602
+ }
603
+ set disabled(val) {
604
+ if (val) {
605
+ this.setAttribute("disabled", "");
606
+ return;
607
+ }
608
+ this.removeAttribute("disabled");
609
+ }
610
+ get active() {
611
+ return this.hasAttribute("active");
612
+ }
613
+ set active(isActive) {
614
+ if (isActive) {
615
+ this.setAttribute("active", "true");
616
+ return;
617
+ }
618
+ this.removeAttribute("active");
619
+ }
620
+ connectedCallback() {
621
+ if (!this.id) {
622
+ this.id = `fc-opt-${Math.random().toString(36).substring(2, 11)}`;
623
+ }
624
+ const btn = this.shadowRoot.querySelector("button");
625
+ if (this.disabled && btn) {
626
+ btn.disabled = true;
627
+ btn.setAttribute("aria-disabled", "true");
628
+ }
629
+ btn.addEventListener("click", this.onClick);
630
+ }
631
+ attributeChangedCallback(name, _oldVal, _newVal) {
632
+ var _a, _b;
633
+ if (name === "selected") {
634
+ this.updateSelection();
635
+ }
636
+ if (name === "disabled") {
637
+ const btn = (_a = this.shadowRoot) == null ? void 0 : _a.querySelector("button");
638
+ if (btn) {
639
+ const isDisabled = this.hasAttribute("disabled");
640
+ btn.disabled = isDisabled;
641
+ btn.setAttribute("aria-disabled", isDisabled.toString());
642
+ }
643
+ }
644
+ if (name === "active") {
645
+ const btn = (_b = this.shadowRoot) == null ? void 0 : _b.querySelector("button");
646
+ if (btn) {
647
+ if (this.active) {
648
+ btn.setAttribute("data-active", "true");
649
+ return;
650
+ }
651
+ btn.removeAttribute("data-active");
652
+ }
653
+ }
654
+ }
655
+ onClick(e) {
656
+ if (this.disabled) {
657
+ e.preventDefault();
658
+ return;
659
+ }
660
+ this.dispatchEvent(new CustomEvent("fc-option-select", {
661
+ detail: {
662
+ value: this.value,
663
+ label: this.label
664
+ },
665
+ bubbles: true,
666
+ composed: true
667
+ }));
668
+ }
669
+ updateSelection() {
670
+ const button = this.shadowRoot.querySelector("button");
671
+ if (!button) {
672
+ return;
673
+ }
674
+ button.setAttribute("aria-selected", this.selected ? "true" : "false");
675
+ }
676
+ setProps(props) {
677
+ for (const property in props) {
678
+ const value = props[property];
679
+ if (property in this) {
680
+ this[property] = value;
681
+ continue;
682
+ }
683
+ if ([ "string", "number", "boolean" ].includes(typeof value)) {
684
+ this.setAttribute(property, String(value));
685
+ }
686
+ }
687
+ }
688
+ };
689
+
690
+ var defineOption = () => {
691
+ if (!customElements.get("fc-option")) {
692
+ customElements.define("fc-option", FcOption);
693
+ }
694
+ return FcOption;
695
+ };
696
+
697
+ var styles3 = `\n\t:host {\n\t\tdisplay: block;\n\t\twidth: 100%;\n\t\tbox-sizing: border-box;\n \tfont-family: var(--fc-font-family);\n\t\tmax-width: var(--fc-input-max-width);\n\t}\n\n\t:host([disabled]) {\n\t\tcursor: not-allowed;\n\t}\n\n\t:host([hidden]) {\n\t\tdisplay: none !important;\n\t}\n\n\t/* only show invalid style if the user has touched the field (blurred). the :invalid pseudo-class comes from \n\tinternals.setValidity() logic. */\n\n\t:host([touched]:invalid) .fc-input-field {\n\t\tbackground-color: var(--fc-input-error-bg);\n\t\tborder-color: var(--fc-input-error-color);\n\t}\n\n\t:host([touched]:invalid) .fc-input-field:focus {\n\t\tbox-shadow: 0 0 0 2px var(--fc-input-error-focus-ring);\n\t}\n\n\t.fc-input-wrapper {\n\t\tposition: relative;\n\t\tdisplay: flex;\n\t\talign-items: center;\n\t\twidth: 100%;\n\t}\n\n\t.fc-input-field {\n\t\twidth: 100%;\n\t\tbox-sizing: border-box;\n\n\t\tpadding: var(--fc-input-padding);\n\t\tborder-radius: var(--fc-input-radius);\n\t\tbackground: var(--fc-input-bg);\n\t\tcolor: var(--fc-input-fg);\n\n\t\tborder: var(--fc-input-border-width) solid var(--fc-input-border);\n\n\t\tfont-size: var(--fc-font-size-md);\n\n\t\tbox-shadow: var(--fc-input-shadow);\n\t\ttransition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n\t\tfont-family: inherit;\n\n\t\t-webkit-appearance: none;\n\t\tappearance: none;\n\t}\n\n\t.fc-input-field::placeholder {\n\t\tcolor: var(--fc-input-placeholder);\n\t}\n\n\t.fc-input-field:hover {\n\t\tborder-color: var(--fc-input-border-hover);\n\t}\n\n\t.fc-input-field:focus {\n\t\tborder-color: var(--fc-input-border-focus);\n\t\toutline: none;\n\t\tbox-shadow: var(--fc-input-focus-ring);\n\t}\n\n\t.fc-input-field:disabled {\n\t\tbackground: var(--fc-input-disabled-bg);\n\t\tcursor: not-allowed;\n\t\tbox-shadow: none;\n\t}\n\n\t.fc-input-field:disabled::placeholder {\n\t\tcolor: var(--fc-input-disabled-placeholder);\n }\n\n\t/* FILE type specific CSS */\n\n\t.fc-input-field[type="file"] {\n\t\tpadding: calc(var(--fc-input-padding));\n\t\tcursor: pointer;\n\t\tdisplay: flex; \n \talign-items: center;\n\t\tborder-color: var(--fc-input-file-border);\n\t\ttransition: border-color 0.15s ease-in-out, color 0.15s ease-in-out;\n\t}\n\n\t.fc-input-field[type="file"]:focus {\n\t\tborder-color: var(--fc-input-border-focus);\n\t\toutline: none;\n\t\tbox-shadow: var(--fc-input-focus-ring);\n\t}\n\n\t/* target the button inside type="file" */\n\n\t.fc-input-field::file-selector-button {\n\t\tpadding: 4px 10px;\n\t\tborder-radius: var(--fc-input-radius);\n\t\tbackground-color: var(--fc-input-btn-bg);\n\t\tcolor: var(--fc-input-file-btn-fg);\n\t\tborder: 1px solid var(--fc-input-file-border);\n\t\tcursor: pointer;\n\t\tfont-family: inherit;\n\t\ttransition: background-color 0.15s ease;\n\t}\n\n\t/* legacy browsers */\n\t.fc-input-field::-webkit-file-upload-button {\n\t\tmargin-right: 12px;\n\t\tpadding: 4px 10px;\n\t\tborder-radius: var(--fc-input-radius);\n\t\tbackground-color: var(--fc-input-file-btn-bg);\n\t\tcolor: var(--fc-input-file-btn-fg);\n\t\tborder: 1px solid var(--fc-input-file-border);\n\t\tcursor: pointer;\n\t\tfont-family: inherit;\n\t\tfont-size: 0.9em;\n\t}\n\n\t/* Hover effects for the button */\n\n\t.fc-input-field::file-selector-button:hover {\n\t\tbackground-color: var(--fc-input-file-btn-bg-hover); \n\t}\n\n\n\t.fc-input-field::-webkit-file-upload-button:hover {\n\t\tbackground-color: var(--fc-input-file-btn-bg-hover);\n\t}\n\n\t/* PASSWORD type specific CSS */\n\n\t/* when password toggle is visible, add padding to input so text doesn't overlap icon */\n\t:host([type="password"]) .fc-input-field {\n\t\tpadding-right: 40px; \n\t}\n\n\t.fc-password-toggle {\n\t\tposition: absolute;\n\t\tright: 8px; /* position inside the input */\n\t\ttop: 50%;\n\t\ttransform: translateY(-50%);\n\t\tbackground: transparent;\n\t\tborder: none;\n\t\tcursor: pointer;\n\t\tdisplay: flex;\n\t\talign-items: center;\n\t\tjustify-content: center;\n\t\tcolor: var(--fc-input-password-icon-color);\n\t\ttransition: color 0.15s ease-in-out;\n\t\tz-index: 2; /* above input */\n\t}\n\t\n\t.fc-password-toggle[hidden] {\n display: none !important;\n }\n\n\t.fc-password-toggle:hover {\n\t\tcolor: var(--fc-input-password-icon-color-hover);\n\t}\n\t\n\t.fc-password-toggle svg {\n\t\twidth: 20px;\n\t\theight: 20px;\n\t}\n\n\t.fc-password-toggle svg[hidden] {\n display: none !important;\n }\n\n`;
698
+
699
+ var template3 = document.createElement("template");
700
+
701
+ template3.innerHTML = `\n\t<style>${styles3}</style>\n\n\t<div class="fc-input-wrapper">\n\n\t\t\x3c!-- prefix slot here --\x3e\n\t\t\n\t\t<input \n\t\t\tid="fc-field" \n\t\t\tclass="fc-input-field" \n\t\t\tpart="input"\n\t\t\ttype="text"\n\t\t/>\n\n\t\t\x3c!-- password toggle button --\x3e\n\t\t<button \n\t\t\tid="btn-show-pass" \n\t\t\tclass="fc-password-toggle" \n\t\t\tpart="password-toggle" \n\t\t\ttype="button" \n\t\t\thidden \n\t\t\taria-label="Toggle password visibility"\n\t\t\taria-pressed="false"\n\t\t>\n\t\t\t<svg class="icon-eye" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n\t\t\t\t<path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path>\n\t\t\t\t<circle cx="12" cy="12" r="3"></circle>\n\t\t\t</svg>\n\t\t\t\n\t\t\t<svg class="icon-eye-off" hidden viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n\t\t\t\t<path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"></path>\n\t\t\t\t<line x1="1" y1="1" x2="23" y2="23"></line>\n\t\t\t</svg>\n\t\t</button>\n\n\t\t\x3c!-- suffix slot here --\x3e\n\t</div>\n`;
702
+
703
+ var FcInput = class extends HTMLElement {
704
+ constructor() {
705
+ super();
706
+ this._value = "";
707
+ this._validatorFunction = null;
708
+ this.ALLOWED_TYPES = [ "text", "email", "number", "password", "file", "url" ];
709
+ const shadow = this.attachShadow({
710
+ mode: "open",
711
+ delegatesFocus: true
712
+ });
713
+ shadow.appendChild(template3.content.cloneNode(true));
714
+ this.internals = this.attachInternals();
715
+ this.onInput = this.onInput.bind(this);
716
+ this.onChange = this.onChange.bind(this);
717
+ this.onBlur = this.onBlur.bind(this);
718
+ this.onTogglePassword = this.onTogglePassword.bind(this);
719
+ this.onInvalid = this.onInvalid.bind(this);
720
+ }
721
+ static get observedAttributes() {
722
+ return [ "value", "placeholder", "disabled", "name", "type", "required", "readonly", "min", "max", "step", "minlength", "maxlength", "pattern" ];
723
+ }
724
+ get validity() {
725
+ return this.internals.validity;
726
+ }
727
+ get validationMessage() {
728
+ return this.internals.validationMessage;
729
+ }
730
+ get willValidate() {
731
+ return this.internals.willValidate;
732
+ }
733
+ checkValidity() {
734
+ return this.internals.checkValidity();
735
+ }
736
+ reportValidity() {
737
+ return this.internals.reportValidity();
738
+ }
739
+ get value() {
740
+ return this._value;
741
+ }
742
+ set value(val) {
743
+ if (this.type === "file") {
744
+ return;
745
+ }
746
+ if (this.inputEl) {
747
+ this.inputEl.value = val;
748
+ this.syncValidity();
749
+ }
750
+ this._value = val;
751
+ this.internals.setFormValue(val);
752
+ }
753
+ get files() {
754
+ var _a, _b;
755
+ return (_b = (_a = this.inputEl) == null ? void 0 : _a.files) != null ? _b : null;
756
+ }
757
+ get placeholder() {
758
+ var _a;
759
+ return (_a = this.getAttribute("placeholder")) != null ? _a : "";
760
+ }
761
+ set placeholder(val) {
762
+ this.setAttribute("placeholder", val);
763
+ }
764
+ get type() {
765
+ var _a;
766
+ return (_a = this.getAttribute("type")) != null ? _a : "text";
767
+ }
768
+ set type(val) {
769
+ if (this.ALLOWED_TYPES.includes(val)) {
770
+ this.setAttribute("type", val);
771
+ return;
772
+ }
773
+ this.setAttribute("type", "text");
774
+ }
775
+ get name() {
776
+ var _a;
777
+ return (_a = this.getAttribute("name")) != null ? _a : "";
778
+ }
779
+ set name(val) {
780
+ this.setAttribute("name", val);
781
+ }
782
+ get disabled() {
783
+ return this.hasAttribute("disabled");
784
+ }
785
+ set disabled(val) {
786
+ if (val) {
787
+ this.setAttribute("disabled", "true");
788
+ return;
789
+ }
790
+ this.removeAttribute("disabled");
791
+ }
792
+ get required() {
793
+ return this.hasAttribute("required");
794
+ }
795
+ set required(val) {
796
+ if (val) {
797
+ this.setAttribute("required", "true");
798
+ return;
799
+ }
800
+ this.removeAttribute("required");
801
+ }
802
+ get readonly() {
803
+ return this.hasAttribute("readonly");
804
+ }
805
+ set readonly(val) {
806
+ if (val) {
807
+ this.setAttribute("readonly", "true");
808
+ return;
809
+ }
810
+ this.removeAttribute("readonly");
811
+ }
812
+ get validator() {
813
+ return this._validatorFunction;
814
+ }
815
+ set validator(func) {
816
+ this._validatorFunction = func;
817
+ this.syncValidity();
818
+ }
819
+ get min() {
820
+ var _a;
821
+ return (_a = this.getAttribute("min")) != null ? _a : "";
822
+ }
823
+ set min(val) {
824
+ this.setAttribute("min", val);
825
+ }
826
+ get max() {
827
+ var _a;
828
+ return (_a = this.getAttribute("max")) != null ? _a : "";
829
+ }
830
+ set max(val) {
831
+ this.setAttribute("max", val);
832
+ }
833
+ get step() {
834
+ var _a;
835
+ return (_a = this.getAttribute("step")) != null ? _a : "";
836
+ }
837
+ set step(val) {
838
+ this.setAttribute("step", val);
839
+ }
840
+ get minLength() {
841
+ return Number(this.getAttribute("minlength")) || -1;
842
+ }
843
+ set minLength(val) {
844
+ this.setAttribute("minlength", String(val));
845
+ }
846
+ get maxLength() {
847
+ return Number(this.getAttribute("maxlength")) || -1;
848
+ }
849
+ set maxLength(val) {
850
+ this.setAttribute("maxlength", String(val));
851
+ }
852
+ get pattern() {
853
+ var _a;
854
+ return (_a = this.getAttribute("pattern")) != null ? _a : "";
855
+ }
856
+ set pattern(val) {
857
+ this.setAttribute("pattern", val);
858
+ }
859
+ connectedCallback() {
860
+ this.inputEl = this.shadowRoot.getElementById("fc-field");
861
+ this.passwordBtnEl = this.shadowRoot.getElementById("btn-show-pass");
862
+ this.fcPassEnableIcon = this.shadowRoot.querySelector(".icon-eye");
863
+ this.fcPassDisableIcon = this.shadowRoot.querySelector(".icon-eye-off");
864
+ if (this.hasAttribute("type")) {
865
+ const type = this.getAttribute("type");
866
+ this.ALLOWED_TYPES.includes(type) ? this.inputEl.type = type : this.inputEl.type = "text";
867
+ if (this.passwordBtnEl) {
868
+ if (type === "password") {
869
+ this.passwordBtnEl.hidden = false;
870
+ this.updateToggleIcon(false);
871
+ } else {
872
+ this.passwordBtnEl.hidden = true;
873
+ }
874
+ }
875
+ }
876
+ if (this.hasAttribute("disabled")) {
877
+ this.inputEl.disabled = true;
878
+ this.internals.ariaDisabled = "true";
879
+ }
880
+ if (this.hasAttribute("readonly")) {
881
+ this.inputEl.readOnly = true;
882
+ }
883
+ if (this.hasAttribute("required")) {
884
+ this.inputEl.required = true;
885
+ }
886
+ if (this.hasAttribute("placeholder")) {
887
+ this.inputEl.placeholder = this.getAttribute("placeholder");
888
+ }
889
+ if (this.hasAttribute("min")) {
890
+ this.inputEl.min = this.getAttribute("min");
891
+ }
892
+ if (this.hasAttribute("max")) {
893
+ this.inputEl.max = this.getAttribute("max");
894
+ }
895
+ if (this.hasAttribute("step")) {
896
+ this.inputEl.step = this.getAttribute("step");
897
+ }
898
+ if (this.hasAttribute("pattern")) {
899
+ this.inputEl.pattern = this.getAttribute("pattern");
900
+ }
901
+ if (this.hasAttribute("minlength")) {
902
+ this.inputEl.minLength = Number(this.getAttribute("minlength"));
903
+ }
904
+ if (this.hasAttribute("maxlength")) {
905
+ this.inputEl.maxLength = Number(this.getAttribute("maxlength"));
906
+ }
907
+ if (this.type !== "file") {
908
+ this.inputEl.value = this._value;
909
+ }
910
+ if (this.type !== "file") {
911
+ this.internals.setFormValue(this._value);
912
+ }
913
+ this.inputEl.addEventListener("input", this.onInput);
914
+ this.inputEl.addEventListener("change", this.onChange);
915
+ this.inputEl.addEventListener("blur", this.onBlur);
916
+ this.passwordBtnEl.addEventListener("click", this.onTogglePassword);
917
+ this.addEventListener("invalid", this.onInvalid);
918
+ this.syncValidity();
919
+ }
920
+ disconnectedCallback() {
921
+ if (this.inputEl) {
922
+ this.inputEl.removeEventListener("input", this.onInput);
923
+ this.inputEl.removeEventListener("change", this.onChange);
924
+ this.inputEl.removeEventListener("blur", this.onBlur);
925
+ }
926
+ }
927
+ attributeChangedCallback(name, _oldVal, newVal) {
928
+ if (name === "value" && !(this.type === "file")) {
929
+ if (this.inputEl) {
930
+ this.inputEl.value = newVal;
931
+ this.syncValidity();
932
+ }
933
+ this._value = newVal;
934
+ this.internals.setFormValue(newVal);
935
+ return;
936
+ }
937
+ if (!this.inputEl) {
938
+ return;
939
+ }
940
+ switch (name) {
941
+ case "placeholder":
942
+ this.inputEl.placeholder = newVal;
943
+ break;
944
+
945
+ case "type":
946
+ const type = this.getAttribute("type");
947
+ this.ALLOWED_TYPES.includes(type) ? this.inputEl.type = type : this.inputEl.type = "text";
948
+ if (this.passwordBtnEl) {
949
+ if (type === "password") {
950
+ this.passwordBtnEl.hidden = false;
951
+ this.updateToggleIcon(false);
952
+ } else {
953
+ this.passwordBtnEl.hidden = true;
954
+ }
955
+ }
956
+ break;
957
+
958
+ case "disabled":
959
+ this.inputEl.disabled = this.hasAttribute("disabled");
960
+ this.internals.ariaDisabled = this.hasAttribute("disabled") ? "true" : "false";
961
+ break;
962
+
963
+ case "readonly":
964
+ this.inputEl.readOnly = this.hasAttribute("readonly");
965
+ break;
966
+
967
+ case "required":
968
+ this.inputEl.required = this.hasAttribute("required");
969
+ this.internals.ariaRequired = this.hasAttribute("required") ? "true" : "false";
970
+ this.syncValidity();
971
+ break;
972
+
973
+ case "name":
974
+ this.internals.setFormValue(this.value);
975
+ break;
976
+
977
+ case "min":
978
+ this.inputEl.min = newVal;
979
+ this.syncValidity();
980
+ break;
981
+
982
+ case "max":
983
+ this.inputEl.max = newVal;
984
+ this.syncValidity();
985
+ break;
986
+
987
+ case "step":
988
+ this.inputEl.step = newVal;
989
+ this.syncValidity();
990
+ break;
991
+
992
+ case "minlength":
993
+ this.inputEl.minLength = Number(newVal);
994
+ this.syncValidity();
995
+ break;
996
+
997
+ case "maxlength":
998
+ this.inputEl.maxLength = Number(newVal);
999
+ this.syncValidity();
1000
+ break;
1001
+
1002
+ case "pattern":
1003
+ this.inputEl.pattern = newVal;
1004
+ this.syncValidity();
1005
+ break;
1006
+ }
1007
+ }
1008
+ formResetCallback() {
1009
+ if (this.inputEl) {
1010
+ this.inputEl.value = "";
1011
+ }
1012
+ this._value = "";
1013
+ this.internals.setFormValue("");
1014
+ this.syncValidity();
1015
+ this.removeAttribute("touched");
1016
+ this.dispatchEvent(new CustomEvent("fc-reset", {
1017
+ bubbles: true,
1018
+ composed: true
1019
+ }));
1020
+ }
1021
+ formStateRestoreCallback(state, _mode) {
1022
+ if (this.type === "file") {
1023
+ return;
1024
+ }
1025
+ const restoredValue = state;
1026
+ if (restoredValue) {
1027
+ if (this.type === "file") {
1028
+ return;
1029
+ }
1030
+ if (this.inputEl) {
1031
+ this.inputEl.value = restoredValue;
1032
+ this.syncValidity();
1033
+ }
1034
+ this._value = restoredValue;
1035
+ this.internals.setFormValue(restoredValue);
1036
+ }
1037
+ }
1038
+ onInput(e) {
1039
+ const value = e.target.value;
1040
+ this._value = value;
1041
+ if (this.type !== "file") {
1042
+ this.internals.setFormValue(value);
1043
+ }
1044
+ this.syncValidity();
1045
+ this.dispatchEvent(new CustomEvent("fc-input", {
1046
+ detail: {
1047
+ value: value
1048
+ },
1049
+ bubbles: true,
1050
+ composed: true
1051
+ }));
1052
+ }
1053
+ onChange(e) {
1054
+ const target = e.target;
1055
+ this._value = target.value;
1056
+ this.internals.setFormValue(target.value);
1057
+ this.syncValidity();
1058
+ this.dispatchEvent(new CustomEvent("fc-change", {
1059
+ detail: {
1060
+ value: target.value,
1061
+ files: target.files
1062
+ },
1063
+ bubbles: true,
1064
+ composed: true
1065
+ }));
1066
+ }
1067
+ onBlur() {
1068
+ this.setAttribute("touched", "");
1069
+ }
1070
+ onInvalid(e) {
1071
+ this.setAttribute("touched", "");
1072
+ }
1073
+ onTogglePassword(e) {
1074
+ e.preventDefault();
1075
+ if (this.inputEl.type === "password") {
1076
+ this.inputEl.type = "text";
1077
+ this.updateToggleIcon(true);
1078
+ this.passwordBtnEl.setAttribute("aria-pressed", "true");
1079
+ this.inputEl.focus();
1080
+ return;
1081
+ }
1082
+ if (this.inputEl.type === "text") {
1083
+ this.inputEl.type = "password";
1084
+ this.updateToggleIcon(false);
1085
+ this.passwordBtnEl.setAttribute("aria-pressed", "false");
1086
+ this.inputEl.focus();
1087
+ }
1088
+ }
1089
+ updateToggleIcon(isVisible) {
1090
+ if (isVisible) {
1091
+ this.fcPassEnableIcon.setAttribute("hidden", "true");
1092
+ this.fcPassDisableIcon.removeAttribute("hidden");
1093
+ return;
1094
+ }
1095
+ this.fcPassEnableIcon.removeAttribute("hidden");
1096
+ this.fcPassDisableIcon.setAttribute("hidden", "true");
1097
+ }
1098
+ syncValidity() {
1099
+ if (!this.inputEl) {
1100
+ return;
1101
+ }
1102
+ if (!this.inputEl.validity.valid) {
1103
+ this.internals.setValidity(this.inputEl.validity, this.inputEl.validationMessage, this.inputEl);
1104
+ return;
1105
+ }
1106
+ if (this._validatorFunction) {
1107
+ const customErrorMessage = this._validatorFunction(this.value);
1108
+ if (customErrorMessage) {
1109
+ this.internals.setValidity({
1110
+ customError: true
1111
+ }, customErrorMessage, this.inputEl);
1112
+ return;
1113
+ }
1114
+ }
1115
+ this.internals.setValidity({});
1116
+ return;
1117
+ }
1118
+ setProps(props) {
1119
+ for (const property in props) {
1120
+ const value = props[property];
1121
+ if (property in this) {
1122
+ this[property] = value;
1123
+ continue;
1124
+ }
1125
+ if ([ "string", "number", "boolean" ].includes(typeof value)) {
1126
+ this.setAttribute(property, String(value));
1127
+ }
1128
+ }
1129
+ }
1130
+ };
1131
+
1132
+ FcInput.formAssociated = true;
1133
+
1134
+ var defineInput = () => {
1135
+ if (!customElements.get("fc-input")) {
1136
+ customElements.define("fc-input", FcInput);
1137
+ }
1138
+ return FcInput;
1139
+ };
1140
+
1141
+ var styles4 = `\n :host {\n display: block;\n width: 100%;\n\t\tbox-sizing: border-box;\n contain: content;\n max-width: var(--fc-error-max-width);\n }\n\n :host([hidden]) {\n display: none !important;\n }\n\n .fc-error-text {\n color: var(--fc-error-color);\n font-family: var(--fc-font-family, inherit);\n font-size: var(--fc-error-font-size);\n display: flex;\n align-items: center;\n gap: 4px;\n }\n`;
1142
+
1143
+ var template4 = document.createElement("template");
1144
+
1145
+ template4.innerHTML = `\n <style>${styles4}</style>\n <div class="fc-error-text" part="text" aria-live="polite">\n </div>\n`;
1146
+
1147
+ var FcError = class extends HTMLElement {
1148
+ constructor() {
1149
+ super();
1150
+ this.targetEl = null;
1151
+ const shadow = this.attachShadow({
1152
+ mode: "open"
1153
+ });
1154
+ shadow.appendChild(template4.content.cloneNode(true));
1155
+ this.errorTextEl = shadow.querySelector(".fc-error-text");
1156
+ this.handleErrorState = this.handleErrorState.bind(this);
1157
+ }
1158
+ static get observedAttributes() {
1159
+ return [ "for" ];
1160
+ }
1161
+ connectedCallback() {
1162
+ this.findTarget();
1163
+ }
1164
+ disconnectedCallback() {
1165
+ this.cleanup();
1166
+ }
1167
+ attributeChangedCallback(name, oldVal, newVal) {
1168
+ if (name === "for" && oldVal !== newVal) {
1169
+ this.findTarget();
1170
+ }
1171
+ }
1172
+ handleErrorState() {
1173
+ if (!this.targetEl) {
1174
+ return;
1175
+ }
1176
+ const isTouched = this.targetEl.hasAttribute("touched");
1177
+ const isValid = this.targetEl.validity.valid;
1178
+ if (!isValid && isTouched) {
1179
+ this.removeAttribute("hidden");
1180
+ this.errorTextEl.textContent = this.targetEl.validationMessage;
1181
+ return;
1182
+ }
1183
+ this.setAttribute("hidden", "");
1184
+ }
1185
+ findTarget() {
1186
+ this.cleanup();
1187
+ const targetId = this.getAttribute("for");
1188
+ if (!targetId) {
1189
+ return;
1190
+ }
1191
+ const target = document.getElementById(targetId);
1192
+ if (target) {
1193
+ this.targetEl = target;
1194
+ this.bindListeners();
1195
+ }
1196
+ }
1197
+ bindListeners() {
1198
+ if (!this.targetEl) {
1199
+ return;
1200
+ }
1201
+ this.targetEl.addEventListener("blur", this.handleErrorState);
1202
+ this.targetEl.addEventListener("invalid", this.handleErrorState);
1203
+ this.targetEl.addEventListener("fc-input", this.handleErrorState);
1204
+ this.targetEl.addEventListener("fc-change", this.handleErrorState);
1205
+ this.targetEl.addEventListener("fc-reset", this.handleErrorState);
1206
+ }
1207
+ cleanup() {
1208
+ if (this.targetEl) {
1209
+ this.targetEl.removeEventListener("blur", this.handleErrorState);
1210
+ this.targetEl.removeEventListener("invalid", this.handleErrorState);
1211
+ this.targetEl.removeEventListener("fc-input", this.handleErrorState);
1212
+ this.targetEl.removeEventListener("fc-change", this.handleErrorState);
1213
+ this.targetEl.removeEventListener("fc-reset", this.handleErrorState);
1214
+ this.targetEl = null;
1215
+ }
1216
+ }
1217
+ };
1218
+
1219
+ var defineError = () => {
1220
+ if (!customElements.get("fc-error")) {
1221
+ customElements.define("fc-error", FcError);
1222
+ }
1223
+ return FcError;
1224
+ };
1225
+
1226
+ var defineAll = () => {
1227
+ defineCombobox();
1228
+ defineOption();
1229
+ defineInput();
1230
+ defineError();
1231
+ };
1232
+
1233
+ export { FcCombobox, FcError, FcInput, FcOption, defineAll, defineCombobox, defineError, defineInput, defineOption };