fancy-ui-ts 1.3.0 → 1.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.css CHANGED
@@ -134,8 +134,25 @@
134
134
  --fc-label-font-size: var(--fc-font-size-md);
135
135
  --fc-label-font-weight: var(--fc-font-weight-bold);
136
136
  --fc-label-fg: var(--fc-gray-900);
137
+ --fc-select-bg: var(--fc-white);
138
+ --fc-select-bg-disabled: var(--fc-gray-50);
139
+ --fc-select-fg: var(--fc-gray-900);
140
+ --fc-select-border: var(--fc-gray-300);
141
+ --fc-select-border-hover: var(--fc-gray-400);
142
+ --fc-select-border-focus: var(--fc-primary-400);
143
+ --fc-select-placeholder: var(--fc-gray-400);
144
+ --fc-select-placeholder-disabled: var(--fc-gray-300);
145
+ --fc-select-focus-ring: var(--fc-focus-ring-sm) var(--fc-focus-ring-primary);
146
+ --fc-select-bg-error: var(--fc-danger-50);
147
+ --fc-select-border-error: var(--fc-danger-300);
148
+ --fc-select-focus-ring-error: var(--fc-focus-ring-danger);
137
149
  --fc-select-dropdown-icon-width: calc(var(--fc-font-size-md) + 4px);
138
150
  --fc-select-dropdown-icon-height: calc(var(--fc-font-size-md) + 4px);
151
+ --fc-select-max-width: 412px;
152
+ --fc-select-padding: var(--fc-space-3);
153
+ --fc-select-border-width: var(--fc-border-width-xs);
154
+ --fc-select-radius: var(--fc-radius-md);
155
+ --fc-select-shadow: var(--fc-shadow-none);
139
156
  }
140
157
 
141
158
  /* src/styles/themes/fc-theme-light.css */
@@ -188,6 +205,18 @@
188
205
  --fc-label-font-size: var(--fc-font-size-md);
189
206
  --fc-label-font-weight: var(--fc-font-weight-bold);
190
207
  --fc-label-fg: var(--fc-gray-900);
208
+ --fc-select-bg: var(--fc-white);
209
+ --fc-select-bg-disabled: var(--fc-gray-50);
210
+ --fc-select-fg: var(--fc-gray-900);
211
+ --fc-select-border: var(--fc-gray-300);
212
+ --fc-select-border-hover: var(--fc-gray-400);
213
+ --fc-select-border-focus: var(--fc-primary-400);
214
+ --fc-select-placeholder: var(--fc-gray-400);
215
+ --fc-select-placeholder-disabled: var(--fc-gray-300);
216
+ --fc-select-focus-ring: var(--fc-focus-ring-sm) var(--fc-focus-ring-primary);
217
+ --fc-select-bg-error: var(--fc-danger-50);
218
+ --fc-select-border-error: var(--fc-danger-300);
219
+ --fc-select-focus-ring-error: var(--fc-focus-ring-danger);
191
220
  }
192
221
 
193
222
  /* src/styles/themes/fc-theme-dark.css */
@@ -240,4 +269,13 @@
240
269
  --fc-label-font-size: var(--fc-font-size-md);
241
270
  --fc-label-font-weight: var(--fc-font-weight-bold);
242
271
  --fc-label-fg: var(--fc-gray-200);
272
+ --fc-select-bg: var(--fc-gray-800);
273
+ --fc-select-bg-disabled: var(--fc-gray-900);
274
+ --fc-select-fg: var(--fc-gray-200);
275
+ --fc-select-border: var(--fc-gray-700);
276
+ --fc-select-border-hover: var(--fc-gray-500);
277
+ --fc-select-border-focus: var(--fc-primary-400);
278
+ --fc-select-placeholder: var(--fc-gray-500);
279
+ --fc-select-placeholder-disabled: var(--fc-gray-700);
280
+ --fc-select-focus-ring: var(--fc-focus-ring-sm) var(--fc-focus-ring-secondary);
243
281
  }
package/dist/index.d.ts CHANGED
@@ -191,6 +191,7 @@ declare class FcSelect extends HTMLElement {
191
191
  private activeIndex;
192
192
  private searchBuffer;
193
193
  private searchTimeout;
194
+ private _validatorFunction;
194
195
  constructor();
195
196
  get validity(): ValidityState;
196
197
  get validationMessage(): string;
@@ -218,7 +219,8 @@ declare class FcSelect extends HTMLElement {
218
219
  }[]);
219
220
  get required(): boolean;
220
221
  set required(val: boolean);
