calcite-combobox_3.entry.js 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053
  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 { r as registerInstance, c as createEvent, h, H as Host, g as getElement } from './index-1f9b54dc.js';
  7. import { f as filter } from './filter-0e5a9913.js';
  8. import { d as defaultMenuPlacement, f as filterComputedPlacements, c as connectFloatingUI, u as updateAfterClose, r as reposition, a as disconnectFloatingUI, F as FloatingCSS } from './floating-ui-5c49748f.js';
  9. import { g as guid } from './guid-9f15e57a.js';
  10. import { n as nodeListToArray, i as isPrimaryPointerButton, t as toAriaBoolean, e as getElementProp, g as getSlotted } from './dom-8f0a9ff2.js';
  11. import { c as connectLabel, d as disconnectLabel, g as getLabelText } from './label-333c4a4c.js';
  12. import { s as submitForm, c as connectForm, a as afterConnectDefaultValueSet, d as disconnectForm, H as HiddenFormInputSlot } from './form-80dbd90e.js';
  13. import { c as createObserver } from './observers-9f44e9b3.js';
  14. import { u as updateHostInteraction } from './interactive-5db230e8.js';
  15. import { c as connectOpenCloseComponent, d as disconnectOpenCloseComponent } from './openCloseComponent-ba7d452b.js';
  16. import { d as debounce } from './debounce-d85a6654.js';
  17. import { c as connectConditionalSlotComponent, d as disconnectConditionalSlotComponent } from './conditionalSlot-a3e8c63a.js';
  18. import './resources-9c476cb6.js';
  19. const ComboboxItem$1 = "CALCITE-COMBOBOX-ITEM";
  20. const ComboboxItemGroup$1 = "CALCITE-COMBOBOX-ITEM-GROUP";
  21. const ComboboxChildSelector = `${ComboboxItem$1}, ${ComboboxItemGroup$1}`;
  22. const TEXT = {
  23. removeTag: "Remove tag"
  24. };
  25. function getAncestors(element) {
  26. var _a, _b;
  27. const parent = (_a = element.parentElement) === null || _a === void 0 ? void 0 : _a.closest(ComboboxChildSelector);
  28. const grandparent = (_b = parent === null || parent === void 0 ? void 0 : parent.parentElement) === null || _b === void 0 ? void 0 : _b.closest(ComboboxChildSelector);
  29. return [parent, grandparent].filter((el) => el);
  30. }
  31. function getItemAncestors(item) {
  32. var _a;
  33. return (((_a = item.ancestors) === null || _a === void 0 ? void 0 : _a.filter((el) => el.nodeName === "CALCITE-COMBOBOX-ITEM")) || []);
  34. }
  35. function getItemChildren(item) {
  36. return nodeListToArray(item.querySelectorAll("calcite-combobox-item"));
  37. }
  38. function hasActiveChildren(node) {
  39. const items = nodeListToArray(node.querySelectorAll("calcite-combobox-item"));
  40. return items.filter((item) => item.selected).length > 0;
  41. }
  42. function getDepth(element) {
  43. const result = document.evaluate("ancestor::calcite-combobox-item | ancestor::calcite-combobox-item-group", element, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
  44. return result.snapshotLength;
  45. }
  46. const comboboxCss = "@keyframes in{0%{opacity:0}100%{opacity:1}}@keyframes in-down{0%{opacity:0;transform:translate3D(0, -5px, 0)}100%{opacity:1;transform:translate3D(0, 0, 0)}}@keyframes in-up{0%{opacity:0;transform:translate3D(0, 5px, 0)}100%{opacity:1;transform:translate3D(0, 0, 0)}}@keyframes in-scale{0%{opacity:0;transform:scale3D(0.95, 0.95, 1)}100%{opacity:1;transform:scale3D(1, 1, 1)}}:root{--calcite-animation-timing:calc(150ms * var(--calcite-internal-duration-factor));--calcite-internal-duration-factor:var(--calcite-duration-factor, 1);--calcite-internal-animation-timing-fast:calc(100ms * var(--calcite-internal-duration-factor));--calcite-internal-animation-timing-medium:calc(200ms * var(--calcite-internal-duration-factor));--calcite-internal-animation-timing-slow:calc(300ms * var(--calcite-internal-duration-factor))}.calcite-animate{opacity:0;animation-fill-mode:both;animation-duration:var(--calcite-animation-timing)}.calcite-animate__in{animation-name:in}.calcite-animate__in-down{animation-name:in-down}.calcite-animate__in-up{animation-name:in-up}.calcite-animate__in-scale{animation-name:in-scale}@media (prefers-reduced-motion: reduce){:root{--calcite-internal-duration-factor:0.01}}:root{--calcite-floating-ui-transition:var(--calcite-animation-timing)}:host([hidden]){display:none}:host([disabled]){pointer-events:none;cursor:default;-webkit-user-select:none;user-select:none;opacity:var(--calcite-ui-opacity-disabled)}:host{position:relative;display:block}:host([disabled]) ::slotted([calcite-hydrated][disabled]),:host([disabled]) [calcite-hydrated][disabled]{opacity:1}:host([scale=s]){font-size:var(--calcite-font-size--2);--calcite-combobox-item-spacing-unit-l:0.5rem;--calcite-combobox-item-spacing-unit-s:0.25rem;--calcite-combobox-input-height:1.5rem}:host([scale=m]){font-size:var(--calcite-font-size--1);--calcite-combobox-item-spacing-unit-l:0.75rem;--calcite-combobox-item-spacing-unit-s:0.5rem;--calcite-combobox-input-height:2rem}:host([scale=l]){font-size:var(--calcite-font-size-0);--calcite-combobox-item-spacing-unit-l:1rem;--calcite-combobox-item-spacing-unit-s:0.75rem;--calcite-combobox-input-height:2.75rem}.wrapper{display:flex;border-width:1px;border-style:solid;border-color:var(--calcite-ui-border-input);background-color:var(--calcite-ui-foreground-1);color:var(--calcite-ui-text-1);outline-color:transparent;padding-block:calc(var(--calcite-combobox-item-spacing-unit-s) / 4);padding-inline:var(--calcite-combobox-item-spacing-unit-l)}:host(:focus-within) .wrapper,.wrapper--active{outline:2px solid var(--calcite-ui-brand);outline-offset:-2px}.wrapper--single{padding-block:0;padding-inline:var(--calcite-combobox-item-spacing-unit-l);cursor:pointer;flex-wrap:nowrap}.grid-input{display:flex;flex-grow:1;flex-wrap:wrap;align-items:center;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding:0px}.input{flex-grow:1;-webkit-appearance:none;appearance:none;border-style:none;background-color:transparent;padding:0px;font-family:inherit;color:var(--calcite-ui-text-1);font-size:inherit;block-size:var(--calcite-combobox-input-height);line-height:var(--calcite-combobox-input-height);min-inline-size:120px;margin-block-end:var(--calcite-combobox-item-spacing-unit-s)}.input:focus{outline:2px solid transparent;outline-offset:2px}.input--transparent{opacity:0}.input--single{margin-block:0px;padding:0px}.wrapper--active .input-single{cursor:text}.input--hidden{pointer-events:none;inline-size:0px;min-inline-size:0px;opacity:0}.input--icon{padding-block:0;padding-inline:var(--calcite-combobox-item-spacing-unit-l)}.input-wrap{display:flex;flex-grow:1}.input-wrap--single{flex:1 1 0%;overflow:hidden}.label{pointer-events:none;display:flex;max-inline-size:100%;flex:1 1 auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding:0px;font-weight:var(--calcite-font-weight-normal);block-size:var(--calcite-combobox-input-height);line-height:var(--calcite-combobox-input-height)}.label--icon{padding-inline:var(--calcite-combobox-item-spacing-unit-l)}.icon-end,.icon-start{display:flex;inline-size:1rem;cursor:pointer;align-items:center}.icon-end{flex:none}.floating-ui-container{display:block;position:absolute;z-index:900;visibility:hidden;pointer-events:none;inline-size:0;block-size:0;overflow:hidden}.floating-ui-container .calcite-floating-ui-anim{position:relative;transition:var(--calcite-floating-ui-transition);visibility:hidden;transition-property:transform, visibility, opacity;opacity:0;box-shadow:0 0 16px 0 rgba(0, 0, 0, 0.16);z-index:1;border-radius:0.25rem}.floating-ui-container[data-placement^=bottom] .calcite-floating-ui-anim{transform:translateY(-5px)}.floating-ui-container[data-placement^=top] .calcite-floating-ui-anim{transform:translateY(5px)}.floating-ui-container[data-placement^=left] .calcite-floating-ui-anim{transform:translateX(5px)}.floating-ui-container[data-placement^=right] .calcite-floating-ui-anim{transform:translateX(-5px)}.floating-ui-container[data-placement] .calcite-floating-ui-anim--active{opacity:1;visibility:visible;transform:translate(0)}.floating-ui-container--active{pointer-events:initial;visibility:visible;inline-size:unset;block-size:unset;overflow:unset}@media (forced-colors: active){.wrapper,.floating-ui-container--active{border:1px solid canvasText}}.screen-readers-only{position:absolute;inline-size:1px;block-size:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border-width:0}.list-container{max-block-size:45vh;overflow-y:auto;background-color:var(--calcite-ui-foreground-1);inline-size:var(--calcite-dropdown-width)}.list{margin:0px;display:block;padding:0px}.list--hide{block-size:0px;overflow:hidden}.chip{margin-block:calc(var(--calcite-combobox-item-spacing-unit-s) / 4);margin-inline:0 var(--calcite-combobox-item-spacing-unit-s);max-inline-size:100%}.chip--active{background-color:var(--calcite-ui-foreground-3)}.item{display:block}::slotted(input[slot=hidden-form-input]){margin:0 !important;opacity:0 !important;outline:none !important;padding:0 !important;position:absolute !important;inset:0 !important;transform:none !important;-webkit-appearance:none !important;z-index:-1 !important}";
  47. const isGroup = (el) => el.tagName === ComboboxItemGroup$1;
  48. const itemUidPrefix = "combobox-item-";
  49. const chipUidPrefix = "combobox-chip-";
  50. const labelUidPrefix = "combobox-label-";
  51. const listboxUidPrefix = "combobox-listbox-";
  52. const inputUidPrefix = "combobox-input-";
  53. const Combobox = class {
  54. constructor(hostRef) {
  55. registerInstance(this, hostRef);
  56. this.calciteLookupChange = createEvent(this, "calciteLookupChange", 6);
  57. this.calciteComboboxChange = createEvent(this, "calciteComboboxChange", 6);
  58. this.calciteComboboxFilterChange = createEvent(this, "calciteComboboxFilterChange", 6);
  59. this.calciteComboboxChipDismiss = createEvent(this, "calciteComboboxChipDismiss", 6);
  60. this.calciteComboboxBeforeClose = createEvent(this, "calciteComboboxBeforeClose", 6);
  61. this.calciteComboboxClose = createEvent(this, "calciteComboboxClose", 6);
  62. this.calciteComboboxBeforeOpen = createEvent(this, "calciteComboboxBeforeOpen", 6);
  63. this.calciteComboboxOpen = createEvent(this, "calciteComboboxOpen", 6);
  64. //--------------------------------------------------------------------------
  65. //
  66. // Public Properties
  67. //
  68. //--------------------------------------------------------------------------
  69. /**
  70. * When `true`, displays and positions the component.
  71. *
  72. * @deprecated use `open` instead.
  73. */
  74. this.active = false;
  75. /**When `true`, displays and positions the component. */
  76. this.open = false;
  77. /** When `true`, interaction is prevented and the component is displayed with lower opacity. */
  78. this.disabled = false;
  79. /** Specifies the maximum number of `calcite-combobox-item`s (including nested children) to display before displaying a scrollbar. */
  80. this.maxItems = 0;
  81. /**
  82. * Determines the type of positioning to use for the overlaid content.
  83. *
  84. * Using `"absolute"` will work for most cases. The component will be positioned inside of overflowing parent containers and will affect the container's layout.
  85. *
  86. * `"fixed"` should be used to escape an overflowing parent container, or when the reference element's `position` CSS property is `"fixed"`.
  87. *
  88. */
  89. this.overlayPositioning = "absolute";
  90. /**
  91. * When `true`, the component must have a value in order for the form to submit.
  92. *
  93. * @internal
  94. */
  95. this.required = false;
  96. /**
  97. * Specifies the selection mode -
  98. * `"multi"` (allow any number of selected items),
  99. * `"single"` (allow only one selection), or
  100. * `"ancestors"` (like `"multi"`, but show ancestors of selected items as selected. Only the deepest children are shown in `calcite-chip`s).
  101. */
  102. this.selectionMode = "multi";
  103. /** Specifies the size of the component. */
  104. this.scale = "m";
  105. /** The component's value(s) from the selected `calcite-combobox-item`(s). */
  106. this.value = null;
  107. /**
  108. * Accessible name for the component's remove tag when a `calcite-combobox-item` is selected.
  109. *
  110. * @default "Remove tag"
  111. */
  112. this.intlRemoveTag = TEXT.removeTag;
  113. //--------------------------------------------------------------------------
  114. //
  115. // Private State/Props
  116. //
  117. //--------------------------------------------------------------------------
  118. this.placement = defaultMenuPlacement;
  119. this.internalValueChangeFlag = false;
  120. this.items = [];
  121. this.groupItems = [];
  122. this.selectedItems = [];
  123. this.visibleItems = [];
  124. this.activeItemIndex = -1;
  125. this.activeChipIndex = -1;
  126. this.activeDescendant = "";
  127. this.text = "";
  128. this.textInput = null;
  129. this.mutationObserver = createObserver("mutation", () => this.updateItems());
  130. this.resizeObserver = createObserver("resize", () => this.setMaxScrollerHeight());
  131. this.guid = guid();
  132. this.inputHeight = 0;
  133. this.ignoreSelectedEventsFlag = false;
  134. this.openTransitionProp = "opacity";
  135. // --------------------------------------------------------------------------
  136. //
  137. // Private Methods
  138. //
  139. // --------------------------------------------------------------------------
  140. this.setFilteredPlacements = () => {
  141. const { el, flipPlacements } = this;
  142. this.filteredFlipPlacements = flipPlacements
  143. ? filterComputedPlacements(flipPlacements, el)
  144. : null;
  145. };
  146. this.getValue = () => {
  147. const items = this.selectedItems.map((item) => { var _a; return (_a = item === null || item === void 0 ? void 0 : item.value) === null || _a === void 0 ? void 0 : _a.toString(); });
  148. return (items === null || items === void 0 ? void 0 : items.length) ? (items.length > 1 ? items : items[0]) : "";
  149. };
  150. this.onLabelClick = () => {
  151. this.setFocus();
  152. };
  153. this.keydownHandler = (event) => {
  154. const { key } = event;
  155. switch (key) {
  156. case "Tab":
  157. this.activeChipIndex = -1;
  158. this.activeItemIndex = -1;
  159. if (this.allowCustomValues && this.text) {
  160. this.addCustomChip(this.text, true);
  161. event.preventDefault();
  162. }
  163. else if (this.open) {
  164. this.open = false;
  165. event.preventDefault();
  166. }
  167. break;
  168. case "ArrowLeft":
  169. this.previousChip();
  170. event.preventDefault();
  171. break;
  172. case "ArrowRight":
  173. this.nextChip();
  174. event.preventDefault();
  175. break;
  176. case "ArrowUp":
  177. event.preventDefault();
  178. this.shiftActiveItemIndex(-1);
  179. if (!this.comboboxInViewport()) {
  180. this.el.scrollIntoView();
  181. }
  182. break;
  183. case "ArrowDown":
  184. event.preventDefault();
  185. if (!this.open) {
  186. this.open = true;
  187. }
  188. this.shiftActiveItemIndex(1);
  189. if (!this.comboboxInViewport()) {
  190. this.el.scrollIntoView();
  191. }
  192. break;
  193. case " ":
  194. if (!this.textInput.value) {
  195. event.preventDefault();
  196. this.open = true;
  197. this.shiftActiveItemIndex(1);
  198. }
  199. break;
  200. case "Home":
  201. if (!this.open) {
  202. return;
  203. }
  204. event.preventDefault();
  205. this.updateActiveItemIndex(0);
  206. this.scrollToActiveItem();
  207. if (!this.comboboxInViewport()) {
  208. this.el.scrollIntoView();
  209. }
  210. break;
  211. case "End":
  212. if (!this.open) {
  213. return;
  214. }
  215. event.preventDefault();
  216. this.updateActiveItemIndex(this.visibleItems.length - 1);
  217. this.scrollToActiveItem();
  218. if (!this.comboboxInViewport()) {
  219. this.el.scrollIntoView();
  220. }
  221. break;
  222. case "Escape":
  223. this.open = false;
  224. event.preventDefault();
  225. break;
  226. case "Enter":
  227. if (this.activeItemIndex > -1) {
  228. this.toggleSelection(this.visibleItems[this.activeItemIndex]);
  229. event.preventDefault();
  230. }
  231. else if (this.activeChipIndex > -1) {
  232. this.removeActiveChip();
  233. event.preventDefault();
  234. }
  235. else if (this.allowCustomValues && this.text) {
  236. this.addCustomChip(this.text, true);
  237. event.preventDefault();
  238. }
  239. else if (!event.defaultPrevented) {
  240. if (submitForm(this)) {
  241. event.preventDefault();
  242. }
  243. }
  244. break;
  245. case "Delete":
  246. case "Backspace":
  247. if (this.activeChipIndex > -1) {
  248. event.preventDefault();
  249. this.removeActiveChip();
  250. }
  251. else if (!this.text && this.isMulti()) {
  252. event.preventDefault();
  253. this.removeLastChip();
  254. }
  255. break;
  256. }
  257. };
  258. this.toggleCloseEnd = () => {
  259. this.open = false;
  260. this.el.removeEventListener("calciteComboboxClose", this.toggleCloseEnd);
  261. };
  262. this.toggleOpenEnd = () => {
  263. this.open = false;
  264. this.el.removeEventListener("calciteComboboxOpen", this.toggleOpenEnd);
  265. };
  266. this.setMaxScrollerHeight = async () => {
  267. const { listContainerEl, open, referenceEl } = this;
  268. if (!listContainerEl || !open) {
  269. return;
  270. }
  271. await this.reposition(true);
  272. const maxScrollerHeight = this.getMaxScrollerHeight();
  273. listContainerEl.style.maxHeight = maxScrollerHeight > 0 ? `${maxScrollerHeight}px` : "";
  274. listContainerEl.style.minWidth = `${referenceEl.clientWidth}px`;
  275. await this.reposition(true);
  276. };
  277. this.calciteChipDismissHandler = (event, comboboxItem) => {
  278. this.open = false;
  279. const selection = this.items.find((item) => item === comboboxItem);
  280. if (selection) {
  281. this.toggleSelection(selection, false);
  282. }
  283. this.calciteComboboxChipDismiss.emit(event.detail);
  284. };
  285. this.clickHandler = (event) => {
  286. if (event.composedPath().some((node) => node.tagName === "CALCITE-CHIP")) {
  287. return;
  288. }
  289. this.open = !this.open;
  290. this.updateActiveItemIndex(0);
  291. this.setFocus();
  292. };
  293. this.setInactiveIfNotContained = (event) => {
  294. const composedPath = event.composedPath();
  295. if (!this.open || composedPath.includes(this.el) || composedPath.includes(this.referenceEl)) {
  296. return;
  297. }
  298. if (this.allowCustomValues && this.text.trim().length) {
  299. this.addCustomChip(this.text);
  300. }
  301. if (this.selectionMode === "single") {
  302. if (this.textInput) {
  303. this.textInput.value = "";
  304. }
  305. this.text = "";
  306. this.filterItems("");
  307. this.updateActiveItemIndex(-1);
  308. }
  309. this.open = false;
  310. };
  311. this.setFloatingEl = (el) => {
  312. this.floatingEl = el;
  313. connectFloatingUI(this, this.referenceEl, this.floatingEl);
  314. };
  315. this.setContainerEl = (el) => {
  316. this.resizeObserver.observe(el);
  317. this.listContainerEl = el;
  318. this.transitionEl = el;
  319. connectOpenCloseComponent(this);
  320. };
  321. this.setReferenceEl = (el) => {
  322. this.referenceEl = el;
  323. connectFloatingUI(this, this.referenceEl, this.floatingEl);
  324. };
  325. this.inputHandler = (event) => {
  326. const value = event.target.value;
  327. this.text = value;
  328. this.filterItems(value);
  329. if (value) {
  330. this.activeChipIndex = -1;
  331. }
  332. };
  333. this.filterItems = (() => {
  334. const find = (item, filteredData) => item &&
  335. filteredData.some(({ label, value }) => {
  336. if (isGroup(item)) {
  337. return value === item.label;
  338. }
  339. return (value === item.textLabel ||
  340. value === item.value ||
  341. label === item.textLabel ||
  342. label === item.value);
  343. });
  344. return debounce((text) => {
  345. const filteredData = filter(this.data, text);
  346. const items = this.getCombinedItems();
  347. items.forEach((item) => {
  348. const hidden = !find(item, filteredData);
  349. item.hidden = hidden;
  350. const [parent, grandparent] = item.ancestors;
  351. if (find(parent, filteredData) || find(grandparent, filteredData)) {
  352. item.hidden = false;
  353. }
  354. if (!hidden) {
  355. item.ancestors.forEach((ancestor) => (ancestor.hidden = false));
  356. }
  357. });
  358. this.visibleItems = this.getVisibleItems();
  359. this.calciteComboboxFilterChange.emit({ visibleItems: [...this.visibleItems], text: text });
  360. }, 100);
  361. })();
  362. this.internalCalciteLookupChangeEvent = () => {
  363. this.calciteLookupChange.emit(this.selectedItems);
  364. };
  365. this.emitCalciteLookupChange = debounce(this.internalCalciteLookupChangeEvent, 0);
  366. this.internalComboboxChangeEvent = () => {
  367. const { selectedItems } = this;
  368. this.calciteComboboxChange.emit({ selectedItems });
  369. };
  370. this.emitComboboxChange = debounce(this.internalComboboxChangeEvent, 0);
  371. this.updateItems = () => {
  372. this.items = this.getItems();
  373. this.groupItems = this.getGroupItems();
  374. this.data = this.getData();
  375. this.selectedItems = this.getSelectedItems();
  376. this.visibleItems = this.getVisibleItems();
  377. this.needsIcon = this.getNeedsIcon();
  378. if (!this.allowCustomValues) {
  379. this.setMaxScrollerHeight();
  380. }
  381. };
  382. this.scrollToActiveItem = () => {
  383. const activeItem = this.visibleItems[this.activeItemIndex];
  384. const height = this.calculateSingleItemHeight(activeItem);
  385. const { offsetHeight, scrollTop } = this.listContainerEl;
  386. if (offsetHeight + scrollTop < activeItem.offsetTop + height) {
  387. this.listContainerEl.scrollTop = activeItem.offsetTop - offsetHeight + height;
  388. }
  389. else if (activeItem.offsetTop < scrollTop) {
  390. this.listContainerEl.scrollTop = activeItem.offsetTop;
  391. }
  392. };
  393. this.comboboxFocusHandler = () => {
  394. var _a;
  395. (_a = this.textInput) === null || _a === void 0 ? void 0 : _a.focus();
  396. };
  397. this.comboboxBlurHandler = (event) => {
  398. this.setInactiveIfNotContained(event);
  399. };
  400. }
  401. activeHandler(value) {
  402. if (this.disabled) {
  403. this.active = false;
  404. this.open = false;
  405. return;
  406. }
  407. this.open = value;
  408. }
  409. openHandler(value) {
  410. if (!value) {
  411. updateAfterClose(this.floatingEl);
  412. }
  413. if (this.disabled) {
  414. this.active = false;
  415. this.open = false;
  416. return;
  417. }
  418. this.active = value;
  419. this.setMaxScrollerHeight();
  420. }
  421. handleDisabledChange(value) {
  422. if (!value) {
  423. this.active = false;
  424. this.open = false;
  425. }
  426. }
  427. maxItemsHandler() {
  428. this.setMaxScrollerHeight();
  429. }
  430. overlayPositioningHandler() {
  431. this.reposition(true);
  432. }
  433. valueHandler(value) {
  434. if (!this.internalValueChangeFlag) {
  435. const items = this.getItems();
  436. if (Array.isArray(value)) {
  437. items.forEach((item) => (item.selected = value.includes(item.value)));
  438. }
  439. else if (value) {
  440. items.forEach((item) => (item.selected = value === item.value));
  441. }
  442. else {
  443. items.forEach((item) => (item.selected = false));
  444. }
  445. this.updateItems();
  446. }
  447. }
  448. flipPlacementsHandler() {
  449. this.setFilteredPlacements();
  450. this.reposition(true);
  451. }
  452. //--------------------------------------------------------------------------
  453. //
  454. // Event Listeners
  455. //
  456. //--------------------------------------------------------------------------
  457. documentClickHandler(event) {
  458. if (!isPrimaryPointerButton(event)) {
  459. return;
  460. }
  461. this.setInactiveIfNotContained(event);
  462. }
  463. calciteComboboxItemChangeHandler(event) {
  464. if (this.ignoreSelectedEventsFlag) {
  465. return;
  466. }
  467. const target = event.target;
  468. const newIndex = this.visibleItems.indexOf(target);
  469. this.updateActiveItemIndex(newIndex);
  470. this.toggleSelection(target, target.selected);
  471. }
  472. //--------------------------------------------------------------------------
  473. //
  474. // Public Methods
  475. //
  476. //--------------------------------------------------------------------------
  477. /**
  478. * Updates the position of the component.
  479. *
  480. * @param delayed
  481. */
  482. async reposition(delayed = false) {
  483. const { floatingEl, referenceEl, placement, overlayPositioning, filteredFlipPlacements } = this;
  484. return reposition(this, {
  485. floatingEl,
  486. referenceEl,
  487. overlayPositioning,
  488. placement,
  489. flipPlacements: filteredFlipPlacements,
  490. type: "menu"
  491. }, delayed);
  492. }
  493. /** Sets focus on the component. */
  494. async setFocus() {
  495. var _a;
  496. (_a = this.textInput) === null || _a === void 0 ? void 0 : _a.focus();
  497. this.activeChipIndex = -1;
  498. this.activeItemIndex = -1;
  499. }
  500. // --------------------------------------------------------------------------
  501. //
  502. // Lifecycle
  503. //
  504. // --------------------------------------------------------------------------
  505. connectedCallback() {
  506. var _a;
  507. this.internalValueChangeFlag = true;
  508. this.value = this.getValue();
  509. this.internalValueChangeFlag = false;
  510. (_a = this.mutationObserver) === null || _a === void 0 ? void 0 : _a.observe(this.el, { childList: true, subtree: true });
  511. connectLabel(this);
  512. connectForm(this);
  513. connectOpenCloseComponent(this);
  514. this.setFilteredPlacements();
  515. this.reposition(true);
  516. if (this.active) {
  517. this.activeHandler(this.active);
  518. }
  519. if (this.open) {
  520. this.openHandler(this.open);
  521. }
  522. }
  523. componentWillLoad() {
  524. this.updateItems();
  525. }
  526. componentDidLoad() {
  527. afterConnectDefaultValueSet(this, this.getValue());
  528. this.reposition(true);
  529. }
  530. componentDidRender() {
  531. if (this.el.offsetHeight !== this.inputHeight) {
  532. this.reposition(true);
  533. this.inputHeight = this.el.offsetHeight;
  534. }
  535. updateHostInteraction(this);
  536. }
  537. disconnectedCallback() {
  538. var _a, _b;
  539. (_a = this.mutationObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
  540. (_b = this.resizeObserver) === null || _b === void 0 ? void 0 : _b.disconnect();
  541. disconnectLabel(this);
  542. disconnectForm(this);
  543. disconnectFloatingUI(this, this.referenceEl, this.floatingEl);
  544. disconnectOpenCloseComponent(this);
  545. }
  546. selectedItemsHandler() {
  547. this.internalValueChangeFlag = true;
  548. this.value = this.getValue();
  549. this.internalValueChangeFlag = false;
  550. }
  551. /** when search text is cleared, reset active to */
  552. textHandler() {
  553. this.updateActiveItemIndex(-1);
  554. }
  555. comboboxInViewport() {
  556. const bounding = this.el.getBoundingClientRect();
  557. return (bounding.top >= 0 &&
  558. bounding.left >= 0 &&
  559. bounding.right <= (window.innerWidth || document.documentElement.clientWidth) &&
  560. bounding.bottom <= (window.innerHeight || document.documentElement.clientHeight));
  561. }
  562. onBeforeOpen() {
  563. this.calciteComboboxBeforeOpen.emit();
  564. }
  565. onOpen() {
  566. this.calciteComboboxOpen.emit();
  567. }
  568. onBeforeClose() {
  569. this.calciteComboboxBeforeClose.emit();
  570. }
  571. onClose() {
  572. this.calciteComboboxClose.emit();
  573. }
  574. getMaxScrollerHeight() {
  575. const items = this.getCombinedItems().filter((item) => !item.hidden);
  576. const { maxItems } = this;
  577. let itemsToProcess = 0;
  578. let maxScrollerHeight = 0;
  579. if (items.length > maxItems) {
  580. items.forEach((item) => {
  581. if (itemsToProcess < maxItems && maxItems > 0) {
  582. const height = this.calculateSingleItemHeight(item);
  583. if (height > 0) {
  584. maxScrollerHeight += height;
  585. itemsToProcess++;
  586. }
  587. }
  588. });
  589. }
  590. return maxScrollerHeight;
  591. }
  592. calculateSingleItemHeight(item) {
  593. let height = item.offsetHeight;
  594. // if item has children items, don't count their height twice
  595. const children = Array.from(item.querySelectorAll(ComboboxChildSelector));
  596. children
  597. .map((child) => child === null || child === void 0 ? void 0 : child.offsetHeight)
  598. .forEach((offsetHeight) => {
  599. height -= offsetHeight;
  600. });
  601. return height;
  602. }
  603. getCombinedItems() {
  604. return [...this.groupItems, ...this.items];
  605. }
  606. toggleSelection(item, value = !item.selected) {
  607. if (!item) {
  608. return;
  609. }
  610. if (this.isMulti()) {
  611. item.selected = value;
  612. this.updateAncestors(item);
  613. this.selectedItems = this.getSelectedItems();
  614. this.emitCalciteLookupChange();
  615. this.emitComboboxChange();
  616. this.resetText();
  617. this.filterItems("");
  618. }
  619. else {
  620. this.ignoreSelectedEventsFlag = true;
  621. this.items.forEach((el) => (el.selected = el === item ? value : false));
  622. this.ignoreSelectedEventsFlag = false;
  623. this.selectedItems = this.getSelectedItems();
  624. this.emitComboboxChange();
  625. if (this.textInput) {
  626. this.textInput.value = item.textLabel;
  627. }
  628. this.open = false;
  629. this.updateActiveItemIndex(-1);
  630. this.resetText();
  631. this.filterItems("");
  632. }
  633. }
  634. updateAncestors(item) {
  635. if (this.selectionMode !== "ancestors") {
  636. return;
  637. }
  638. const ancestors = getItemAncestors(item);
  639. const children = getItemChildren(item);
  640. if (item.selected) {
  641. ancestors.forEach((el) => {
  642. el.selected = true;
  643. });
  644. }
  645. else {
  646. children.forEach((el) => (el.selected = false));
  647. [...ancestors].forEach((el) => {
  648. if (!hasActiveChildren(el)) {
  649. el.selected = false;
  650. }
  651. });
  652. }
  653. }
  654. getVisibleItems() {
  655. return this.items.filter((item) => !item.hidden);
  656. }
  657. getSelectedItems() {
  658. if (!this.isMulti()) {
  659. const match = this.items.find(({ selected }) => selected);
  660. return match ? [match] : [];
  661. }
  662. return (this.items
  663. .filter((item) => item.selected && (this.selectionMode !== "ancestors" || !hasActiveChildren(item)))
  664. /** Preserve order of entered tags */
  665. .sort((a, b) => {
  666. const aIdx = this.selectedItems.indexOf(a);
  667. const bIdx = this.selectedItems.indexOf(b);
  668. if (aIdx > -1 && bIdx > -1) {
  669. return aIdx - bIdx;
  670. }
  671. return bIdx - aIdx;
  672. }));
  673. }
  674. getData() {
  675. return this.items.map((item) => ({
  676. constant: item.constant,
  677. filterDisabled: item.filterDisabled,
  678. value: item.value,
  679. label: item.textLabel
  680. }));
  681. }
  682. getNeedsIcon() {
  683. return this.selectionMode === "single" && this.items.some((item) => item.icon);
  684. }
  685. resetText() {
  686. if (this.textInput) {
  687. this.textInput.value = "";
  688. }
  689. this.text = "";
  690. }
  691. getItems() {
  692. const items = Array.from(this.el.querySelectorAll(ComboboxItem$1));
  693. return items.filter((item) => !item.disabled);
  694. }
  695. getGroupItems() {
  696. return Array.from(this.el.querySelectorAll(ComboboxItemGroup$1));
  697. }
  698. addCustomChip(value, focus) {
  699. const existingItem = this.items.find((el) => el.textLabel === value);
  700. if (existingItem) {
  701. this.toggleSelection(existingItem, true);
  702. }
  703. else {
  704. if (!this.isMulti()) {
  705. this.toggleSelection(this.selectedItems[this.selectedItems.length - 1], false);
  706. }
  707. const item = document.createElement(ComboboxItem$1);
  708. item.value = value;
  709. item.textLabel = value;
  710. item.selected = true;
  711. this.el.appendChild(item);
  712. this.resetText();
  713. if (focus) {
  714. this.setFocus();
  715. }
  716. this.updateItems();
  717. this.filterItems("");
  718. this.emitCalciteLookupChange();
  719. this.emitComboboxChange();
  720. }
  721. }
  722. removeActiveChip() {
  723. this.toggleSelection(this.selectedItems[this.activeChipIndex], false);
  724. this.setFocus();
  725. }
  726. removeLastChip() {
  727. this.toggleSelection(this.selectedItems[this.selectedItems.length - 1], false);
  728. this.setFocus();
  729. }
  730. previousChip() {
  731. if (this.text) {
  732. return;
  733. }
  734. const length = this.selectedItems.length - 1;
  735. const active = this.activeChipIndex;
  736. this.activeChipIndex = active === -1 ? length : Math.max(active - 1, 0);
  737. this.updateActiveItemIndex(-1);
  738. this.focusChip();
  739. }
  740. nextChip() {
  741. if (this.text || this.activeChipIndex === -1) {
  742. return;
  743. }
  744. const last = this.selectedItems.length - 1;
  745. const newIndex = this.activeChipIndex + 1;
  746. if (newIndex > last) {
  747. this.activeChipIndex = -1;
  748. this.setFocus();
  749. }
  750. else {
  751. this.activeChipIndex = newIndex;
  752. this.focusChip();
  753. }
  754. this.updateActiveItemIndex(-1);
  755. }
  756. focusChip() {
  757. var _a;
  758. const guid = (_a = this.selectedItems[this.activeChipIndex]) === null || _a === void 0 ? void 0 : _a.guid;
  759. const chip = guid
  760. ? this.referenceEl.querySelector(`#${chipUidPrefix}${guid}`)
  761. : null;
  762. chip === null || chip === void 0 ? void 0 : chip.setFocus();
  763. }
  764. shiftActiveItemIndex(delta) {
  765. const { length } = this.visibleItems;
  766. const newIndex = (this.activeItemIndex + length + delta) % length;
  767. this.updateActiveItemIndex(newIndex);
  768. this.scrollToActiveItem();
  769. }
  770. updateActiveItemIndex(index) {
  771. var _a;
  772. this.activeItemIndex = index;
  773. let activeDescendant = null;
  774. this.visibleItems.forEach((el, i) => {
  775. if (i === index) {
  776. el.active = true;
  777. activeDescendant = `${itemUidPrefix}${el.guid}`;
  778. }
  779. else {
  780. el.active = false;
  781. }
  782. });
  783. this.activeDescendant = activeDescendant;
  784. if (this.activeItemIndex > -1) {
  785. this.activeChipIndex = -1;
  786. (_a = this.textInput) === null || _a === void 0 ? void 0 : _a.focus();
  787. }
  788. }
  789. isMulti() {
  790. return this.selectionMode !== "single";
  791. }
  792. //--------------------------------------------------------------------------
  793. //
  794. // Render Methods
  795. //
  796. //--------------------------------------------------------------------------
  797. renderChips() {
  798. const { activeChipIndex, scale, selectionMode, intlRemoveTag } = this;
  799. return this.selectedItems.map((item, i) => {
  800. const chipClasses = {
  801. chip: true,
  802. "chip--active": activeChipIndex === i
  803. };
  804. const ancestors = [...getItemAncestors(item)].reverse();
  805. const pathLabel = [...ancestors, item].map((el) => el.textLabel);
  806. const label = selectionMode !== "ancestors" ? item.textLabel : pathLabel.join(" / ");
  807. return (h("calcite-chip", { class: chipClasses, dismissLabel: intlRemoveTag, dismissible: true, icon: item.icon, id: item.guid ? `${chipUidPrefix}${item.guid}` : null, key: item.textLabel, onCalciteChipDismiss: (event) => this.calciteChipDismissHandler(event, item), scale: scale, title: label, value: item.value }, label));
  808. });
  809. }
  810. renderInput() {
  811. const { guid, active, disabled, placeholder, selectionMode, selectedItems, open } = this;
  812. const single = selectionMode === "single";
  813. const selectedItem = selectedItems[0];
  814. const showLabel = !(open || active) && single && !!selectedItem;
  815. return (h("span", { class: {
  816. "input-wrap": true,
  817. "input-wrap--single": single
  818. } }, showLabel && (h("span", { class: {
  819. label: true,
  820. "label--icon": !!(selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.icon)
  821. }, key: "label" }, selectedItem.textLabel)), h("input", { "aria-activedescendant": this.activeDescendant, "aria-autocomplete": "list", "aria-controls": `${listboxUidPrefix}${guid}`, "aria-label": getLabelText(this), class: {
  822. input: true,
  823. "input--single": true,
  824. "input--transparent": this.activeChipIndex > -1,
  825. "input--hidden": showLabel,
  826. "input--icon": !!this.placeholderIcon
  827. }, disabled: disabled, id: `${inputUidPrefix}${guid}`, key: "input", onBlur: this.comboboxBlurHandler, onFocus: this.comboboxFocusHandler, onInput: this.inputHandler, placeholder: placeholder, ref: (el) => (this.textInput = el), type: "text" })));
  828. }
  829. renderListBoxOptions() {
  830. return this.visibleItems.map((item) => (h("li", { "aria-selected": toAriaBoolean(item.selected), id: item.guid ? `${itemUidPrefix}${item.guid}` : null, role: "option", tabindex: "-1" }, item.textLabel)));
  831. }
  832. renderFloatingUIContainer() {
  833. const { active, setFloatingEl, setContainerEl, open } = this;
  834. const classes = {
  835. "list-container": true,
  836. [FloatingCSS.animation]: true,
  837. [FloatingCSS.animationActive]: open || active
  838. };
  839. return (h("div", { "aria-hidden": "true", class: {
  840. "floating-ui-container": true,
  841. "floating-ui-container--active": open || active
  842. }, ref: setFloatingEl }, h("div", { class: classes, ref: setContainerEl }, h("ul", { class: { list: true, "list--hide": !(open || active) } }, h("slot", null)))));
  843. }
  844. renderIconStart() {
  845. const { selectedItems, placeholderIcon, selectionMode } = this;
  846. const selectedItem = selectedItems[0];
  847. const selectedIcon = selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.icon;
  848. const singleSelectionMode = selectionMode === "single";
  849. const iconAtStart = !this.open && selectedItem
  850. ? !!selectedIcon && singleSelectionMode
  851. : !!this.placeholderIcon && (!selectedItem || singleSelectionMode);
  852. return (iconAtStart && (h("span", { class: "icon-start" }, h("calcite-icon", { class: "selected-icon", icon: !this.open && selectedItem ? selectedIcon : placeholderIcon, scale: "s" }))));
  853. }
  854. renderIconEnd() {
  855. const { active, open } = this;
  856. return (h("span", { class: "icon-end" }, h("calcite-icon", { icon: active || open ? "chevron-up" : "chevron-down", scale: "s" })));
  857. }
  858. render() {
  859. const { active, guid, label, open } = this;
  860. const single = this.selectionMode === "single";
  861. return (h(Host, null, h("div", { "aria-autocomplete": "list", "aria-controls": `${listboxUidPrefix}${guid}`, "aria-expanded": toAriaBoolean(open || active), "aria-haspopup": "listbox", "aria-labelledby": `${labelUidPrefix}${guid}`, "aria-live": "polite", "aria-owns": `${listboxUidPrefix}${guid}`, class: {
  862. wrapper: true,
  863. "wrapper--single": single || !this.selectedItems.length,
  864. "wrapper--active": open || active
  865. }, onClick: this.clickHandler, onKeyDown: this.keydownHandler, ref: this.setReferenceEl, role: "combobox" }, h("div", { class: "grid-input" }, this.renderIconStart(), !single && this.renderChips(), h("label", { class: "screen-readers-only", htmlFor: `${inputUidPrefix}${guid}`, id: `${labelUidPrefix}${guid}` }, label), this.renderInput()), this.renderIconEnd()), h("ul", { "aria-labelledby": `${labelUidPrefix}${guid}`, "aria-multiselectable": "true", class: "screen-readers-only", id: `${listboxUidPrefix}${guid}`, role: "listbox", tabIndex: -1 }, this.renderListBoxOptions()), this.renderFloatingUIContainer(), h(HiddenFormInputSlot, { component: this })));
  866. }
  867. get el() { return getElement(this); }
  868. static get watchers() { return {
  869. "active": ["activeHandler"],
  870. "open": ["openHandler"],
  871. "disabled": ["handleDisabledChange"],
  872. "maxItems": ["maxItemsHandler"],
  873. "overlayPositioning": ["overlayPositioningHandler"],
  874. "value": ["valueHandler"],
  875. "flipPlacements": ["flipPlacementsHandler"],
  876. "selectedItems": ["selectedItemsHandler"],
  877. "text": ["textHandler"]
  878. }; }
  879. };
  880. Combobox.style = comboboxCss;
  881. const CSS$1 = {
  882. icon: "icon",
  883. iconActive: "icon--active",
  884. custom: "icon--custom",
  885. dot: "icon--dot",
  886. single: "label--single",
  887. label: "label",
  888. active: "label--active",
  889. selected: "label--selected",
  890. title: "title",
  891. textContainer: "text-container"
  892. };
  893. const comboboxItemCss = "@charset \"UTF-8\";@keyframes in{0%{opacity:0}100%{opacity:1}}@keyframes in-down{0%{opacity:0;transform:translate3D(0, -5px, 0)}100%{opacity:1;transform:translate3D(0, 0, 0)}}@keyframes in-up{0%{opacity:0;transform:translate3D(0, 5px, 0)}100%{opacity:1;transform:translate3D(0, 0, 0)}}@keyframes in-scale{0%{opacity:0;transform:scale3D(0.95, 0.95, 1)}100%{opacity:1;transform:scale3D(1, 1, 1)}}:root{--calcite-animation-timing:calc(150ms * var(--calcite-internal-duration-factor));--calcite-internal-duration-factor:var(--calcite-duration-factor, 1);--calcite-internal-animation-timing-fast:calc(100ms * var(--calcite-internal-duration-factor));--calcite-internal-animation-timing-medium:calc(200ms * var(--calcite-internal-duration-factor));--calcite-internal-animation-timing-slow:calc(300ms * var(--calcite-internal-duration-factor))}.calcite-animate{opacity:0;animation-fill-mode:both;animation-duration:var(--calcite-animation-timing)}.calcite-animate__in{animation-name:in}.calcite-animate__in-down{animation-name:in-down}.calcite-animate__in-up{animation-name:in-up}.calcite-animate__in-scale{animation-name:in-scale}@media (prefers-reduced-motion: reduce){:root{--calcite-internal-duration-factor:0.01}}:root{--calcite-floating-ui-transition:var(--calcite-animation-timing)}:host([hidden]){display:none}:host([disabled]){pointer-events:none;cursor:default;-webkit-user-select:none;user-select:none;opacity:var(--calcite-ui-opacity-disabled)}.scale--s{font-size:var(--calcite-font-size--2);line-height:1rem;--calcite-combobox-item-spacing-unit-l:0.5rem;--calcite-combobox-item-spacing-unit-s:0.25rem;--calcite-combobox-item-spacing-indent:0.5rem}.scale--m{font-size:var(--calcite-font-size--1);line-height:1rem;--calcite-combobox-item-spacing-unit-l:0.75rem;--calcite-combobox-item-spacing-unit-s:0.5rem;--calcite-combobox-item-spacing-indent:0.75rem}.scale--l{font-size:var(--calcite-font-size-0);line-height:1.25rem;--calcite-combobox-item-spacing-unit-l:1rem;--calcite-combobox-item-spacing-unit-s:0.75rem;--calcite-combobox-item-spacing-indent:1rem}.container{--calcite-combobox-item-indent-value:calc(\n var(--calcite-combobox-item-spacing-indent) * var(--calcite-combobox-item-spacing-indent-multiplier)\n )}:host(:focus){--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow)}:host([disabled]) ::slotted([calcite-hydrated][disabled]),:host([disabled]) [calcite-hydrated][disabled]{opacity:1}:host,ul{margin:0px;display:flex;flex-direction:column;padding:0px}:host(:focus),ul:focus{outline:2px solid transparent;outline-offset:2px}.label{position:relative;box-sizing:border-box;display:flex;inline-size:100%;min-inline-size:100%;cursor:pointer;align-items:center;color:var(--calcite-ui-text-3);text-decoration-line:none;transition-duration:150ms;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);outline-color:transparent;padding-block:var(--calcite-combobox-item-spacing-unit-s);padding-inline:var(--calcite-combobox-item-spacing-unit-l)}:host([disabled]) .label{cursor:default}.label--selected{font-weight:var(--calcite-font-weight-medium);color:var(--calcite-ui-text-1)}.label--active{outline:2px solid var(--calcite-ui-brand);outline-offset:-2px}.label:hover,.label:active{background-color:var(--calcite-ui-foreground-2);color:var(--calcite-ui-text-1);text-decoration-line:none;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow)}.title{padding-block:0;padding-inline:var(--calcite-combobox-item-spacing-unit-l)}.icon{display:inline-flex;opacity:0;transition-duration:150ms;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);color:var(--calcite-ui-border-1)}.icon--indent{padding-inline-start:var(--calcite-combobox-item-indent-value)}.icon--custom{margin-block-start:-1px;color:var(--calcite-ui-text-3)}.icon--active{color:var(--calcite-ui-text-1)}.icon--dot{display:flex;justify-content:flex-end;min-inline-size:var(--calcite-combobox-item-spacing-unit-l)}.icon--dot:before{text-align:start;content:\"•\"}.label--active .icon{opacity:1}.label--selected .icon{opacity:1;color:var(--calcite-ui-brand)}:host(:hover[disabled]) .icon{opacity:1}";
  894. const ComboboxItem = class {
  895. constructor(hostRef) {
  896. registerInstance(this, hostRef);
  897. this.calciteComboboxItemChange = createEvent(this, "calciteComboboxItemChange", 6);
  898. // --------------------------------------------------------------------------
  899. //
  900. // Properties
  901. //
  902. // --------------------------------------------------------------------------
  903. /** When `true`, interaction is prevented and the component is displayed with lower opacity. */
  904. this.disabled = false;
  905. /**
  906. * When `true`, the component is selected.
  907. */
  908. this.selected = false;
  909. /** When `true`, the component is active. */
  910. this.active = false;
  911. /** The `id` attribute of the component. When omitted, a globally unique identifier is used. */
  912. this.guid = guid();
  913. this.scale = "m";
  914. // --------------------------------------------------------------------------
  915. //
  916. // Private Methods
  917. //
  918. // --------------------------------------------------------------------------
  919. this.itemClickHandler = (event) => {
  920. event.preventDefault();
  921. if (this.disabled) {
  922. return;
  923. }
  924. this.selected = !this.selected;
  925. };
  926. }
  927. selectedWatchHandler() {
  928. this.calciteComboboxItemChange.emit(this.el);
  929. }
  930. // --------------------------------------------------------------------------
  931. //
  932. // Lifecycle
  933. //
  934. // --------------------------------------------------------------------------
  935. connectedCallback() {
  936. this.ancestors = getAncestors(this.el);
  937. this.scale = getElementProp(this.el, "scale", this.scale);
  938. connectConditionalSlotComponent(this);
  939. }
  940. disconnectedCallback() {
  941. disconnectConditionalSlotComponent(this);
  942. }
  943. componentDidRender() {
  944. updateHostInteraction(this);
  945. }
  946. // --------------------------------------------------------------------------
  947. //
  948. // Public Methods
  949. //
  950. // --------------------------------------------------------------------------
  951. /**
  952. * Used to toggle the selection state. By default this won't trigger an event.
  953. * The first argument allows the value to be coerced, rather than swapping values.
  954. *
  955. * @param coerce
  956. */
  957. async toggleSelected(coerce) {
  958. if (this.disabled) {
  959. return;
  960. }
  961. this.selected = typeof coerce === "boolean" ? coerce : !this.selected;
  962. }
  963. // --------------------------------------------------------------------------
  964. //
  965. // Render Methods
  966. //
  967. // --------------------------------------------------------------------------
  968. renderIcon(isSingle) {
  969. const { icon, disabled, selected } = this;
  970. const level = `${CSS$1.icon}--indent`;
  971. const defaultIcon = isSingle ? "dot" : "check";
  972. const iconPath = disabled ? "circle-disallowed" : defaultIcon;
  973. const showDot = isSingle && !icon && !disabled;
  974. return showDot ? (h("span", { class: {
  975. [CSS$1.icon]: true,
  976. [CSS$1.dot]: true,
  977. [level]: true
  978. } })) : (h("calcite-icon", { class: {
  979. [CSS$1.icon]: !icon,
  980. [CSS$1.custom]: !!icon,
  981. [CSS$1.iconActive]: icon && selected,
  982. [level]: true
  983. }, icon: icon || iconPath, scale: "s" }));
  984. }
  985. renderChildren() {
  986. if (getSlotted(this.el)) {
  987. return (h("ul", { key: "default-slot-container" }, h("slot", null)));
  988. }
  989. return null;
  990. }
  991. render() {
  992. const isSingleSelect = getElementProp(this.el, "selection-mode", "multi") === "single";
  993. const classes = {
  994. [CSS$1.label]: true,
  995. [CSS$1.selected]: this.selected,
  996. [CSS$1.active]: this.active,
  997. [CSS$1.single]: isSingleSelect
  998. };
  999. const depth = getDepth(this.el);
  1000. return (h(Host, { "aria-hidden": "true" }, h("div", { class: `container scale--${this.scale}`, style: { "--calcite-combobox-item-spacing-indent-multiplier": `${depth}` } }, h("li", { class: classes, id: this.guid, onClick: this.itemClickHandler }, this.renderIcon(isSingleSelect), h("span", { class: CSS$1.title }, this.textLabel)), this.renderChildren())));
  1001. }
  1002. get el() { return getElement(this); }
  1003. static get watchers() { return {
  1004. "selected": ["selectedWatchHandler"]
  1005. }; }
  1006. };
  1007. ComboboxItem.style = comboboxItemCss;
  1008. const CSS = {
  1009. list: "list",
  1010. label: "label",
  1011. title: "title"
  1012. };
  1013. const comboboxItemGroupCss = "@keyframes in{0%{opacity:0}100%{opacity:1}}@keyframes in-down{0%{opacity:0;transform:translate3D(0, -5px, 0)}100%{opacity:1;transform:translate3D(0, 0, 0)}}@keyframes in-up{0%{opacity:0;transform:translate3D(0, 5px, 0)}100%{opacity:1;transform:translate3D(0, 0, 0)}}@keyframes in-scale{0%{opacity:0;transform:scale3D(0.95, 0.95, 1)}100%{opacity:1;transform:scale3D(1, 1, 1)}}:root{--calcite-animation-timing:calc(150ms * var(--calcite-internal-duration-factor));--calcite-internal-duration-factor:var(--calcite-duration-factor, 1);--calcite-internal-animation-timing-fast:calc(100ms * var(--calcite-internal-duration-factor));--calcite-internal-animation-timing-medium:calc(200ms * var(--calcite-internal-duration-factor));--calcite-internal-animation-timing-slow:calc(300ms * var(--calcite-internal-duration-factor))}.calcite-animate{opacity:0;animation-fill-mode:both;animation-duration:var(--calcite-animation-timing)}.calcite-animate__in{animation-name:in}.calcite-animate__in-down{animation-name:in-down}.calcite-animate__in-up{animation-name:in-up}.calcite-animate__in-scale{animation-name:in-scale}@media (prefers-reduced-motion: reduce){:root{--calcite-internal-duration-factor:0.01}}:root{--calcite-floating-ui-transition:var(--calcite-animation-timing)}:host([hidden]){display:none}.scale--s{font-size:var(--calcite-font-size--2);line-height:1rem;--calcite-combobox-item-spacing-unit-l:0.5rem;--calcite-combobox-item-spacing-unit-s:0.25rem;--calcite-combobox-item-spacing-indent-1:0.5rem;--calcite-combobox-item-spacing-indent-2:1rem}.scale--m{font-size:var(--calcite-font-size--1);line-height:1rem;--calcite-combobox-item-spacing-unit-l:0.75rem;--calcite-combobox-item-spacing-unit-s:0.5rem;--calcite-combobox-item-spacing-indent-1:0.75rem;--calcite-combobox-item-spacing-indent-2:1.5rem}.scale--l{font-size:var(--calcite-font-size-0);line-height:1.25rem;--calcite-combobox-item-spacing-unit-l:1rem;--calcite-combobox-item-spacing-unit-s:0.75rem;--calcite-combobox-item-spacing-indent-1:1rem;--calcite-combobox-item-spacing-indent-2:2rem}:host,.list{margin:0px;display:flex;flex-direction:column;padding:0px}:host(:focus),.list:focus{outline:2px solid transparent;outline-offset:2px}.label{box-sizing:border-box;display:flex;inline-size:100%;min-inline-size:0px;max-inline-size:100%;color:var(--calcite-ui-text-3)}.label--indent-1{padding-inline-start:var(--calcite-combobox-item-spacing-indent-1)}.label--indent-2{padding-inline-start:var(--calcite-combobox-item-spacing-indent-2)}.title{border:0 solid;display:block;flex:1 1 0%;border-block-end-width:1px;font-weight:var(--calcite-font-weight-bold);color:var(--calcite-ui-text-2);word-wrap:break-word;word-break:break-word;border-block-end-color:var(--calcite-ui-border-3);padding-block:var(--calcite-combobox-item-spacing-unit-l);padding-inline:0;margin-inline:var(--calcite-combobox-item-spacing-unit-s)}";
  1014. const ComboboxItemGroup = class {
  1015. constructor(hostRef) {
  1016. registerInstance(this, hostRef);
  1017. this.guid = guid();
  1018. this.scale = "m";
  1019. }
  1020. // --------------------------------------------------------------------------
  1021. //
  1022. // Lifecycle
  1023. //
  1024. // --------------------------------------------------------------------------
  1025. connectedCallback() {
  1026. this.ancestors = getAncestors(this.el);
  1027. this.scale = getElementProp(this.el, "scale", this.scale);
  1028. }
  1029. // --------------------------------------------------------------------------
  1030. //
  1031. // Render Methods
  1032. //
  1033. // --------------------------------------------------------------------------
  1034. render() {
  1035. const { el, scale } = this;
  1036. const indent = `${CSS.label}--indent-${getDepth(el)}`;
  1037. return (h("ul", { "aria-labelledby": this.guid, class: { [CSS.list]: true, [`scale--${scale}`]: true }, role: "group" }, h("li", { class: { [CSS.label]: true, [indent]: true }, id: this.guid, role: "presentation" }, h("span", { class: CSS.title }, this.label)), h("slot", null)));
  1038. }
  1039. get el() { return getElement(this); }
  1040. };
  1041. ComboboxItemGroup.style = comboboxItemGroupCss;
  1042. export { Combobox as calcite_combobox, ComboboxItem as calcite_combobox_item, ComboboxItemGroup as calcite_combobox_item_group };