calcite-stepper.js 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  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 { proxyCustomElement, HTMLElement, createEvent, h } from '@stencil/core/internal/client/index.js';
  7. import { f as focusElement } from './dom.js';
  8. const stepperCss = "@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{position:relative;display:flex;inline-size:100%;min-inline-size:-moz-fit-content;min-inline-size:fit-content;flex-direction:row;flex-wrap:wrap;align-items:stretch;justify-content:space-between}:host([layout=vertical]){flex:1 1 auto;flex-direction:column}:host([layout=horizontal]){display:grid;grid-template-areas:\"items\" \"content\"}";
  9. const Stepper = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
  10. constructor() {
  11. super();
  12. this.__registerHost();
  13. this.__attachShadow();
  14. this.calciteStepperItemChange = createEvent(this, "calciteStepperItemChange", 6);
  15. this.calciteInternalStepperItemChange = createEvent(this, "calciteInternalStepperItemChange", 6);
  16. //--------------------------------------------------------------------------
  17. //
  18. // Public Properties
  19. //
  20. //--------------------------------------------------------------------------
  21. /** When `true`, displays a status icon in the `calcite-stepper-item` heading. */
  22. this.icon = false;
  23. /** Defines the layout of the component. */
  24. this.layout = "horizontal";
  25. /** When `true`, displays the step number in the `calcite-stepper-item` heading. */
  26. this.numbered = false;
  27. /** Specifies the size of the component. */
  28. this.scale = "m";
  29. //--------------------------------------------------------------------------
  30. //
  31. // Private State/Props
  32. //
  33. //--------------------------------------------------------------------------
  34. this.itemMap = new Map();
  35. /** list of sorted Stepper items */
  36. this.items = [];
  37. /** list of enabled Stepper items */
  38. this.enabledItems = [];
  39. }
  40. //--------------------------------------------------------------------------
  41. //
  42. // Lifecycle
  43. //
  44. //--------------------------------------------------------------------------
  45. componentDidLoad() {
  46. // if no stepper items are set as active, default to the first one
  47. if (typeof this.currentPosition !== "number") {
  48. this.calciteInternalStepperItemChange.emit({
  49. position: 0
  50. });
  51. }
  52. }
  53. render() {
  54. return (h("slot", { onSlotchange: (event) => {
  55. const items = event.currentTarget
  56. .assignedElements()
  57. .filter((el) => (el === null || el === void 0 ? void 0 : el.tagName) === "CALCITE-STEPPER-ITEM");
  58. const spacing = Array(items.length).fill("1fr").join(" ");
  59. this.el.style.gridTemplateAreas = spacing;
  60. this.el.style.gridTemplateColumns = spacing;
  61. } }));
  62. }
  63. //--------------------------------------------------------------------------
  64. //
  65. // Event Listeners
  66. //
  67. //--------------------------------------------------------------------------
  68. calciteInternalStepperItemKeyEvent(event) {
  69. const item = event.detail.item;
  70. const itemToFocus = event.target;
  71. const isFirstItem = this.itemIndex(itemToFocus) === 0;
  72. const isLastItem = this.itemIndex(itemToFocus) === this.enabledItems.length - 1;
  73. switch (item.key) {
  74. case "ArrowDown":
  75. case "ArrowRight":
  76. if (isLastItem) {
  77. this.focusFirstItem();
  78. }
  79. else {
  80. this.focusNextItem(itemToFocus);
  81. }
  82. break;
  83. case "ArrowUp":
  84. case "ArrowLeft":
  85. if (isFirstItem) {
  86. this.focusLastItem();
  87. }
  88. else {
  89. this.focusPrevItem(itemToFocus);
  90. }
  91. break;
  92. case "Home":
  93. this.focusFirstItem();
  94. break;
  95. case "End":
  96. this.focusLastItem();
  97. break;
  98. }
  99. event.stopPropagation();
  100. }
  101. registerItem(event) {
  102. const item = event.target;
  103. const { content, position } = event.detail;
  104. this.itemMap.set(item, { position, content });
  105. this.items = this.sortItems();
  106. this.enabledItems = this.filterItems();
  107. event.stopPropagation();
  108. }
  109. updateItem(event) {
  110. const { position } = event.detail;
  111. if (typeof position === "number") {
  112. this.currentPosition = position;
  113. }
  114. this.calciteInternalStepperItemChange.emit({
  115. position
  116. });
  117. }
  118. handleUserRequestedStepperItemSelect(event) {
  119. const { position } = event.detail;
  120. this.calciteStepperItemChange.emit({
  121. position
  122. });
  123. }
  124. //--------------------------------------------------------------------------
  125. //
  126. // Public Methods
  127. //
  128. //--------------------------------------------------------------------------
  129. /** Set the next `calcite-stepper-item` as active. */
  130. async nextStep() {
  131. const enabledStepIndex = this.getEnabledStepIndex(this.currentPosition + 1, "next");
  132. if (typeof enabledStepIndex !== "number") {
  133. return;
  134. }
  135. this.updateStep(enabledStepIndex);
  136. }
  137. /** Set the previous `calcite-stepper-item` as active. */
  138. async prevStep() {
  139. const enabledStepIndex = this.getEnabledStepIndex(this.currentPosition - 1, "previous");
  140. if (typeof enabledStepIndex !== "number") {
  141. return;
  142. }
  143. this.updateStep(enabledStepIndex);
  144. }
  145. /**
  146. * Set a specified `calcite-stepper-item` as active.
  147. *
  148. * @param step
  149. */
  150. async goToStep(step) {
  151. const position = step - 1;
  152. if (this.currentPosition !== position) {
  153. this.updateStep(position);
  154. }
  155. }
  156. /** Set the first `calcite-stepper-item` as active. */
  157. async startStep() {
  158. const enabledStepIndex = this.getEnabledStepIndex(0, "next");
  159. if (typeof enabledStepIndex !== "number") {
  160. return;
  161. }
  162. this.updateStep(enabledStepIndex);
  163. }
  164. /** Set the last `calcite-stepper-item` as active. */
  165. async endStep() {
  166. const enabledStepIndex = this.getEnabledStepIndex(this.items.length - 1, "previous");
  167. if (typeof enabledStepIndex !== "number") {
  168. return;
  169. }
  170. this.updateStep(enabledStepIndex);
  171. }
  172. //--------------------------------------------------------------------------
  173. //
  174. // Private Methods
  175. //
  176. //--------------------------------------------------------------------------
  177. getEnabledStepIndex(startIndex, direction = "next") {
  178. var _a;
  179. const { items, currentPosition } = this;
  180. let newIndex = startIndex;
  181. while ((_a = items[newIndex]) === null || _a === void 0 ? void 0 : _a.disabled) {
  182. newIndex = newIndex + (direction === "previous" ? -1 : 1);
  183. }
  184. return newIndex !== currentPosition && newIndex < items.length && newIndex >= 0
  185. ? newIndex
  186. : null;
  187. }
  188. updateStep(position) {
  189. this.currentPosition = position;
  190. this.calciteInternalStepperItemChange.emit({
  191. position
  192. });
  193. }
  194. focusFirstItem() {
  195. const firstItem = this.enabledItems[0];
  196. focusElement(firstItem);
  197. }
  198. focusLastItem() {
  199. const lastItem = this.enabledItems[this.enabledItems.length - 1];
  200. focusElement(lastItem);
  201. }
  202. focusNextItem(el) {
  203. const index = this.itemIndex(el);
  204. const nextItem = this.enabledItems[index + 1] || this.enabledItems[0];
  205. focusElement(nextItem);
  206. }
  207. focusPrevItem(el) {
  208. const index = this.itemIndex(el);
  209. const prevItem = this.enabledItems[index - 1] || this.enabledItems[this.enabledItems.length - 1];
  210. focusElement(prevItem);
  211. }
  212. itemIndex(el) {
  213. return this.enabledItems.indexOf(el);
  214. }
  215. sortItems() {
  216. const { itemMap } = this;
  217. return Array.from(itemMap.keys()).sort((a, b) => itemMap.get(a).position - itemMap.get(b).position);
  218. }
  219. filterItems() {
  220. return this.items.filter((item) => !item.disabled);
  221. }
  222. get el() { return this; }
  223. static get style() { return stepperCss; }
  224. }, [1, "calcite-stepper", {
  225. "icon": [516],
  226. "layout": [513],
  227. "numbered": [516],
  228. "numberingSystem": [513, "numbering-system"],
  229. "scale": [513],
  230. "nextStep": [64],
  231. "prevStep": [64],
  232. "goToStep": [64],
  233. "startStep": [64],
  234. "endStep": [64]
  235. }, [[0, "calciteInternalStepperItemKeyEvent", "calciteInternalStepperItemKeyEvent"], [0, "calciteInternalStepperItemRegister", "registerItem"], [0, "calciteInternalStepperItemSelect", "updateItem"], [0, "calciteInternalUserRequestedStepperItemSelect", "handleUserRequestedStepperItemSelect"]]]);
  236. function defineCustomElement$1() {
  237. if (typeof customElements === "undefined") {
  238. return;
  239. }
  240. const components = ["calcite-stepper"];
  241. components.forEach(tagName => { switch (tagName) {
  242. case "calcite-stepper":
  243. if (!customElements.get(tagName)) {
  244. customElements.define(tagName, Stepper);
  245. }
  246. break;
  247. } });
  248. }
  249. defineCustomElement$1();
  250. const CalciteStepper = Stepper;
  251. const defineCustomElement = defineCustomElement$1;
  252. export { CalciteStepper, defineCustomElement };