stepper-item.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640
  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, Host } from "@stencil/core";
  7. import { getElementProp, toAriaBoolean } from "../../utils/dom";
  8. import { updateHostInteraction } from "../../utils/interactive";
  9. import { numberStringFormatter, disconnectLocalized, connectLocalized } from "../../utils/locale";
  10. /**
  11. * @slot - A slot for adding custom content.
  12. */
  13. export class StepperItem {
  14. constructor() {
  15. //--------------------------------------------------------------------------
  16. //
  17. // Public Properties
  18. //
  19. //--------------------------------------------------------------------------
  20. /**
  21. * When `true`, the component is selected.
  22. *
  23. * @deprecated Use `selected` instead.
  24. */
  25. this.active = false;
  26. /**
  27. * When `true`, the component is selected.
  28. */
  29. this.selected = false;
  30. /** When `true`, the step has been completed. */
  31. this.complete = false;
  32. /** When `true`, the component contains an error that requires resolution from the user. */
  33. this.error = false;
  34. /** When `true`, interaction is prevented and the component is displayed with lower opacity. */
  35. this.disabled = false;
  36. // internal props inherited from wrapping calcite-stepper
  37. /** Defines the layout of the component. */
  38. /** @internal */
  39. this.layout = "horizontal";
  40. /** When `true`, displays a status icon in the component's heading. */
  41. /** @internal */
  42. this.icon = false;
  43. /** When `true`, displays the step number in the component's heading. */
  44. /** @internal */
  45. this.numbered = false;
  46. /** Specifies the size of the component. */
  47. /** @internal */
  48. this.scale = "m";
  49. //--------------------------------------------------------------------------
  50. //
  51. // Internal State/Props
  52. //
  53. //--------------------------------------------------------------------------
  54. this.effectiveLocale = "";
  55. //--------------------------------------------------------------------------
  56. //
  57. // Private Methods
  58. //
  59. //--------------------------------------------------------------------------
  60. this.keyDownHandler = (event) => {
  61. if (!this.disabled && event.target === this.el) {
  62. switch (event.key) {
  63. case " ":
  64. case "Enter":
  65. this.emitUserRequestedItem();
  66. event.preventDefault();
  67. break;
  68. case "ArrowUp":
  69. case "ArrowDown":
  70. case "ArrowLeft":
  71. case "ArrowRight":
  72. case "Home":
  73. case "End":
  74. this.calciteInternalStepperItemKeyEvent.emit({ item: event });
  75. event.preventDefault();
  76. break;
  77. }
  78. }
  79. };
  80. this.handleItemClick = (event) => {
  81. if (this.layout === "horizontal" &&
  82. event
  83. .composedPath()
  84. .some((el) => { var _a; return (_a = el.classList) === null || _a === void 0 ? void 0 : _a.contains("stepper-item-content"); })) {
  85. return;
  86. }
  87. this.emitUserRequestedItem();
  88. };
  89. this.emitUserRequestedItem = () => {
  90. this.emitRequestedItem();
  91. if (!this.disabled) {
  92. const position = this.itemPosition;
  93. this.calciteInternalUserRequestedStepperItemSelect.emit({
  94. position
  95. });
  96. }
  97. };
  98. this.emitRequestedItem = () => {
  99. if (!this.disabled) {
  100. const position = this.itemPosition;
  101. this.calciteInternalStepperItemSelect.emit({
  102. position
  103. });
  104. }
  105. };
  106. }
  107. activeHandler(value) {
  108. this.selected = value;
  109. }
  110. selectedHandler(value) {
  111. this.active = value;
  112. if (this.selected) {
  113. this.emitRequestedItem();
  114. }
  115. }
  116. // watch for removal of disabled to register step
  117. disabledWatcher() {
  118. this.registerStepperItem();
  119. }
  120. effectiveLocaleWatcher(locale) {
  121. var _a;
  122. numberStringFormatter.numberFormatOptions = {
  123. locale,
  124. numberingSystem: (_a = this.parentStepperEl) === null || _a === void 0 ? void 0 : _a.numberingSystem,
  125. useGrouping: false
  126. };
  127. }
  128. //--------------------------------------------------------------------------
  129. //
  130. // Lifecycle
  131. //
  132. //--------------------------------------------------------------------------
  133. connectedCallback() {
  134. connectLocalized(this);
  135. const { selected, active } = this;
  136. if (selected) {
  137. this.active = selected;
  138. }
  139. else if (active) {
  140. this.selected = active;
  141. }
  142. }
  143. componentWillLoad() {
  144. var _a;
  145. this.icon = getElementProp(this.el, "icon", false);
  146. this.numbered = getElementProp(this.el, "numbered", false);
  147. this.layout = getElementProp(this.el, "layout", false);
  148. this.scale = getElementProp(this.el, "scale", "m");
  149. this.parentStepperEl = this.el.parentElement;
  150. this.itemPosition = this.getItemPosition();
  151. this.registerStepperItem();
  152. if (this.selected) {
  153. this.emitRequestedItem();
  154. }
  155. numberStringFormatter.numberFormatOptions = {
  156. locale: this.effectiveLocale,
  157. numberingSystem: (_a = this.parentStepperEl) === null || _a === void 0 ? void 0 : _a.numberingSystem,
  158. useGrouping: false
  159. };
  160. }
  161. componentDidRender() {
  162. updateHostInteraction(this, true);
  163. }
  164. disconnectedCallback() {
  165. disconnectLocalized(this);
  166. }
  167. render() {
  168. return (h(Host, { "aria-expanded": toAriaBoolean(this.active), onClick: this.handleItemClick, onKeyDown: this.keyDownHandler }, h("div", { class: "container" }, h("div", { class: "stepper-item-header", ref: (el) => (this.headerEl = el), tabIndex:
  169. /* additional tab index logic needed because of display: contents */
  170. this.layout === "horizontal" && !this.disabled ? 0 : null }, this.icon ? this.renderIcon() : null, this.numbered ? (h("div", { class: "stepper-item-number" }, numberStringFormatter.numberFormatter.format(this.itemPosition + 1), ".")) : null, h("div", { class: "stepper-item-header-text" }, h("span", { class: "stepper-item-heading" }, this.heading || this.itemTitle), h("span", { class: "stepper-item-description" }, this.description || this.itemSubtitle))), h("div", { class: "stepper-item-content" }, h("slot", null)))));
  171. }
  172. //--------------------------------------------------------------------------
  173. //
  174. // Event Listeners
  175. //
  176. //--------------------------------------------------------------------------
  177. updateActiveItemOnChange(event) {
  178. if (event.target === this.parentStepperEl ||
  179. event.composedPath().includes(this.parentStepperEl)) {
  180. this.selectedPosition = event.detail.position;
  181. this.determineSelectedItem();
  182. }
  183. }
  184. //--------------------------------------------------------------------------
  185. //
  186. // Public Methods
  187. //
  188. //--------------------------------------------------------------------------
  189. async setFocus() {
  190. var _a;
  191. (_a = (this.layout === "vertical" ? this.el : this.headerEl)) === null || _a === void 0 ? void 0 : _a.focus();
  192. }
  193. renderIcon() {
  194. const path = this.selected
  195. ? "circleF"
  196. : this.error
  197. ? "exclamationMarkCircleF"
  198. : this.complete
  199. ? "checkCircleF"
  200. : "circle";
  201. return h("calcite-icon", { class: "stepper-item-icon", icon: path, scale: "s" });
  202. }
  203. determineSelectedItem() {
  204. this.selected = !this.disabled && this.itemPosition === this.selectedPosition;
  205. }
  206. registerStepperItem() {
  207. this.calciteInternalStepperItemRegister.emit({
  208. position: this.itemPosition
  209. });
  210. }
  211. getItemPosition() {
  212. var _a;
  213. return Array.from((_a = this.parentStepperEl) === null || _a === void 0 ? void 0 : _a.querySelectorAll("calcite-stepper-item")).indexOf(this.el);
  214. }
  215. static get is() { return "calcite-stepper-item"; }
  216. static get encapsulation() { return "shadow"; }
  217. static get originalStyleUrls() {
  218. return {
  219. "$": ["stepper-item.scss"]
  220. };
  221. }
  222. static get styleUrls() {
  223. return {
  224. "$": ["stepper-item.css"]
  225. };
  226. }
  227. static get properties() {
  228. return {
  229. "active": {
  230. "type": "boolean",
  231. "mutable": true,
  232. "complexType": {
  233. "original": "boolean",
  234. "resolved": "boolean",
  235. "references": {}
  236. },
  237. "required": false,
  238. "optional": false,
  239. "docs": {
  240. "tags": [{
  241. "name": "deprecated",
  242. "text": "Use `selected` instead."
  243. }],
  244. "text": "When `true`, the component is selected."
  245. },
  246. "attribute": "active",
  247. "reflect": true,
  248. "defaultValue": "false"
  249. },
  250. "selected": {
  251. "type": "boolean",
  252. "mutable": true,
  253. "complexType": {
  254. "original": "boolean",
  255. "resolved": "boolean",
  256. "references": {}
  257. },
  258. "required": false,
  259. "optional": false,
  260. "docs": {
  261. "tags": [],
  262. "text": "When `true`, the component is selected."
  263. },
  264. "attribute": "selected",
  265. "reflect": true,
  266. "defaultValue": "false"
  267. },
  268. "complete": {
  269. "type": "boolean",
  270. "mutable": false,
  271. "complexType": {
  272. "original": "boolean",
  273. "resolved": "boolean",
  274. "references": {}
  275. },
  276. "required": false,
  277. "optional": false,
  278. "docs": {
  279. "tags": [],
  280. "text": "When `true`, the step has been completed."
  281. },
  282. "attribute": "complete",
  283. "reflect": true,
  284. "defaultValue": "false"
  285. },
  286. "error": {
  287. "type": "boolean",
  288. "mutable": false,
  289. "complexType": {
  290. "original": "boolean",
  291. "resolved": "boolean",
  292. "references": {}
  293. },
  294. "required": false,
  295. "optional": false,
  296. "docs": {
  297. "tags": [],
  298. "text": "When `true`, the component contains an error that requires resolution from the user."
  299. },
  300. "attribute": "error",
  301. "reflect": true,
  302. "defaultValue": "false"
  303. },
  304. "disabled": {
  305. "type": "boolean",
  306. "mutable": false,
  307. "complexType": {
  308. "original": "boolean",
  309. "resolved": "boolean",
  310. "references": {}
  311. },
  312. "required": false,
  313. "optional": false,
  314. "docs": {
  315. "tags": [],
  316. "text": "When `true`, interaction is prevented and the component is displayed with lower opacity."
  317. },
  318. "attribute": "disabled",
  319. "reflect": true,
  320. "defaultValue": "false"
  321. },
  322. "itemTitle": {
  323. "type": "string",
  324. "mutable": false,
  325. "complexType": {
  326. "original": "string",
  327. "resolved": "string",
  328. "references": {}
  329. },
  330. "required": false,
  331. "optional": true,
  332. "docs": {
  333. "tags": [{
  334. "name": "deprecated",
  335. "text": "use `heading` instead."
  336. }],
  337. "text": "The component header text."
  338. },
  339. "attribute": "item-title",
  340. "reflect": false
  341. },
  342. "heading": {
  343. "type": "string",
  344. "mutable": false,
  345. "complexType": {
  346. "original": "string",
  347. "resolved": "string",
  348. "references": {}
  349. },
  350. "required": false,
  351. "optional": true,
  352. "docs": {
  353. "tags": [],
  354. "text": "The component header text."
  355. },
  356. "attribute": "heading",
  357. "reflect": false
  358. },
  359. "itemSubtitle": {
  360. "type": "string",
  361. "mutable": false,
  362. "complexType": {
  363. "original": "string",
  364. "resolved": "string",
  365. "references": {}
  366. },
  367. "required": false,
  368. "optional": true,
  369. "docs": {
  370. "tags": [{
  371. "name": "deprecated",
  372. "text": "use `description` instead."
  373. }],
  374. "text": "A description for the component. Displays below the header text."
  375. },
  376. "attribute": "item-subtitle",
  377. "reflect": false
  378. },
  379. "description": {
  380. "type": "string",
  381. "mutable": false,
  382. "complexType": {
  383. "original": "string",
  384. "resolved": "string",
  385. "references": {}
  386. },
  387. "required": false,
  388. "optional": false,
  389. "docs": {
  390. "tags": [],
  391. "text": "A description for the component. Displays below the header text."
  392. },
  393. "attribute": "description",
  394. "reflect": false
  395. },
  396. "layout": {
  397. "type": "string",
  398. "mutable": true,
  399. "complexType": {
  400. "original": "Extract<\"horizontal\" | \"vertical\", Layout>",
  401. "resolved": "\"horizontal\" | \"vertical\"",
  402. "references": {
  403. "Extract": {
  404. "location": "global"
  405. },
  406. "Layout": {
  407. "location": "import",
  408. "path": "../interfaces"
  409. }
  410. }
  411. },
  412. "required": false,
  413. "optional": true,
  414. "docs": {
  415. "tags": [{
  416. "name": "internal",
  417. "text": undefined
  418. }],
  419. "text": ""
  420. },
  421. "attribute": "layout",
  422. "reflect": true,
  423. "defaultValue": "\"horizontal\""
  424. },
  425. "icon": {
  426. "type": "boolean",
  427. "mutable": true,
  428. "complexType": {
  429. "original": "boolean",
  430. "resolved": "boolean",
  431. "references": {}
  432. },
  433. "required": false,
  434. "optional": false,
  435. "docs": {
  436. "tags": [{
  437. "name": "internal",
  438. "text": undefined
  439. }],
  440. "text": ""
  441. },
  442. "attribute": "icon",
  443. "reflect": false,
  444. "defaultValue": "false"
  445. },
  446. "numbered": {
  447. "type": "boolean",
  448. "mutable": true,
  449. "complexType": {
  450. "original": "boolean",
  451. "resolved": "boolean",
  452. "references": {}
  453. },
  454. "required": false,
  455. "optional": false,
  456. "docs": {
  457. "tags": [{
  458. "name": "internal",
  459. "text": undefined
  460. }],
  461. "text": ""
  462. },
  463. "attribute": "numbered",
  464. "reflect": false,
  465. "defaultValue": "false"
  466. },
  467. "scale": {
  468. "type": "string",
  469. "mutable": true,
  470. "complexType": {
  471. "original": "Scale",
  472. "resolved": "\"l\" | \"m\" | \"s\"",
  473. "references": {
  474. "Scale": {
  475. "location": "import",
  476. "path": "../interfaces"
  477. }
  478. }
  479. },
  480. "required": false,
  481. "optional": false,
  482. "docs": {
  483. "tags": [{
  484. "name": "internal",
  485. "text": undefined
  486. }],
  487. "text": ""
  488. },
  489. "attribute": "scale",
  490. "reflect": true,
  491. "defaultValue": "\"m\""
  492. }
  493. };
  494. }
  495. static get states() {
  496. return {
  497. "effectiveLocale": {}
  498. };
  499. }
  500. static get events() {
  501. return [{
  502. "method": "calciteInternalStepperItemKeyEvent",
  503. "name": "calciteInternalStepperItemKeyEvent",
  504. "bubbles": true,
  505. "cancelable": false,
  506. "composed": true,
  507. "docs": {
  508. "tags": [{
  509. "name": "internal",
  510. "text": undefined
  511. }],
  512. "text": ""
  513. },
  514. "complexType": {
  515. "original": "StepperItemKeyEventDetail",
  516. "resolved": "StepperItemKeyEventDetail",
  517. "references": {
  518. "StepperItemKeyEventDetail": {
  519. "location": "import",
  520. "path": "../stepper/interfaces"
  521. }
  522. }
  523. }
  524. }, {
  525. "method": "calciteInternalStepperItemSelect",
  526. "name": "calciteInternalStepperItemSelect",
  527. "bubbles": true,
  528. "cancelable": false,
  529. "composed": true,
  530. "docs": {
  531. "tags": [{
  532. "name": "internal",
  533. "text": undefined
  534. }],
  535. "text": ""
  536. },
  537. "complexType": {
  538. "original": "StepperItemEventDetail",
  539. "resolved": "StepperItemEventDetail",
  540. "references": {
  541. "StepperItemEventDetail": {
  542. "location": "import",
  543. "path": "../stepper/interfaces"
  544. }
  545. }
  546. }
  547. }, {
  548. "method": "calciteInternalUserRequestedStepperItemSelect",
  549. "name": "calciteInternalUserRequestedStepperItemSelect",
  550. "bubbles": true,
  551. "cancelable": false,
  552. "composed": true,
  553. "docs": {
  554. "tags": [{
  555. "name": "internal",
  556. "text": undefined
  557. }],
  558. "text": ""
  559. },
  560. "complexType": {
  561. "original": "StepperItemChangeEventDetail",
  562. "resolved": "StepperItemChangeEventDetail",
  563. "references": {
  564. "StepperItemChangeEventDetail": {
  565. "location": "import",
  566. "path": "../stepper/interfaces"
  567. }
  568. }
  569. }
  570. }, {
  571. "method": "calciteInternalStepperItemRegister",
  572. "name": "calciteInternalStepperItemRegister",
  573. "bubbles": true,
  574. "cancelable": false,
  575. "composed": true,
  576. "docs": {
  577. "tags": [{
  578. "name": "internal",
  579. "text": undefined
  580. }],
  581. "text": ""
  582. },
  583. "complexType": {
  584. "original": "StepperItemEventDetail",
  585. "resolved": "StepperItemEventDetail",
  586. "references": {
  587. "StepperItemEventDetail": {
  588. "location": "import",
  589. "path": "../stepper/interfaces"
  590. }
  591. }
  592. }
  593. }];
  594. }
  595. static get methods() {
  596. return {
  597. "setFocus": {
  598. "complexType": {
  599. "signature": "() => Promise<void>",
  600. "parameters": [],
  601. "references": {
  602. "Promise": {
  603. "location": "global"
  604. }
  605. },
  606. "return": "Promise<void>"
  607. },
  608. "docs": {
  609. "text": "",
  610. "tags": []
  611. }
  612. }
  613. };
  614. }
  615. static get elementRef() { return "el"; }
  616. static get watchers() {
  617. return [{
  618. "propName": "active",
  619. "methodName": "activeHandler"
  620. }, {
  621. "propName": "selected",
  622. "methodName": "selectedHandler"
  623. }, {
  624. "propName": "disabled",
  625. "methodName": "disabledWatcher"
  626. }, {
  627. "propName": "effectiveLocale",
  628. "methodName": "effectiveLocaleWatcher"
  629. }];
  630. }
  631. static get listeners() {
  632. return [{
  633. "name": "calciteInternalStepperItemChange",
  634. "method": "updateActiveItemOnChange",
  635. "target": "body",
  636. "capture": false,
  637. "passive": false
  638. }];
  639. }
  640. }