@melodicdev/components 1.0.7 → 1.0.9

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.
@@ -716,6 +716,7 @@ var HttpClient = class {
716
716
  if (!response.ok) throw new HttpError(`HTTP Error: ${response.status} ${response.statusText}`, httpResponse, config);
717
717
  return httpResponse;
718
718
  }).catch((error) => {
719
+ if (error instanceof HttpError) throw error;
719
720
  if (error instanceof Error && error.name === "AbortError") throw new AbortError("Request aborted", config);
720
721
  throw new NetworkError((error instanceof Error ? error.message : "Network error") || "Network error", config);
721
722
  });
@@ -1456,8 +1457,8 @@ var TemplateResult = class TemplateResult {
1456
1457
  for (let i = 1; i < this.strings.length; i++) {
1457
1458
  const s = this.strings[i];
1458
1459
  const valueIndex = i - 1;
1459
- const match = /([@.:]?[\w:-]+)\s*=\s*["']?$/.exec(html$1);
1460
- const quotedAttrMatch = /([@.:]?[\w:-]+)\s*=\s*(["'])([^"']*)$/.exec(html$1);
1460
+ const match = /([@.:?]?[\w:-]+)\s*=\s*["']?$/.exec(html$1);
1461
+ const quotedAttrMatch = /([@.:?]?[\w:-]+)\s*=\s*(["'])([^"']*)$/.exec(html$1);
1461
1462
  let attrKey = "___";
1462
1463
  if (activeAttributeName) html$1 += createAttributeMarker(valueIndex);
1463
1464
  else {
@@ -1502,6 +1503,7 @@ var TemplateResult = class TemplateResult {
1502
1503
  const eventPartsByIndex = /* @__PURE__ */ new Map();
1503
1504
  const propertyPartsByIndex = /* @__PURE__ */ new Map();
1504
1505
  const actionPartsByIndex = /* @__PURE__ */ new Map();
1506
+ const booleanPartsByIndex = /* @__PURE__ */ new Map();
1505
1507
  for (const part of parts) switch (part.type) {
1506
1508
  case "event":
1507
1509
  eventPartsByIndex.set(part.index, part);
@@ -1512,6 +1514,9 @@ var TemplateResult = class TemplateResult {
1512
1514
  case "action":
1513
1515
  actionPartsByIndex.set(part.index, part);
1514
1516
  break;
1517
+ case "boolean-attribute":
1518
+ booleanPartsByIndex.set(part.index, part);
1519
+ break;
1515
1520
  case "node":
1516
1521
  nodeParts.push(part);
1517
1522
  break;
@@ -1558,6 +1563,15 @@ var TemplateResult = class TemplateResult {
1558
1563
  index: part.index,
1559
1564
  name: part.name
1560
1565
  });
1566
+ } else if (attr.name.startsWith("__bool-")) {
1567
+ const index = parseInt(attr.name.match(/__bool-(\d+)__/)?.[1] || "0");
1568
+ const part = booleanPartsByIndex.get(index);
1569
+ if (part) partPaths.push({
1570
+ path: [...path],
1571
+ type: "boolean-attribute",
1572
+ index: part.index,
1573
+ name: part.name
1574
+ });
1561
1575
  } else if (attr.name.startsWith(":")) partPaths.push({
1562
1576
  path: [...path],
1563
1577
  type: "action",
@@ -1627,6 +1641,14 @@ var TemplateResult = class TemplateResult {
1627
1641
  });
1628
1642
  return html$1.slice(0, -(match?.[0].length ?? 0)) + `__action-${index}__=""`;
1629
1643
  },
1644
+ "?": (index, html$1, attrName, match) => {
1645
+ parts.push({
1646
+ type: "boolean-attribute",
1647
+ index,
1648
+ name: attrName?.slice(1)
1649
+ });
1650
+ return html$1.slice(0, -(match?.[0].length ?? 0)) + `__bool-${index}__=""`;
1651
+ },
1630
1652
  "__": (index, html$1, _) => {
1631
1653
  return html$1 + createAttributeMarker(index);
1632
1654
  },
@@ -1682,6 +1704,15 @@ var TemplateResult = class TemplateResult {
1682
1704
  node: element,
1683
1705
  staticValue: partPath.staticValue
1684
1706
  });
1707
+ } else if (partPath.type === "boolean-attribute") {
1708
+ const element = node;
1709
+ element.removeAttribute(`__bool-${partPath.index}__`);
1710
+ parts.push({
1711
+ type: "boolean-attribute",
1712
+ index: partPath.index,
1713
+ name: partPath.name,
1714
+ node: element
1715
+ });
1685
1716
  } else if (partPath.type === "attribute") {
1686
1717
  const element = node;
1687
1718
  element.removeAttribute(partPath.name);
@@ -1903,6 +1934,13 @@ var TemplateResult = class TemplateResult {
1903
1934
  else element.setAttribute(part.name, String(value));
1904
1935
  }
1905
1936
  break;
1937
+ case "boolean-attribute":
1938
+ if (part.node && part.name) {
1939
+ const element = part.node;
1940
+ if (value) element.setAttribute(part.name, "");
1941
+ else element.removeAttribute(part.name);
1942
+ }
1943
+ break;
1906
1944
  case "property":
1907
1945
  if (part.node && part.name) if (isDirective(value)) part.directiveState = value.render(part.node, part.directiveState);
1908
1946
  else part.node[part.name] = value;
@@ -2072,6 +2110,16 @@ var RouterOutletComponent = class RouterOutletComponent$1 {
2072
2110
  if (window.location.pathname !== matchResult.redirectTo) this._router.navigate(matchResult.redirectTo, { replace: true });
2073
2111
  return;
2074
2112
  }
2113
+ if (matchResult.matches.length > 0) {
2114
+ const guardResult = await this._router.runGuards(matchResult);
2115
+ if (guardResult !== true) {
2116
+ if (typeof guardResult === "string") this._router.navigate(guardResult, {
2117
+ replace: true,
2118
+ skipGuards: true
2119
+ });
2120
+ return;
2121
+ }
2122
+ }
2075
2123
  if (matchResult.matches.length > 0) {
2076
2124
  const resolverResult = await this._router.runResolvers(matchResult);
2077
2125
  if (!resolverResult.success) {
@@ -7169,11 +7217,9 @@ function selectTemplate(c) {
7169
7217
  </div>
7170
7218
 
7171
7219
  <div
7172
- class=${classMap({
7173
- "ml-select__dropdown": true,
7174
- "ml-select__dropdown--open": c.isOpen
7175
- })}
7220
+ class="ml-select__dropdown"
7176
7221
  role="listbox"
7222
+ popover="auto"
7177
7223
  aria-multiselectable=${c.multiple || false}
7178
7224
  >
7179
7225
  ${c.filteredOptions.length ? repeat(c.filteredOptions, (option) => `${option.value}-${c.multiple ? c.values.includes(option.value) : c.value === option.value}`, (option, index) => renderOption(c, option, index)) : html`<div class="ml-select__empty">No results found</div>`}
@@ -7264,10 +7310,6 @@ const selectStyles = () => css`
7264
7310
  max-width: 100%;
7265
7311
  }
7266
7312
 
7267
- .ml-select--open .ml-select__control {
7268
- z-index: 100;
7269
- }
7270
-
7271
7313
  .ml-select__label {
7272
7314
  font-size: var(--ml-text-sm);
7273
7315
  font-weight: var(--ml-font-medium);
@@ -7455,12 +7497,10 @@ const selectStyles = () => css`
7455
7497
  }
7456
7498
 
7457
7499
  .ml-select__dropdown {
7458
- position: absolute;
7459
- top: 100%;
7460
- left: 0;
7461
- right: 0;
7500
+ position: fixed;
7501
+ inset: unset;
7502
+ margin: 0;
7462
7503
  z-index: 50;
7463
- margin-top: var(--ml-space-1);
7464
7504
  background-color: var(--ml-color-surface);
7465
7505
  border: var(--ml-border) solid var(--ml-color-border);
7466
7506
  border-radius: var(--ml-radius);
@@ -7468,13 +7508,13 @@ const selectStyles = () => css`
7468
7508
  max-height: 280px;
7469
7509
  overflow-y: auto;
7470
7510
  padding: var(--ml-space-1-5);
7471
- display: none;
7511
+ display: flex;
7472
7512
  flex-direction: column;
7473
7513
  gap: var(--ml-space-1);
7474
7514
  }
7475
7515
 
7476
- .ml-select__dropdown--open {
7477
- display: flex;
7516
+ .ml-select__dropdown:not(:popover-open) {
7517
+ display: none;
7478
7518
  }
7479
7519
 
7480
7520
  .ml-select__empty {
@@ -7607,8 +7647,10 @@ var SelectComponent = class SelectComponent$1 {
7607
7647
  this.search = "";
7608
7648
  this.isOpen = false;
7609
7649
  this.focusedIndex = -1;
7610
- this._handleDocumentClick = this.onDocumentClick.bind(this);
7611
7650
  this._handleKeyDown = this.onKeyDown.bind(this);
7651
+ this._handlePopoverToggle = this.onPopoverToggle.bind(this);
7652
+ this._handleScroll = null;
7653
+ this._lastCloseTime = 0;
7612
7654
  this._syncingValues = false;
7613
7655
  this.toggle = () => {
7614
7656
  if (this.disabled) return;
@@ -7616,30 +7658,16 @@ var SelectComponent = class SelectComponent$1 {
7616
7658
  if (!this.isOpen) this.open();
7617
7659
  return;
7618
7660
  }
7619
- if (this.isOpen) {
7620
- this.close();
7621
- return;
7622
- }
7623
- this.open();
7661
+ if (this.isOpen) this.close();
7662
+ else if (Date.now() - this._lastCloseTime > 150) this.open();
7624
7663
  };
7625
7664
  this.open = () => {
7626
7665
  if (this.disabled || this.isOpen) return;
7627
- this.isOpen = true;
7628
- this.focusedIndex = this.getInitialFocusIndex();
7629
- this.elementRef.dispatchEvent(new CustomEvent("ml:open", {
7630
- bubbles: true,
7631
- composed: true
7632
- }));
7666
+ this.getDropdownEl()?.showPopover();
7633
7667
  };
7634
7668
  this.close = () => {
7635
7669
  if (!this.isOpen) return;
7636
- this.isOpen = false;
7637
- this.focusedIndex = -1;
7638
- this.search = "";
7639
- this.elementRef.dispatchEvent(new CustomEvent("ml:close", {
7640
- bubbles: true,
7641
- composed: true
7642
- }));
7670
+ this.getDropdownEl()?.hidePopover();
7643
7671
  };
7644
7672
  this.selectOption = (option) => {
7645
7673
  if (option.disabled) return;
@@ -7687,12 +7715,13 @@ var SelectComponent = class SelectComponent$1 {
7687
7715
  };
7688
7716
  }
7689
7717
  onCreate() {
7690
- document.addEventListener("click", this._handleDocumentClick);
7691
7718
  this.elementRef.addEventListener("keydown", this._handleKeyDown);
7719
+ this.getDropdownEl()?.addEventListener("toggle", this._handlePopoverToggle);
7692
7720
  }
7693
7721
  onDestroy() {
7694
- document.removeEventListener("click", this._handleDocumentClick);
7695
7722
  this.elementRef.removeEventListener("keydown", this._handleKeyDown);
7723
+ this.removeScrollListener();
7724
+ this.getDropdownEl()?.removeEventListener("toggle", this._handlePopoverToggle);
7696
7725
  }
7697
7726
  onPropertyChange(name) {
7698
7727
  if (this._syncingValues) return;
@@ -7761,8 +7790,59 @@ var SelectComponent = class SelectComponent$1 {
7761
7790
  }
7762
7791
  }));
7763
7792
  }
7764
- onDocumentClick(event) {
7765
- if (!event.composedPath().includes(this.elementRef)) this.close();
7793
+ onPopoverToggle(event) {
7794
+ if (event.newState === "open") {
7795
+ this.isOpen = true;
7796
+ this.focusedIndex = this.getInitialFocusIndex();
7797
+ this.positionDropdown();
7798
+ this.addScrollListener();
7799
+ this.elementRef.dispatchEvent(new CustomEvent("ml:open", {
7800
+ bubbles: true,
7801
+ composed: true
7802
+ }));
7803
+ } else {
7804
+ this.isOpen = false;
7805
+ this.focusedIndex = -1;
7806
+ this.search = "";
7807
+ this._lastCloseTime = Date.now();
7808
+ this.removeScrollListener();
7809
+ this.elementRef.dispatchEvent(new CustomEvent("ml:close", {
7810
+ bubbles: true,
7811
+ composed: true
7812
+ }));
7813
+ }
7814
+ }
7815
+ positionDropdown() {
7816
+ const triggerEl = this.elementRef.shadowRoot?.querySelector(".ml-select__trigger");
7817
+ const dropdownEl = this.getDropdownEl();
7818
+ if (!triggerEl || !dropdownEl) return;
7819
+ dropdownEl.style.width = `${triggerEl.offsetWidth}px`;
7820
+ const { x, y } = computePosition(triggerEl, dropdownEl, {
7821
+ placement: "bottom-start",
7822
+ middleware: [
7823
+ offset(4),
7824
+ flip(),
7825
+ shift({ padding: 8 })
7826
+ ]
7827
+ });
7828
+ dropdownEl.style.left = `${x}px`;
7829
+ dropdownEl.style.top = `${y}px`;
7830
+ }
7831
+ addScrollListener() {
7832
+ this._handleScroll = (event) => {
7833
+ if (this.getDropdownEl()?.contains(event.target)) return;
7834
+ this.close();
7835
+ };
7836
+ window.addEventListener("scroll", this._handleScroll, true);
7837
+ }
7838
+ removeScrollListener() {
7839
+ if (this._handleScroll) {
7840
+ window.removeEventListener("scroll", this._handleScroll, true);
7841
+ this._handleScroll = null;
7842
+ }
7843
+ }
7844
+ getDropdownEl() {
7845
+ return this.elementRef.shadowRoot?.querySelector(".ml-select__dropdown");
7766
7846
  }
7767
7847
  onKeyDown(event) {
7768
7848
  if (this.disabled) return;
@@ -18555,12 +18635,23 @@ var _ref;
18555
18635
  var DialogComponent = class DialogComponent$1 {
18556
18636
  constructor() {
18557
18637
  this._dialogID = newID();
18638
+ this._registered = false;
18558
18639
  }
18559
18640
  onCreate() {
18560
- this._dialogEl = this.elementRef.shadowRoot?.querySelector("dialog");
18641
+ this.registerDialog();
18642
+ }
18643
+ onRender() {
18644
+ this.registerDialog();
18645
+ }
18646
+ registerDialog() {
18647
+ if (this._registered) return;
18648
+ const dialogEl = this.elementRef.shadowRoot?.querySelector("dialog");
18649
+ if (!dialogEl) return;
18650
+ this._dialogEl = dialogEl;
18561
18651
  this._dialogID = this.createDialogID();
18562
18652
  this._dialogEl.id = this._dialogID;
18563
18653
  this._dialogRef = this._dialogService.addDialog(this._dialogID, this._dialogEl);
18654
+ this._registered = true;
18564
18655
  }
18565
18656
  onDestroy() {
18566
18657
  this._dialogService.removeDialog(this._dialogID);