UNPKG

9.96 kBSource Map (JSON)View Raw
1{"version":3,"file":"Collapse.umd.js","sources":["../src/components/collapse/Collapse.jsx"],"sourcesContent":["/* eslint-env browser */\r\n\r\n/**\r\n * All debug logs are removed on build\r\n */\r\n\r\nimport \"./collapse.css\";\r\nimport React, {\r\n useState,\r\n useEffect,\r\n useRef,\r\n useCallback,\r\n useReducer\r\n} from \"react\";\r\nimport debugLog from \"./debugLog\";\r\n\r\n// using let instead of const,\r\n// experimenting with ES2015 bundle which gets a bit smaller when using let over const.\r\nlet COLLAPSED = \"collapsed\";\r\nlet COLLAPSING = \"collapsing\";\r\nlet EXPANDING = \"expanding\";\r\nlet EXPANDED = \"expanded\";\r\n\r\nlet defaultClassName = \"collapse-css-transition\";\r\nlet defaultElementType = \"div\";\r\nlet defaultCollapseHeight = \"0px\";\r\n\r\n/**\r\n *\r\n * @param {function} callback\r\n */\r\nfunction nextFrame(callback) {\r\n requestAnimationFrame(function() {\r\n //setTimeout(callback, 0); // NOT used because can be jumpy if click-spamming.\r\n requestAnimationFrame(callback); // This is used.\r\n });\r\n}\r\n\r\nfunction Collapse({\r\n children,\r\n transition,\r\n style,\r\n render,\r\n elementType = defaultElementType,\r\n isOpen,\r\n collapseHeight = defaultCollapseHeight,\r\n onInit,\r\n onChange,\r\n className = defaultClassName,\r\n addState,\r\n noAnim,\r\n overflowOnExpanded,\r\n ...rest\r\n}) {\r\n let getCollapsedVisibility = () => (collapseHeight === \"0px\" ? \"hidden\" : \"\");\r\n\r\n let [__, forceUpdate] = useReducer(_ => _ + 1, 0);\r\n\r\n let elementRef = useRef();\r\n let [callbackTick, setCallbackTick] = useState(0);\r\n\r\n // Avoiding setState to control when stuff are updated.\r\n // Might not be needed.\r\n let state = useRef({\r\n collapse: isOpen ? EXPANDED : COLLAPSED,\r\n style: {\r\n height: isOpen ? \"\" : collapseHeight,\r\n visibility: isOpen ? \"\" : getCollapsedVisibility()\r\n }\r\n }).current;\r\n\r\n useEffect(() => {\r\n // Invoke callback when data are updated, use Effect to sync state.\r\n callbackTick && onCallback(onChange);\r\n }, [callbackTick]);\r\n\r\n /**\r\n *\r\n * @param {function} callback\r\n */\r\n let onCallback = (callback, params = {}) => {\r\n if (callback) {\r\n debugLog(\"onCallback \" + callback.name);\r\n callback({ state: state.collapse, style: state.style, ...params });\r\n }\r\n };\r\n\r\n function setCollapsed() {\r\n if (!elementRef.current) return; // might be redundant\r\n\r\n // Update state\r\n state.collapse = COLLAPSED;\r\n\r\n debugLog(\"setCollapsed\");\r\n\r\n state.style = {\r\n height: collapseHeight,\r\n visibility: getCollapsedVisibility()\r\n };\r\n forceUpdate();\r\n\r\n setTimeout(() => setCallbackTick(Date.now), 0); // callback and re-render\r\n }\r\n\r\n function setCollapsing() {\r\n if (!elementRef.current) return; // might be redundant\r\n\r\n if (noAnim) {\r\n return setCollapsed();\r\n }\r\n\r\n // Update state\r\n state.collapse = COLLAPSING;\r\n\r\n debugLog(\"setCollapsing\");\r\n\r\n state.style = {\r\n height: getElementHeight(),\r\n visibility: \"\"\r\n };\r\n forceUpdate();\r\n\r\n nextFrame(() => {\r\n if (!elementRef.current) return;\r\n if (state.collapse !== COLLAPSING) return;\r\n\r\n state.style = {\r\n height: collapseHeight,\r\n visibility: \"\"\r\n };\r\n //forceUpdate();\r\n\r\n setCallbackTick(Date.now); // callback and re-render\r\n });\r\n }\r\n\r\n function setExpanding() {\r\n if (!elementRef.current) return; // might be redundant\r\n\r\n if (noAnim) {\r\n return setExpanded();\r\n }\r\n\r\n // Updatetate\r\n state.collapse = EXPANDING;\r\n\r\n debugLog(\"setExpanding\");\r\n\r\n nextFrame(() => {\r\n if (!elementRef.current) return; // might be redundant\r\n if (state.collapse !== EXPANDING) return;\r\n\r\n state.style = {\r\n height: getElementHeight(),\r\n visibility: \"\"\r\n };\r\n // forceUpdate();\r\n\r\n setCallbackTick(Date.now); // callback and re-render\r\n });\r\n }\r\n\r\n function setExpanded() {\r\n if (!elementRef.current) return; // might be redundant\r\n\r\n // Update state\r\n state.collapse = EXPANDED;\r\n\r\n debugLog(\"setExpanded\");\r\n\r\n state.style = {\r\n height: \"\",\r\n visibility: \"\"\r\n };\r\n forceUpdate();\r\n\r\n setTimeout(() => setCallbackTick(Date.now), 0); // callback and re-render\r\n }\r\n\r\n function getElementHeight() {\r\n // @ts-ignore\r\n return `${elementRef.current.scrollHeight}px`;\r\n }\r\n\r\n function onTransitionEnd({ target, propertyName }) {\r\n if (target === elementRef.current && propertyName === \"height\") {\r\n let styleHeight = target.style.height;\r\n\r\n debugLog(\"onTransitionEnd\", state.collapse, propertyName, styleHeight);\r\n\r\n switch (state.collapse) {\r\n case EXPANDING:\r\n if (styleHeight === \"\" || styleHeight === collapseHeight)\r\n // This is stale, a newer event has happened before this could execute\r\n console.warn(\r\n `onTransitionEnd height unexpected ${styleHeight}`,\r\n \"ignore setExpanded\"\r\n );\r\n else setExpanded();\r\n break;\r\n case COLLAPSING:\r\n if (styleHeight === \"\" || styleHeight !== collapseHeight)\r\n // This is stale, a newer event has happened before this could execute\r\n console.warn(\r\n `onTransitionEnd height unexpected ${styleHeight}`,\r\n \"ignore setCollapsed\"\r\n );\r\n else setCollapsed();\r\n break;\r\n default:\r\n console.warn(\"Ignored in onTransitionEnd\", state.collapse);\r\n }\r\n }\r\n }\r\n\r\n // getDerivedStateFromProps\r\n let didOpen = state.collapse === EXPANDED || state.collapse === EXPANDING;\r\n\r\n if (!didOpen && isOpen) setExpanding();\r\n\r\n if (didOpen && !isOpen) setCollapsing();\r\n // END getDerivedStateFromProps\r\n\r\n let overflow =\r\n state.collapse === EXPANDED && overflowOnExpanded ? \"\" : \"hidden\";\r\n\r\n let computedStyle = {\r\n overflow,\r\n transition,\r\n ...style,\r\n ...state.style\r\n };\r\n let ElementType = elementType;\r\n\r\n let callbackRef = useCallback(\r\n node => {\r\n if (node) {\r\n elementRef.current = node;\r\n onCallback(onInit, { node });\r\n debugLog(\"callback ref\");\r\n }\r\n },\r\n [elementType]\r\n );\r\n\r\n let collapseClassName = addState\r\n ? `${className} --c-${state.collapse}`\r\n : className;\r\n\r\n debugLog(\"Render\");\r\n\r\n return (\r\n <ElementType\r\n ref={callbackRef}\r\n style={computedStyle}\r\n onTransitionEnd={onTransitionEnd}\r\n className={collapseClassName}\r\n {...rest}\r\n >\r\n {typeof children === \"function\"\r\n ? children(state.collapse)\r\n : typeof render === \"function\"\r\n ? render(state.collapse)\r\n : children}\r\n </ElementType>\r\n );\r\n}\r\n\r\nexport default Collapse;\r\n"],"names":["nextFrame","callback","requestAnimationFrame","children","transition","style","render","elementType","isOpen","collapseHeight","onInit","onChange","className","addState","noAnim","overflowOnExpanded","rest","getCollapsedVisibility","useReducer","_","forceUpdate","elementRef","useRef","useState","callbackTick","setCallbackTick","state","collapse","height","visibility","current","useEffect","onCallback","params","name","setCollapsed","setTimeout","Date","now","setExpanded","getElementHeight","scrollHeight","didOpen","setExpanding","setCollapsing","computedStyle","overflow","ElementType","callbackRef","useCallback","node","collapseClassName","React","ref","onTransitionEnd","target","propertyName","styleHeight"],"mappings":"k8EA+BA,SAASA,EAAUC,GACjBC,uBAAsB,WAEpBA,sBAAsBD,aAI1B,gBACEE,IAAAA,SACAC,IAAAA,WACAC,IAAAA,MACAC,IAAAA,WACAC,YAAAA,aAnBuB,QAoBvBC,IAAAA,WACAC,eAAAA,aApB0B,QAqB1BC,IAAAA,OACAC,IAAAA,aACAC,UAAAA,aAzBqB,4BA0BrBC,IAAAA,SACAC,IAAAA,OACAC,IAAAA,mBACGC,mKAECC,EAAyB,iBAA0B,QAAnBR,EAA2B,SAAW,QAElDS,cAAW,SAAAC,UAAKA,EAAI,IAAG,MAAtCC,cAELC,EAAaC,eACqBC,WAAS,MAA1CC,OAAcC,OAIfC,EAAQJ,SAAO,CACjBK,SAAUnB,EA3CC,WAHC,YA+CZH,MAAO,CACLuB,OAAQpB,EAAS,GAAKC,EACtBoB,WAAYrB,EAAS,GAAKS,OAE3Ba,QAEHC,aAAU,WAERP,GAAgBQ,EAAWrB,KAC1B,CAACa,QAMAQ,EAAa,SAAC/B,OAAUgC,yDAAS,GAC/BhC,IACuBA,EAASiC,KAClCjC,KAAWyB,MAAOA,EAAMC,SAAUtB,MAAOqB,EAAMrB,OAAU4B,eAIpDE,IACFd,EAAWS,UAGhBJ,EAAMC,SAzEM,YA6EZD,EAAMrB,MAAQ,CACZuB,OAAQnB,EACRoB,WAAYZ,KAEdG,IAEAgB,YAAW,kBAAMX,EAAgBY,KAAKC,OAAM,aA6DrCC,IACFlB,EAAWS,UAGhBJ,EAAMC,SAjJK,WAqJXD,EAAMrB,MAAQ,CACZuB,OAAQ,GACRC,WAAY,IAEdT,IAEAgB,YAAW,kBAAMX,EAAgBY,KAAKC,OAAM,aAGrCE,oBAEGnB,EAAWS,QAAQW,uBAmC3BC,EAnMS,aAmMChB,EAAMC,UApMN,cAoM+BD,EAAMC,UAE9Ce,GAAWlC,iBAjFTa,EAAWS,YAEZhB,SACKyB,IAITb,EAAMC,SA5HM,YAgIZ3B,GAAU,WACHqB,EAAWS,SAjIN,cAkINJ,EAAMC,WAEVD,EAAMrB,MAAQ,CACZuB,OAAQY,IACRX,WAAY,IAIdJ,EAAgBY,KAAKC,UA4DDK,GAEpBD,IAAYlC,iBAnHTa,EAAWS,YAEZhB,SACKqB,IAITT,EAAMC,SA7FO,aAiGbD,EAAMrB,MAAQ,CACZuB,OAAQY,IACRX,WAAY,IAEdT,IAEApB,GAAU,WACHqB,EAAWS,SAxGL,eAyGPJ,EAAMC,WAEVD,EAAMrB,MAAQ,CACZuB,OAAQnB,EACRoB,WAAY,IAIdJ,EAAgBY,KAAKC,UAwFDM,OAMpBC,KACFC,SA9MW,aA2MXpB,EAAMC,UAAyBZ,EAAqB,GAAK,SAIzDX,WAAAA,GACGC,KACAqB,EAAMrB,OAEP0C,EAAcxC,EAEdyC,EAAcC,eAChB,SAAAC,GACMA,IACF7B,EAAWS,QAAUoB,EACrBlB,EAAWtB,EAAQ,CAAEwC,KAAAA,OAIzB,CAAC3C,IAGC4C,EAAoBtC,YACjBD,kBAAiBc,EAAMC,UAC1Bf,SAKFwC,gBAACL,KACCM,IAAKL,EACL3C,MAAOwC,EACPS,gCAvEuBC,IAAAA,OAAQC,IAAAA,gBAC7BD,IAAWlC,EAAWS,SAA4B,WAAjB0B,EAA2B,KAC1DC,EAAcF,EAAOlD,MAAMuB,cAEHF,EAAMC,SAE1BD,EAAMC,cA1KJ,YA4Kc,KAAhB8B,GAAsBA,IAAgBhD,GAMrC8B,cAnLE,aAsLa,KAAhBkB,GAAsBA,IAAgBhD,GAMrC0B,OAiDTvB,UAAWuC,GACPnC,GAEiB,mBAAbb,EACJA,EAASuB,EAAMC,UACG,mBAAXrB,EACPA,EAAOoB,EAAMC,UACbxB"}
\No newline at end of file