@nanoporetech-digital/components 4.5.3 → 4.7.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.
Files changed (127) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/dist/cjs/index.cjs.js +1 -1
  3. package/dist/cjs/loader.cjs.js +1 -1
  4. package/dist/cjs/{modal-5884a6de.js → modal-b9b40f6d.js} +2 -2
  5. package/dist/cjs/{modal-5884a6de.js.map → modal-b9b40f6d.js.map} +1 -1
  6. package/dist/cjs/nano-alert.cjs.entry.js +2 -2
  7. package/dist/cjs/nano-components.cjs.js +1 -1
  8. package/dist/cjs/nano-datalist_3.cjs.entry.js +6 -0
  9. package/dist/cjs/nano-datalist_3.cjs.entry.js.map +1 -1
  10. package/dist/cjs/nano-dialog.cjs.entry.js +3 -3
  11. package/dist/cjs/nano-dialog.cjs.entry.js.map +1 -1
  12. package/dist/cjs/nano-drawer.cjs.entry.js +2 -2
  13. package/dist/cjs/nano-dropdown.cjs.entry.js +1 -1
  14. package/dist/cjs/nano-field-validator.cjs.entry.js +43 -29
  15. package/dist/cjs/nano-field-validator.cjs.entry.js.map +1 -1
  16. package/dist/cjs/nano-global-nav-user-profile_3.cjs.entry.js +1 -1
  17. package/dist/cjs/nano-global-nav.cjs.entry.js +1 -1
  18. package/dist/cjs/nano-global-nav.cjs.entry.js.map +1 -1
  19. package/dist/cjs/nano-icon-button_2.cjs.entry.js +2 -1
  20. package/dist/cjs/nano-icon-button_2.cjs.entry.js.map +1 -1
  21. package/dist/cjs/{nano-table-f47280ac.js → nano-table-3231e33a.js} +2 -2
  22. package/dist/cjs/{nano-table-f47280ac.js.map → nano-table-3231e33a.js.map} +1 -1
  23. package/dist/cjs/nano-table.cjs.entry.js +1 -1
  24. package/dist/cjs/{tabbable-bdf10c84.js → tabbable-4a2b1566.js} +10 -4
  25. package/dist/cjs/tabbable-4a2b1566.js.map +1 -0
  26. package/dist/cjs/{table.worker-9a1585c7.js → table.worker-1cf646db.js} +2 -2
  27. package/dist/cjs/table.worker-1cf646db.js.map +1 -0
  28. package/dist/collection/components/datalist/datalist.js +6 -0
  29. package/dist/collection/components/datalist/datalist.js.map +1 -1
  30. package/dist/collection/components/dialog/dialog.css +1 -0
  31. package/dist/collection/components/dialog/dialog.js +1 -1
  32. package/dist/collection/components/dialog/dialog.js.map +1 -1
  33. package/dist/collection/components/field-validator/field-validator.js +81 -33
  34. package/dist/collection/components/field-validator/field-validator.js.map +1 -1
  35. package/dist/collection/components/global-nav/global-nav.js +3 -2
  36. package/dist/collection/components/global-nav/global-nav.js.map +1 -1
  37. package/dist/collection/components/tooltip/tooltip.js +2 -1
  38. package/dist/collection/components/tooltip/tooltip.js.map +1 -1
  39. package/dist/collection/utils/tabbable.js +9 -3
  40. package/dist/collection/utils/tabbable.js.map +1 -1
  41. package/dist/components/datalist.js +6 -0
  42. package/dist/components/datalist.js.map +1 -1
  43. package/dist/components/nano-dialog.js +1 -1
  44. package/dist/components/nano-dialog.js.map +1 -1
  45. package/dist/components/nano-field-validator.js +45 -30
  46. package/dist/components/nano-field-validator.js.map +1 -1
  47. package/dist/components/nano-global-nav.js +1 -1
  48. package/dist/components/nano-global-nav.js.map +1 -1
  49. package/dist/components/tabbable.js +9 -3
  50. package/dist/components/tabbable.js.map +1 -1
  51. package/dist/components/tooltip.js +2 -1
  52. package/dist/components/tooltip.js.map +1 -1
  53. package/dist/esm/index.js +1 -1
  54. package/dist/esm/loader.js +1 -1
  55. package/dist/esm/{modal-1f3223cd.js → modal-bd9638c0.js} +2 -2
  56. package/dist/esm/{modal-1f3223cd.js.map → modal-bd9638c0.js.map} +1 -1
  57. package/dist/esm/nano-alert.entry.js +2 -2
  58. package/dist/esm/nano-components.js +1 -1
  59. package/dist/esm/nano-datalist_3.entry.js +6 -0
  60. package/dist/esm/nano-datalist_3.entry.js.map +1 -1
  61. package/dist/esm/nano-dialog.entry.js +3 -3
  62. package/dist/esm/nano-dialog.entry.js.map +1 -1
  63. package/dist/esm/nano-drawer.entry.js +2 -2
  64. package/dist/esm/nano-dropdown.entry.js +1 -1
  65. package/dist/esm/nano-field-validator.entry.js +43 -29
  66. package/dist/esm/nano-field-validator.entry.js.map +1 -1
  67. package/dist/esm/nano-global-nav-user-profile_3.entry.js +1 -1
  68. package/dist/esm/nano-global-nav.entry.js +1 -1
  69. package/dist/esm/nano-global-nav.entry.js.map +1 -1
  70. package/dist/esm/nano-icon-button_2.entry.js +2 -1
  71. package/dist/esm/nano-icon-button_2.entry.js.map +1 -1
  72. package/dist/esm/{nano-table-7d22e310.js → nano-table-073a807b.js} +2 -2
  73. package/dist/esm/{nano-table-7d22e310.js.map → nano-table-073a807b.js.map} +1 -1
  74. package/dist/esm/nano-table.entry.js +1 -1
  75. package/dist/esm/{tabbable-31485ff7.js → tabbable-26a66a22.js} +10 -4
  76. package/dist/esm/tabbable-26a66a22.js.map +1 -0
  77. package/dist/esm/{table.worker-55bb0326.js → table.worker-3db952f1.js} +2 -2
  78. package/dist/esm/table.worker-3db952f1.js.map +1 -0
  79. package/dist/nano-components/index.esm.js +1 -1
  80. package/dist/nano-components/nano-components.esm.js +1 -1
  81. package/dist/nano-components/nano-components.esm.js.map +1 -1
  82. package/dist/nano-components/{p-dbf47e49.js → p-0ee2a9bf.js} +2 -2
  83. package/dist/nano-components/{p-e04f2333.js → p-2234694a.js} +2 -2
  84. package/dist/nano-components/{p-0c077605.entry.js → p-241056f4.entry.js} +2 -2
  85. package/dist/nano-components/{p-d5b63150.entry.js → p-272b2f59.entry.js} +2 -2
  86. package/dist/nano-components/p-272b2f59.entry.js.map +1 -0
  87. package/dist/nano-components/p-3dd8ae89.entry.js +5 -0
  88. package/dist/nano-components/p-3dd8ae89.entry.js.map +1 -0
  89. package/dist/nano-components/{p-ffb57a0d.js → p-4384a4c2.js} +2 -2
  90. package/dist/nano-components/{p-691c4268.entry.js → p-64b56ee6.entry.js} +2 -2
  91. package/dist/nano-components/{p-691c4268.entry.js.map → p-64b56ee6.entry.js.map} +1 -1
  92. package/dist/nano-components/{p-27b5e10c.entry.js → p-692ae029.entry.js} +2 -2
  93. package/dist/nano-components/{p-578f5e8d.entry.js → p-acd0ec64.entry.js} +2 -2
  94. package/dist/nano-components/{p-b6306aff.entry.js → p-b04fd7ca.entry.js} +2 -2
  95. package/dist/nano-components/p-b0c60290.entry.js +5 -0
  96. package/dist/nano-components/p-b0c60290.entry.js.map +1 -0
  97. package/dist/nano-components/{p-dc2c37d5.entry.js → p-e2b2b015.entry.js} +2 -2
  98. package/dist/nano-components/{p-27eb26ef.entry.js → p-eb6c9191.entry.js} +2 -2
  99. package/dist/nano-components/{p-27eb26ef.entry.js.map → p-eb6c9191.entry.js.map} +1 -1
  100. package/dist/nano-components/{p-45abbbdd.js → p-f88fa15c.js} +2 -2
  101. package/dist/nano-components/p-f88fa15c.js.map +1 -0
  102. package/dist/types/components/datalist/datalist.d.ts +1 -0
  103. package/dist/types/components/field-validator/field-validator.d.ts +11 -3
  104. package/dist/types/components/global-nav/global-nav.d.ts +2 -1
  105. package/dist/types/components.d.ts +7 -1
  106. package/dist/types/utils/tabbable.d.ts +8 -0
  107. package/docs-json.json +38 -5
  108. package/hydrate/index.js +66 -37
  109. package/package.json +2 -2
  110. package/dist/cjs/tabbable-bdf10c84.js.map +0 -1
  111. package/dist/cjs/table.worker-9a1585c7.js.map +0 -1
  112. package/dist/esm/tabbable-31485ff7.js.map +0 -1
  113. package/dist/esm/table.worker-55bb0326.js.map +0 -1
  114. package/dist/nano-components/p-2ad0d9a3.entry.js +0 -5
  115. package/dist/nano-components/p-2ad0d9a3.entry.js.map +0 -1
  116. package/dist/nano-components/p-357a0a3f.entry.js +0 -5
  117. package/dist/nano-components/p-357a0a3f.entry.js.map +0 -1
  118. package/dist/nano-components/p-45abbbdd.js.map +0 -1
  119. package/dist/nano-components/p-d5b63150.entry.js.map +0 -1
  120. /package/dist/nano-components/{p-27b5e10c.entry.js.map → p-0ee2a9bf.js.map} +0 -0
  121. /package/dist/nano-components/{p-e04f2333.js.map → p-2234694a.js.map} +0 -0
  122. /package/dist/nano-components/{p-0c077605.entry.js.map → p-241056f4.entry.js.map} +0 -0
  123. /package/dist/nano-components/{p-ffb57a0d.js.map → p-4384a4c2.js.map} +0 -0
  124. /package/dist/nano-components/{p-dbf47e49.js.map → p-692ae029.entry.js.map} +0 -0
  125. /package/dist/nano-components/{p-578f5e8d.entry.js.map → p-acd0ec64.entry.js.map} +0 -0
  126. /package/dist/nano-components/{p-b6306aff.entry.js.map → p-b04fd7ca.entry.js.map} +0 -0
  127. /package/dist/nano-components/{p-dc2c37d5.entry.js.map → p-e2b2b015.entry.js.map} +0 -0
package/docs-json.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "timestamp": "2023-05-09T21:38:01",
2
+ "timestamp": "2023-05-30T15:16:23",
3
3
  "compiler": {
4
4
  "name": "@stencil/core",
5
5
  "version": "2.23.0",
@@ -4668,6 +4668,11 @@
4668
4668
  "annotation": "prop",
4669
4669
  "docs": "defaults to #f0efed;"
4670
4670
  },
4671
+ {
4672
+ "name": "--nano-layer-overlay-blur",
4673
+ "annotation": "prop",
4674
+ "docs": "inheritable theme applied to backdrop. Default to var(--nano-layer-overlay-blur, 3px)"
4675
+ },
4671
4676
  {
4672
4677
  "name": "--scrim-color",
4673
4678
  "annotation": "prop",
@@ -5726,19 +5731,39 @@
5726
5731
  }
5727
5732
  ]
5728
5733
  },
5734
+ {
5735
+ "name": "scrollToFirstInvalid",
5736
+ "returns": {
5737
+ "type": "Promise<void>",
5738
+ "docs": ""
5739
+ },
5740
+ "signature": "scrollToFirstInvalid(force?: boolean) => Promise<void>",
5741
+ "parameters": [],
5742
+ "docs": "Scrolls to first invalid form field.",
5743
+ "docsTags": [
5744
+ {
5745
+ "name": "param",
5746
+ "text": "force - forces the scroll behaviour (default). Otherwise will use the default set in `scrollToInvalid` prop"
5747
+ }
5748
+ ]
5749
+ },
5729
5750
  {
5730
5751
  "name": "setCustomValidity",
5731
5752
  "returns": {
5732
5753
  "type": "Promise<void[]>",
5733
5754
  "docs": ""
5734
5755
  },
5735
- "signature": "setCustomValidity(validity: { [key: string]: string; }) => Promise<void[]>",
5756
+ "signature": "setCustomValidity(validity: { [key: string]: string; }, scrollToInvalid?: boolean) => Promise<void[]>",
5736
5757
  "parameters": [],
5737
5758
  "docs": "Sets custom validity for all / some form fields.",
5738
5759
  "docsTags": [
5739
5760
  {
5740
5761
  "name": "param",
5741
- "text": "validity - a validity object of `{fieldName: errorString}` pairs. Set as an empty string to clear the error."
5762
+ "text": "validity - a validity object of `{fieldName: errorString}` pairs.\nSet as an empty string to clear the error."
5763
+ },
5764
+ {
5765
+ "name": "param",
5766
+ "text": "scrollToInvalid - whether to scroll to the first invalid field.\nIf not present, will follow the value set on `scrollToInvalid` prop."
5742
5767
  }
5743
5768
  ]
5744
5769
  },
@@ -6483,7 +6508,11 @@
6483
6508
  },
6484
6509
  {
6485
6510
  "name": "part",
6486
- "text": "burger - the overflow / burger menu"
6511
+ "text": "burger - the overflow / burger ui element"
6512
+ },
6513
+ {
6514
+ "name": "part",
6515
+ "text": "burger-menu - the overflow / burger menu"
6487
6516
  },
6488
6517
  {
6489
6518
  "name": "part",
@@ -7130,7 +7159,7 @@
7130
7159
  },
7131
7160
  {
7132
7161
  "name": "burger",
7133
- "docs": "the overflow / burger menu"
7162
+ "docs": "the overflow / burger ui element"
7134
7163
  },
7135
7164
  {
7136
7165
  "name": "burger-actions-bar",
@@ -7140,6 +7169,10 @@
7140
7169
  "name": "burger-content",
7141
7170
  "docs": "the main content area of the overflow / burger menu"
7142
7171
  },
7172
+ {
7173
+ "name": "burger-menu",
7174
+ "docs": "the overflow / burger menu"
7175
+ },
7143
7176
  {
7144
7177
  "name": "logo-link",
7145
7178
  "docs": "the link wrapping the logo"
package/hydrate/index.js CHANGED
@@ -6350,8 +6350,14 @@ function isTabbable(el) {
6350
6350
  'summary',
6351
6351
  ].includes(tag);
6352
6352
  }
6353
- // Locates all tabbable elements within an element. If the target element is tabbable, it will be included in the
6354
- // resulting array. This function will also look in open shadow roots.
6353
+ /**
6354
+ * Recursively locate all tabbable elements within an element.
6355
+ * If the target element is tabbable, it will be included in the
6356
+ * resulting array. This function will also look in open shadow roots.
6357
+ * @param root the root to search from
6358
+ * @param first return the first tabbable element found
6359
+ * @returns an array of tabbable elements
6360
+ */
6355
6361
  function getTabbableElements(root, first = false) {
6356
6362
  const tabbableElements = [];
6357
6363
  if (root instanceof HTMLElement) {
@@ -6379,7 +6385,7 @@ function getTabbableElements(root, first = false) {
6379
6385
  }
6380
6386
  }
6381
6387
  // Look for tabbable elements in children
6382
- Array.from(root.querySelectorAll('*')).map((el) => {
6388
+ Array.from(root.children).map((el) => {
6383
6389
  getTabbableElements(el, first).map((el) => {
6384
6390
  if (!tabbableElements.includes(el))
6385
6391
  tabbableElements.push(el);
@@ -11855,6 +11861,12 @@ class DataList {
11855
11861
  console.warn('no `nano-input` found. `nano-datalist` should be nested within an `nano-input` or linked via `input` prop', this.host);
11856
11862
  }, 500);
11857
11863
  }
11864
+ disconnectedCallback() {
11865
+ if (!!this.mo) {
11866
+ this.mo.disconnect();
11867
+ this.mo = undefined;
11868
+ }
11869
+ }
11858
11870
  render() {
11859
11871
  return (hAsync(Host, { role: this.actvOptEles.length ? 'listbox' : undefined, "aria-owns": this.optionIds.length ? this.optionIds.join(' ') : undefined, "aria-label": this.optionIds.length
11860
11872
  ? 'Select options from the list below'
@@ -13554,7 +13566,7 @@ class Dialog {
13554
13566
  'dialog--has-header': !this.noHeader,
13555
13567
  'dialog--nodismiss': this.noDismiss,
13556
13568
  'dialog--with-ribbon': this.showRibbon,
13557
- }, onKeyDown: this.handleKeyDown }, hAsync("div", { part: "overlay", class: "dialog__overlay", ref: (el) => (this.overlay = el), onClick: this.requestClose }), hAsync("div", { ref: (el) => (this.panel = el), part: "panel", class: "dialog__panel", role: "dialog", "aria-modal": "true", "aria-hidden": this.open ? 'false' : 'true', "aria-label": this.noHeader ? this.label : null, "aria-labelledby": !this.noHeader ? `${this.componentId}-title` : null, tabIndex: 0 }, hAsync("div", { class: "dialog__body-wrap" }, !this.noHeader && (hAsync("nano-sticker", null, hAsync("header", { part: "header", class: "dialog__header" }, hAsync("span", { part: "title", class: "dialog__title", id: `${this.componentId}-title` }, hAsync("slot", { name: "label" }, this.label || String.fromCharCode(65279))), !this.noUserDismiss && (hAsync("nano-icon-button", { exportparts: "base:close-button", class: "dialog__close-icon", label: "close dialog", onClick: this.requestClose, iconName: "light/times" }))))), hAsync("div", { part: "body", class: "dialog__body" }, hAsync("slot", null)), !this.noFooter && (this.hasFooter || !this.noUserDismiss) && (hAsync("nano-sticker", { position: "bottom" }, hAsync("footer", { part: "footer", class: "dialog__footer" }, hAsync("slot", { name: "footer", onSlotchange: this.handleSlotChange }), !this.noUserDismiss && (hAsync("button", { class: "dialog__close-txt", onClick: this.requestClose }, "Close"))))))))));
13569
+ }, onKeyDown: this.handleKeyDown }, hAsync("div", { part: "overlay", class: "dialog__overlay", ref: (el) => (this.overlay = el), onClick: this.requestClose }), hAsync("div", { ref: (el) => (this.panel = el), part: "panel", class: "dialog__panel", role: "dialog", "aria-modal": "true", "aria-hidden": this.open ? 'false' : 'true', "aria-label": this.noHeader ? this.label : null, "aria-labelledby": !this.noHeader ? `${this.componentId}-title` : null, tabIndex: 0 }, hAsync("div", { class: "dialog__body-wrap" }, !this.noHeader && (hAsync("nano-sticker", null, hAsync("header", { part: "header", class: "dialog__header" }, hAsync("span", { part: "title", class: "dialog__title", id: `${this.componentId}-title` }, hAsync("slot", { name: "label" }, this.label || String.fromCharCode(65279))), !this.noUserDismiss && (hAsync("nano-icon-button", { exportparts: "base:close-button", class: "dialog__close-icon", label: "close dialog", onClick: this.requestClose, iconName: "light/times" }))))), hAsync("div", { part: "body", class: "dialog__body", style: { display: !this.isVisible ? 'none' : '' } }, hAsync("slot", null)), !this.noFooter && (this.hasFooter || !this.noUserDismiss) && (hAsync("nano-sticker", { position: "bottom" }, hAsync("footer", { part: "footer", class: "dialog__footer" }, hAsync("slot", { name: "footer", onSlotchange: this.handleSlotChange }), !this.noUserDismiss && (hAsync("button", { class: "dialog__close-txt", onClick: this.requestClose }, "Close"))))))))));
13558
13570
  }
