calcite-combobox_3.entry.js 57 KB

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