dom-8f0a9ff2.js 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. /*!
  2. * All material copyright ESRI, All Rights Reserved, unless otherwise specified.
  3. * See https://github.com/Esri/calcite-components/blob/master/LICENSE.md for details.
  4. * v1.0.0-beta.97
  5. */
  6. import { C as CSS_UTILITY } from './resources-9c476cb6.js';
  7. import { g as guid } from './guid-9f15e57a.js';
  8. /**
  9. * This helper will guarantee an ID on the provided element.
  10. *
  11. * If it already has an ID, it will be preserved, otherwise a unique one will be generated and assigned.
  12. *
  13. * @param el
  14. * @returns {string} The element's ID.
  15. */
  16. function ensureId(el) {
  17. if (!el) {
  18. return "";
  19. }
  20. return (el.id = el.id || `${el.tagName.toLowerCase()}-${guid()}`);
  21. }
  22. function nodeListToArray(nodeList) {
  23. return Array.isArray(nodeList) ? nodeList : Array.from(nodeList);
  24. }
  25. function getThemeName(el) {
  26. const closestElWithTheme = closestElementCrossShadowBoundary(el, `.${CSS_UTILITY.darkTheme}, .${CSS_UTILITY.lightTheme}`);
  27. return (closestElWithTheme === null || closestElWithTheme === void 0 ? void 0 : closestElWithTheme.classList.contains("calcite-theme-dark")) ? "dark" : "light";
  28. }
  29. function getElementDir(el) {
  30. const prop = "dir";
  31. const selector = `[${prop}]`;
  32. const closest = closestElementCrossShadowBoundary(el, selector);
  33. return closest ? closest.getAttribute(prop) : "ltr";
  34. }
  35. function getElementProp(el, prop, fallbackValue) {
  36. const selector = `[${prop}]`;
  37. const closest = el.closest(selector);
  38. return closest ? closest.getAttribute(prop) : fallbackValue;
  39. }
  40. function getRootNode(el) {
  41. return el.getRootNode();
  42. }
  43. function getHost(root) {
  44. return root.host || null;
  45. }
  46. /**
  47. * This helper queries an element's rootNode and any ancestor rootNodes.
  48. *
  49. * If both an 'id' and 'selector' are supplied, 'id' will take precedence over 'selector'.
  50. *
  51. * @param element
  52. * @param root0
  53. * @param root0.selector
  54. * @param root0.id
  55. * @returns {Element} The element.
  56. */
  57. function queryElementRoots(element, { selector, id }) {
  58. // Gets the rootNode and any ancestor rootNodes (shadowRoot or document) of an element and queries them for a selector.
  59. // Based on: https://stackoverflow.com/q/54520554/194216
  60. function queryFrom(el) {
  61. if (!el) {
  62. return null;
  63. }
  64. if (el.assignedSlot) {
  65. el = el.assignedSlot;
  66. }
  67. const rootNode = getRootNode(el);
  68. const found = id
  69. ? "getElementById" in rootNode
  70. ? /*
  71. Check to make sure 'getElementById' exists in cases where element is no longer connected to the DOM and getRootNode() returns the element.
  72. https://github.com/Esri/calcite-components/pull/4280
  73. */
  74. rootNode.getElementById(id)
  75. : null
  76. : selector
  77. ? rootNode.querySelector(selector)
  78. : null;
  79. const host = getHost(rootNode);
  80. return found ? found : host ? queryFrom(host) : null;
  81. }
  82. return queryFrom(element);
  83. }
  84. function closestElementCrossShadowBoundary(element, selector) {
  85. // based on https://stackoverflow.com/q/54520554/194216
  86. function closestFrom(el) {
  87. return el ? el.closest(selector) || closestFrom(getHost(getRootNode(el))) : null;
  88. }
  89. return closestFrom(element);
  90. }
  91. /**
  92. * This utility helps invoke a callback as it traverses a node and its ancestors until reaching the root document.
  93. *
  94. * Returning early or undefined in `onVisit` will continue traversing up the DOM tree. Otherwise, traversal will halt with the returned value as the result of the function
  95. *
  96. * @param element
  97. * @param onVisit
  98. */
  99. function walkUpAncestry(element, onVisit) {
  100. return visit(element, onVisit);
  101. }
  102. function visit(node, onVisit) {
  103. if (!node) {
  104. return;
  105. }
  106. const result = onVisit(node);
  107. if (result !== undefined) {
  108. return result;
  109. }
  110. const { parentNode } = node;
  111. return visit(parentNode instanceof ShadowRoot ? parentNode.host : parentNode, onVisit);
  112. }
  113. function containsCrossShadowBoundary(element, maybeDescendant) {
  114. return !!walkUpAncestry(maybeDescendant, (node) => (node === element ? true : undefined));
  115. }
  116. function isCalciteFocusable(el) {
  117. return typeof (el === null || el === void 0 ? void 0 : el.setFocus) === "function";
  118. }
  119. async function focusElement(el) {
  120. if (!el) {
  121. return;
  122. }
  123. return isCalciteFocusable(el) ? el.setFocus() : el.focus();
  124. }
  125. const defaultSlotSelector = ":not([slot])";
  126. function getSlotted(element, slotName, options) {
  127. if (slotName && !Array.isArray(slotName) && typeof slotName !== "string") {
  128. options = slotName;
  129. slotName = null;
  130. }
  131. const slotSelector = slotName
  132. ? Array.isArray(slotName)
  133. ? slotName.map((name) => `[slot="${name}"]`).join(",")
  134. : `[slot="${slotName}"]`
  135. : defaultSlotSelector;
  136. if (options === null || options === void 0 ? void 0 : options.all) {
  137. return queryMultiple(element, slotSelector, options);
  138. }
  139. return querySingle(element, slotSelector, options);
  140. }
  141. function getDirectChildren(el, selector) {
  142. return el ? Array.from(el.children || []).filter((child) => child === null || child === void 0 ? void 0 : child.matches(selector)) : [];
  143. }
  144. function queryMultiple(element, slotSelector, options) {
  145. let matches = slotSelector === defaultSlotSelector
  146. ? getDirectChildren(element, defaultSlotSelector)
  147. : Array.from(element.querySelectorAll(slotSelector));
  148. matches = options && options.direct === false ? matches : matches.filter((el) => el.parentElement === element);
  149. matches = (options === null || options === void 0 ? void 0 : options.matches) ? matches.filter((el) => el === null || el === void 0 ? void 0 : el.matches(options.matches)) : matches;
  150. const selector = options === null || options === void 0 ? void 0 : options.selector;
  151. return selector
  152. ? matches
  153. .map((item) => Array.from(item.querySelectorAll(selector)))
  154. .reduce((previousValue, currentValue) => [...previousValue, ...currentValue], [])
  155. .filter((match) => !!match)
  156. : matches;
  157. }
  158. function querySingle(element, slotSelector, options) {
  159. let match = slotSelector === defaultSlotSelector
  160. ? getDirectChildren(element, defaultSlotSelector)[0] || null
  161. : element.querySelector(slotSelector);
  162. match = options && options.direct === false ? match : (match === null || match === void 0 ? void 0 : match.parentElement) === element ? match : null;
  163. match = (options === null || options === void 0 ? void 0 : options.matches) ? ((match === null || match === void 0 ? void 0 : match.matches(options.matches)) ? match : null) : match;
  164. const selector = options === null || options === void 0 ? void 0 : options.selector;
  165. return selector ? match === null || match === void 0 ? void 0 : match.querySelector(selector) : match;
  166. }
  167. function filterDirectChildren(el, selector) {
  168. return Array.from(el.children).filter((child) => child.matches(selector));
  169. }
  170. // set a default icon from a defined set or allow an override with an icon name string
  171. function setRequestedIcon(iconObject, iconValue, matchedValue) {
  172. if (typeof iconValue === "string" && iconValue !== "") {
  173. return iconValue;
  174. }
  175. else if (iconValue === "") {
  176. return iconObject[matchedValue];
  177. }
  178. }
  179. function intersects(rect1, rect2) {
  180. return !(rect2.left > rect1.right ||
  181. rect2.right < rect1.left ||
  182. rect2.top > rect1.bottom ||
  183. rect2.bottom < rect1.top);
  184. }
  185. /**
  186. * This helper makes sure that boolean aria attributes are properly converted to a string.
  187. *
  188. * It should only be used for aria attributes that require a string value of "true" or "false".
  189. *
  190. * @param value
  191. * @returns {string} The string conversion of a boolean value ("true" | "false").
  192. */
  193. function toAriaBoolean(value) {
  194. return Boolean(value).toString();
  195. }
  196. /**
  197. * This helper returns true if the pointer event fired from the primary button of the device.
  198. *
  199. * See https://www.w3.org/TR/pointerevents/#the-button-property.
  200. *
  201. * @param event
  202. * @returns {boolean}
  203. */
  204. function isPrimaryPointerButton(event) {
  205. return !!(event.isPrimary && event.button === 0);
  206. }
  207. export { getElementDir as a, containsCrossShadowBoundary as b, closestElementCrossShadowBoundary as c, getThemeName as d, getElementProp as e, focusElement as f, getSlotted as g, ensureId as h, isPrimaryPointerButton as i, isCalciteFocusable as j, intersects as k, getRootNode as l, filterDirectChildren as m, nodeListToArray as n, queryElementRoots as q, setRequestedIcon as s, toAriaBoolean as t };