13559
13571
  get host() { return getElement(this); }
13560
13572
  static get watchers() { return {
@@ -16264,7 +16276,7 @@ class FieldValidator {
16264
16276
  return;
16265
16277
  }
16266
16278
  }
16267
- this.scrollToFirstInvalid();
16279
+ this.scrollToFirstInvalid(false);
16268
16280
  this.nanoInvalid.emit();
16269
16281
  };
16270
16282
  this.submitted = false;
@@ -16411,14 +16423,19 @@ class FieldValidator {
16411
16423
  }
16412
16424
  /**
16413
16425
  * Sets custom validity for all / some form fields.
16414
- * @param validity - a validity object of `{fieldName: errorString}` pairs. Set as an empty string to clear the error.
16426
+ * @param validity - a validity object of `{fieldName: errorString}` pairs.
16427
+ * Set as an empty string to clear the error.
16428
+ * @param scrollToInvalid - whether to scroll to the first invalid field.
16429
+ * If not present, will follow the value set on `scrollToInvalid` prop.
16415
16430
  */
16416
- async setCustomValidity(validity) {
16431
+ async setCustomValidity(validity, scrollToInvalid) {
16417
16432
  return await Promise.all(Object.entries(validity).map(async ([key, err]) => {
16418
16433
  const field = this.allFields.find((f) => this.getName(f) === key);
16419
16434
  if (!!field)
16420
16435
  await this.setFieldError(field, err);
16421
- }));
16436
+ })).finally(() => {
16437
+ this.scrollToFirstInvalid(scrollToInvalid);
16438
+ });
16422
16439
  }
16423
16440
  /**
16424
16441
  * Clear all custom validation.
@@ -16427,6 +16444,23 @@ class FieldValidator {
16427
16444
  async resetValidity() {
16428
16445
  return await Promise.all(this.allFields.map(async (field) => await this.setFieldError(field, '')));
16429
16446
  }
16447
+ /**
16448
+ * Scrolls to first invalid form field.
16449
+ * @param force - forces the scroll behaviour (default). Otherwise will use the default set in `scrollToInvalid` prop
16450
+ */
16451
+ async scrollToFirstInvalid(force = true) {
16452
+ if (!force && !this.scrollToInvalid)
16453
+ return;
16454
+ setTimeout(() => {
16455
+ const invalidField = this.validationState.find((f) => !f.valid);
16456
+ if (!invalidField)
16457
+ return;
16458
+ invalidField.fields[0].scrollIntoView({
16459
+ behavior: 'smooth',
16460
+ block: 'nearest',
16461
+ });
16462
+ }, 200);
16463
+ }
16430
16464
  // private methods
16431
16465
  attachSlotObserver() {
16432
16466
  if (!!this.mo)
@@ -16523,6 +16557,15 @@ class FieldValidator {
16523
16557
  field.value = this._store.state[fieldName];
16524
16558
  });
16525
16559
  }
16560
+ getValidityTarget(field) {
16561
+ let validityTarget = field;
16562
+ if (field.tagName === 'NANO-CHECKBOX') {
16563
+ // if we have a checkbox-group, set the validation message there
16564
+ const cbg = field.closest('nano-checkbox-group');
16565
+ validityTarget = cbg || field;
16566
+ }
16567
+ return validityTarget;
16568
+ }
16526
16569
  /** Loops through all `nano-...` fields and extracts their values into our store */
