flow.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  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 { h } from "@stencil/core";
  7. import { CSS } from "./resources";
  8. import { createObserver } from "../../utils/observers";
  9. /**
  10. * @slot - A slot for adding `calcite-flow-item` or `calcite-panel`s (deprecated) to the flow.
  11. */
  12. export class Flow {
  13. constructor() {
  14. this.flowDirection = null;
  15. this.itemCount = 0;
  16. this.items = [];
  17. this.itemMutationObserver = createObserver("mutation", () => this.updateFlowProps());
  18. this.getFlowDirection = (oldFlowItemCount, newFlowItemCount) => {
  19. const allowRetreatingDirection = oldFlowItemCount > 1;
  20. const allowAdvancingDirection = oldFlowItemCount && newFlowItemCount > 1;
  21. if (!allowAdvancingDirection && !allowRetreatingDirection) {
  22. return null;
  23. }
  24. return newFlowItemCount < oldFlowItemCount ? "retreating" : "advancing";
  25. };
  26. this.updateFlowProps = () => {
  27. const { el, items } = this;
  28. const newItems = Array.from(el.querySelectorAll("calcite-flow-item, calcite-panel")).filter((flowItem) => !flowItem.matches("calcite-flow-item calcite-flow-item, calcite-panel calcite-panel"));
  29. const oldItemCount = items.length;
  30. const newItemCount = newItems.length;
  31. const activeItem = newItems[newItemCount - 1];
  32. const previousItem = newItems[newItemCount - 2];
  33. if (newItemCount && activeItem) {
  34. newItems.forEach((itemNode) => {
  35. itemNode.showBackButton = itemNode === activeItem && newItemCount > 1;
  36. itemNode.hidden = itemNode !== activeItem;
  37. });
  38. }
  39. if (previousItem) {
  40. previousItem.menuOpen = false;
  41. }
  42. this.items = newItems;
  43. if (oldItemCount !== newItemCount) {
  44. const flowDirection = this.getFlowDirection(oldItemCount, newItemCount);
  45. this.itemCount = newItemCount;
  46. this.flowDirection = flowDirection;
  47. }
  48. };
  49. }
  50. // --------------------------------------------------------------------------
  51. //
  52. // Public Methods
  53. //
  54. // --------------------------------------------------------------------------
  55. /**
  56. * Removes the currently active `calcite-flow-item` or `calcite-panel`.
  57. */
  58. async back() {
  59. const { items } = this;
  60. const lastItem = items[items.length - 1];
  61. if (!lastItem) {
  62. return;
  63. }
  64. const beforeBack = lastItem.beforeBack
  65. ? lastItem.beforeBack
  66. : () => Promise.resolve();
  67. return beforeBack.call(lastItem).then(() => {
  68. lastItem.remove();
  69. return lastItem;
  70. });
  71. }
  72. // --------------------------------------------------------------------------
  73. //
  74. // Lifecycle
  75. //
  76. // --------------------------------------------------------------------------
  77. connectedCallback() {
  78. var _a;
  79. (_a = this.itemMutationObserver) === null || _a === void 0 ? void 0 : _a.observe(this.el, { childList: true, subtree: true });
  80. this.updateFlowProps();
  81. }
  82. disconnectedCallback() {
  83. var _a;
  84. (_a = this.itemMutationObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
  85. }
  86. // --------------------------------------------------------------------------
  87. //
  88. // Private Methods
  89. //
  90. // --------------------------------------------------------------------------
  91. handleItemBackClick() {
  92. this.back();
  93. }
  94. // --------------------------------------------------------------------------
  95. //
  96. // Render Methods
  97. //
  98. // --------------------------------------------------------------------------
  99. render() {
  100. const { flowDirection } = this;
  101. const frameDirectionClasses = {
  102. [CSS.frame]: true,
  103. [CSS.frameAdvancing]: flowDirection === "advancing",
  104. [CSS.frameRetreating]: flowDirection === "retreating"
  105. };
  106. return (h("div", { class: frameDirectionClasses }, h("slot", null)));
  107. }
  108. static get is() { return "calcite-flow"; }
  109. static get encapsulation() { return "shadow"; }
  110. static get originalStyleUrls() {
  111. return {
  112. "$": ["flow.scss"]
  113. };
  114. }
  115. static get styleUrls() {
  116. return {
  117. "$": ["flow.css"]
  118. };
  119. }
  120. static get states() {
  121. return {
  122. "flowDirection": {},
  123. "itemCount": {},
  124. "items": {}
  125. };
  126. }
  127. static get methods() {
  128. return {
  129. "back": {
  130. "complexType": {
  131. "signature": "() => Promise<HTMLCalciteFlowItemElement>",
  132. "parameters": [],
  133. "references": {
  134. "Promise": {
  135. "location": "global"
  136. },
  137. "HTMLCalciteFlowItemElement": {
  138. "location": "global"
  139. }
  140. },
  141. "return": "Promise<HTMLCalciteFlowItemElement>"
  142. },
  143. "docs": {
  144. "text": "Removes the currently active `calcite-flow-item` or `calcite-panel`.",
  145. "tags": []
  146. }
  147. }
  148. };
  149. }
  150. static get elementRef() { return "el"; }
  151. static get listeners() {
  152. return [{
  153. "name": "calciteFlowItemBackClick",
  154. "method": "handleItemBackClick",
  155. "target": undefined,
  156. "capture": false,
  157. "passive": false
  158. }, {
  159. "name": "calcitePanelBackClick",
  160. "method": "handleItemBackClick",
  161. "target": undefined,
  162. "capture": false,
  163. "passive": false
  164. }];
  165. }
  166. }