fancy-ui-ts 1.3.0 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/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;
@@ -237,7 +238,8 @@ declare class FcSelect extends HTMLElement {
237
238
  private setActiveOption;
238
239
  private getVisibleOptions;
239
240
  private selectOption;
240
- private toggleDropdown;
241
+ private showDropdown;
242
+ private hideDropdown;
241
243
  private syncValidity;
242
244
  setProps(props: Record<string, any>): void;
243
245
  }
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
@@ -1509,7 +1510,7 @@ var FcSelect = class extends HTMLElement {
1509
1510
  this.inputEl.disabled = isDisabled;
1510
1511
  this.internals.ariaDisabled = isDisabled ? "true" : "false";
1511
1512
  if (isDisabled) {
1512
- this.toggleDropdown(false);
1513
+ this.hideDropdown();
1513
1514
  }
1514
1515
  }
1515
1516
  if (name === "required" && this.inputEl) {
@@ -1532,7 +1533,7 @@ var FcSelect = class extends HTMLElement {
1532
1533
  options.forEach(option => {
1533
1534
  option.selected = false;
1534
1535
  });
1535
- this.toggleDropdown(false);
1536
+ this.hideDropdown();
1536
1537
  this.removeAttribute("touched");
1537
1538
  this.syncValidity();
1538
1539
  this.dispatchEvent(new CustomEvent("fc-reset", {
@@ -1565,7 +1566,11 @@ var FcSelect = class extends HTMLElement {
1565
1566
  if (this.disabled) {
1566
1567
  return;
1567
1568
  }
1568
- this.toggleDropdown(this.dropdownEl.hidden);
1569
+ if (this.dropdownEl.hidden) {
1570
+ this.showDropdown();
1571
+ } else {
1572
+ this.hideDropdown();
1573
+ }
1569
1574
  }
1570
1575
  onChange(e) {
1571
1576
  e.stopPropagation();
@@ -1592,7 +1597,7 @@ var FcSelect = class extends HTMLElement {
1592
1597
  option.selected = selected;
1593
1598
  option.active = false;
1594
1599
  });
1595
- this.toggleDropdown(false);
1600
+ this.hideDropdown();
1596
1601
  this.syncValidity();
1597
1602
  this.dispatchEvent(new CustomEvent("fc-change", {
1598
1603
  detail: {
@@ -1605,13 +1610,13 @@ var FcSelect = class extends HTMLElement {
1605
1610
  }
1606
1611
  onOutsideClick(e) {
1607
1612
  if (!this.contains(e.target)) {
1608
- this.toggleDropdown(false);
1613
+ this.hideDropdown();
1609
1614
  }
1610
1615
  }
1611
1616
  onFocusOut(e) {
1612
1617
  const target = e.relatedTarget;
1613
1618
  if (!target || !this.contains(target)) {
1614
- this.toggleDropdown(false);
1619
+ this.hideDropdown();
1615
1620
  }
1616
1621
  }
1617
1622
  onSlotChange() {
@@ -1640,7 +1645,7 @@ var FcSelect = class extends HTMLElement {
1640
1645
  if (e.key === "ArrowDown") {
1641
1646
  e.preventDefault();
1642
1647
  if (this.dropdownEl.hidden) {
1643
- this.toggleDropdown(true);
1648
+ this.showDropdown();
1644
1649
  return;
1645
1650
  }
1646
1651
  const nextIndex = this.activeIndex >= options.length - 1 ? 0 : this.activeIndex + 1;
@@ -1648,7 +1653,7 @@ var FcSelect = class extends HTMLElement {
1648
1653
  } else if (e.key === "ArrowUp") {
1649
1654
  e.preventDefault();
1650
1655
  if (this.dropdownEl.hidden) {
1651
- this.toggleDropdown(true);
1656
+ this.showDropdown();
1652
1657
  return;
1653
1658
  }
1654
1659
  const prevIndex = this.activeIndex <= 0 ? options.length - 1 : this.activeIndex - 1;
@@ -1656,20 +1661,20 @@ var FcSelect = class extends HTMLElement {
1656
1661
  } else if (e.key === "Enter" || e.key === " ") {
1657
1662
  e.preventDefault();
1658
1663
  if (this.dropdownEl.hidden) {
1659
- this.toggleDropdown(true);
1664
+ this.showDropdown();
1660
1665
  } else {
1661
1666
  if (this.activeIndex > -1 && options[this.activeIndex]) {
1662
1667
  const target = options[this.activeIndex];
1663
1668
  this.selectOption(target);
1664
1669
  } else {
1665
- this.toggleDropdown(false);
1670
+ this.hideDropdown();
1666
1671
  }
1667
1672
  }
1668
1673
  } else if (e.key === "Escape") {
1669
1674
  e.preventDefault();
1670
- this.toggleDropdown(false);
1675
+ this.hideDropdown();
1671
1676
  } else if (e.key === "Tab") {
1672
- this.toggleDropdown(false);
1677
+ this.hideDropdown();
1673
1678
  } else if (e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) {
1674
1679
  e.preventDefault();
1675
1680
  this.handleTypeAhead(e.key);
@@ -1738,7 +1743,7 @@ var FcSelect = class extends HTMLElement {
1738
1743
  opt.selected = selected;
1739
1744
  opt.active = false;
1740
1745
  });
1741
- this.toggleDropdown(false);
1746
+ this.hideDropdown();
1742
1747
  this.syncValidity();
1743
1748
  this.dispatchEvent(new CustomEvent("fc-change", {
1744
1749
  detail: {
@@ -1749,41 +1754,41 @@ var FcSelect = class extends HTMLElement {
1749
1754
  composed: true
1750
1755
  }));
1751
1756
  }
1752
- toggleDropdown(show) {
1753
- if (!this.dropdownEl) {
1757
+ showDropdown() {
1758
+ if (!this.dropdownEl || this.disabled) {
1754
1759
  return;
1755
1760
  }
1756
- if (this.disabled && show) {
1761
+ const dropdown = this.dropdownEl;
1762
+ const showEvent = new CustomEvent("fc-show", {
1763
+ bubbles: true,
1764
+ composed: true,
1765
+ cancelable: true
1766
+ });
1767
+ this.dispatchEvent(showEvent);
1768
+ if (showEvent.defaultPrevented) {
1757
1769
  return;
1758
1770
  }
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);
1771
+ const spaceBelow = calculateBottomAvaliableSpace(this.inputEl);
1772
+ const spaceAbove = calculateTopAvaliableSpace(this.inputEl);
1773
+ dropdown.hidden = false;
1774
+ this.setAttribute("open", "true");
1775
+ this.inputEl.setAttribute("aria-expanded", "true");
1776
+ const shouldOpenUp = spaceBelow < dropdown.clientHeight && spaceAbove > spaceBelow;
1777
+ dropdown.classList.toggle("opens-up", shouldOpenUp);
1778
+ const options = this.getVisibleOptions();
1779
+ const selectedIndex = options.findIndex(opt => opt.value === this._value);
1780
+ if (selectedIndex >= 0) {
1781
+ this.setActiveOption(selectedIndex, options);
1782
+ } else {
1783
+ this.activeIndex = -1;
1784
+ }
1785
+ setTimeout(() => {
1786
+ document.addEventListener("click", this.onOutsideClick);
1787
+ }, 0);
1788
+ return;
1789
+ }
1790
+ hideDropdown() {
1791
+ if (!this.dropdownEl) {
1787
1792
  return;
1788
1793
  }
1789
1794
  if (!this.dropdownEl.hidden) {
@@ -1808,18 +1813,15 @@ var FcSelect = class extends HTMLElement {
1808
1813
  this.internals.setValidity(this.inputEl.validity, this.inputEl.validationMessage, this.inputEl);
1809
1814
  return;
1810
1815
  }
1811
- const options = this.querySelectorAll("fc-option");
1812
- let match = false;
1813
- options.forEach(option => {
1814
- if (option.value === this._value) {
1815
- match = true;
1816
+ this.querySelectorAll("fc-option");
1817
+ if (this._validatorFunction) {
1818
+ const customErrorMessage = this._validatorFunction(this.value);
1819
+ if (customErrorMessage) {
1820
+ this.internals.setValidity({
1821
+ customError: true
1822
+ }, customErrorMessage, this.inputEl);
1823
+ return;
1816
1824
  }
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
1825
  }
1824
1826
  this.internals.setValidity({});
1825
1827
  }
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.1",
4
4
  "type": "module",
5
5
  "description": "A library to easily create cool and customizable webcomponents.",
6
6
  "main": "dist/index.js",