16527
16570
  fieldsToStore(fields, init = false) {
16528
16571
  fields.forEach((field) => {
@@ -16614,12 +16657,7 @@ class FieldValidator {
16614
16657
  return validityState.fields.map(async (fieldName) => {
16615
16658
  // switch on/off validation messages
16616
16659
  const field = this.allFields.find((f) => this.getName(f) === fieldName);
16617
- let validityTarget = field;
16618
- if (field.tagName === 'NANO-CHECKBOX') {
16619
- // if we have a checkbox-group, set the validation message there
16620
- const cbg = field.closest('nano-checkbox-group');
16621
- validityTarget = cbg || field;
16622
- }
16660
+ const validityTarget = this.getValidityTarget(field);
16623
16661
  if ((validityTarget.validityMessage ||
16624
16662
  validityTarget.validationMessage) === msg &&
16625
16663
  validityState.valid) {
@@ -16648,26 +16686,14 @@ class FieldValidator {
16648
16686
  * @param msg
16649
16687
  */
16650
16688
  async setFieldError(field, msg) {
16651
- if (field['showError']) {
16652
- await field.showError(msg);
16689
+ const validityTarget = this.getValidityTarget(field);
16690
+ if (validityTarget['showError']) {
16691
+ await validityTarget.showError(msg);
16653
16692
  }
16654
- else if (field['setError'])
16655
- await field.setError(msg);
16693
+ else if (validityTarget['setError'])
16694
+ await validityTarget.setError(msg);
16656
16695
  else
16657
- field.setCustomValidity(msg);
16658
- }
16659
- scrollToFirstInvalid() {
16660
- if (!this.scrollToInvalid)
16661
- return;
16662
- setTimeout(() => {
16663
- const invalidField = this.validationState.find((f) => !f.valid);
16664
- if (!invalidField)
16665
- return;
16666
- invalidField.fields[0].scrollIntoView({
16667
- behavior: 'smooth',
16668
- block: 'nearest',
16669
- });
16670
- }, 200);
16696
+ validityTarget.setCustomValidity(msg);
16671
16697
  }
16672
16698
  submitForm() {
16673
16699
  const nanoSubmit = this.nanoSubmit.emit();
@@ -16708,7 +16734,7 @@ class FieldValidator {
16708
16734
  this._valid = this.activeForm.checkValidity();
16709
16735
  this.internalValidate = false;
16710
16736
  if (!this._valid) {
16711
- this.scrollToFirstInvalid();
16737
+ this.scrollToFirstInvalid(false);
16712
16738
  return;
16713
16739
  }
16714
16740
  this.submitForm();
@@ -16761,7 +16787,8 @@ class FieldValidator {
16761
16787
  "_store": [32],
16762
16788
  "setStore": [64],
16763
16789
  "setCustomValidity": [64],
16764
- "resetValidity": [64]
16790
+ "resetValidity": [64],
16791
+ "scrollToFirstInvalid": [64]
16765
16792
  },
16766
16793
  "$listeners$": [[0, "nanoChange", "handleFieldChange"], [0, "input", "handlePlainFieldChange"], [0, "change", "handlePlainFieldChange"], [0, "submit", "handleSubmit"]],
16767
16794
  "$lazyBundleId$": "-",
@@ -17258,7 +17285,8 @@ const THRESHOLDBREAKS = {
17258
17285
  * @slot logo - when show-logo="false" you can utilise the logo slot
17259
17286
  * @slot - if using search functionality, place a `<nano-search-results />` element in the default slot
17260
17287
  *
17261
- * @part burger - the overflow / burger menu
17288
+ * @part burger - the overflow / burger ui element
17289
+ * @part burger-menu - the overflow / burger menu
17262
17290
  * @part burger-actions-bar - the top bar of the overflow / burger menu
17263
17291
  * @part burger-content - the main content area of the overflow / burger menu
17264
17292
  * @part sticker - the `nano-sticker` wrapping the main nav-bar
@@ -18117,7 +18145,7 @@ class GlobalNav {
18117
18145
  'has-promotion': this.hasPromotionSlot,
18118
18146
  'menu-full-screen': this.menuFullScreen,
18119
18147
  'secondary-open': !!this.secondaryMenuOpen,
18120
- }, "aria-expanded": this.modalOpen ? 'true' : 'false', ref: (div) => (this.menuDiv = div), part: "burger" }, hAsync("div", { class: "gn-menu_wrap", ref: (div) => (this.menuWrapDiv = div), tabindex: "-1" }, hAsync("div", { class: "gn-menu_actions", part: "burger-actions-bar" }, hAsync("button", { class: "menu-btn icon-btn icon-btn", onMouseDown: this.onMenuBtnClick, onKeyDown: this.onMenuBtnKeyDown }, this.threshold < this.THRESHOLDLIMIT - 3 && (hAsync("nano-icon", { name: "light/times", "aria-label": "close menu" })), this.threshold >= this.THRESHOLDLIMIT - 3 && (hAsync("nano-icon", { name: "light/bars", "aria-label": "close menu" }))), this.threshold <
18148
+ }, "aria-expanded": this.modalOpen ? 'true' : 'false', ref: (div) => (this.menuDiv = div), part: "burger" }, hAsync("div", { class: "gn-menu_wrap", ref: (div) => (this.menuWrapDiv = div), tabindex: "-1", part: "burger-menu" }, hAsync("div", { class: "gn-menu_actions", part: "burger-actions-bar" }, hAsync("button", { class: "menu-btn icon-btn icon-btn", onMouseDown: this.onMenuBtnClick, onKeyDown: this.onMenuBtnKeyDown }, this.threshold < this.THRESHOLDLIMIT - 3 && (hAsync("nano-icon", { name: "light/times", "aria-label": "close menu" })), this.threshold >= this.THRESHOLDLIMIT - 3 && (hAsync("nano-icon", { name: "light/bars", "aria-label": "close menu" }))), this.threshold <
18121
18149
  this.THRESHOLDLIMIT - THRESHOLDBREAKS.icon && [
18122
18150
  !!this.iconSlotLen && hAsync("slot", { name: "icon" }),
18123
18151
  this.myAccData &&
@@ -31293,7 +31321,8 @@ class Tooltip {
31293
31321
  this.syncOptions();
31294
31322
  }
31295
31323
  disconnectedCallback() {
31296
- this.popover.destroy();
31324
+ if (this.popover)
31325
+ this.popover.destroy();
31297
31326
  }
31298
31327
  render() {
31299
31328
  return (hAsync(Host, { onKeyDown: this.handleKeyDown, onMouseOver: this.handleMouseOver, onMouseOut: this.handleMouseOut, onBlur: this.handleBlur, onFocus: this.handleFocus, onClick: this.handleClick }, hAsync("slot", { onSlotchange: this.handleSlotChange }), hAsync("div", { ref: (el) => (this.tooltipPositioner = el), class: "tooltip-positioner" }, hAsync("div", { part: "base", ref: (el) => (this.tooltip = el), class: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nanoporetech-digital/components",
3
- "version": "4.5.3",
3
+ "version": "4.7.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://git.oxfordnanolabs.local/Digital/nano-components"
@@ -131,7 +131,7 @@
131
131
  "nanopore",
132
132
  "digital"
133
133
  ],
134
- "gitHead": "edfa532414d0634a098e6e9c797b6bed32540f93",
134
+ "gitHead": "9381323b36d7a48304347a486271aba11552ceb6",
135
135
  "volta": {
136
136
  "node": "14.18.1",
137
137
  "npm": "8.6.0"
@@ -1 +0,0 @@
1
- {"file":"tabbable-bdf10c84.js","mappings":"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","names":[],"sources":["./src/utils/tabbable.ts"],"sourcesContent":["// Determines if the specified element is tabbable using heuristics inspired by https://github.com/focus-trap/tabbable\nfunction isTabbable(el: HTMLElement) {\n const tag = el.tagName.toLowerCase();\n\n // Elements with a -1 tab index are not tabbable\n if (el.getAttribute('tabindex') === '-1') {\n return false;\n }\n\n // Elements with a disabled attribute are not tabbable\n if (el.hasAttribute('disabled')) {\n return false;\n }\n\n // Elements with aria-disabled are not tabbable\n if (\n el.hasAttribute('aria-disabled') &&\n el.getAttribute('aria-disabled') !== 'false'\n ) {\n return false;\n }\n\n // Elements with a tabindex other than -1 are tabbable\n if (el.hasAttribute('tabindex')) {\n return true;\n }\n\n // Elements with a contenteditable attribute are tabbable\n if (\n el.hasAttribute('contenteditable') &&\n el.getAttribute('contenteditable') !== 'false'\n ) {\n return true;\n }\n\n // Audio and video elements with the controls attribute are tabbable\n if ((tag === 'audio' || tag === 'video') && el.hasAttribute('controls')) {\n return true;\n }\n\n // Radios without a checked attribute are not tabbable\n if (\n tag === 'input' &&\n el.getAttribute('type') === 'radio' &&\n !el.hasAttribute('checked')\n ) {\n return false;\n }\n\n // Elements that are hidden have no offsetParent and are not tabbable\n if (!el.offsetParent) {\n return false;\n }\n\n // Elements without visibility are not tabbable (calculated last due to performance)\n if (window.getComputedStyle(el).visibility === 'hidden') {\n return false;\n }\n\n // At this point, the following elements are considered tabbable\n return [\n 'button',\n 'input',\n 'select',\n 'textarea',\n 'a',\n 'audio',\n 'video',\n 'summary',\n ].includes(tag);\n}\n\n// Locates all tabbable elements within an element. If the target element is tabbable, it will be included in the\n// resulting array. This function will also look in open shadow roots.\nexport function getTabbableElements(\n root: HTMLElement | ShadowRoot,\n first: boolean = false\n) {\n const tabbableElements: HTMLElement[] = [];\n\n if (root instanceof HTMLElement) {\n // Is the root element tabbable?\n if (isTabbable(root)) {\n tabbableElements.push(root);\n\n if (first) return tabbableElements;\n }\n\n // Look for tabbable elements in the shadow root\n if (root.shadowRoot && root.shadowRoot.mode === 'open') {\n getTabbableElements(root.shadowRoot, first).map((el) => {\n if (!tabbableElements.includes(el)) tabbableElements.push(el);\n });\n }\n\n // Look at slotted elements\n if (HTMLSlotElement && root instanceof HTMLSlotElement) {\n root.assignedElements().map((slottedEl: HTMLElement) => {\n getTabbableElements(slottedEl, first).map((el) => {\n if (!tabbableElements.includes(el)) tabbableElements.push(el);\n });\n });\n }\n }\n\n // Look for tabbable elements in children\n Array.from(root.querySelectorAll('*')).map((el: HTMLElement) => {\n getTabbableElements(el, first).map((el) => {\n if (!tabbableElements.includes(el)) tabbableElements.push(el);\n });\n });\n\n return tabbableElements;\n}\n\nexport function getNearestTabbableElement(el: Element): HTMLElement | null {\n const tabbableElements = getTabbableElements(el as HTMLElement, true);\n return tabbableElements.length ? tabbableElements[0] : null;\n}\n"],"version":3}
@@ -1 +0,0 @@
1
- {"file":"table.worker-9a1585c7.js","mappings":";;;;;;;;;;;;;;;;;;;;;;;;","names":[],"sources":[],"sourcesContent":[],"version":3}
@@ -1 +0,0 @@
1
- {"file":"tabbable-31485ff7.js","mappings":"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","names":[],"sources":["./src/utils/tabbable.ts"],"sourcesContent":["// Determines if the specified element is tabbable using heuristics inspired by https://github.com/focus-trap/tabbable\nfunction isTabbable(el: HTMLElement) {\n const tag = el.tagName.toLowerCase();\n\n // Elements with a -1 tab index are not tabbable\n if (el.getAttribute('tabindex') === '-1') {\n return false;\n }\n\n // Elements with a disabled attribute are not tabbable\n if (el.hasAttribute('disabled')) {\n return false;\n }\n\n // Elements with aria-disabled are not tabbable\n if (\n el.hasAttribute('aria-disabled') &&\n el.getAttribute('aria-disabled') !== 'false'\n ) {\n return false;\n }\n\n // Elements with a tabindex other than -1 are tabbable\n if (el.hasAttribute('tabindex')) {\n return true;\n }\n\n // Elements with a contenteditable attribute are tabbable\n if (\n el.hasAttribute('contenteditable') &&\n el.getAttribute('contenteditable') !== 'false'\n ) {\n return true;\n }\n\n // Audio and video elements with the controls attribute are tabbable\n if ((tag === 'audio' || tag === 'video') && el.hasAttribute('controls')) {\n return true;\n }\n\n // Radios without a checked attribute are not tabbable\n if (\n tag === 'input' &&\n el.getAttribute('type') === 'radio' &&\n !el.hasAttribute('checked')\n ) {\n return false;\n }\n\n // Elements that are hidden have no offsetParent and are not tabbable\n if (!el.offsetParent) {\n return false;\n }\n\n // Elements without visibility are not tabbable (calculated last due to performance)\n if (window.getComputedStyle(el).visibility === 'hidden') {\n return false;\n }\n\n // At this point, the following elements are considered tabbable\n return [\n 'button',\n 'input',\n 'select',\n 'textarea',\n 'a',\n 'audio',\n 'video',\n 'summary',\n ].includes(tag);\n}\n\n// Locates all tabbable elements within an element. If the target element is tabbable, it will be included in the\n// resulting array. This function will also look in open shadow roots.\nexport function getTabbableElements(\n root: HTMLElement | ShadowRoot,\n first: boolean = false\n) {\n const tabbableElements: HTMLElement[] = [];\n\n if (root instanceof HTMLElement) {\n // Is the root element tabbable?\n if (isTabbable(root)) {\n tabbableElements.push(root);\n\n if (first) return tabbableElements;\n }\n\n // Look for tabbable elements in the shadow root\n if (root.shadowRoot && root.shadowRoot.mode === 'open') {\n getTabbableElements(root.shadowRoot, first).map((el) => {\n if (!tabbableElements.includes(el)) tabbableElements.push(el);\n });\n }\n\n // Look at slotted elements\n if (HTMLSlotElement && root instanceof HTMLSlotElement) {\n root.assignedElements().map((slottedEl: HTMLElement) => {\n getTabbableElements(slottedEl, first).map((el) => {\n if (!tabbableElements.includes(el)) tabbableElements.push(el);\n });\n });\n }\n }\n\n // Look for tabbable elements in children\n Array.from(root.querySelectorAll('*')).map((el: HTMLElement) => {\n getTabbableElements(el, first).map((el) => {\n if (!tabbableElements.includes(el)) tabbableElements.push(el);\n });\n });\n\n return tabbableElements;\n}\n\nexport function getNearestTabbableElement(el: Element): HTMLElement | null {\n const tabbableElements = getTabbableElements(el as HTMLElement, true);\n return tabbableElements.length ? tabbableElements[0] : null;\n}\n"],"version":3}
@@ -1 +0,0 @@
1
- {"file":"table.worker-55bb0326.js","mappings":";;;;;;;;;;;;;;;;;;;","names":[],"sources":[],"sourcesContent":[],"version":3}
@@ -1,5 +0,0 @@
1
- /*!
2
- * Web Components for Nanopore digital Web Apps
3
- */
4
- import{r as t,c as i,w as s,h as e,a as n,g as o}from"./p-f6a8467a.js";import{g as a}from"./p-74a7fc4f.js";import{d as h}from"./p-9746b0a5.js";import{g as r}from"./p-257432ff.js";import{g as l}from"./p-58cf5446.js";const c=":host{box-sizing:border-box}*,*::before,*::after{box-sizing:border-box}[hidden]{display:none !important}:host{--padding-top:var(--nano-spacing-small, 8px);--padding-bottom:var(--nano-spacing-small, 8px);--padding-start:var(--nano-spacing-xlarge, 24px);--padding-end:var(--nano-spacing-xlarge, 24px);--font-size:0.8em;--color:#b5aea7;color:var(--color)}.dlist--isfiltered ::slotted(*:not(nano-option):not([slot=no-result]):not([slot=list-top]):not([slot=list-bottom])){display:none !important}.dlist__dropdown{--min-width:100%;--overflow:auto}.dlist__status{clip:rect(1px, 1px, 1px, 1px);-webkit-clip-path:inset(50%);clip-path:inset(50%);block-size:1px;inline-size:1px;margin:-1px;overflow:hidden;padding:0;position:absolute}.dlist__menu{--padding-top:inherit;--padding-bottom:inherit;--padding-start:inherit;--padding-end:inherit;--font-size:inherit}";function d(t){let i;if(t.id){i=document.querySelector(`label[for='${t.id}']`)}if(!i){i=t.closest("label")}return i}let p=0;const u=class{get allOptEles(){return this._allOptEles}set allOptEles(t){var i;this._allOptEles=t;if((i=this.connectedInput)===null||i===void 0?void 0:i.value)return;t.forEach((t=>{if(t.selected&&!this.selected.includes(t.value)){this.changeInputValue(t)}}))}constructor(s){t(this,s);this.nanoSelect=i(this,"nanoSelect",7);this.nanoDeselect=i(this,"nanoDeselect",7);this.nanoOptionsUpdated=i(this,"nanoOptionsUpdated",7);this.isNanoInput=false;this.typeToSelect="";this.listId=`nano-datalist-${p++}`;this.isFiltered=false;this.shouldFocus=false;this._allOptEles=[];this._dropDownConfig={skidding:-1};this.optSelected=t=>{t.stopPropagation();this.changeInputValue(t.detail);requestAnimationFrame((()=>this.inputChange()));if(this.type!=="selctMulti")this.shouldOpen=false};this.handleShow=async()=>{if(this.shouldFocus){this.shouldFocus=false;this.listBox.setFocus()}else if(this.type==="select")this.listBox.showActiveElement()};this.handleHide=()=>{this.open=false;const t=a();if(t.closest(this.host.tagName.toLowerCase())){this.connectedInput.select()}};this.inputClick=()=>{this.shouldOpen=true;this.manageDropdownDisplay()};this.inputKeydown=t=>{const i=["Shift","ArrowRight","ArrowLeft","Escape","Enter","Tab"];if(i.includes(t.key)){if(t.key==="Tab")this.shouldOpen=false;return}if(this.type==="select"&&!["ArrowDown","ArrowUp"].includes(t.key)&&(t.key!==" "||this.typeToSelectTimeout)){if(t.key===" "||/^[a-z0-9]+$/i.test(t.key)){clearTimeout(this.typeToSelectTimeout);this.typeToSelectTimeout=window.setTimeout((()=>{this.typeToSelect="";this.typeToSelectTimeout=0}),750);this.typeToSelect+=t.key;this.setOptStartsWith()}return}this.shouldOpen=true;this.manageDropdownDisplay();if(["ArrowDown","ArrowUp"].includes(t.key)){t.preventDefault();this.shouldFocus=true}};this.optionKeyDown=t=>{const i=["Shift","ArrowUp","ArrowDown","Escape","Enter","Tab","Space","PageUp","PageDown","Home","End"," "];if(i.includes(t.key)){if(t.key==="Escape")this.connectedInput.focus();return}const s=["Delete","Backspace"];if(this.type!=="select"&&(!this.exactMatch||s.includes(t.key))){this.connectedInput.focus()}};this.actvOptEles=[];this.connectedInput=undefined;this.inputLabel=undefined;this.hasNoResult=undefined;this.shouldOpen=undefined;this.canOpen=true;this.optionIds=[];this.selected=[];this.options=[];this.input=undefined;this.type="input";this.open=false;this.disableFilter=false;this.disabled=false;this.inputChange=h(this.inputChange.bind(this),50)}get dropDownConfig(){return this._dropDownConfig}set dropDownConfig(t){this._dropDownConfig=Object.assign(Object.assign({},this._dropDownConfig),t)}get activeOptions(){return this.allOptEles}openWatcher(){s((()=>{this.nanoDropdown.open=this.open;if(this.connectedInput)this.connectedInput.setAttribute("aria-expanded",this.open.toString())}))}async watchInputChange(){let t;if(t=this.host.closest("nano-input")){this.isNanoInput=true;this.connectedInput=await t.getInputElement()}else if(this.input&&typeof this.input==="string"&&(t=document.querySelector(this.input))){this.isNanoInput=false;this.connectedInput=t}else if(typeof this.input==="object"){this.connectedInput=this.input}}manageSlotChangeListener(){var t;if(!this.host)return;if((!this.options||!this.options.length)&&!this.mo){{const t=this.mo=new MutationObserver((()=>this.processSlottedContent()));t.observe(this.host,{childList:true,subtree:true})}this.processSlottedContent();return}if((t=this.options)===null||t===void 0?void 0:t.length){if(!!this.mo){this.mo.disconnect();this.mo=undefined}const t=this.host.querySelectorAll('[slot="internal-opts"]');s((()=>{var i;if(t===null||t===void 0?void 0:t.length)t.forEach((t=>t.remove()));this.allOptEles=this.options.flatMap(((t,i)=>{if(t.value||t.label){const s=Object.assign(document.createElement("nano-option"),{label:t.label,value:t.value,ariaPosinset:i,ariaSetsize:this.options.length,selected:t.selected,id:this.listId+"-option-"+i,textContent:t.label?t.label:t.value,slot:"internal-opts"});this.host.append(s);return s}}));if(((i=this.connectedInput)===null||i===void 0?void 0:i.value.length)&&this.type!=="select"){this.inputChange()}else{this.actvOptEles=[...this.allOptEles]}}))}}watchTypeChange(){if(!this.connectedInput)return;let t={closeOnSelect:false};let i="both";let s=false;switch(this.type){case"input":t={closeOnSelect:true};break;case"select":i="list";s=true;t={closeOnSelect:true,placement:"center"};break}if(!this.isNanoInput){t.tetherTo=this.connectedInput}this.dropDownConfig=Object.assign(Object.assign({},this.dropDownConfig),t);this.connectedInput.setAttribute("aria-autocomplete",i);this.connectedInput.readOnly=s}manageInputEvents(t,i){var e;if(!!i){const t=i.closest("nano-input");if(t){t.removeEventListener("nanoChange",this.inputChange)}i.removeEventListener("change",this.inputChange);i.removeEventListener("click",this.inputClick);i.removeEventListener("keydown",this.inputKeydown);i.removeEventListener("input",this.inputChange);this.inputLabel=null;s((()=>{i.removeAttribute("role");i.removeAttribute("aria-expanded");i.removeAttribute("aria-controls");i.removeAttribute("aria-owns");i.removeAttribute("aria-haspopup");i.removeAttribute("aria-autocomplete");i.removeAttribute("autocomplete")}))}if(!!t){const i=t.closest("nano-input");if(i){i.addEventListener("nanoChange",this.inputChange)}t.addEventListener("change",this.inputChange);t.addEventListener("click",this.inputClick);t.addEventListener("keydown",this.inputKeydown);t.addEventListener("input",this.inputChange);this.listId=this.host.id||this.listId;this.inputLabel=((e=t===null||t===void 0?void 0:t.labels)===null||e===void 0?void 0:e.item(0))||d(t);s((()=>{this.host.id=this.listId;t.setAttribute("role","combobox");t.setAttribute("aria-expanded","false");t.setAttribute("aria-controls",this.listId);t.setAttribute("aria-owns",this.listId);t.setAttribute("aria-haspopup","listbox");t.setAttribute("autocomplete","off")}))}}watchActvOptChange(){var t;let i=0;const e=((t=this.connectedInput)===null||t===void 0?void 0:t.value)||"";const n=[];s((()=>{this.allOptEles.forEach(((t,s)=>{if(this.actvOptEles.includes(t)){i++;t.setAttribute("aria-posinset",i+"");t.setAttribute("aria-setsize",this.actvOptEles.length+"");t.hidden=false;this.isSelected(t,e)}else{t.removeAttribute("aria-posinset");t.removeAttribute("aria-setsize");t.hidden=true;t.selected=false}t.id=this.listId+"-option-"+s;n.push(t.id)}));this.optionIds=n}))}manageCanOpen(){if(this.actvOptEles.length||this.hasNoResult)this.canOpen=true;else this.canOpen=false}manageDropdownDisplay(){if(this.shouldOpen&&this.canOpen&&!this.disabled)this.open=true;if(!this.shouldOpen||!this.canOpen)this.open=false;this.openWatcher()}fireActiveOptsEvent(){this.nanoOptionsUpdated.emit(this.actvOptEles)}isSelected(t,i){if(i===t.value||this.selected.includes(t.value)){t.selected=true}else t.selected=false}get dropwdownOpen(){if(!this.nanoDropdown||!this.open)return false;return true}get exactMatch(){return this.allOptEles.find((t=>this.connectedInput.value===t.value))}changeInputValue(t){var i;let s;if(this.selected.includes(t.value)){this.selected=this.selected.filter((i=>i!==t.value));s=this.nanoDeselect.emit(t)}else{this.selected=[...this.selected];s=this.nanoSelect.emit(t)}if(!s.defaultPrevented){if(this.connectedInput)this.connectedInput.value=t.value;const s=new window.Event("change");(i=this.connectedInput)===null||i===void 0?void 0:i.dispatchEvent(s)}}setOptStartsWith(){const t=t=>t.toLowerCase().substring(0,this.typeToSelect.length)===this.typeToSelect;const i=this.allOptEles.find((i=>i.value.trim().length>0&&!i.disabled&&(t(i.textContent)||t(i.value)||t(i.label)||t(i.filterMeta))));if(i)this.changeInputValue(i)}processSlottedContent(){requestAnimationFrame((()=>{var t;this.allOptEles=Array.from(this.host.querySelectorAll("nano-option"));this.hasNoResult=!!this.host.querySelector('[slot="no-result"]');if(((t=this.connectedInput)===null||t===void 0?void 0:t.value.length)&&this.type!=="select"){this.inputChange()}else this.actvOptEles=this.allOptEles}))}inputChange(){if(this.disableFilter){this.actvOptEles=this.allOptEles;return}const t=this.connectedInput.value;const i=t.trim().toLowerCase();let s=false;const e=[];const n=t=>t.toLowerCase().indexOf(i)>-1;this.allOptEles.forEach((i=>{if((t===i.value||t===i.label)&&this.type!=="selctMulti"){i.selected=true;s=true}else this.isSelected(i,t)}));this.allOptEles.forEach((t=>{if(!i.length||s){e.push(t)}else if(t.value.trim().length>0&&!t.disabled&&(n(t.textContent)||n(t.value)||n(t.label)||n(t.filterMeta))){e.push(t)}}));this.isFiltered=i.length&&!s;this.actvOptEles=e}connectedCallback(){this.watchInputChange()}componentDidLoad(){this.manageSlotChangeListener();this.openWatcher()}componentDidRender(){setTimeout((()=>{if(!this.connectedInput)console.warn("no `nano-input` found. `nano-datalist` should be nested within an `nano-input` or linked via `input` prop",this.host)}),500)}render(){return e(n,{role:this.actvOptEles.length?"listbox":undefined,"aria-owns":this.optionIds.length?this.optionIds.join(" "):undefined,"aria-label":this.optionIds.length?"Select options from the list below":undefined},e("nano-dropdown",Object.assign({},this.dropDownConfig,{ref:t=>this.nanoDropdown=t,dialogTitle:"Select options from the list below",class:{dlist__dropdown:true,"dlist--isfiltered":this.isFiltered},onNanoAfterShow:this.handleShow,onNanoAfterHide:this.handleHide,role:"group"}),e("nano-menu",{hidden:!this.actvOptEles.length,type:"listbox",label:this.inputLabel?this.inputLabel.textContent:undefined,class:{dlist__menu:true,"dlist__menu--open":this.dropwdownOpen},tabIndex:-1,onNanoSelect:this.optSelected,onKeyDown:this.optionKeyDown,ref:t=>this.listBox=t,role:"list"},e("slot",{name:"list-top"}),!this.options.length&&e("slot",null),!!this.options.length&&e("slot",{name:"internal-opts"}),e("slot",{name:"list-bottom"})),e("nano-menu",{type:"listbox",label:"No results found",hidden:!!this.actvOptEles.length,class:{dlist__menu:true,"dlist__menu--open":this.dropwdownOpen}},e("slot",{name:"no-result"})),!!this.actvOptEles&&e("div",{class:"dlist__status"},this.actvOptEles.length," result",this.actvOptEles.length>1?"s":""," available.")))}get host(){return o(this)}static get watchers(){return{open:["openWatcher"],input:["watchInputChange"],options:["manageSlotChangeListener"],type:["watchTypeChange"],connectedInput:["watchTypeChange","manageInputEvents"],selected:["watchActvOptChange"],actvOptEles:["watchActvOptChange","manageCanOpen","fireActiveOptsEvent"],hasNoResult:["manageCanOpen"],shouldOpen:["manageDropdownDisplay"],canOpen:["manageDropdownDisplay"]}}};u.style=c;const f=":host{box-sizing:border-box}*,*::before,*::after{box-sizing:border-box}[hidden]{display:none !important}:host{--padding-start:var(--nano-spacing-medium, 16px);--padding-end:var(--nano-spacing-medium, 16px);--padding-top:var(--nano-spacing-small, 8px);--padding-bottom:var(--nano-spacing-small, 8px);--secondary-padding-top:0;--secondary-padding-bottom:0;--bg-color-hover:#f2f7f9;--bg-color-focus:#f2f7f9;--bg-color-selected:#f2f7f9;--color-hover:#007495;--color-selected:#007495;--color-focus:#007495;--focus-outline:none;--font-size:0.9em;display:block}.menu{font-size:var(--font-size, 0.9em);overscroll-behavior:none;min-width:var(--width);position:relative}.menu:focus{outline:none}::slotted(*:not(nano-nav-item):not(nano-option):not(hr):not(slot)){padding-inline:var(--padding-start) var(--padding-end);padding-block:var(--padding-top) var(--padding-bottom);display:block}";const g=class{constructor(s){t(this,s);this.nanoFocus=i(this,"nanoFocus",7);this.nanoBlur=i(this,"nanoBlur",7);this.nanoSelect=i(this,"nanoSelect",7);this.ignoreMouseEvents=false;this.typeToSelect="";this._hasFocus=false;this.handleFocus=()=>{this.setActiveFocusItem(this.selectedItem||this.getItems[0]);this._hasFocus=true;this.nanoFocus.emit()};this.handleClick=t=>{const i=t.target;const s=i.closest("nano-nav-item");if(s&&!s.disabled){this.nanoSelect.emit(s)}};this.handleKeyDown=t=>{clearTimeout(this.ignoreMouseTimeout);this.ignoreMouseTimeout=setTimeout((()=>this.ignoreMouseEvents=false),500);this.ignoreMouseEvents=true;switch(t.key){case" ":if(this.activeItem)this.activeItem.click();break;case"ArrowDown":case"ArrowUp":case"PageDown":case"PageUp":case"Home":case"End":const i=this.getItems;const s=this.activeItem;let e=i.indexOf(s);if(i.length){t.preventDefault();if(t.key==="ArrowDown"){e++}else if(t.key==="ArrowUp"){e--}else if(t.key==="Home"||t.key==="PageUp"){e=0}else if(t.key==="End"||t.key==="PageDown"){e=i.length-1}if(e<0)e=i.length-1;if(e>i.length-1)e=0;this.setActiveFocusItem(i[e]);if(i[e])i[e].scrollIntoView({block:"nearest"});return}break}if(t.key===" "||/^[a-z0-9]+$/i.test(t.key)){clearTimeout(this.typeToSelectTimeout);this.typeToSelectTimeout=setTimeout((()=>this.typeToSelect=""),750);this.typeToSelect+=t.key;const i=this.getItems;for(const t of i){const i=t.shadowRoot.querySelector("slot:not([name])");const s=l(i).toLowerCase().trim();if(s.substring(0,this.typeToSelect.length)===this.typeToSelect){this.setActiveFocusItem(t);break}}}};this.handleMouseOver=t=>{const i=t.target;const s=i.closest("nano-nav-item")||i.closest("nano-option");if(s&&!this.ignoreMouseEvents){this.setActiveFocusItem(s)}};this.type="menu";this.label=undefined}get hasFocus(){return this._hasFocus}async setFocus(){var t;if((t=this.menu)===null||t===void 0?void 0:t.focus)this.menu.focus({preventScroll:true})}async removeFocus(){var t;if((t=this.menu)===null||t===void 0?void 0:t.blur)this.menu.blur()}async showActiveElement(){if(this.selectedItem)this.selectedItem.scrollIntoView({block:"nearest"})}async resetActiveItem(){this.getItems.filter((t=>t.tagName.toLowerCase()==="nano-option")).map((t=>t.setAttribute("tabindex","-1")))}get getItems(){let t;const i=this.el.querySelectorAll("nano-nav-item.secondary-open");if(i.length){const s=i[i.length-1];t=Array.from(s.querySelectorAll("nano-nav-item, nano-option"))}else{t=r(this.el,"nano-nav-item, nano-option","slot")}return t.filter((t=>!t.disabled&&!t.hidden))}get activeItem(){const t=a();return this.getItems.find((i=>i.getAttribute("tabindex")==="0"||i===t||i.classList.contains("has-focus")))}get selectedItem(){return this.getItems.find((t=>t.selected))}async setActiveFocusItem(t,i=true){const s=this.getItems;const e=!t||t.disabled?s.find((t=>t.selected))||s[0]:t;s.filter((t=>t.tagName.toLowerCase()==="nano-option")).map((t=>t.setAttribute("tabindex",t===e?"0":"-1")));if(!i)return;if(e){e.setFocus?e.setFocus():e.focus()}else this.menu.focus()}handleBlur(t){if(!this.hasFocus)return;const i=t;let s;if(i.key){if(i.key!=="Tab")return;s=a()&&a().closest(this.el.tagName.toLowerCase())===this.el}else s=!!t.composedPath().find((t=>t===this.el));if(!s){this.resetActiveItem();this._hasFocus=false;this.nanoBlur.emit()}}componentDidLoad(){{r(this.el,":not(nano-nav-item):not(nano-option):not([role])",true).forEach((t=>t.setAttribute("role","none")))}}render(){return e(n,{role:this.type==="menu"?"menu":"group"},e("div",{onClick:this.handleClick,onKeyDown:this.handleKeyDown,onMouseOver:this.handleMouseOver,onFocus:this.handleFocus,"aria-label":this.label?this.label:undefined,ref:t=>this.menu=t,part:"base",class:{menu:true,["menu--"+this.type]:true,"menu--has-focus":this.hasFocus},tabIndex:-1,role:"group"},e("slot",null)))}get el(){return o(this)}};g.style=f;const m=":host{box-sizing:border-box}*,*::before,*::after{box-sizing:border-box}[hidden]{display:none !important}:host{--bg:none;--bg-selected:var(--nano-select-opt-bg, #f2f7f9);--bg-focus:var(--nano-color-base, var(--nano-color-primary-tint, #2689a5));--bg-disabled:none;--color:var(--input-text-color, var(--nano-input-text-color, #4a4a4a));--color-selected:var(--nano-color-base, var(--nano-color-primary, #007495));--color-focus:var(--nano-color-contrast, var(--nano-color-primary-contrast, #fff));--color-disabled:#b5aea7;--opt-icon-size:1.6em;display:block;color:var(--color);overflow:hidden;font-size:14px;font-size:clamp(12px, .9em, 16px)}:host(:focus){outline:none}.option{position:relative;-webkit-user-select:none;user-select:none;cursor:pointer;display:flex;align-items:stretch;width:100%;background:var(--bg);padding-inline:var(--padding-start) var(--padding-end);padding-block:var(--padding-top) var(--padding-bottom)}:host(:focus) .option:not(.option--disabled),:host .option.option--selected{outline:none;background:var(--bg-selected);color:var(--color-selected)}:host(:focus) .option:not(.option--disabled){background:var(--bg-focus);color:var(--color-focus)}.option.option--disabled{outline:none;color:var(--color-disabled);cursor:not-allowed;background:var(--bg-disabled)}.option.option--novalue{font-style:italic;opacity:0.7}.option__label{flex:1 1 auto;display:flex;align-items:center}.option__start{flex:0 0 auto;display:flex;align-items:center}.option__start ::slotted(nano-icon){font-size:var(--opt-icon-size)}.option__start ::slotted(:last-child){-webkit-margin-end:0.5em;margin-inline-end:0.5em}.option__end{flex:0 0 auto;display:flex;align-items:center}.option__end ::slotted(nano-icon){font-size:var(--opt-icon-size)}.option__end ::slotted(:first-child){-webkit-margin-start:0.5em;margin-inline-start:0.5em}.option__check{visibility:hidden;display:flex;position:absolute;inset-inline-start:0.6em;inset-block-start:calc(50% - 0.6em);align-items:center;font-size:0.9em}.option--selected:not(.option--novalue) .option__check{visibility:visible}";let b=0;const v=class{constructor(s){t(this,s);this.nanoSelect=i(this,"nanoSelect",7);this.optId=`nano-option-${b++}`;this.hasFocus=false;this.value="";this.label="";this.selected=false;this.disabled=false;this.filterMeta="";this.handleClick=h(this.handleClick.bind(this),5)}valueChanged(){if(!this.value||!this.value.length)this.value=this.labelContent}labelChanged(){if(!this.label||!this.label.length)this.label=this.labelContent.length?this.labelContent:this.value}handleKeyDown(t){if(t.key!==" "&&t.key!=="Enter")return;t.preventDefault();this.nanoSelect.emit(this.host)}handleClick(){if(this.disabled)return;this.nanoSelect.emit(this.host)}get labelContent(){return r(this.host,"*:not([slot])",false).map((t=>t.textContent)).join(" ").trim()}componentWillLoad(){this.valueChanged();this.labelChanged()}render(){return e(n,{role:"option","aria-selected":this.selected?"true":"false","aria-disabled":this.disabled?"true":"false"},e("div",{onMouseDown:this.handleClick,id:this.optId,class:{option:true,"option--selected":this.selected,"option--disabled":this.disabled,"option--novalue":!this.value}},e("div",{part:"check-icon",class:"option__check"},e("slot",{name:"check-icon"},e("nano-icon",{name:"light/check","aria-hidden":"true"}))),e("div",{part:"start",class:"option__start"},e("slot",{name:"start"})),e("div",{part:"label",class:"option__label"},e("slot",null,this.label||this.value)),e("div",{part:"end",class:"option__end"},e("slot",{name:"end"}))))}get host(){return o(this)}static get watchers(){return{value:["valueChanged"],label:["labelChanged"]}}};v.style=m;export{u as nano_datalist,g as nano_menu,v as nano_option};
5
- //# sourceMappingURL=p-2ad0d9a3.entry.js.map
@@ -1 +0,0 @@
1
- {"version":3,"names":["datalistCss","findLabel","formCtrl","foundLabel","id","document","querySelector","closest","listIds","DataList","allOptEles","this","_allOptEles","opts","_a","connectedInput","value","forEach","opt","selected","includes","changeInputValue","constructor","hostRef","isNanoInput","typeToSelect","listId","isFiltered","shouldFocus","_dropDownConfig","skidding","optSelected","e","stopPropagation","detail","requestAnimationFrame","inputChange","type","shouldOpen","handleShow","async","listBox","setFocus","showActiveElement","handleHide","open","activeElement","getActiveElement","host","tagName","toLowerCase","select","inputClick","manageDropdownDisplay","inputKeydown","ignoreKeys","key","typeToSelectTimeout","test","clearTimeout","window","setTimeout","setOptStartsWith","preventDefault","optionKeyDown","focus","deleteKeys","exactMatch","debounce","bind","dropDownConfig","ddc","Object","assign","activeOptions","openWatcher","writeTask","nanoDropdown","setAttribute","toString","nanoInput","getInputElement","input","manageSlotChangeListener","options","length","mo","MutationObserver","processSlottedContent","observe","childList","subtree","disconnect","undefined","previousOptions","querySelectorAll","internalOpt","remove","flatMap","option","i","label","createElement","ariaPosinset","ariaSetsize","textContent","slot","append","actvOptEles","watchTypeChange","dwConfig","closeOnSelect","autocompleteType","readonly","placement","tetherTo","readOnly","manageInputEvents","newInput","oldInput","removeEventListener","inputLabel","removeAttribute","addEventListener","labels","item","watchActvOptChange","c","val","optIds","hidden","isSelected","push","optionIds","manageCanOpen","hasNoResult","canOpen","disabled","fireActiveOptsEvent","nanoOptionsUpdated","emit","dropwdownOpen","find","nanoSelected","filter","nanoDeselect","nanoSelect","defaultPrevented","event","Event","dispatchEvent","attrFind","toFind","substring","foundEle","trim","filterMeta","Array","from","disableFilter","valStr","activeEles","indexOf","connectedCallback","watchInputChange","componentDidLoad","componentDidRender","console","warn","render","h","Host","role","join","ref","el","dialogTitle","class","dlist__dropdown","onNanoAfterShow","onNanoAfterHide","dlist__menu","tabIndex","onNanoSelect","onKeyDown","name","menuCss","Menu","ignoreMouseEvents","_hasFocus","handleFocus","setActiveFocusItem","selectedItem","getItems","nanoFocus","handleClick","target","handleKeyDown","ignoreMouseTimeout","activeItem","click","items","index","scrollIntoView","block","shadowRoot","getTextContent","handleMouseOver","hasFocus","menu","preventScroll","blur","map","opened","ctx","getDirectChildren","getAttribute","classList","contains","handleBlur","kev","found","composedPath","resetActiveItem","nanoBlur","onClick","onMouseOver","onFocus","part","optionCss","Option","optId","valueChanged","labelContent","labelChanged","componentWillLoad","onMouseDown"],"sources":["./src/components/datalist/datalist.scss?tag=nano-datalist&encapsulation=shadow","./src/components/datalist/datalist.tsx","./src/components/menu/menu.scss?tag=nano-menu&encapsulation=shadow","./src/components/menu/menu.tsx","./src/components/option/option.scss?tag=nano-option&encapsulation=shadow","./src/components/option/option.tsx"],"sourcesContent":["@use 'sass:map';\n@use 'sass:list';\n\n@import '../../global/style/utilities/globals';\n@import '../../global/style/nano-theme/form';\n@import '../../global/style/nano-theme/base';\n@import '../../global/style/nano-theme/layers';\n\n:host {\n /**\n * @prop --padding-top: for all nested `nano-option` elements. Defaults to #{$spacing-small};\n * @prop --padding-bottom: for all nested `nano-option` elements. Defaults to #{$spacing-small};\n * @prop --padding-start: for all nested `nano-option` elements. Defaults to #{$spacing-xlarge};\n * @prop --padding-end: for all nested `nano-option` elements. Defaults to #{$spacing-xlarge};\n * @prop --font-size: for all nested `nano-option` elements. Defaults to .8em;\n * @prop --color: default text color of content other than `nano-option`. Defaults to #{map.get($colors, palegrey)};\n */\n\n --padding-top: #{$spacing-small};\n --padding-bottom: #{$spacing-small};\n --padding-start: #{$spacing-xlarge};\n --padding-end: #{$spacing-xlarge};\n --font-size: 0.8em;\n --color: #{map.get($colors, palegrey)};\n\n color: var(--color);\n}\n\n.dlist {\n &--isfiltered {\n ::slotted(*:not(nano-option):not([slot='no-result']):not([slot='list-top']):not([slot='list-bottom'])) {\n display: none !important;\n }\n }\n\n &__dropdown {\n --min-width: 100%;\n --overflow: auto;\n }\n\n &__status {\n @include visually-hide();\n }\n\n &__menu {\n --padding-top: inherit;\n --padding-bottom: inherit;\n --padding-start: inherit;\n --padding-end: inherit;\n --font-size: inherit;\n }\n}\n","import {\n Component,\n ComponentInterface,\n h,\n Host,\n Element,\n State,\n Watch,\n Prop,\n Event,\n writeTask,\n Build,\n EventEmitter,\n} from '@stencil/core';\nimport { getActiveElement } from '../../utils/active-element';\nimport { debounce } from '../../utils/throttle';\nimport type { NanoMenuCustomEvent, OptionInterface } from '../../interface';\nimport type { Dropdown } from '../dropdown/dropdown';\n\nfunction findLabel(formCtrl: Element) {\n let foundLabel: HTMLLabelElement;\n\n if (formCtrl.id) {\n foundLabel = document.querySelector(`label[for='${formCtrl.id}']`);\n }\n if (!foundLabel) {\n foundLabel = formCtrl.closest('label');\n }\n return foundLabel;\n}\n\nlet listIds = 0;\n\n/**\n * `nano-datalist` a visually consistent and more flexible replacement for a native\n * [datalist](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/datalist). Can be nested within a `nano-input`\n * or linked to any input control via the `input` prop. Is used internally within `nano-select`.\n * Options can be defined declaratively by nesting `<nano-option>` elements or imperatively using the `options` prop\n *\n * @slot - use `<nano-option>` elements for more complex html. Alternatively use the `options` prop\n * @slot list-top - shows at the top of the list when there are options present\n * @slot list-bottom - shows at the bottom of the list when there are options present\n * @slot no-result - shown when there are no results otherwise nothing will be shown\n */\n@Component({\n tag: 'nano-datalist',\n styleUrl: 'datalist.scss',\n shadow: true,\n})\nexport class DataList implements ComponentInterface {\n // Private State\n\n private isNanoInput = false;\n private typeToSelect = '';\n private typeToSelectTimeout: number;\n private nanoDropdown: HTMLNanoDropdownElement;\n private listBox: HTMLNanoMenuElement;\n private mo?: MutationObserver;\n private listId = `nano-datalist-${listIds++}`;\n private isFiltered = false;\n private shouldFocus = false;\n // all potential option eles. Set via slot or `options` prop.\n // Some may get hidden due to filtering\n private get allOptEles() {\n return this._allOptEles;\n }\n private set allOptEles(opts) {\n // when allOptEles are initially set (on slot change / options) -\n // add options to 'selected' and fire selected event *if*\n // value isn't set on the input\n this._allOptEles = opts;\n if (this.connectedInput?.value) return;\n\n opts.forEach((opt) => {\n if (opt.selected && !this.selected.includes(opt.value)) {\n this.changeInputValue(opt);\n }\n });\n }\n private _allOptEles: HTMLNanoOptionElement[] = [];\n\n @Element() host: HTMLNanoDatalistElement;\n\n // active option eles that are not hidden.\n @State() actvOptEles: HTMLNanoOptionElement[] = [];\n @State() connectedInput: HTMLInputElement | HTMLTextAreaElement;\n @State() inputLabel: HTMLLabelElement;\n @State() hasNoResult: boolean;\n @State() shouldOpen: boolean;\n @State() canOpen: boolean = true;\n @State() optionIds: string[] = [];\n\n constructor() {\n this.inputChange = debounce(this.inputChange.bind(this), 50);\n }\n\n // Public API\n\n /** By default, items in the list will appear 'selected' when the value in the linked input control matches.\n * However you can add other selected options via the the selected prop. */\n @Prop({ mutable: true }) selected: string[] = [];\n\n /** nano-dropdown config options you can pass to the nested dropdown component */\n @Prop()\n get dropDownConfig() {\n return this._dropDownConfig;\n }\n set dropDownConfig(ddc: Partial<Dropdown>) {\n this._dropDownConfig = { ...this._dropDownConfig, ...ddc };\n }\n private _dropDownConfig: Partial<Dropdown> = {\n skidding: -1,\n };\n\n /** Provide an option list.\n * Options can be defined declaratively by nesting `<nano-option>` elements or imperatively using this prop */\n @Prop() options?: OptionInterface[] = [];\n\n /** A selector to a HTMLInputElement */\n @Prop() input?: string | HTMLInputElement;\n\n /** Tweaks the datalist behaviour and linked control semantics and behaviour.\n * e.g. 'select' will make the linked input control `readonly`.\n */\n @Prop() type: 'select' | 'selctMulti' | 'input' = 'input';\n\n /** return all the active options currently within the datalist. Can be useful for validation */\n @Prop()\n get activeOptions() {\n return this.allOptEles;\n }\n\n /** Force datalist open */\n @Prop({ mutable: true }) open: boolean = false;\n\n @Watch('open')\n openWatcher() {\n writeTask(() => {\n this.nanoDropdown.open = this.open;\n if (this.connectedInput)\n this.connectedInput.setAttribute('aria-expanded', this.open.toString());\n });\n }\n\n /** Use this option to disable to default filtering. This is useful if filtering happens\n * externally via another method (e.g. via ajax)\n */\n @Prop() disableFilter = false;\n\n /** Activate / deactivate the datalist control */\n @Prop() disabled = false;\n\n // State change watchers\n\n @Watch('input')\n async watchInputChange() {\n let nanoInput;\n if ((nanoInput = this.host.closest('nano-input'))) {\n this.isNanoInput = true;\n this.connectedInput = await nanoInput.getInputElement();\n } else if (\n this.input &&\n typeof this.input === 'string' &&\n (nanoInput = document.querySelector(this.input))\n ) {\n this.isNanoInput = false;\n this.connectedInput = nanoInput;\n } else if (typeof this.input === 'object') {\n this.connectedInput = this.input;\n }\n }\n\n @Watch('options')\n manageSlotChangeListener() {\n if (!this.host) return;\n\n // we're not using `options` - setup new MO\n if ((!this.options || !this.options.length) && !this.mo) {\n if (Build.isBrowser) {\n const mo = (this.mo = new MutationObserver(() =>\n this.processSlottedContent()\n ));\n mo.observe(this.host, { childList: true, subtree: true });\n }\n this.processSlottedContent();\n return;\n }\n\n // we're using `options` - trash current MO\n if (this.options?.length) {\n if (!!this.mo) {\n this.mo.disconnect();\n this.mo = undefined;\n }\n\n const previousOptions = this.host.querySelectorAll(\n '[slot=\"internal-opts\"]'\n );\n\n // add imperative `options`\n writeTask(() => {\n // clear all previous\n if (previousOptions?.length)\n previousOptions.forEach((internalOpt) => internalOpt.remove());\n\n this.allOptEles = this.options.flatMap((option, i) => {\n if (option.value || option.label) {\n const opt = Object.assign(document.createElement('nano-option'), {\n label: option.label,\n value: option.value,\n ariaPosinset: i,\n ariaSetsize: this.options.length,\n selected: option.selected,\n id: this.listId + '-option-' + i,\n textContent: option.label ? option.label : option.value,\n slot: 'internal-opts',\n });\n this.host.append(opt);\n return opt;\n }\n });\n\n if (this.connectedInput?.value.length && this.type !== 'select') {\n this.inputChange();\n } else {\n this.actvOptEles = [...this.allOptEles];\n }\n });\n }\n // forceUpdate(this.host);\n }\n\n @Watch('type')\n @Watch('connectedInput')\n watchTypeChange() {\n if (!this.connectedInput) return;\n\n let dwConfig: Partial<Dropdown> = { closeOnSelect: false };\n let autocompleteType: 'list' | 'both' = 'both';\n let readonly = false;\n\n switch (this.type) {\n case 'input':\n dwConfig = { closeOnSelect: true };\n break;\n case 'select':\n autocompleteType = 'list';\n readonly = true;\n dwConfig = { closeOnSelect: true, placement: 'center' };\n break;\n }\n\n if (!this.isNanoInput) {\n dwConfig.tetherTo = this.connectedInput;\n }\n\n this.dropDownConfig = { ...this.dropDownConfig, ...dwConfig };\n this.connectedInput.setAttribute('aria-autocomplete', autocompleteType);\n this.connectedInput.readOnly = readonly;\n }\n\n @Watch('connectedInput')\n manageInputEvents(newInput?: HTMLInputElement, oldInput?: HTMLInputElement) {\n if (!!oldInput) {\n const nanoInput = oldInput.closest('nano-input');\n if (nanoInput) {\n nanoInput.removeEventListener('nanoChange', this.inputChange);\n }\n oldInput.removeEventListener('change', this.inputChange);\n oldInput.removeEventListener('click', this.inputClick);\n oldInput.removeEventListener('keydown', this.inputKeydown);\n oldInput.removeEventListener('input', this.inputChange);\n\n this.inputLabel = null;\n\n writeTask(() => {\n oldInput.removeAttribute('role');\n oldInput.removeAttribute('aria-expanded');\n oldInput.removeAttribute('aria-controls');\n oldInput.removeAttribute('aria-owns');\n oldInput.removeAttribute('aria-haspopup');\n oldInput.removeAttribute('aria-autocomplete');\n oldInput.removeAttribute('autocomplete');\n });\n }\n if (!!newInput) {\n const nanoInput = newInput.closest('nano-input');\n if (nanoInput) {\n nanoInput.addEventListener('nanoChange', this.inputChange);\n }\n newInput.addEventListener('change', this.inputChange);\n newInput.addEventListener('click', this.inputClick);\n newInput.addEventListener('keydown', this.inputKeydown);\n newInput.addEventListener('input', this.inputChange);\n this.listId = this.host.id || this.listId;\n\n this.inputLabel = newInput?.labels?.item(0) || findLabel(newInput);\n\n writeTask(() => {\n this.host.id = this.listId;\n newInput.setAttribute('role', 'combobox');\n newInput.setAttribute('aria-expanded', 'false');\n newInput.setAttribute('aria-controls', this.listId);\n newInput.setAttribute('aria-owns', this.listId);\n newInput.setAttribute('aria-haspopup', 'listbox');\n newInput.setAttribute('autocomplete', 'off');\n });\n }\n }\n\n @Watch('selected')\n @Watch('actvOptEles')\n watchActvOptChange() {\n let c = 0;\n const val = this.connectedInput?.value || '';\n const optIds = [];\n\n writeTask(() => {\n this.allOptEles.forEach((opt, i) => {\n if (this.actvOptEles.includes(opt)) {\n c++;\n opt.setAttribute('aria-posinset', c + '');\n opt.setAttribute('aria-setsize', this.actvOptEles.length + '');\n opt.hidden = false;\n this.isSelected(opt, val);\n } else {\n opt.removeAttribute('aria-posinset');\n opt.removeAttribute('aria-setsize');\n opt.hidden = true;\n opt.selected = false;\n }\n opt.id = this.listId + '-option-' + i;\n optIds.push(opt.id);\n });\n this.optionIds = optIds;\n });\n }\n\n @Watch('actvOptEles')\n @Watch('hasNoResult')\n manageCanOpen() {\n if (this.actvOptEles.length || this.hasNoResult) this.canOpen = true;\n else this.canOpen = false;\n }\n\n /**\n * Opens the dropdown if it can, it should and there are items to display.\n */\n @Watch('shouldOpen')\n @Watch('canOpen')\n manageDropdownDisplay() {\n if (this.shouldOpen && this.canOpen && !this.disabled) this.open = true;\n if (!this.shouldOpen || !this.canOpen) this.open = false;\n this.openWatcher();\n }\n\n @Watch('actvOptEles')\n fireActiveOptsEvent() {\n this.nanoOptionsUpdated.emit(this.actvOptEles);\n }\n\n // Events\n\n /** Fired when an item is selected. */\n @Event() nanoSelect: EventEmitter<HTMLNanoOptionElement>;\n\n /** Fired when a currently selected item is reselected. */\n @Event() nanoDeselect: EventEmitter<HTMLNanoOptionElement>;\n\n /** Fired when active options change */\n @Event() nanoOptionsUpdated: EventEmitter<HTMLNanoOptionElement[]>;\n\n // Private logic\n\n private isSelected(opt: HTMLNanoOptionElement, val: string) {\n if (val === opt.value || this.selected.includes(opt.value)) {\n opt.selected = true;\n } else opt.selected = false;\n }\n\n private get dropwdownOpen() {\n if (!this.nanoDropdown || !this.open) return false;\n return true;\n }\n\n private get exactMatch() {\n return this.allOptEles.find(\n (opt) => this.connectedInput.value === opt.value\n );\n }\n\n /** reflect value back to the connected input unless the event is cancelled */\n private changeInputValue(opt: HTMLNanoOptionElement) {\n let nanoSelected;\n\n if (this.selected.includes(opt.value)) {\n // deselect option\n this.selected = this.selected.filter((val) => val !== opt.value);\n nanoSelected = this.nanoDeselect.emit(opt);\n } else {\n // select new option\n this.selected = [...this.selected];\n nanoSelected = this.nanoSelect.emit(opt);\n }\n\n if (!nanoSelected.defaultPrevented) {\n if (this.connectedInput) this.connectedInput.value = opt.value;\n\n const event = new window.Event('change');\n this.connectedInput?.dispatchEvent(event);\n }\n }\n\n // a new option has been picked\n private optSelected = (e: NanoMenuCustomEvent<HTMLNanoOptionElement>) => {\n e.stopPropagation();\n this.changeInputValue(e.detail);\n requestAnimationFrame(() => this.inputChange());\n\n if (this.type !== 'selctMulti') this.shouldOpen = false;\n };\n\n // this is for type=\"select\" only.\n // Filter options that start with text - aggregates letters (as opposed to getting the value from input)\n private setOptStartsWith() {\n const attrFind = (toFind: string) =>\n toFind.toLowerCase().substring(0, this.typeToSelect.length) ===\n this.typeToSelect;\n\n const foundEle = this.allOptEles.find(\n (opt) =>\n opt.value.trim().length > 0 &&\n !opt.disabled &&\n (attrFind(opt.textContent) ||\n attrFind(opt.value) ||\n attrFind(opt.label) ||\n attrFind(opt.filterMeta))\n );\n if (foundEle) this.changeInputValue(foundEle);\n }\n\n // Event handlers\n\n private processSlottedContent() {\n requestAnimationFrame(() => {\n this.allOptEles = Array.from(this.host.querySelectorAll('nano-option'));\n this.hasNoResult = !!this.host.querySelector('[slot=\"no-result\"]');\n\n if (this.connectedInput?.value.length && this.type !== 'select') {\n this.inputChange();\n } else this.actvOptEles = this.allOptEles;\n });\n }\n\n // sets focus immediately on open when 'select' - mirroring native behaviour\n private handleShow = async () => {\n if (this.shouldFocus) {\n this.shouldFocus = false;\n this.listBox.setFocus();\n } else if (this.type === 'select') this.listBox.showActiveElement();\n };\n\n private handleHide = () => {\n this.open = false;\n const activeElement = getActiveElement();\n if (activeElement.closest(this.host.tagName.toLowerCase())) {\n this.connectedInput.select();\n }\n };\n\n // any changes to the connected input value will filter the list of active options\n private inputChange() {\n if (this.disableFilter) {\n this.actvOptEles = this.allOptEles;\n return;\n }\n\n const val = this.connectedInput.value;\n const valStr = val.trim().toLowerCase();\n\n let exactMatch = false;\n const activeEles = [];\n const attrFind = (toFind: string) =>\n toFind.toLowerCase().indexOf(valStr) > -1;\n\n this.allOptEles.forEach((opt) => {\n if (\n (val === opt.value || val === opt.label) &&\n this.type !== 'selctMulti'\n ) {\n opt.selected = true;\n exactMatch = true;\n } else this.isSelected(opt, val);\n });\n\n this.allOptEles.forEach((opt) => {\n if (!valStr.length || exactMatch) {\n activeEles.push(opt);\n } else if (\n opt.value.trim().length > 0 &&\n !opt.disabled &&\n (attrFind(opt.textContent) ||\n attrFind(opt.value) ||\n attrFind(opt.label) ||\n attrFind(opt.filterMeta))\n ) {\n activeEles.push(opt);\n }\n });\n\n this.isFiltered = valStr.length && !exactMatch;\n this.actvOptEles = activeEles;\n }\n\n private inputClick = () => {\n this.shouldOpen = true;\n // open dropdown if possible\n this.manageDropdownDisplay();\n };\n\n private inputKeydown = (e: KeyboardEvent) => {\n const ignoreKeys = [\n 'Shift',\n 'ArrowRight',\n 'ArrowLeft',\n 'Escape',\n 'Enter',\n 'Tab',\n ];\n if (ignoreKeys.includes(e.key)) {\n if (e.key === 'Tab') this.shouldOpen = false;\n return;\n }\n\n // When select, mirror native select behaviour. Search on closed list\n if (\n this.type === 'select' &&\n !['ArrowDown', 'ArrowUp'].includes(e.key) &&\n (e.key !== ' ' || this.typeToSelectTimeout)\n ) {\n if (e.key === ' ' || /^[a-z0-9]+$/i.test(e.key)) {\n clearTimeout(this.typeToSelectTimeout);\n this.typeToSelectTimeout = window.setTimeout(() => {\n this.typeToSelect = '';\n this.typeToSelectTimeout = 0;\n }, 750);\n this.typeToSelect += e.key;\n this.setOptStartsWith();\n }\n return;\n }\n\n this.shouldOpen = true;\n // open dropdown if possible\n this.manageDropdownDisplay();\n if (['ArrowDown', 'ArrowUp'].includes(e.key)) {\n e.preventDefault();\n this.shouldFocus = true;\n }\n };\n\n // handles key down on options. Either 'picks'\n // an option or passes event back to input for search / filter\n private optionKeyDown = (\n e: KeyboardEvent & { target: HTMLNanoOptionElement }\n ) => {\n const ignoreKeys = [\n 'Shift',\n 'ArrowUp',\n 'ArrowDown',\n 'Escape',\n 'Enter',\n 'Tab',\n 'Space',\n 'PageUp',\n 'PageDown',\n 'Home',\n 'End',\n ' ',\n ];\n if (ignoreKeys.includes(e.key)) {\n if (e.key === 'Escape') this.connectedInput.focus();\n return;\n }\n\n const deleteKeys = ['Delete', 'Backspace'];\n // this passes whatever's typed back to our input control\n if (\n this.type !== 'select' &&\n (!this.exactMatch || deleteKeys.includes(e.key))\n ) {\n this.connectedInput.focus();\n }\n };\n\n // Component lifecycle\n\n connectedCallback() {\n this.watchInputChange();\n }\n\n componentDidLoad() {\n this.manageSlotChangeListener();\n this.openWatcher();\n }\n\n componentDidRender(): void {\n setTimeout(() => {\n if (!this.connectedInput)\n console.warn(\n 'no `nano-input` found. `nano-datalist` should be nested within an `nano-input` or linked via `input` prop',\n this.host\n );\n }, 500);\n }\n\n render() {\n return (\n <Host\n role={this.actvOptEles.length ? 'listbox' : undefined}\n aria-owns={this.optionIds.length ? this.optionIds.join(' ') : undefined}\n aria-label={\n this.optionIds.length\n ? 'Select options from the list below'\n : undefined\n }\n >\n <nano-dropdown\n {...this.dropDownConfig}\n ref={(el) => (this.nanoDropdown = el)}\n dialogTitle=\"Select options from the list below\"\n class={{\n dlist__dropdown: true,\n 'dlist--isfiltered': this.isFiltered,\n }}\n onNanoAfterShow={this.handleShow}\n onNanoAfterHide={this.handleHide}\n role=\"group\"\n >\n <nano-menu\n hidden={!this.actvOptEles.length}\n type=\"listbox\"\n label={this.inputLabel ? this.inputLabel.textContent : undefined}\n class={{\n dlist__menu: true,\n 'dlist__menu--open': this.dropwdownOpen,\n }}\n tabIndex={-1}\n onNanoSelect={this.optSelected}\n onKeyDown={this.optionKeyDown}\n ref={(el) => (this.listBox = el)}\n role=\"list\"\n >\n <slot name=\"list-top\" />\n {!this.options.length && <slot />}\n {!!this.options.length && <slot name=\"internal-opts\" />}\n <slot name=\"list-bottom\" />\n </nano-menu>\n <nano-menu\n type=\"listbox\"\n label=\"No results found\"\n hidden={!!this.actvOptEles.length}\n class={{\n dlist__menu: true,\n 'dlist__menu--open': this.dropwdownOpen,\n }}\n >\n <slot name=\"no-result\" />\n </nano-menu>\n {!!this.actvOptEles && (\n <div class=\"dlist__status\">\n {this.actvOptEles.length} result\n {this.actvOptEles.length > 1 ? 's' : ''} available.\n </div>\n )}\n </nano-dropdown>\n </Host>\n );\n }\n}\n","@use 'sass:map';\n@use 'sass:list';\n\n@import '../../global/style/utilities/globals';\n@import '../../global/style/nano-theme/colours';\n@import '../../global/style/nano-theme/layers';\n\n:host {\n /**\n * @prop --padding-start: padding at the start of nav-items (left r2l / right l2r). Defaults to '10px'\n * @prop --padding-end: padding at the end of nav-items (right r2l / left l2r). Defaults to '10px'\n * @prop --padding-top: padding at the top of nav-items. Defaults to '10px'\n * @prop --padding-bottom: padding at the bottom of nav-items. Defaults to '10px'\n\n * @prop --secondary-padding-top: padding at the top of nested nav-items. Defaults to 0\n * @prop --secondary-padding-bottom: padding at the bottom of nested nav-items. Defaults to 0\n\n * @prop --bg-color-hover: bg hover color of nav-items. Defaults to #{map.get($colors, blue--faded)};\n * @prop --bg-color-focus: bg focus color of nav-items. Defaults to #{map.get($colors, blue--faded)};\n * @prop --bg-color-selected: bg selected color of nav-items. Defaults to #{map.get($colors, blue--faded)};\n\n * @prop --color-hover: text hover color of nav-items. Defaults to #{map.get($colors, blue)}\n * @prop --color-selected: text selected color of nav-items. Defaults to #{map.get($colors, blue)}\n * @prop --color-focus: text focus color of nav-items. Defaults to #{map.get($colors, blue)}\n\n * @prop --focus-outline: the focus style of nav-items. Defaults to 'none'\n * @prop --font-size: default font-size for all items. Defaults .9em;\n */\n\n --padding-start: #{$spacing-medium};\n --padding-end: #{$spacing-medium};\n --padding-top: #{$spacing-small};\n --padding-bottom: #{$spacing-small};\n --secondary-padding-top: 0;\n --secondary-padding-bottom: 0;\n --bg-color-hover: #{map.get($colors, blue--faded)};\n --bg-color-focus: #{map.get($colors, blue--faded)};\n --bg-color-selected: #{map.get($colors, blue--faded)};\n --color-hover: #{map.get($colors, blue)};\n --color-selected: #{map.get($colors, blue)};\n --color-focus: #{map.get($colors, blue)};\n --focus-outline: none;\n --font-size: 0.9em;\n\n display: block;\n}\n\n.menu {\n font-size: var(--font-size, 0.9em);\n overscroll-behavior: none;\n min-width: var(--width);\n position: relative;\n\n &:focus {\n outline: none;\n }\n}\n\n::slotted(*:not(nano-nav-item):not(nano-option):not(hr):not(slot)) {\n padding-inline: var(--padding-start) var(--padding-end);\n padding-block: var(--padding-top) var(--padding-bottom);\n display: block;\n}\n","import {\n Component,\n Event,\n EventEmitter,\n Method,\n h,\n Host,\n Element,\n Prop,\n Listen,\n Build,\n} from '@stencil/core';\nimport { getActiveElement } from '../../utils/active-element';\nimport { getDirectChildren } from '../../utils/dom';\nimport { getTextContent } from '../../utils/slot';\n\ntype ValidElement = HTMLNanoNavItemElement | HTMLNanoOptionElement;\ntype NNI = HTMLNanoNavItemElement;\n\n/**\n * Menu element. Commonly wrapped by `nano-dropdown` with `nano-option` and `nano-nav-item` elements nested.\n * Manages focus state / active.\n * @slot - The menu's content; `nano-option`, `nano-nav-item` elements as well as <hr> and more.\n */\n@Component({\n tag: 'nano-menu',\n styleUrl: 'menu.scss',\n shadow: true,\n})\nexport class Menu {\n private ignoreMouseEvents = false;\n private ignoreMouseTimeout: any;\n private menu: HTMLElement;\n private typeToSelect = '';\n private typeToSelectTimeout: any;\n\n @Element() private el: HTMLNanoMenuElement;\n\n // Public API\n\n /** get the focus state of the menu @readonly */\n @Prop()\n get hasFocus() {\n return this._hasFocus;\n }\n private _hasFocus = false;\n\n /** changes the role of the underlying control - sometimes required for semantics */\n @Prop() type: 'menu' | 'listbox' = 'menu';\n\n /** an accessible label */\n @Prop() label: string;\n\n // Events\n\n /** Emitted when the menu gains focus. */\n @Event() nanoFocus: EventEmitter;\n\n /** Emitted when the menu loses focus. */\n @Event() nanoBlur: EventEmitter;\n\n /** Emitted when a menu item is selected. */\n @Event() nanoSelect: EventEmitter<\n HTMLNanoOptionElement | HTMLNanoNavItemElement\n >;\n\n // Public Methods\n\n /** Sets focus on the menu. */\n @Method()\n async setFocus() {\n if (this.menu?.focus) this.menu.focus({ preventScroll: true });\n }\n\n /** Removes focus from the menu. */\n @Method()\n async removeFocus() {\n if (this.menu?.blur) this.menu.blur();\n }\n\n /** Sets the current active item */\n @Method()\n async showActiveElement() {\n if (this.selectedItem)\n this.selectedItem.scrollIntoView({ block: 'nearest' });\n }\n\n /** Removes any active item's state */\n @Method()\n async resetActiveItem() {\n this.getItems\n .filter((i) => i.tagName.toLowerCase() === 'nano-option')\n .map((i) => i.setAttribute('tabindex', '-1'));\n }\n\n // Private methods\n\n get getItems() {\n let items: ValidElement[];\n const opened = this.el.querySelectorAll('nano-nav-item.secondary-open');\n if (opened.length) {\n const ctx = opened[opened.length - 1] as HTMLNanoNavItemElement;\n items = Array.from(ctx.querySelectorAll('nano-nav-item, nano-option'));\n } else {\n items = getDirectChildren(\n this.el,\n 'nano-nav-item, nano-option',\n 'slot'\n ) as ValidElement[];\n }\n return items.filter((el) => !el.disabled && !el.hidden);\n }\n\n get activeItem() {\n const activeElement = getActiveElement();\n return this.getItems.find(\n (i) =>\n i.getAttribute('tabindex') === '0' ||\n i === activeElement ||\n i.classList.contains('has-focus')\n );\n }\n\n get selectedItem() {\n return this.getItems.find((i) => i.selected);\n }\n\n private async setActiveFocusItem(item?: ValidElement, focus = true) {\n const items = this.getItems;\n const activeItem =\n !item || item.disabled ? items.find((i) => i.selected) || items[0] : item;\n\n items\n .filter((i) => i.tagName.toLowerCase() === 'nano-option')\n .map((i: HTMLNanoOptionElement) =>\n i.setAttribute('tabindex', i === activeItem ? '0' : '-1')\n );\n\n if (!focus) return;\n\n if (activeItem) {\n (activeItem as NNI).setFocus\n ? (activeItem as NNI).setFocus()\n : activeItem.focus();\n } else this.menu.focus();\n }\n\n // Event Handlers\n\n @Listen('mousedown', { target: 'body' })\n @Listen('keydown')\n handleBlur(e: KeyboardEvent | MouseEvent) {\n if (!this.hasFocus) return;\n\n const kev = e as KeyboardEvent;\n let found: boolean;\n\n if (kev.key) {\n if (kev.key !== 'Tab') return;\n found =\n getActiveElement() &&\n getActiveElement().closest(this.el.tagName.toLowerCase()) === this.el;\n } else found = !!e.composedPath().find((el) => el === this.el);\n\n if (!found) {\n this.resetActiveItem();\n this._hasFocus = false;\n this.nanoBlur.emit();\n }\n }\n\n private handleFocus = () => {\n this.setActiveFocusItem(this.selectedItem || this.getItems[0]);\n\n this._hasFocus = true;\n this.nanoFocus.emit();\n };\n\n private handleClick = (event: MouseEvent) => {\n const target = event.target as HTMLElement;\n const item = target.closest('nano-nav-item');\n\n if (item && !item.disabled) {\n this.nanoSelect.emit(item);\n }\n };\n\n private handleKeyDown = (event: KeyboardEvent) => {\n // When keying through the menu, if the mouse happens to be hovering over a menu item and the menu scrolls, the\n // mouseout/mouseover event will fire causing the selection to be different than what the user expects. This gives\n // us a way to temporarily ignore mouse events while the user is interacting with a keyboard.\n clearTimeout(this.ignoreMouseTimeout);\n this.ignoreMouseTimeout = setTimeout(\n () => (this.ignoreMouseEvents = false),\n 500\n );\n this.ignoreMouseEvents = true;\n\n // Make a selection when pressing enter\n switch (event.key) {\n case ' ':\n if (this.activeItem) this.activeItem.click();\n break;\n case 'ArrowDown':\n case 'ArrowUp':\n case 'PageDown':\n case 'PageUp':\n case 'Home':\n case 'End':\n const items = this.getItems;\n const selectedItem = this.activeItem;\n let index = items.indexOf(selectedItem);\n\n if (items.length) {\n event.preventDefault();\n\n if (event.key === 'ArrowDown') {\n index++;\n } else if (event.key === 'ArrowUp') {\n index--;\n } else if (event.key === 'Home' || event.key === 'PageUp') {\n index = 0;\n } else if (event.key === 'End' || event.key === 'PageDown') {\n index = items.length - 1;\n }\n\n if (index < 0) index = items.length - 1;\n if (index > items.length - 1) index = 0;\n\n this.setActiveFocusItem(items[index]);\n if (items[index]) items[index].scrollIntoView({ block: 'nearest' });\n return;\n }\n break;\n }\n\n // Handle type-to-search behavior when non-control characters are entered\n if (event.key === ' ' || /^[a-z0-9]+$/i.test(event.key)) {\n clearTimeout(this.typeToSelectTimeout);\n this.typeToSelectTimeout = setTimeout(\n () => (this.typeToSelect = ''),\n 750\n );\n this.typeToSelect += event.key;\n\n const items = this.getItems;\n for (const item of items) {\n const slot = item.shadowRoot.querySelector(\n 'slot:not([name])'\n ) as HTMLSlotElement;\n const label = getTextContent(slot).toLowerCase().trim();\n if (\n label.substring(0, this.typeToSelect.length) === this.typeToSelect\n ) {\n this.setActiveFocusItem(item);\n break;\n }\n }\n }\n };\n\n private handleMouseOver = (event: MouseEvent) => {\n const target = event.target as HTMLElement;\n const item =\n target.closest('nano-nav-item') || target.closest('nano-option');\n\n if (item && !this.ignoreMouseEvents) {\n this.setActiveFocusItem(item);\n }\n };\n\n // Component Lifecycle\n\n componentDidLoad() {\n if (Build.isBrowser) {\n getDirectChildren(\n this.el,\n ':not(nano-nav-item):not(nano-option):not([role])',\n true\n ).forEach((el) => el.setAttribute('role', 'none'));\n }\n }\n\n render() {\n return (\n <Host role={this.type === 'menu' ? 'menu' : 'group'}>\n <div\n onClick={this.handleClick}\n onKeyDown={this.handleKeyDown}\n onMouseOver={this.handleMouseOver}\n onFocus={this.handleFocus}\n aria-label={this.label ? this.label : undefined}\n ref={(el) => (this.menu = el)}\n part=\"base\"\n class={{\n menu: true,\n ['menu--' + this.type]: true,\n 'menu--has-focus': this.hasFocus,\n }}\n tabIndex={-1}\n role=\"group\"\n >\n <slot />\n </div>\n </Host>\n );\n }\n}\n","@use 'sass:map';\n@use 'sass:list';\n\n@import '../../global/style/utilities/globals';\n@import '../../global/style/nano-theme/form';\n@import '../../global/style/nano-theme/base';\n@import '../../global/style/nano-theme/layers';\n\n:host {\n /**\n * @prop --padding-top: Defaults to #{$spacing-small};\n * @prop --padding-bottom: Defaults to #{$spacing-small};\n * @prop --padding-start: Defaults to #{$spacing-small};\n * @prop --padding-end: Defaults to #{$spacing-small};\n\n * @prop --bg: default background. Defaults to none;\n * @prop --bg-selected: background when selected. Defaults to #{$select-opt-selected};\n * @prop --bg-focus: background when focused. Defaults to var(--nano-color-base, #{nano-color(primary, tint)});\n * @prop --bg-disabled: background when disabled. Defaults to none;\n\n * @prop --color: default text color. Defaults to var(--input-text-color, #{$input-text-color});\n * @prop --color-selected: text color when selected. Defaults to var(--nano-color-base, #{nano-color(primary, base)});\n * @prop --color-focus: text color when focused. Defaults to var(--nano-color-base, #{nano-color(primary, contrast)});\n * @prop --color-disabled: text color when disabled. Defaults to #{map.get($colors, palegrey)};\n\n * @prop --opt-icon-size: Sizes all icons within the option. Defaults to 1.4em;\n */\n\n --bg: none;\n --bg-selected: #{$select-opt-selected};\n --bg-focus: var(--nano-color-base, #{nano-color(primary, tint)});\n --bg-disabled: none;\n --color: var(--input-text-color, #{$input-text-color});\n --color-selected: var(--nano-color-base, #{nano-color(primary, base)});\n --color-focus: var(--nano-color-contrast, #{nano-color(primary, contrast)});\n --color-disabled: #{map.get($colors, palegrey)};\n --opt-icon-size: 1.6em;\n\n display: block;\n color: var(--color);\n overflow: hidden;\n font-size: 14px;\n font-size: #{'clamp(12px, .9em, 16px)'};\n}\n\n:host(:focus) {\n outline: none;\n}\n\n.option {\n $self: &;\n\n position: relative;\n user-select: none;\n cursor: pointer;\n display: flex;\n align-items: stretch;\n width: 100%;\n background: var(--bg);\n padding-inline: var(--padding-start) var(--padding-end);\n padding-block: var(--padding-top) var(--padding-bottom);\n\n // focus\n :host(:focus) &:not(.option--disabled),\n :host &.option--selected {\n outline: none;\n background: var(--bg-selected);\n color: var(--color-selected);\n }\n\n :host(:focus) &:not(.option--disabled) {\n background: var(--bg-focus);\n color: var(--color-focus);\n }\n\n // disabled\n &.option--disabled {\n outline: none;\n color: var(--color-disabled);\n cursor: not-allowed;\n background: var(--bg-disabled);\n }\n\n // no value\n &.option--novalue {\n font-style: italic;\n opacity: 0.7;\n }\n\n &__label {\n flex: 1 1 auto;\n display: flex;\n align-items: center;\n }\n\n &__start {\n flex: 0 0 auto;\n display: flex;\n align-items: center;\n\n ::slotted(nano-icon) {\n font-size: var(--opt-icon-size);\n }\n\n ::slotted(:last-child) {\n margin-inline-end: 0.5em;\n }\n }\n\n &__end {\n flex: 0 0 auto;\n display: flex;\n align-items: center;\n\n ::slotted(nano-icon) {\n font-size: var(--opt-icon-size);\n }\n\n ::slotted(:first-child) {\n margin-inline-start: 0.5em;\n }\n }\n\n &__check {\n visibility: hidden;\n display: flex;\n position: absolute;\n inset-inline-start: 0.6em;\n inset-block-start: calc(50% - 0.6em);\n align-items: center;\n font-size: 0.9em;\n\n #{$self}--selected:not(#{$self}--novalue) & {\n visibility: visible;\n }\n }\n}\n","import {\n Component,\n Prop,\n h,\n Host,\n State,\n Watch,\n Element,\n Listen,\n Event,\n EventEmitter,\n} from '@stencil/core';\nimport { getDirectChildren } from '../../utils/dom';\nimport { debounce } from '../../utils/throttle';\nimport type { OptionInterface } from '../../interface';\n\nlet optIds = 0;\n\n/**\n * Select options to be used with [nano-select](/story/nano-components-select) or [nano-datalist](/story/nano-components-select)\n *\n * @slot - main label. Defaults to `label` or `value` prop\n * @slot checked-icon - icon to indicated checked / selected state. Defaults to fontawesome light/check\n * @slot start - suitable for an icon or content displayed at the start of the main label\n * @slot end - suitable for an icon or content displayed at the end of the main label\n */\n@Component({\n tag: 'nano-option',\n styleUrl: 'option.scss',\n shadow: true,\n})\nexport class Option implements OptionInterface {\n private optId = `nano-option-${optIds++}`;\n @Element() host: HTMLNanoOptionElement;\n @State() hasFocus = false;\n\n constructor() {\n this.handleClick = debounce(this.handleClick.bind(this), 5);\n }\n\n // Public API\n\n /**\n * Value of the option\n */\n @Prop({ mutable: true, reflect: true }) value: string = '';\n\n @Watch('value')\n valueChanged() {\n if (!this.value || !this.value.length) this.value = this.labelContent;\n }\n\n /**\n * Label of the option\n */\n @Prop({ mutable: true, reflect: true }) label: string = '';\n\n @Watch('label')\n labelChanged() {\n if (!this.label || !this.label.length)\n this.label = this.labelContent.length ? this.labelContent : this.value;\n }\n\n /**\n * Whether this option is selected\n */\n @Prop({ reflect: true }) selected: boolean = false;\n\n /**\n * Whether this option should be disabled\n */\n @Prop({ reflect: true }) disabled: boolean = false;\n\n /** You can add extra meta for this option. When displayed in a list, users\n * search / filter via extra related terms. Another usecase is 'endonyms'\n */\n @Prop() filterMeta: string = '';\n\n /** Fired when an option is selected */\n @Event() nanoSelect!: EventEmitter<HTMLNanoOptionElement>;\n\n // Event handlers\n\n // stop scrolling on select\n @Listen('keydown')\n handleKeyDown(e: KeyboardEvent) {\n if (e.key !== ' ' && e.key !== 'Enter') return;\n e.preventDefault();\n this.nanoSelect.emit(this.host);\n }\n\n private handleClick() {\n if (this.disabled) return;\n this.nanoSelect.emit(this.host);\n }\n\n // Private logic\n\n private get labelContent() {\n return getDirectChildren(this.host, '*:not([slot])', false)\n .map((el) => el.textContent)\n .join(' ')\n .trim();\n }\n\n // Component lifecycle\n\n componentWillLoad() {\n this.valueChanged();\n this.labelChanged();\n }\n\n render() {\n return (\n <Host\n role=\"option\"\n aria-selected={this.selected ? 'true' : 'false'}\n aria-disabled={this.disabled ? 'true' : 'false'}\n >\n <div\n onMouseDown={this.handleClick}\n id={this.optId}\n class={{\n option: true,\n 'option--selected': this.selected,\n 'option--disabled': this.disabled,\n 'option--novalue': !this.value,\n }}\n >\n <div part=\"check-icon\" class=\"option__check\">\n <slot name=\"check-icon\">\n <nano-icon name=\"light/check\" aria-hidden=\"true\" />\n </slot>\n </div>\n <div part=\"start\" class=\"option__start\">\n <slot name=\"start\"></slot>\n </div>\n <div part=\"label\" class=\"option__label\">\n <slot>{this.label || this.value}</slot>\n </div>\n <div part=\"end\" class=\"option__end\">\n <slot name=\"end\"></slot>\n </div>\n </div>\n </Host>\n );\n }\n}\n"],"mappings":";;;uNAAA,MAAMA,EAAc,q1BCmBpB,SAASC,EAAUC,GACjB,IAAIC,EAEJ,GAAID,EAASE,GAAI,CACfD,EAAaE,SAASC,cAAc,cAAcJ,EAASE,O,CAE7D,IAAKD,EAAY,CACfA,EAAaD,EAASK,QAAQ,Q,CAEhC,OAAOJ,CACT,CAEA,IAAIK,EAAU,E,MAkBDC,EAAQ,MAcPC,iBACV,OAAOC,KAAKC,W,CAEFF,eAAWG,G,MAIrBF,KAAKC,YAAcC,EACnB,IAAIC,EAAAH,KAAKI,kBAAc,MAAAD,SAAA,SAAAA,EAAEE,MAAO,OAEhCH,EAAKI,SAASC,IACZ,GAAIA,EAAIC,WAAaR,KAAKQ,SAASC,SAASF,EAAIF,OAAQ,CACtDL,KAAKU,iBAAiBH,E,KAiB5BI,YAAAC,G,mJAxCQZ,KAAAa,YAAc,MACdb,KAAAc,aAAe,GAKfd,KAAAe,OAAS,iBAAiBlB,MAC1BG,KAAAgB,WAAa,MACbhB,KAAAiB,YAAc,MAmBdjB,KAAAC,YAAuC,GA+BvCD,KAAAkB,gBAAqC,CAC3CC,UAAW,GA+SLnB,KAAAoB,YAAeC,IACrBA,EAAEC,kBACFtB,KAAKU,iBAAiBW,EAAEE,QACxBC,uBAAsB,IAAMxB,KAAKyB,gBAEjC,GAAIzB,KAAK0B,OAAS,aAAc1B,KAAK2B,WAAa,KAAK,EAoCjD3B,KAAA4B,WAAaC,UACnB,GAAI7B,KAAKiB,YAAa,CACpBjB,KAAKiB,YAAc,MACnBjB,KAAK8B,QAAQC,U,MACR,GAAI/B,KAAK0B,OAAS,SAAU1B,KAAK8B,QAAQE,mBAAmB,EAG7DhC,KAAAiC,WAAa,KACnBjC,KAAKkC,KAAO,MACZ,MAAMC,EAAgBC,IACtB,GAAID,EAAcvC,QAAQI,KAAKqC,KAAKC,QAAQC,eAAgB,CAC1DvC,KAAKI,eAAeoC,Q,GAgDhBxC,KAAAyC,WAAa,KACnBzC,KAAK2B,WAAa,KAElB3B,KAAK0C,uBAAuB,EAGtB1C,KAAA2C,aAAgBtB,IACtB,MAAMuB,EAAa,CACjB,QACA,aACA,YACA,SACA,QACA,OAEF,GAAIA,EAAWnC,SAASY,EAAEwB,KAAM,CAC9B,GAAIxB,EAAEwB,MAAQ,MAAO7C,KAAK2B,WAAa,MACvC,M,CAIF,GACE3B,KAAK0B,OAAS,WACb,CAAC,YAAa,WAAWjB,SAASY,EAAEwB,OACpCxB,EAAEwB,MAAQ,KAAO7C,KAAK8C,qBACvB,CACA,GAAIzB,EAAEwB,MAAQ,KAAO,eAAeE,KAAK1B,EAAEwB,KAAM,CAC/CG,aAAahD,KAAK8C,qBAClB9C,KAAK8C,oBAAsBG,OAAOC,YAAW,KAC3ClD,KAAKc,aAAe,GACpBd,KAAK8C,oBAAsB,CAAC,GAC3B,KACH9C,KAAKc,cAAgBO,EAAEwB,IACvB7C,KAAKmD,kB,CAEP,M,CAGFnD,KAAK2B,WAAa,KAElB3B,KAAK0C,wBACL,GAAI,CAAC,YAAa,WAAWjC,SAASY,EAAEwB,KAAM,CAC5CxB,EAAE+B,iBACFpD,KAAKiB,YAAc,I,GAMfjB,KAAAqD,cACNhC,IAEA,MAAMuB,EAAa,CACjB,QACA,UACA,YACA,SACA,QACA,MACA,QACA,SACA,WACA,OACA,MACA,KAEF,GAAIA,EAAWnC,SAASY,EAAEwB,KAAM,CAC9B,GAAIxB,EAAEwB,MAAQ,SAAU7C,KAAKI,eAAekD,QAC5C,M,CAGF,MAAMC,EAAa,CAAC,SAAU,aAE9B,GACEvD,KAAK0B,OAAS,YACZ1B,KAAKwD,YAAcD,EAAW9C,SAASY,EAAEwB,MAC3C,CACA7C,KAAKI,eAAekD,O,oBA3fwB,G,0HAKpB,K,eACG,G,cAUe,G,aAgBR,G,+BAQY,Q,UAST,M,mBAcjB,M,cAGL,MAzDjBtD,KAAKyB,YAAcgC,EAASzD,KAAKyB,YAAYiC,KAAK1D,MAAO,G,CAWvD2D,qBACF,OAAO3D,KAAKkB,e,CAEVyC,mBAAeC,GACjB5D,KAAKkB,gBAAe2C,OAAAC,OAAAD,OAAAC,OAAA,GAAQ9D,KAAKkB,iBAAoB0C,E,CAoBnDG,oBACF,OAAO/D,KAAKD,U,CAOdiE,cACEC,GAAU,KACRjE,KAAKkE,aAAahC,KAAOlC,KAAKkC,KAC9B,GAAIlC,KAAKI,eACPJ,KAAKI,eAAe+D,aAAa,gBAAiBnE,KAAKkC,KAAKkC,WAAW,G,CAe7EvC,yBACE,IAAIwC,EACJ,GAAKA,EAAYrE,KAAKqC,KAAKzC,QAAQ,cAAgB,CACjDI,KAAKa,YAAc,KACnBb,KAAKI,qBAAuBiE,EAAUC,iB,MACjC,GACLtE,KAAKuE,cACEvE,KAAKuE,QAAU,WACrBF,EAAY3E,SAASC,cAAcK,KAAKuE,QACzC,CACAvE,KAAKa,YAAc,MACnBb,KAAKI,eAAiBiE,C,MACjB,UAAWrE,KAAKuE,QAAU,SAAU,CACzCvE,KAAKI,eAAiBJ,KAAKuE,K,EAK/BC,2B,MACE,IAAKxE,KAAKqC,KAAM,OAGhB,KAAMrC,KAAKyE,UAAYzE,KAAKyE,QAAQC,UAAY1E,KAAK2E,GAAI,CAClC,CACnB,MAAMA,EAAM3E,KAAK2E,GAAK,IAAIC,kBAAiB,IACzC5E,KAAK6E,0BAEPF,EAAGG,QAAQ9E,KAAKqC,KAAM,CAAE0C,UAAW,KAAMC,QAAS,M,CAEpDhF,KAAK6E,wBACL,M,CAIF,IAAI1E,EAAAH,KAAKyE,WAAO,MAAAtE,SAAA,SAAAA,EAAEuE,OAAQ,CACxB,KAAM1E,KAAK2E,GAAI,CACb3E,KAAK2E,GAAGM,aACRjF,KAAK2E,GAAKO,S,CAGZ,MAAMC,EAAkBnF,KAAKqC,KAAK+C,iBAChC,0BAIFnB,GAAU,K,MAER,GAAIkB,IAAe,MAAfA,SAAe,SAAfA,EAAiBT,OACnBS,EAAgB7E,SAAS+E,GAAgBA,EAAYC,WAEvDtF,KAAKD,WAAaC,KAAKyE,QAAQc,SAAQ,CAACC,EAAQC,KAC9C,GAAID,EAAOnF,OAASmF,EAAOE,MAAO,CAChC,MAAMnF,EAAMsD,OAAOC,OAAOpE,SAASiG,cAAc,eAAgB,CAC/DD,MAAOF,EAAOE,MACdrF,MAAOmF,EAAOnF,MACduF,aAAcH,EACdI,YAAa7F,KAAKyE,QAAQC,OAC1BlE,SAAUgF,EAAOhF,SACjBf,GAAIO,KAAKe,OAAS,WAAa0E,EAC/BK,YAAaN,EAAOE,MAAQF,EAAOE,MAAQF,EAAOnF,MAClD0F,KAAM,kBAER/F,KAAKqC,KAAK2D,OAAOzF,GACjB,OAAOA,C,KAIX,KAAIJ,EAAAH,KAAKI,kBAAc,MAAAD,SAAA,SAAAA,EAAEE,MAAMqE,SAAU1E,KAAK0B,OAAS,SAAU,CAC/D1B,KAAKyB,a,KACA,CACLzB,KAAKiG,YAAc,IAAIjG,KAAKD,W,MASpCmG,kBACE,IAAKlG,KAAKI,eAAgB,OAE1B,IAAI+F,EAA8B,CAAEC,cAAe,OACnD,IAAIC,EAAoC,OACxC,IAAIC,EAAW,MAEf,OAAQtG,KAAK0B,MACX,IAAK,QACHyE,EAAW,CAAEC,cAAe,MAC5B,MACF,IAAK,SACHC,EAAmB,OACnBC,EAAW,KACXH,EAAW,CAAEC,cAAe,KAAMG,UAAW,UAC7C,MAGJ,IAAKvG,KAAKa,YAAa,CACrBsF,EAASK,SAAWxG,KAAKI,c,CAG3BJ,KAAK2D,eAAcE,OAAAC,OAAAD,OAAAC,OAAA,GAAQ9D,KAAK2D,gBAAmBwC,GACnDnG,KAAKI,eAAe+D,aAAa,oBAAqBkC,GACtDrG,KAAKI,eAAeqG,SAAWH,C,CAIjCI,kBAAkBC,EAA6BC,G,MAC7C,KAAMA,EAAU,CACd,MAAMvC,EAAYuC,EAAShH,QAAQ,cACnC,GAAIyE,EAAW,CACbA,EAAUwC,oBAAoB,aAAc7G,KAAKyB,Y,CAEnDmF,EAASC,oBAAoB,SAAU7G,KAAKyB,aAC5CmF,EAASC,oBAAoB,QAAS7G,KAAKyC,YAC3CmE,EAASC,oBAAoB,UAAW7G,KAAK2C,cAC7CiE,EAASC,oBAAoB,QAAS7G,KAAKyB,aAE3CzB,KAAK8G,WAAa,KAElB7C,GAAU,KACR2C,EAASG,gBAAgB,QACzBH,EAASG,gBAAgB,iBACzBH,EAASG,gBAAgB,iBACzBH,EAASG,gBAAgB,aACzBH,EAASG,gBAAgB,iBACzBH,EAASG,gBAAgB,qBACzBH,EAASG,gBAAgB,eAAe,G,CAG5C,KAAMJ,EAAU,CACd,MAAMtC,EAAYsC,EAAS/G,QAAQ,cACnC,GAAIyE,EAAW,CACbA,EAAU2C,iBAAiB,aAAchH,KAAKyB,Y,CAEhDkF,EAASK,iBAAiB,SAAUhH,KAAKyB,aACzCkF,EAASK,iBAAiB,QAAShH,KAAKyC,YACxCkE,EAASK,iBAAiB,UAAWhH,KAAK2C,cAC1CgE,EAASK,iBAAiB,QAAShH,KAAKyB,aACxCzB,KAAKe,OAASf,KAAKqC,KAAK5C,IAAMO,KAAKe,OAEnCf,KAAK8G,aAAa3G,EAAAwG,IAAQ,MAARA,SAAQ,SAARA,EAAUM,UAAM,MAAA9G,SAAA,SAAAA,EAAE+G,KAAK,KAAM5H,EAAUqH,GAEzD1C,GAAU,KACRjE,KAAKqC,KAAK5C,GAAKO,KAAKe,OACpB4F,EAASxC,aAAa,OAAQ,YAC9BwC,EAASxC,aAAa,gBAAiB,SACvCwC,EAASxC,aAAa,gBAAiBnE,KAAKe,QAC5C4F,EAASxC,aAAa,YAAanE,KAAKe,QACxC4F,EAASxC,aAAa,gBAAiB,WACvCwC,EAASxC,aAAa,eAAgB,MAAM,G,EAOlDgD,qB,MACE,IAAIC,EAAI,EACR,MAAMC,IAAMlH,EAAAH,KAAKI,kBAAc,MAAAD,SAAA,SAAAA,EAAEE,QAAS,GAC1C,MAAMiH,EAAS,GAEfrD,GAAU,KACRjE,KAAKD,WAAWO,SAAQ,CAACC,EAAKkF,KAC5B,GAAIzF,KAAKiG,YAAYxF,SAASF,GAAM,CAClC6G,IACA7G,EAAI4D,aAAa,gBAAiBiD,EAAI,IACtC7G,EAAI4D,aAAa,eAAgBnE,KAAKiG,YAAYvB,OAAS,IAC3DnE,EAAIgH,OAAS,MACbvH,KAAKwH,WAAWjH,EAAK8G,E,KAChB,CACL9G,EAAIwG,gBAAgB,iBACpBxG,EAAIwG,gBAAgB,gBACpBxG,EAAIgH,OAAS,KACbhH,EAAIC,SAAW,K,CAEjBD,EAAId,GAAKO,KAAKe,OAAS,WAAa0E,EACpC6B,EAAOG,KAAKlH,EAAId,GAAG,IAErBO,KAAK0H,UAAYJ,CAAM,G,CAM3BK,gBACE,GAAI3H,KAAKiG,YAAYvB,QAAU1E,KAAK4H,YAAa5H,KAAK6H,QAAU,UAC3D7H,KAAK6H,QAAU,K,CAQtBnF,wBACE,GAAI1C,KAAK2B,YAAc3B,KAAK6H,UAAY7H,KAAK8H,SAAU9H,KAAKkC,KAAO,KACnE,IAAKlC,KAAK2B,aAAe3B,KAAK6H,QAAS7H,KAAKkC,KAAO,MACnDlC,KAAKgE,a,CAIP+D,sBACE/H,KAAKgI,mBAAmBC,KAAKjI,KAAKiG,Y,CAgB5BuB,WAAWjH,EAA4B8G,GAC7C,GAAIA,IAAQ9G,EAAIF,OAASL,KAAKQ,SAASC,SAASF,EAAIF,OAAQ,CAC1DE,EAAIC,SAAW,I,MACVD,EAAIC,SAAW,K,CAGZ0H,oBACV,IAAKlI,KAAKkE,eAAiBlE,KAAKkC,KAAM,OAAO,MAC7C,OAAO,I,CAGGsB,iBACV,OAAOxD,KAAKD,WAAWoI,MACpB5H,GAAQP,KAAKI,eAAeC,QAAUE,EAAIF,O,CAKvCK,iBAAiBH,G,MACvB,IAAI6H,EAEJ,GAAIpI,KAAKQ,SAASC,SAASF,EAAIF,OAAQ,CAErCL,KAAKQ,SAAWR,KAAKQ,SAAS6H,QAAQhB,GAAQA,IAAQ9G,EAAIF,QAC1D+H,EAAepI,KAAKsI,aAAaL,KAAK1H,E,KACjC,CAELP,KAAKQ,SAAW,IAAIR,KAAKQ,UACzB4H,EAAepI,KAAKuI,WAAWN,KAAK1H,E,CAGtC,IAAK6H,EAAaI,iBAAkB,CAClC,GAAIxI,KAAKI,eAAgBJ,KAAKI,eAAeC,MAAQE,EAAIF,MAEzD,MAAMoI,EAAQ,IAAIxF,OAAOyF,MAAM,WAC/BvI,EAAAH,KAAKI,kBAAc,MAAAD,SAAA,SAAAA,EAAEwI,cAAcF,E,EAe/BtF,mBACN,MAAMyF,EAAYC,GAChBA,EAAOtG,cAAcuG,UAAU,EAAG9I,KAAKc,aAAa4D,UACpD1E,KAAKc,aAEP,MAAMiI,EAAW/I,KAAKD,WAAWoI,MAC9B5H,GACCA,EAAIF,MAAM2I,OAAOtE,OAAS,IACzBnE,EAAIuH,WACJc,EAASrI,EAAIuF,cACZ8C,EAASrI,EAAIF,QACbuI,EAASrI,EAAImF,QACbkD,EAASrI,EAAI0I,eAEnB,GAAIF,EAAU/I,KAAKU,iBAAiBqI,E,CAK9BlE,wBACNrD,uBAAsB,K,MACpBxB,KAAKD,WAAamJ,MAAMC,KAAKnJ,KAAKqC,KAAK+C,iBAAiB,gBACxDpF,KAAK4H,cAAgB5H,KAAKqC,KAAK1C,cAAc,sBAE7C,KAAIQ,EAAAH,KAAKI,kBAAc,MAAAD,SAAA,SAAAA,EAAEE,MAAMqE,SAAU1E,KAAK0B,OAAS,SAAU,CAC/D1B,KAAKyB,a,MACAzB,KAAKiG,YAAcjG,KAAKD,UAAU,G,CAqBrC0B,cACN,GAAIzB,KAAKoJ,cAAe,CACtBpJ,KAAKiG,YAAcjG,KAAKD,WACxB,M,CAGF,MAAMsH,EAAMrH,KAAKI,eAAeC,MAChC,MAAMgJ,EAAShC,EAAI2B,OAAOzG,cAE1B,IAAIiB,EAAa,MACjB,MAAM8F,EAAa,GACnB,MAAMV,EAAYC,GAChBA,EAAOtG,cAAcgH,QAAQF,IAAW,EAE1CrJ,KAAKD,WAAWO,SAASC,IACvB,IACG8G,IAAQ9G,EAAIF,OAASgH,IAAQ9G,EAAImF,QAClC1F,KAAK0B,OAAS,aACd,CACAnB,EAAIC,SAAW,KACfgD,EAAa,I,MACRxD,KAAKwH,WAAWjH,EAAK8G,EAAI,IAGlCrH,KAAKD,WAAWO,SAASC,IACvB,IAAK8I,EAAO3E,QAAUlB,EAAY,CAChC8F,EAAW7B,KAAKlH,E,MACX,GACLA,EAAIF,MAAM2I,OAAOtE,OAAS,IACzBnE,EAAIuH,WACJc,EAASrI,EAAIuF,cACZ8C,EAASrI,EAAIF,QACbuI,EAASrI,EAAImF,QACbkD,EAASrI,EAAI0I,aACf,CACAK,EAAW7B,KAAKlH,E,KAIpBP,KAAKgB,WAAaqI,EAAO3E,SAAWlB,EACpCxD,KAAKiG,YAAcqD,C,CAsFrBE,oBACExJ,KAAKyJ,kB,CAGPC,mBACE1J,KAAKwE,2BACLxE,KAAKgE,a,CAGP2F,qBACEzG,YAAW,KACT,IAAKlD,KAAKI,eACRwJ,QAAQC,KACN,4GACA7J,KAAKqC,KACN,GACF,I,CAGLyH,SACE,OACEC,EAACC,EAAI,CACHC,KAAMjK,KAAKiG,YAAYvB,OAAS,UAAYQ,UAAS,YAC1ClF,KAAK0H,UAAUhD,OAAS1E,KAAK0H,UAAUwC,KAAK,KAAOhF,UAAS,aAErElF,KAAK0H,UAAUhD,OACX,qCACAQ,WAGN6E,EAAA,gBAAAlG,OAAAC,OAAA,GACM9D,KAAK2D,eAAc,CACvBwG,IAAMC,GAAQpK,KAAKkE,aAAekG,EAClCC,YAAY,qCACZC,MAAO,CACLC,gBAAiB,KACjB,oBAAqBvK,KAAKgB,YAE5BwJ,gBAAiBxK,KAAK4B,WACtB6I,gBAAiBzK,KAAKiC,WACtBgI,KAAK,UAELF,EAAA,aACExC,QAASvH,KAAKiG,YAAYvB,OAC1BhD,KAAK,UACLgE,MAAO1F,KAAK8G,WAAa9G,KAAK8G,WAAWhB,YAAcZ,UACvDoF,MAAO,CACLI,YAAa,KACb,oBAAqB1K,KAAKkI,eAE5ByC,UAAW,EACXC,aAAc5K,KAAKoB,YACnByJ,UAAW7K,KAAKqD,cAChB8G,IAAMC,GAAQpK,KAAK8B,QAAUsI,EAC7BH,KAAK,QAELF,EAAA,QAAMe,KAAK,cACT9K,KAAKyE,QAAQC,QAAUqF,EAAA,eACtB/J,KAAKyE,QAAQC,QAAUqF,EAAA,QAAMe,KAAK,kBACrCf,EAAA,QAAMe,KAAK,iBAEbf,EAAA,aACErI,KAAK,UACLgE,MAAM,mBACN6B,SAAUvH,KAAKiG,YAAYvB,OAC3B4F,MAAO,CACLI,YAAa,KACb,oBAAqB1K,KAAKkI,gBAG5B6B,EAAA,QAAMe,KAAK,iBAEV9K,KAAKiG,aACN8D,EAAA,OAAKO,MAAM,iBACRtK,KAAKiG,YAAYvB,OAAM,UACvB1E,KAAKiG,YAAYvB,OAAS,EAAI,IAAM,GAAE,gB,wbChqBrD,MAAMqG,EAAU,+2B,MC6BHC,EAAI,M,wIACPhL,KAAAiL,kBAAoB,MAGpBjL,KAAAc,aAAe,GAYfd,KAAAkL,UAAY,MA8HZlL,KAAAmL,YAAc,KACpBnL,KAAKoL,mBAAmBpL,KAAKqL,cAAgBrL,KAAKsL,SAAS,IAE3DtL,KAAKkL,UAAY,KACjBlL,KAAKuL,UAAUtD,MAAM,EAGfjI,KAAAwL,YAAe/C,IACrB,MAAMgD,EAAShD,EAAMgD,OACrB,MAAMvE,EAAOuE,EAAO7L,QAAQ,iBAE5B,GAAIsH,IAASA,EAAKY,SAAU,CAC1B9H,KAAKuI,WAAWN,KAAKf,E,GAIjBlH,KAAA0L,cAAiBjD,IAIvBzF,aAAahD,KAAK2L,oBAClB3L,KAAK2L,mBAAqBzI,YACxB,IAAOlD,KAAKiL,kBAAoB,OAChC,KAEFjL,KAAKiL,kBAAoB,KAGzB,OAAQxC,EAAM5F,KACZ,IAAK,IACH,GAAI7C,KAAK4L,WAAY5L,KAAK4L,WAAWC,QACrC,MACF,IAAK,YACL,IAAK,UACL,IAAK,WACL,IAAK,SACL,IAAK,OACL,IAAK,MACH,MAAMC,EAAQ9L,KAAKsL,SACnB,MAAMD,EAAerL,KAAK4L,WAC1B,IAAIG,EAAQD,EAAMvC,QAAQ8B,GAE1B,GAAIS,EAAMpH,OAAQ,CAChB+D,EAAMrF,iBAEN,GAAIqF,EAAM5F,MAAQ,YAAa,CAC7BkJ,G,MACK,GAAItD,EAAM5F,MAAQ,UAAW,CAClCkJ,G,MACK,GAAItD,EAAM5F,MAAQ,QAAU4F,EAAM5F,MAAQ,SAAU,CACzDkJ,EAAQ,C,MACH,GAAItD,EAAM5F,MAAQ,OAAS4F,EAAM5F,MAAQ,WAAY,CAC1DkJ,EAAQD,EAAMpH,OAAS,C,CAGzB,GAAIqH,EAAQ,EAAGA,EAAQD,EAAMpH,OAAS,EACtC,GAAIqH,EAAQD,EAAMpH,OAAS,EAAGqH,EAAQ,EAEtC/L,KAAKoL,mBAAmBU,EAAMC,IAC9B,GAAID,EAAMC,GAAQD,EAAMC,GAAOC,eAAe,CAAEC,MAAO,YACvD,M,CAEF,MAIJ,GAAIxD,EAAM5F,MAAQ,KAAO,eAAeE,KAAK0F,EAAM5F,KAAM,CACvDG,aAAahD,KAAK8C,qBAClB9C,KAAK8C,oBAAsBI,YACzB,IAAOlD,KAAKc,aAAe,IAC3B,KAEFd,KAAKc,cAAgB2H,EAAM5F,IAE3B,MAAMiJ,EAAQ9L,KAAKsL,SACnB,IAAK,MAAMpE,KAAQ4E,EAAO,CACxB,MAAM/F,EAAOmB,EAAKgF,WAAWvM,cAC3B,oBAEF,MAAM+F,EAAQyG,EAAepG,GAAMxD,cAAcyG,OACjD,GACEtD,EAAMoD,UAAU,EAAG9I,KAAKc,aAAa4D,UAAY1E,KAAKc,aACtD,CACAd,KAAKoL,mBAAmBlE,GACxB,K,KAMAlH,KAAAoM,gBAAmB3D,IACzB,MAAMgD,EAAShD,EAAMgD,OACrB,MAAMvE,EACJuE,EAAO7L,QAAQ,kBAAoB6L,EAAO7L,QAAQ,eAEpD,GAAIsH,IAASlH,KAAKiL,kBAAmB,CACnCjL,KAAKoL,mBAAmBlE,E,aA3NO,O,qBAN/BmF,eACF,OAAOrM,KAAKkL,S,CA2BdrJ,iB,MACE,IAAI1B,EAAAH,KAAKsM,QAAI,MAAAnM,SAAA,SAAAA,EAAEmD,MAAOtD,KAAKsM,KAAKhJ,MAAM,CAAEiJ,cAAe,M,CAKzD1K,oB,MACE,IAAI1B,EAAAH,KAAKsM,QAAI,MAAAnM,SAAA,SAAAA,EAAEqM,KAAMxM,KAAKsM,KAAKE,M,CAKjC3K,0BACE,GAAI7B,KAAKqL,aACPrL,KAAKqL,aAAaW,eAAe,CAAEC,MAAO,W,CAK9CpK,wBACE7B,KAAKsL,SACFjD,QAAQ5C,GAAMA,EAAEnD,QAAQC,gBAAkB,gBAC1CkK,KAAKhH,GAAMA,EAAEtB,aAAa,WAAY,O,CAKvCmH,eACF,IAAIQ,EACJ,MAAMY,EAAS1M,KAAKoK,GAAGhF,iBAAiB,gCACxC,GAAIsH,EAAOhI,OAAQ,CACjB,MAAMiI,EAAMD,EAAOA,EAAOhI,OAAS,GACnCoH,EAAQ5C,MAAMC,KAAKwD,EAAIvH,iBAAiB,8B,KACnC,CACL0G,EAAQc,EACN5M,KAAKoK,GACL,6BACA,O,CAGJ,OAAO0B,EAAMzD,QAAQ+B,IAAQA,EAAGtC,WAAasC,EAAG7C,Q,CAG9CqE,iBACF,MAAMzJ,EAAgBC,IACtB,OAAOpC,KAAKsL,SAASnD,MAClB1C,GACCA,EAAEoH,aAAa,cAAgB,KAC/BpH,IAAMtD,GACNsD,EAAEqH,UAAUC,SAAS,c,CAIvB1B,mBACF,OAAOrL,KAAKsL,SAASnD,MAAM1C,GAAMA,EAAEjF,U,CAG7BqB,yBAAyBqF,EAAqB5D,EAAQ,MAC5D,MAAMwI,EAAQ9L,KAAKsL,SACnB,MAAMM,GACH1E,GAAQA,EAAKY,SAAWgE,EAAM3D,MAAM1C,GAAMA,EAAEjF,YAAasL,EAAM,GAAK5E,EAEvE4E,EACGzD,QAAQ5C,GAAMA,EAAEnD,QAAQC,gBAAkB,gBAC1CkK,KAAKhH,GACJA,EAAEtB,aAAa,WAAYsB,IAAMmG,EAAa,IAAM,QAGxD,IAAKtI,EAAO,OAEZ,GAAIsI,EAAY,CACbA,EAAmB7J,SACf6J,EAAmB7J,WACpB6J,EAAWtI,O,MACVtD,KAAKsM,KAAKhJ,O,CAOnB0J,WAAW3L,GACT,IAAKrB,KAAKqM,SAAU,OAEpB,MAAMY,EAAM5L,EACZ,IAAI6L,EAEJ,GAAID,EAAIpK,IAAK,CACX,GAAIoK,EAAIpK,MAAQ,MAAO,OACvBqK,EACE9K,KACAA,IAAmBxC,QAAQI,KAAKoK,GAAG9H,QAAQC,iBAAmBvC,KAAKoK,E,MAChE8C,IAAU7L,EAAE8L,eAAehF,MAAMiC,GAAOA,IAAOpK,KAAKoK,KAE3D,IAAK8C,EAAO,CACVlN,KAAKoN,kBACLpN,KAAKkL,UAAY,MACjBlL,KAAKqN,SAASpF,M,EA0GlByB,mBACuB,CACnBkD,EACE5M,KAAKoK,GACL,mDACA,MACA9J,SAAS8J,GAAOA,EAAGjG,aAAa,OAAQ,S,EAI9C2F,SACE,OACEC,EAACC,EAAI,CAACC,KAAMjK,KAAK0B,OAAS,OAAS,OAAS,SAC1CqI,EAAA,OACEuD,QAAStN,KAAKwL,YACdX,UAAW7K,KAAK0L,cAChB6B,YAAavN,KAAKoM,gBAClBoB,QAASxN,KAAKmL,YAAW,aACbnL,KAAK0F,MAAQ1F,KAAK0F,MAAQR,UACtCiF,IAAMC,GAAQpK,KAAKsM,KAAOlC,EAC1BqD,KAAK,OACLnD,MAAO,CACLgC,KAAM,KACN,CAAC,SAAWtM,KAAK0B,MAAO,KACxB,kBAAmB1B,KAAKqM,UAE1B1B,UAAW,EACXV,KAAK,SAELF,EAAA,c,qCC9SV,MAAM2D,EAAY,+gECgBlB,IAAIpG,EAAS,E,MAeAqG,EAAM,MAKjBhN,YAAAC,G,iDAJQZ,KAAA4N,MAAQ,eAAetG,M,cAEX,M,WAWoC,G,WAUA,G,cAWX,M,cAKA,M,gBAKhB,GAvC3BtH,KAAKwL,YAAc/H,EAASzD,KAAKwL,YAAY9H,KAAK1D,MAAO,E,CAW3D6N,eACE,IAAK7N,KAAKK,QAAUL,KAAKK,MAAMqE,OAAQ1E,KAAKK,MAAQL,KAAK8N,Y,CAS3DC,eACE,IAAK/N,KAAK0F,QAAU1F,KAAK0F,MAAMhB,OAC7B1E,KAAK0F,MAAQ1F,KAAK8N,aAAapJ,OAAS1E,KAAK8N,aAAe9N,KAAKK,K,CAyBrEqL,cAAcrK,GACZ,GAAIA,EAAEwB,MAAQ,KAAOxB,EAAEwB,MAAQ,QAAS,OACxCxB,EAAE+B,iBACFpD,KAAKuI,WAAWN,KAAKjI,KAAKqC,K,CAGpBmJ,cACN,GAAIxL,KAAK8H,SAAU,OACnB9H,KAAKuI,WAAWN,KAAKjI,KAAKqC,K,CAKhByL,mBACV,OAAOlB,EAAkB5M,KAAKqC,KAAM,gBAAiB,OAClDoK,KAAKrC,GAAOA,EAAGtE,cACfoE,KAAK,KACLlB,M,CAKLgF,oBACEhO,KAAK6N,eACL7N,KAAK+N,c,CAGPjE,SACE,OACEC,EAACC,EAAI,CACHC,KAAK,SAAQ,gBACEjK,KAAKQ,SAAW,OAAS,QAAO,gBAChCR,KAAK8H,SAAW,OAAS,SAExCiC,EAAA,OACEkE,YAAajO,KAAKwL,YAClB/L,GAAIO,KAAK4N,MACTtD,MAAO,CACL9E,OAAQ,KACR,mBAAoBxF,KAAKQ,SACzB,mBAAoBR,KAAK8H,SACzB,mBAAoB9H,KAAKK,QAG3B0J,EAAA,OAAK0D,KAAK,aAAanD,MAAM,iBAC3BP,EAAA,QAAMe,KAAK,cACTf,EAAA,aAAWe,KAAK,cAAa,cAAa,WAG9Cf,EAAA,OAAK0D,KAAK,QAAQnD,MAAM,iBACtBP,EAAA,QAAMe,KAAK,WAEbf,EAAA,OAAK0D,KAAK,QAAQnD,MAAM,iBACtBP,EAAA,YAAO/J,KAAK0F,OAAS1F,KAAKK,QAE5B0J,EAAA,OAAK0D,KAAK,MAAMnD,MAAM,eACpBP,EAAA,QAAMe,KAAK,U"}
@@ -1,5 +0,0 @@
1
- /*!
2
- * Web Components for Nanopore digital Web Apps
3
- */
4
- import{r as t,c as i,h as s,a as e,g as h}from"./p-f6a8467a.js";import{c as a}from"./p-9ebbb814.js";const r=class{constructor(s){t(this,s);this.nanoPayloadChange=i(this,"nanoPayloadChange",7);this.nanoSubmit=i(this,"nanoSubmit",7);this.nanoInvalid=i(this,"nanoInvalid",7);this.allFields=[];this.nanoFieldSelector=`\n nano-input,\n nano-select,\n nano-file-upload,\n nano-date-input,\n nano-checkbox\n `;this.hasSetStore=false;this.internalValidate=false;this.handleStoreChange=async(t,i)=>{const s=this.allFields.find((i=>this.getName(i)===t));if(s&&(s.tagName==="NANO-CHECKBOX"||["radio","checkbox"].includes(s.type))){this.storeToFields([s])}else if(s&&(s.tagName==="NANO-FILE-UPLOAD"&&!this.fileStateEqual(t,s)||s.tagName!=="NANO-FILE-UPLOAD"&&s.value!==i)){this.storeToFields([s])}if(this.validateOn==="dirty"&&this.dirty){this.internalValidate=true;await this.validateAllFields();this._valid=this.activeForm.checkValidity();this.internalValidate=false}this.nanoPayloadChange.emit(this._store.state)};this.handleFormInvalid=async t=>{if(!this.plainFields.includes(t.target)){t.preventDefault()}this._valid=false;if(this.internalValidate)return;if(this.validateOn==="submitThenDirty")this.validateOn="dirty";this.submitted=true;await this.validateAllFields();this.internalValidate=true;this._valid=this.activeForm.checkValidity();this.internalValidate=false;if(this.validateOn==="submit"){if(this._valid){this.submitForm();return}}this.scrollToFirstInvalid();this.nanoInvalid.emit()};this.submitted=false;this.userForm=undefined;this.validateOn="submitThenDirty";this.scrollToInvalid=true;this._dirty=false;this._valid=undefined;this._store=undefined;this.extraFieldSelector="input, select, textarea";this.validation=undefined}userFormChange(){if(!!this.userForm)this.activeForm=this.userForm}get activeForm(){return this._activeForm}set activeForm(t){if(!t)return;if(this._activeForm){this._activeForm.removeEventListener("invalid",this.handleFormInvalid,true)}t.addEventListener("invalid",this.handleFormInvalid,true);this._activeForm=t}validateOnChange(){this.nanoFields.forEach((t=>{if(t.tagName==="NANO-CHECKBOX"){const i=t.closest("nano-checkbox-group");if(i)i.validateOn=this.validateOn}else{t.validateOn=this.validateOn}}))}get dirty(){return this._dirty}get valid(){return this._valid}get store(){return this._store}get payload(){return this._store.state}get showValidation(){return this.validateOn==="dirty"&&this.dirty||this.submitted}get validationState(){const t=[];this.allFields.forEach((async i=>{const s=t.find((t=>t.name===this.getName(i)));let e;let h;if(s){if(i.validationMessage){e=i;s.validityMessage=e.validationMessage.length?e.validationMessage:s.validityMessage;this.internalValidate=true;if(s.valid&&!e.checkValidity())s.valid=false;this.internalValidate=false}else if(i.validityMessage){h=i;s.validityMessage=h.validityMessage.length?h.validityMessage:h.validityMessage;if(s.valid&&h.invalid)s.valid=false}if(!s.fields.find((t=>t===i)))s.fields.push(i)}let a;let r;if(i.checkValidity){e=i;this.internalValidate=true;a=e.checkValidity();this.internalValidate=false;r=e.validationMessage}else{h=i;a=!h.invalid;r=h.validityMessage}t.push({fields:[i],name:this.getName(i),value:this._store.state[this.getName(i)],dirty:false,valid:a,validityMessage:r})}));return t}async setStore(t){this.hasSetStore=true;Object.entries(t).forEach((([t,i])=>{this.store.state[t]=i}))}async setCustomValidity(t){return await Promise.all(Object.entries(t).map((async([t,i])=>{const s=this.allFields.find((i=>this.getName(i)===t));if(!!s)await this.setFieldError(s,i)})))}async resetValidity(){return await Promise.all(this.allFields.map((async t=>await this.setFieldError(t,""))))}attachSlotObserver(){if(!!this.mo)return;const t=this.mo=new MutationObserver((t=>{const i=this.host.querySelector("form");if(i&&i!==this.activeForm)this.activeForm=i;this.setupFields()}));t.observe(this.host,{childList:true,attributes:true,attributeFilter:["name"],subtree:true})}getName(t){return t.name||t.getAttribute("name")}setupFields(){let t=Array.from(this.host.querySelectorAll(this.nanoFieldSelector));let i=Array.from(this.host.querySelectorAll(this.extraFieldSelector)).filter((t=>!t.closest(this.nanoFieldSelector)));t=t.filter((t=>!!this.getName(t)&&!!this.getName(t).length));i=i.filter((t=>!!this.getName(t)&&!!this.getName(t).length));if(![...t,...i].filter((t=>!this.allFields.includes(t))).length)return;this.nanoFields=t;this.plainFields=i;this.allFields=[...t,...i];this.storeToFields(this.allFields);this.validateOnChange();this.fieldsToStore(this.allFields,true);this.nanoPayloadChange.emit(this._store.state)}storeToFields(t){t.forEach((t=>{var i;const s=this.getName(t);if(!s.length||typeof this._store.state[s]==="undefined")return;if(t.tagName==="NANO-CHECKBOX"||["radio","checkbox"].includes(t.type)){const i=this.allFields.filter((i=>this.getName(t)===this.getName(i)));if(i[0].type==="radio"||i[0].type==="segment"||i[0].type==="segment-pill"){i.forEach((t=>{if(this._store.state[s]===t.value)t.checked=true;else t.checked=false}))}else if(Array.isArray(this._store.state[s])){i.forEach((t=>{if(this._store.state[s].includes(t.value))t.checked=true;else t.checked=false}))}else{i.forEach((t=>{if(this._store.state[s]===t.value)t.checked=true;else t.checked=false}))}return}if(t.tagName==="NANO-FILE-UPLOAD"){const e=t;if(!((i=e.files)===null||i===void 0?void 0:i.length))e.files=this._store.state[s];return}t.value=this._store.state[s]}))}fieldsToStore(t,i=false){t.forEach((t=>{const s=this.getName(t);if(!s.length)return;if(!!this._store.state[s]&&this.hasSetStore&&i){return}if(t.tagName==="NANO-CHECKBOX"||["radio","checkbox"].includes(t.type)){const i=t;if(i.type==="radio"||i.type==="segment"||i.type==="segment-pill"){if(i.checked)this._store.state[s]=i.value}else if(this.allFields.filter((t=>this.getName(t)===s&&(t.tagName==="NANO-CHECKBOX"||t.type==="checkbox"))).length>1){const t=Array.isArray(this._store.state[s])?this._store.state[s]:[];if(i.checked){if(!this._store.state[s].includes(i.value)){this._store.state[s]=[...t,i.value]}}else{this._store.state[s]=t.filter((t=>t!==i.value))}}else{if(i.checked)this._store.state[s]=i.value;else this._store.state[s]=""}return}if(t.tagName==="NANO-FILE-UPLOAD"){const i=t;if(!this.fileStateEqual(s,i))this._store.state[s]=i.files;return}this._store.state[s]=t.value}))}fileStateEqual(t,i){return JSON.stringify(this._store.state[t])===JSON.stringify(i.files)||this._store.state[t]==i.files}async validate(t,i){if(!this.validation)return;const s=this.validation(t,i,this._store.state);if(!s)return;await Promise.all(Object.entries(s).map((async([t,i])=>i.fields.map((async s=>{const e=this.allFields.find((t=>this.getName(t)===s));let h=e;if(e.tagName==="NANO-CHECKBOX"){const t=e.closest("nano-checkbox-group");h=t||e}if((h.validityMessage||h.validationMessage)===t&&i.valid){await this.setFieldError(h,"")}else if(!i.valid){await this.setFieldError(h,t)}})))))}async validateAllFields(){await Object.entries(this._store.state).reduce((async(t,[i,s])=>{await t;await this.validate(i,s)}),undefined)}async setFieldError(t,i){if(t["showError"]){await t.showError(i)}else if(t["setError"])await t.setError(i);else t.setCustomValidity(i)}scrollToFirstInvalid(){if(!this.scrollToInvalid)return;setTimeout((()=>{const t=this.validationState.find((t=>!t.valid));if(!t)return;t.fields[0].scrollIntoView({behavior:"smooth",block:"nearest"})}),200)}submitForm(){const t=this.nanoSubmit.emit();if(t.defaultPrevented)return;this.activeForm.submit()}handleFieldChange(t){if(!this.nanoFields.includes(t.target))return;this._dirty=true;this.fieldsToStore([t.target])}handlePlainFieldChange(t){if(!this.plainFields.includes(t.target))return;this.fieldsToStore([t.target])}async handleSubmit(t){t.preventDefault();if(this.validateOn==="submitThenDirty")this.validateOn="dirty";this.submitted=true;await this.validateAllFields();this.internalValidate=true;this._valid=this.activeForm.checkValidity();this.internalValidate=false;if(!this._valid){this.scrollToFirstInvalid();return}this.submitForm()}connectedCallback(){this.userForm=this.host.querySelector("form");this._store=a({})}componentDidLoad(){requestAnimationFrame((()=>{this.setupFields();this.attachSlotObserver();this._store.on("set",this.handleStoreChange)}))}disconnectedCallback(){if(this.mo)this.mo.disconnect();this._store.reset();if(this.activeForm)this.activeForm.removeEventListener("invalid",this.handleFormInvalid,true)}render(){return s(e,null,this.userForm&&s("slot",null),!this.userForm&&s("form",{ref:t=>this.activeForm=t},s("slot",null)))}get host(){return h(this)}static get watchers(){return{userForm:["userFormChange"],validateOn:["validateOnChange"],extraFieldSelector:["attachSlotObserver"]}}};export{r as nano_field_validator};
5
- //# sourceMappingURL=p-357a0a3f.entry.js.map