{"version":3,"names":["resolveMap","WeakMap","promiseMap","setUpLoadableComponent","component","set","Promise","resolve","setComponentLoaded","get","componentLoaded","async","componentFocusable","isBrowser","forceUpdate","requestAnimationFrame"],"sources":["src/utils/loadable.ts"],"sourcesContent":["import { forceUpdate } from \"@stencil/core\";\nimport { isBrowser } from \"./browser\";\n\n/**\n * This helper adds support for knowing when a component has been loaded.\n *\n * Related issue: https://github.com/Esri/calcite-design-system/issues/5369\n * Could be related to Stencil.js issue: https://github.com/ionic-team/stencil/issues/3580\n *\n * Implementing\n *\n * ```\n * export class MyComponent implements LoadableComponent { }\n * ```\n *\n * ```\n * //--------------------------------------------------------------------------\n * //\n * // Lifecycle\n * //\n * //--------------------------------------------------------------------------\n *\n * componentWillLoad(): void {\n * setUpLoadableComponent(this);\n * }\n *\n * componentDidLoad(): void {\n * setComponentLoaded(this);\n * }\n *\n * // --------------------------------------------------------------------------\n * //\n * // Methods\n * //\n * // --------------------------------------------------------------------------\n *\n * async myMethod(): Promise {\n * await componentLoaded(this);\n * }\n * ```\n */\nexport interface LoadableComponent {\n /**\n * Stencil lifecycle method.\n * https://stenciljs.com/docs/component-lifecycle#componentwillload\n *\n * Called once just after the component is first connected to the DOM. Since this method is only called once, it's a good place to load data asynchronously and to setup the state without triggering extra re-renders.\n */\n componentWillLoad: () => Promise | void;\n\n /**\n * Stencil lifecycle method.\n * https://stenciljs.com/docs/component-lifecycle#componentdidload\n *\n * Called once just after the component is fully loaded and the first render() occurs.\n */\n componentDidLoad: () => Promise | void;\n}\n\nconst resolveMap = new WeakMap) => void>();\n\nconst promiseMap = new WeakMap>();\n\n/**\n * This helper util sets up the component for the ability to know when the component has been loaded.\n *\n * This should be used in the `componentWillLoad` lifecycle hook.\n *\n * ```\n * componentWillLoad(): void {\n * setUpLoadableComponent(this);\n * }\n * ```\n *\n * @param component\n */\nexport function setUpLoadableComponent(component: LoadableComponent): void {\n promiseMap.set(component, new Promise((resolve) => resolveMap.set(component, resolve)));\n}\n\n/**\n * This helper util lets the loadable component know that it is now loaded.\n *\n * This should be used in the `componentDidLoad` lifecycle hook.\n *\n * ```\n * componentDidLoad(): void {\n * setComponentLoaded(this);\n * }\n * ```\n *\n * @param component\n */\nexport function setComponentLoaded(component: LoadableComponent): void {\n resolveMap.get(component)();\n}\n\n/**\n * This helper util can be used to ensure a component has been loaded (The \"componentDidLoad\" Stencil lifecycle method has been called).\n *\n * Requires requires `LoadableComponent` to be implemented.\n *\n * A component developer can await this method before proceeding with any logic that requires a component to be loaded first.\n *\n * ```\n * async myMethod(): Promise {\n * await componentLoaded(this);\n * }\n * ```\n *\n * @param component\n * @returns Promise\n */\nexport function componentLoaded(component: LoadableComponent): Promise {\n return promiseMap.get(component);\n}\n\n/**\n * This helper util can be used to ensuring the component is loaded and rendered by the browser (The \"componentDidLoad\" Stencil lifecycle method has been called and any internal elements are focusable).\n *\n * Requires `LoadableComponent` to be implemented.\n *\n * A component developer can await this method before proceeding with any logic that requires a component to be loaded first and then an internal element be focused.\n *\n * ```\n * async setFocus(): Promise {\n * await componentFocusable(this);\n * this.internalElement?.focus();\n * }\n * ```\n *\n * @param component\n * @returns Promise\n */\nexport async function componentFocusable(component: LoadableComponent): Promise {\n await componentLoaded(component);\n\n if (!isBrowser()) {\n return;\n }\n\n forceUpdate(component);\n return new Promise((resolve) => requestAnimationFrame(() => resolve()));\n}\n"],"mappings":";;;;;wEA2DA,MAAMA,EAAa,IAAIC,QAEvB,MAAMC,EAAa,IAAID,Q,SAePE,EAAuBC,GACrCF,EAAWG,IAAID,EAAW,IAAIE,SAASC,GAAYP,EAAWK,IAAID,EAAWG,KAC/E,C,SAegBC,EAAmBJ,GACjCJ,EAAWS,IAAIL,EAAfJ,EACF,C,SAkBgBU,EAAgBN,GAC9B,OAAOF,EAAWO,IAAIL,EACxB,CAmBOO,eAAeC,EAAmBR,SACjCM,EAAgBN,GAEtB,IAAKS,IAAa,CAChB,M,CAGFC,EAAYV,GACZ,OAAO,IAAIE,SAASC,GAAYQ,uBAAsB,IAAMR,OAC9D,Q","ignoreList":[]}