221
- get readonly(): boolean;
222
+ get validator(): ((value: string) => string | null) | null;
223
+ set validator(func: ((value: string) => string | null) | null);
222
224
  connectedCallback(): void;
223
225
  attributeChangedCallback(name: string, _old: string, newVal: string): void;
224
226
  disconnectedCallback(): void;
@@ -237,7 +239,8 @@ declare class FcSelect extends HTMLElement {
237
239
  private setActiveOption;
238
240
  private getVisibleOptions;
239
241
  private selectOption;
240
- private toggleDropdown;
242
+ private showDropdown;
243
+ private hideDropdown;
241
244
  private syncValidity;
242
245
  setProps(props: Record<string, any>): void;
243
246
  }
package/dist/index.js CHANGED
@@ -1343,7 +1343,7 @@ var defineLabel = () => {
1343
1343
  return FcLabel;
1344
1344
  };
1345
1345
 
1346
- var styles6 = `\n :host {\n display: block;\n position: relative;\n width: 100%;\n box-sizing: border-box;\n font-family: var(--fc-font-family);\n max-width: var(--fc-combobox-max-width);\n cursor: pointer; \n }\n\n \n .fc-input {\n width: 100%;\n box-sizing: border-box;\n padding: var(--fc-combobox-padding);\n padding-right: 36px;\n \n border-radius: var(--fc-combobox-radius);\n background: var(--fc-combobox-bg);\n color: var(--fc-combobox-fg);\n border: var(--fc-combobox-border-width) solid var(--fc-combobox-border);\n font-size: var(--fc-font-size-md);\n box-shadow: var(--fc-combobox-shadow);\n transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n \n cursor: pointer; \n caret-color: transparent; \n user-select: none;\n }\n\n \n :host([touched]:invalid) .fc-input {\n background-color: var(--fc-combobox-bg-error);\n border-color: var(--fc-combobox-border-error);\n }\n\n :host([touched]:invalid) .fc-input:focus {\n box-shadow: 0 0 0 2px var(--fc-combobox-focus-ring-error);\n }\n\n .fc-input::placeholder {\n color: var(--fc-combobox-placeholder);\n }\n\n .fc-input:hover {\n border-color: var(--fc-combobox-border-hover);\n }\n\n .fc-input:focus {\n border-color: var(--fc-combobox-border-focus);\n outline: none;\n box-shadow: var(--fc-combobox-focus-ring);\n }\n\n \n .fc-chevron {\n position: absolute;\n right: 12px;\n top: 50%;\n transform: translateY(-50%);\n width: var(--fc-select-dropdown-icon-width);\n height: var(--fc-select-dropdown-icon-height);\n pointer-events: none;\n color: var(--fc-combobox-fg);\n transition: transform 0.2s ease;\n }\n\n \n :host([open]) .fc-chevron {\n transform: translateY(-50%) rotate(180deg);\n }\n\n :host([disabled]) {\n cursor: not-allowed;\n }\n\n .fc-input:disabled {\n background: var(--fc-combobox-bg-disabled);\n cursor: not-allowed;\n box-shadow: none;\n color: var(--fc-combobox-placeholder-disabled);\n }\n\n :host([disabled]) .fc-chevron {\n color: var(--fc-combobox-placeholder-disabled);\n }\n\n .fc-options {\n position: absolute;\n top: calc(100% + 6px);\n left: 0;\n right: 0;\n z-index: 1000;\n background: var(--fc-combobox-dropdown-bg, var(--fc-combobox-bg));\n border: var(--fc-combobox-border-width) solid var(--fc-combobox-border);\n border-radius: var(--fc-combobox-dropdown-radius, var(--fc-combobox-radius));\n padding: var(--fc-combobox-dropdown-padding, calc(var(--fc-combobox-padding) - 5px));\n box-shadow: var(--fc-combobox-dropdown-shadow);\n max-height: var(--fc-combobox-dropdown-max-height, 240px);\n overflow-y: auto;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n gap: 4px;\n }\n\n .fc-options.opens-up {\n top: auto;\n bottom: calc(100% + 6px);\n }\n \n .fc-options[hidden] {\n display: none !important;\n }\n`;
1346
+ var styles6 = `\n :host {\n display: block;\n position: relative;\n width: 100%;\n box-sizing: border-box;\n font-family: var(--fc-font-family);\n max-width: var(--fc-select-max-width);\n cursor: pointer; \n }\n\n \n .fc-input {\n width: 100%;\n box-sizing: border-box;\n padding: var(--fc-select-padding);\n padding-right: 36px; /* space for dropdown icon */\n border-radius: var(--fc-select-radius);\n background: var(--fc-select-bg);\n color: var(--fc-select-fg);\n border: var(--fc-select-border-width) solid var(--fc-select-border);\n font-size: var(--fc-font-size-md);\n box-shadow: var(--fc-select-shadow);\n transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n \n cursor: pointer; \n caret-color: transparent; \n user-select: none;\n }\n\n \n :host([touched]:invalid) .fc-input {\n background-color: var(--fc-select-bg-error);\n border-color: var(--fc-select-border-error);\n }\n\n :host([touched]:invalid) .fc-input:focus {\n box-shadow: 0 0 0 2px var(--fc-select-focus-ring-error);\n }\n\n .fc-input::placeholder {\n color: var(--fc-select-placeholder);\n }\n\n .fc-input:hover {\n border-color: var(--fc-select-border-hover);\n }\n\n .fc-input:focus {\n border-color: var(--fc-select-border-focus);\n outline: none;\n box-shadow: var(--fc-select-focus-ring);\n }\n\n \n .fc-chevron {\n position: absolute;\n right: 12px;\n top: 50%;\n transform: translateY(-50%);\n width: var(--fc-select-dropdown-icon-width);\n height: var(--fc-select-dropdown-icon-height);\n pointer-events: none;\n color: var(--fc-select-fg);\n transition: transform 0.2s ease;\n }\n\n \n :host([open]) .fc-chevron {\n transform: translateY(-50%) rotate(180deg);\n }\n\n :host([disabled]) {\n cursor: not-allowed;\n }\n\n .fc-input:disabled {\n background: var(--fc-select-bg-disabled);\n cursor: not-allowed;\n box-shadow: none;\n color: var(--fc-select-placeholder-disabled);\n }\n\n :host([disabled]) .fc-chevron {\n color: var(--fc-select-placeholder-disabled);\n }\n\n .fc-options {\n position: absolute;\n top: calc(100% + 6px);\n left: 0;\n right: 0;\n z-index: 1000;\n background: var(--fc-select-dropdown-bg, var(--fc-select-bg));\n border: var(--fc-select-border-width) solid var(--fc-select-border);\n border-radius: var(--fc-select-dropdown-radius, var(--fc-select-radius));\n padding: var(--fc-select-dropdown-padding, calc(var(--fc-select-padding) - 5px));\n box-shadow: var(--fc-select-dropdown-shadow);\n max-height: var(--fc-select-dropdown-max-height, 240px);\n overflow-y: auto;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n gap: 4px;\n }\n\n .fc-options.opens-up {\n top: auto;\n bottom: calc(100% + 6px);\n }\n \n .fc-options[hidden] {\n display: none !important;\n }\n`;
1347
1347
 
