resources-684ec2e5.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  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. 'use strict';
  7. const dom = require('./dom-9ac0341c.js');
  8. const array = require('./array-f1fe66d8.js');
  9. const debounce = require('./debounce-94d2834e.js');
  10. const index = require('./index-5c65e149.js');
  11. const CSS$2 = {
  12. heading: "heading",
  13. container: "container",
  14. indented: "container--indented"
  15. };
  16. const SLOTS$2 = {
  17. parentItem: "parent-item"
  18. };
  19. const HEADING_LEVEL = 3;
  20. function mutationObserverCallback() {
  21. this.setUpItems();
  22. this.setUpFilter();
  23. this.deselectRemovedItems();
  24. }
  25. const SUPPORTED_ARROW_KEYS = ["ArrowUp", "ArrowDown"];
  26. // --------------------------------------------------------------------------
  27. //
  28. // Lifecycle
  29. //
  30. // --------------------------------------------------------------------------
  31. function initialize() {
  32. this.setUpItems();
  33. this.setUpFilter();
  34. this.emitCalciteListChange = debounce.debounce(internalCalciteListChangeEvent.bind(this), 0);
  35. }
  36. function initializeObserver() {
  37. var _a;
  38. (_a = this.mutationObserver) === null || _a === void 0 ? void 0 : _a.observe(this.el, { childList: true, subtree: true });
  39. }
  40. function cleanUpObserver() {
  41. var _a;
  42. (_a = this.mutationObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
  43. }
  44. // --------------------------------------------------------------------------
  45. //
  46. // Listeners
  47. //
  48. // --------------------------------------------------------------------------
  49. function calciteListItemChangeHandler(event) {
  50. const { selectedValues } = this;
  51. const { item, value, selected, shiftPressed } = event.detail;
  52. if (selected) {
  53. if (this.multiple && shiftPressed) {
  54. this.selectSiblings(item);
  55. }
  56. if (!this.multiple) {
  57. this.deselectSiblingItems(item);
  58. }
  59. selectedValues.set(value, item);
  60. }
  61. else {
  62. selectedValues.delete(value);
  63. if (this.multiple && shiftPressed) {
  64. this.selectSiblings(item, true);
  65. }
  66. }
  67. if (!this.multiple) {
  68. toggleSingleSelectItemTabbing(item, selected);
  69. if (selected) {
  70. dom.focusElement(item);
  71. }
  72. }
  73. this.lastSelectedItem = item;
  74. this.emitCalciteListChange();
  75. }
  76. function calciteListItemValueChangeHandler(event) {
  77. event.stopPropagation();
  78. const oldValue = event.detail.oldValue;
  79. const selectedValues = this.selectedValues;
  80. if (selectedValues.has(oldValue)) {
  81. const item = selectedValues.get(oldValue);
  82. selectedValues.delete(oldValue);
  83. selectedValues.set(event.detail.newValue, item);
  84. }
  85. }
  86. // --------------------------------------------------------------------------
  87. //
  88. // Private Methods
  89. //
  90. // --------------------------------------------------------------------------
  91. function isValidNavigationKey(key) {
  92. return !!SUPPORTED_ARROW_KEYS.find((k) => k === key);
  93. }
  94. function calciteListFocusOutHandler(event) {
  95. const { el, items, multiple, selectedValues } = this;
  96. if (multiple) {
  97. return;
  98. }
  99. const focusedInside = el.contains(event.relatedTarget);
  100. if (focusedInside) {
  101. return;
  102. }
  103. filterOutDisabled(items).forEach((item) => {
  104. toggleSingleSelectItemTabbing(item, selectedValues.size === 0 ? item.contains(event.target) || event.target === item : item.selected);
  105. });
  106. }
  107. function keyDownHandler(event) {
  108. const { key, target } = event;
  109. if (!isValidNavigationKey(key)) {
  110. return;
  111. }
  112. const { items, multiple, selectionFollowsFocus } = this;
  113. const { length: totalItems } = items;
  114. const currentIndex = items.indexOf(target);
  115. if (!totalItems || currentIndex === -1) {
  116. return;
  117. }
  118. event.preventDefault();
  119. const index = moveItemIndex(this, target, key === "ArrowUp" ? "up" : "down");
  120. const item = items[index];
  121. items.forEach((i) => toggleSingleSelectItemTabbing(i, i === item));
  122. if (!multiple && selectionFollowsFocus) {
  123. item.selected = true;
  124. }
  125. dom.focusElement(item);
  126. }
  127. function moveItemIndex(list, item, direction) {
  128. const { items } = list;
  129. const { length: totalItems } = items;
  130. const currentIndex = items.indexOf(item);
  131. const directionFactor = direction === "up" ? -1 : 1;
  132. let moveOffset = 1;
  133. let index = array.getRoundRobinIndex(currentIndex + directionFactor * moveOffset++, totalItems);
  134. const firstMovedIndex = index;
  135. while (items[index].disabled) {
  136. index = array.getRoundRobinIndex(currentIndex + directionFactor * moveOffset++, totalItems);
  137. if (index === firstMovedIndex) {
  138. break;
  139. }
  140. }
  141. return index;
  142. }
  143. function filterOutDisabled(items) {
  144. return items.filter((item) => !item.disabled);
  145. }
  146. function internalCalciteListChangeEvent() {
  147. this.calciteListChange.emit(this.selectedValues);
  148. }
  149. function removeItem(event) {
  150. if (event.defaultPrevented) {
  151. return;
  152. }
  153. const item = event.target;
  154. const selectedValues = this.selectedValues;
  155. if (item.parentElement.tagName === "CALCITE-PICK-LIST-GROUP" && item.slot === SLOTS$2.parentItem) {
  156. item.parentElement.remove();
  157. Array.from(item.parentElement.children).forEach((item) => selectedValues.delete(item.value));
  158. }
  159. else {
  160. item.remove();
  161. selectedValues.delete(item.value);
  162. }
  163. this.emitCalciteListChange();
  164. }
  165. function toggleSingleSelectItemTabbing(item, selectable) {
  166. if (item.disabled) {
  167. return;
  168. }
  169. // using attribute intentionally
  170. if (selectable) {
  171. item.removeAttribute("tabindex");
  172. }
  173. else {
  174. item.setAttribute("tabindex", "-1");
  175. }
  176. }
  177. async function setFocus(focusId) {
  178. var _a;
  179. if (this.filterEnabled && focusId === "filter") {
  180. await dom.focusElement(this.filterEl);
  181. return;
  182. }
  183. const { items, multiple, selectionFollowsFocus } = this;
  184. if (items.length === 0) {
  185. return;
  186. }
  187. if (multiple) {
  188. return (_a = filterOutDisabled(items)[0]) === null || _a === void 0 ? void 0 : _a.setFocus();
  189. }
  190. const filtered = filterOutDisabled(items);
  191. const focusTarget = filtered.find((item) => item.selected) || filtered[0];
  192. if (selectionFollowsFocus && focusTarget) {
  193. focusTarget.selected = true;
  194. }
  195. return focusTarget.setFocus();
  196. }
  197. function setUpItems(tagName) {
  198. this.items = Array.from(this.el.querySelectorAll(tagName));
  199. let hasSelected = false;
  200. const { items } = this;
  201. items.forEach((item) => {
  202. item.icon = this.getIconType();
  203. if (!this.multiple) {
  204. item.disableDeselect = true;
  205. toggleSingleSelectItemTabbing(item, false);
  206. }
  207. if (item.selected) {
  208. hasSelected = true;
  209. toggleSingleSelectItemTabbing(item, true);
  210. this.selectedValues.set(item.value, item);
  211. }
  212. });
  213. const [first] = items;
  214. if (!hasSelected && first && !first.disabled) {
  215. toggleSingleSelectItemTabbing(first, true);
  216. }
  217. }
  218. function deselectRemovedItems() {
  219. const selectedValues = this.selectedValues;
  220. const itemValues = this.items.map(({ value }) => value);
  221. selectedValues.forEach((selectedItem) => {
  222. if (!itemValues.includes(selectedItem.value)) {
  223. this.selectedValues.delete(selectedItem.value);
  224. }
  225. });
  226. }
  227. function deselectSiblingItems(item) {
  228. this.items.forEach((currentItem) => {
  229. if (currentItem.value !== item.value) {
  230. currentItem.toggleSelected(false);
  231. if (this.selectedValues.has(currentItem.value)) {
  232. this.selectedValues.delete(currentItem.value);
  233. }
  234. }
  235. });
  236. }
  237. function selectSiblings(item, deselect = false) {
  238. if (!this.lastSelectedItem) {
  239. return;
  240. }
  241. const { items } = this;
  242. const start = items.findIndex((currentItem) => {
  243. return currentItem.value === this.lastSelectedItem.value;
  244. });
  245. const end = items.findIndex((currentItem) => {
  246. return currentItem.value === item.value;
  247. });
  248. items.slice(Math.min(start, end), Math.max(start, end)).forEach((currentItem) => {
  249. currentItem.toggleSelected(!deselect);
  250. if (!deselect) {
  251. this.selectedValues.set(currentItem.value, currentItem);
  252. }
  253. else {
  254. this.selectedValues.delete(currentItem.value);
  255. }
  256. });
  257. }
  258. let groups;
  259. function handleFilter(event) {
  260. const { filteredItems } = event.currentTarget;
  261. const values = filteredItems.map((item) => item.value);
  262. let hasSelectedMatch = false;
  263. if (!groups) {
  264. groups = new Set();
  265. }
  266. const matchedItems = this.items.filter((item) => {
  267. const parent = item.parentElement;
  268. const grouped = parent.matches("calcite-pick-list-group");
  269. if (grouped) {
  270. groups.add(parent);
  271. }
  272. const matches = values.includes(item.value);
  273. item.hidden = !matches;
  274. if (!hasSelectedMatch) {
  275. hasSelectedMatch = matches && item.selected;
  276. }
  277. return matches;
  278. });
  279. groups.forEach((group) => {
  280. const hasAtLeastOneMatch = matchedItems.some((item) => group.contains(item));
  281. group.hidden = !hasAtLeastOneMatch;
  282. if (!hasAtLeastOneMatch) {
  283. return;
  284. }
  285. const parentItem = dom.getSlotted(group, "parent-item");
  286. if (parentItem) {
  287. parentItem.hidden = false;
  288. if (matchedItems.includes(parentItem)) {
  289. Array.from(group.children).forEach((child) => (child.hidden = false));
  290. }
  291. }
  292. });
  293. groups.clear();
  294. if (matchedItems.length > 0 && !hasSelectedMatch && !this.multiple) {
  295. toggleSingleSelectItemTabbing(matchedItems[0], true);
  296. }
  297. }
  298. function getItemData() {
  299. return this.items.map((item) => ({
  300. label: item.label,
  301. description: item.description,
  302. metadata: item.metadata,
  303. value: item.value
  304. }));
  305. }
  306. const CSS$1 = {
  307. sticky: "sticky-pos"
  308. };
  309. exports.ICON_TYPES = void 0;
  310. (function (ICON_TYPES) {
  311. ICON_TYPES["circle"] = "circle";
  312. ICON_TYPES["square"] = "square";
  313. ICON_TYPES["grip"] = "grip";
  314. })(exports.ICON_TYPES || (exports.ICON_TYPES = {}));
  315. const SLOTS$1 = {
  316. menuActions: "menu-actions"
  317. };
  318. var __rest = (undefined && undefined.__rest) || function (s, e) {
  319. var t = {};
  320. for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
  321. t[p] = s[p];
  322. if (s != null && typeof Object.getOwnPropertySymbols === "function")
  323. for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
  324. if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
  325. t[p[i]] = s[p[i]];
  326. }
  327. return t;
  328. };
  329. const List = (_a) => {
  330. var { props: { disabled, loading, filterEnabled, dataForFilter, handleFilter, filterPlaceholder, setFilterEl } } = _a, rest = __rest(_a, ["props"]);
  331. const defaultSlot = index.h("slot", null);
  332. return (index.h(index.Host, Object.assign({ "aria-busy": dom.toAriaBoolean(loading), role: "menu" }, rest),
  333. index.h("section", null,
  334. index.h("header", { class: { [CSS$1.sticky]: true } },
  335. filterEnabled ? (index.h("calcite-filter", { "aria-label": filterPlaceholder, disabled: loading || disabled, items: dataForFilter, onCalciteFilterChange: handleFilter, placeholder: filterPlaceholder, ref: setFilterEl })) : null,
  336. index.h("slot", { name: SLOTS$1.menuActions })),
  337. loading ? index.h("calcite-scrim", { loading: loading }) : null,
  338. defaultSlot)));
  339. };
  340. const CSS = {
  341. actions: "actions",
  342. actionsEnd: "actions--end",
  343. actionsStart: "actions--start",
  344. description: "description",
  345. handle: "handle",
  346. handleActivated: "handle--activated",
  347. highlight: "highlight",
  348. icon: "icon",
  349. iconDot: "icon-dot",
  350. label: "label",
  351. remove: "remove",
  352. title: "title",
  353. textContainer: "text-container"
  354. };
  355. const ICONS = {
  356. checked: "check",
  357. remove: "x"
  358. };
  359. const SLOTS = {
  360. actionsEnd: "actions-end",
  361. actionsStart: "actions-start"
  362. };
  363. const TEXT = {
  364. remove: "Remove"
  365. };
  366. exports.CSS = CSS;
  367. exports.CSS$1 = CSS$2;
  368. exports.HEADING_LEVEL = HEADING_LEVEL;
  369. exports.ICONS = ICONS;
  370. exports.List = List;
  371. exports.SLOTS = SLOTS;
  372. exports.SLOTS$1 = SLOTS$2;
  373. exports.TEXT = TEXT;
  374. exports.calciteListFocusOutHandler = calciteListFocusOutHandler;
  375. exports.calciteListItemChangeHandler = calciteListItemChangeHandler;
  376. exports.calciteListItemValueChangeHandler = calciteListItemValueChangeHandler;
  377. exports.cleanUpObserver = cleanUpObserver;
  378. exports.deselectRemovedItems = deselectRemovedItems;
  379. exports.deselectSiblingItems = deselectSiblingItems;
  380. exports.getItemData = getItemData;
  381. exports.handleFilter = handleFilter;
  382. exports.initialize = initialize;
  383. exports.initializeObserver = initializeObserver;
  384. exports.keyDownHandler = keyDownHandler;
  385. exports.moveItemIndex = moveItemIndex;
  386. exports.mutationObserverCallback = mutationObserverCallback;
  387. exports.removeItem = removeItem;
  388. exports.selectSiblings = selectSiblings;
  389. exports.setFocus = setFocus;
  390. exports.setUpItems = setUpItems;