1348
1348
  var template6 = document.createElement("template");
1349
1349
 
@@ -1356,6 +1356,7 @@ var FcSelect = class extends HTMLElement {
1356
1356
  this.activeIndex = -1;
1357
1357
  this.searchBuffer = "";
1358
1358
  this.searchTimeout = null;
1359
+ this._validatorFunction = null;
1359
1360
  const shadow = this.attachShadow({
1360
1361
  mode: "open",
1361
1362
  delegatesFocus: true
@@ -1467,8 +1468,12 @@ var FcSelect = class extends HTMLElement {
1467
1468
  }
1468
1469
  this.removeAttribute("required");
1469
1470
  }
1470
- get readonly() {
1471
- return this.hasAttribute("readonly");
1471
+ get validator() {
1472
+ return this._validatorFunction;
1473
+ }
1474
+ set validator(func) {
1475
+ this._validatorFunction = func;
1476
+ this.syncValidity();
1472
1477
  }
1473
1478
  connectedCallback() {
1474
1479
  this.internals.setFormValue(this.value);
@@ -1509,7 +1514,7 @@ var FcSelect = class extends HTMLElement {
1509
1514
  this.inputEl.disabled = isDisabled;
1510
1515
  this.internals.ariaDisabled = isDisabled ? "true" : "false";
1511
1516
  if (isDisabled) {
1512
- this.toggleDropdown(false);
1517
+ this.hideDropdown();
1513
1518
  }
1514
1519
  }
1515
1520
  if (name === "required" && this.inputEl) {
@@ -1532,7 +1537,7 @@ var FcSelect = class extends HTMLElement {
1532
1537
  options.forEach(option => {
1533
1538
  option.selected = false;
1534
1539
  });
1535
- this.toggleDropdown(false);
1540
+ this.hideDropdown();
1536
1541
  this.removeAttribute("touched");
1537
1542
  this.syncValidity();
1538
1543
  this.dispatchEvent(new CustomEvent("fc-reset", {
@@ -1565,7 +1570,11 @@ var FcSelect = class extends HTMLElement {
1565
1570
  if (this.disabled) {
1566
1571
  return;
1567
1572
  }
1568
- this.toggleDropdown(this.dropdownEl.hidden);
1573
+ if (this.dropdownEl.hidden) {
1574
+ this.showDropdown();
1575
+ } else {
1576
+ this.hideDropdown();
1577
+ }
1569
1578
  }
1570
1579
  onChange(e) {
1571
1580
  e.stopPropagation();
@@ -1592,7 +1601,7 @@ var FcSelect = class extends HTMLElement {
1592
1601
  option.selected = selected;
1593
1602
  option.active = false;
1594
1603
  });
1595
- this.toggleDropdown(false);
1604
+ this.hideDropdown();
1596
1605
  this.syncValidity();
1597
1606
  this.dispatchEvent(new CustomEvent("fc-change", {
1598
1607
  detail: {
@@ -1605,13 +1614,13 @@ var FcSelect = class extends HTMLElement {
1605
1614
  }
1606
1615
  onOutsideClick(e) {
1607
1616
  if (!this.contains(e.target)) {
1608
- this.toggleDropdown(false);
1617
+ this.hideDropdown();
1609
1618
  }
1610
1619
  }
1611
1620
  onFocusOut(e) {
1612
1621
  const target = e.relatedTarget;
1613
1622
  if (!target || !this.contains(target)) {
1614
- this.toggleDropdown(false);
1623
+ this.hideDropdown();
1615
1624
  }
1616
1625
  }
1617
1626
  onSlotChange() {
@@ -1640,7 +1649,7 @@ var FcSelect = class extends HTMLElement {
1640
1649
  if (e.key === "ArrowDown") {
1641
1650
  e.preventDefault();
1642
1651
  if (this.dropdownEl.hidden) {
1643
- this.toggleDropdown(true);
1652
+ this.showDropdown();
1644
1653
  return;
1645
1654
  }
1646
1655
  const nextIndex = this.activeIndex >= options.length - 1 ? 0 : this.activeIndex + 1;
@@ -1648,7 +1657,7 @@ var FcSelect = class extends HTMLElement {
1648
1657
  } else if (e.key === "ArrowUp") {
1649
1658
  e.preventDefault();
1650
1659
  if (this.dropdownEl.hidden) {
1651
- this.toggleDropdown(true);
1660
+ this.showDropdown();
1652
1661
  return;
1653
1662
  }
1654
1663
  const prevIndex = this.activeIndex <= 0 ? options.length - 1 : this.activeIndex - 1;
@@ -1656,20 +1665,20 @@ var FcSelect = class extends HTMLElement {
1656
1665
  } else if (e.key === "Enter" || e.key === " ") {
1657
1666
  e.preventDefault();
1658
1667
  if (this.dropdownEl.hidden) {
1659
- this.toggleDropdown(true);
1668
+ this.showDropdown();
1660
1669
  } else {
1661
1670
  if (this.activeIndex > -1 && options[this.activeIndex]) {
1662
1671
  const target = options[this.activeIndex];
1663
1672
  this.selectOption(target);
1664
1673
  } else {
1665
- this.toggleDropdown(false);
1674
+ this.hideDropdown();
1666
1675
  }
1667
1676
  }
1668
1677
  } else if (e.key === "Escape") {
1669
1678
  e.preventDefault();
1670
- this.toggleDropdown(false);
1679
+ this.hideDropdown();
1671
1680
  } else if (e.key === "Tab") {
1672
- this.toggleDropdown(false);
1681
+ this.hideDropdown();
1673
1682
  } else if (e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) {
1674
1683
  e.preventDefault();
1675
1684
  this.handleTypeAhead(e.key);
@@ -1738,7 +1747,7 @@ var FcSelect = class extends HTMLElement {
1738
1747
  opt.selected = selected;
1739
1748
  opt.active = false;
1740
1749
  });
1741
- this.toggleDropdown(false);
1750
+ this.hideDropdown();
1742
1751
  this.syncValidity();
1743
1752
  this.dispatchEvent(new CustomEvent("fc-change", {
1744
1753
  detail: {
@@ -1749,41 +1758,41 @@ var FcSelect = class extends HTMLElement {
1749
1758
  composed: true
1750
1759
  }));
1751
1760
  }
1752
- toggleDropdown(show) {
1753
- if (!this.dropdownEl) {
1761
+ showDropdown() {
1762
+ if (!this.dropdownEl || this.disabled) {
1754
1763
  return;
1755
1764
  }
1756
- if (this.disabled && show) {
1765
+ const dropdown = this.dropdownEl;
1766
+ const showEvent = new CustomEvent("fc-show", {
1767
+ bubbles: true,
1768
+ composed: true,
1769
+ cancelable: true
1770
+ });
1771
+ this.dispatchEvent(showEvent);
1772
+ if (showEvent.defaultPrevented) {
1757
1773
  return;
1758
1774
  }
1759
- const dropdown = this.dropdownEl;
1760
- if (show) {
1761
- const showEvent = new CustomEvent("fc-show", {
1762
- bubbles: true,
1763
- composed: true,
1764
- cancelable: true
1765
- });
1766
- this.dispatchEvent(showEvent);
1767
- if (showEvent.defaultPrevented) {
1768
- return;
1769
- }
1770
- const spaceBelow = calculateBottomAvaliableSpace(this.inputEl);
1771
- const spaceAbove = calculateTopAvaliableSpace(this.inputEl);
1772
- dropdown.hidden = false;
1773
- this.setAttribute("open", "true");
1774
- this.inputEl.setAttribute("aria-expanded", "true");
1775
- const shouldOpenUp = spaceBelow < dropdown.clientHeight && spaceAbove > spaceBelow;
1776
- dropdown.classList.toggle("opens-up", shouldOpenUp);
1777
- const options = this.getVisibleOptions();
1778
- const selectedIndex = options.findIndex(opt => opt.value === this._value);
1779
- if (selectedIndex >= 0) {
1780
- this.setActiveOption(selectedIndex, options);
1781
- } else {
1782
- this.activeIndex = -1;
1783
- }
1784
- setTimeout(() => {
1785
- document.addEventListener("click", this.onOutsideClick);
1786
- }, 0);
1775
+ const spaceBelow = calculateBottomAvaliableSpace(this.inputEl);
1776
+ const spaceAbove = calculateTopAvaliableSpace(this.inputEl);
1777
+ dropdown.hidden = false;
1778
+ this.setAttribute("open", "true");
1779
+ this.inputEl.setAttribute("aria-expanded", "true");
1780
+ const shouldOpenUp = spaceBelow < dropdown.clientHeight && spaceAbove > spaceBelow;
1781
+ dropdown.classList.toggle("opens-up", shouldOpenUp);
1782
+ const options = this.getVisibleOptions();
1783
+ const selectedIndex = options.findIndex(opt => opt.value === this._value);
1784
+ if (selectedIndex >= 0) {
1785
+ this.setActiveOption(selectedIndex, options);
1786
+ } else {
1787
+ this.activeIndex = -1;
1788
+ }
1789
+ setTimeout(() => {
1790
+ document.addEventListener("click", this.onOutsideClick);
1791
+ }, 0);
1792
+ return;
1793
+ }
1794
+ hideDropdown() {
1795
+ if (!this.dropdownEl) {
1787
1796
  return;
1788
1797
  }
1789
1798
  if (!this.dropdownEl.hidden) {
@@ -1808,18 +1817,15 @@ var FcSelect = class extends HTMLElement {
1808
1817
  this.internals.setValidity(this.inputEl.validity, this.inputEl.validationMessage, this.inputEl);
1809
1818
  return;
1810
1819
  }
1811
- const options = this.querySelectorAll("fc-option");
1812
- let match = false;
1813
- options.forEach(option => {
1814
- if (option.value === this._value) {
1815
- match = true;
1820
+ this.querySelectorAll("fc-option");
1821
+ if (this._validatorFunction) {
1822
+ const customErrorMessage = this._validatorFunction(this.value);
1823
+ if (customErrorMessage) {
1824
+ this.internals.setValidity({
1825
+ customError: true
1826
+ }, customErrorMessage, this.inputEl);
1827
+ return;
1816
1828
  }
1817
- });
1818
- if (!match) {
1819
- this.internals.setValidity({
1820
- customError: true
1821
- }, "Please select a valid option from the list.", this.inputEl);
1822
- return;
1823
1829
  }
1824
1830
  this.internals.setValidity({});
1825
1831
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fancy-ui-ts",
3
- "version": "1.3.0",
3
+ "version": "1.3.2",
4
4
  "type": "module",
5
5
  "description": "A library to easily create cool and customizable webcomponents.",
6
6
  "main": "dist/index.js",