@react-spectrum/s2
Version:
Spectrum 2 UI components in React
1 lines • 7.1 kB
Source Map (JSON)
{"mappings":";;;;;;;AAAA;;;;;;;;;;CAUC;;;;;AAUM,SAAS,0CAAoB,WAAoB;IACtD,IAAI,eAAe,CAAA,GAAA,aAAK,EAAoB;IAC5C,IAAI,eAAe,CAAA,GAAA,oBAAY,EAAE;IACjC,OAAO,CAAA,GAAA,kBAAU,EAAE,CAAC;QAClB,IAAI,eAAe,CAAC,aAAa,OAAO,IAAI,WAAW,CAAC,cAAc;YACpE,iEAAiE;YACjE,2EAA2E;YAC3E,aAAa,OAAO,GAAG,QAAQ,OAAO,CACpC;gBACE;oBAAC,oBAAoB;gBAAM;gBAC3B;oBAAC,oBAAoB;gBAAI;aAC1B,EACD;gBACE,UAAU;gBACV,YAAY;gBACZ,QAAQ;YACV;YAEF,aAAa,OAAO,CAAC,SAAS,GAAG;QACnC,OAAO,IAAI,CAAC,eAAe,aAAa,OAAO,EAAE;YAC/C,aAAa,OAAO,CAAC,MAAM;YAC3B,aAAa,OAAO,GAAG;QACzB;IACF,GAAG;QAAC;KAAY;AAClB;AASO,MAAM,0DAAkB,CAAA,GAAA,oBAAY,EAAkB;AACtD,SAAS;IACd,OAAO,CAAA,GAAA,iBAAS,EAAE,8CAAoB;AACxC;AAUO,SAAS,0CAAS,YAAC,QAAQ,aAAE,SAAS,EAAgB;IAC3D,iDAAiD;IACjD,qBACE,gBAAC,0CAAgB,QAAQ;QAAC,OAAO;kBAC9B;;AAGP;AAEO,MAAM,sDAMJ,qEAAqE;AAEvE,SAAS,0CAAgB,QAAmB,EAAE,KAAgC;IACnF,IAAI,aAAa,CAAA,GAAA,iBAAS,EAAE;IAC5B,IAAI,YAAY;QACd,yBAAW,gBAAC;sBAAc;;QAC1B,QAAQ;YACN,GAAG,KAAK;YACR,8DAA8D;YAC9D,2EAA2E;YAC3E,qBAAqB;QACvB;IACF;IACA,OAAO;QAAC;QAAU;KAAM;AAC1B;AAGO,SAAS,0CAAa,YAAC,QAAQ,EAAwB;IAC5D,qBACE,gBAAC;QACC,6CAA6C;QAC7C,OAAO,CAAA,GAAA,iBAAS,EAAE;QAClB,KAAK,0CAAoB;QACzB,WAAW;kBAKV;;AAGP;AAGO,SAAS,0CAAgB,YAAC,QAAQ,EAA8B;IACrE,IAAI,YAAY,CAAA,GAAA,iBAAS,EAAE;IAC3B,IAAI,YAAY,0CAAoB,aAAa;IACjD,IAAI,aAAa,MACf,OAAO;IAGT,IAAI,WAAW,SAAS,WAAW,SAAS,GAAG,GAAU,SAAS,KAAK,CAAC,GAAG;IAC3E,qBACE,gBAAC,0CAAgB,QAAQ;QAAC,OAAO;kBAC9B,0BAAY,CAAA,GAAA,mBAAW,EAAE,UAAU;YAClC,KAAK,CAAA,GAAA,gBAAQ,EAAE,UAAU;YACzB,WAAW,AAAC,CAAA,SAAS,KAAK,CAAC,SAAS,IAAI,EAAC,IAAK,MAAM;YACpD,6CAA6C;YAC7C,OAAO,CAAA,GAAA,iBAAS,EAAE;QACpB,KAAK;;AAGX;AAGO,SAAS,0CAAgB,MAAmB;IACjD,IAAI,aAAa,CAAA,GAAA,iBAAS,EAAE;IAC5B,IAAI,YACF,OAAO,CAAA,GAAA,yCAAU,0BAA+B;IAElD,OAAO,UAAU;AACnB","sources":["packages/@react-spectrum/s2/src/Skeleton.tsx"],"sourcesContent":["/*\n * Copyright 2024 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {cloneElement, createContext, CSSProperties, ReactElement, ReactNode, Ref, useCallback, useContext, useRef} from 'react';\nimport {color, style} from '../style' with {type: 'macro'};\nimport {inertValue, mergeRefs} from '@react-aria/utils';\nimport {mergeStyles} from '../style/runtime';\nimport {raw} from '../style/style-macro' with {type: 'macro'};\nimport {StyleString} from '../style/types';\nimport {useMediaQuery} from '@react-spectrum/utils';\n\nexport function useLoadingAnimation(isAnimating: boolean): (element: HTMLElement | null) => void {\n let animationRef = useRef<Animation | null>(null);\n let reduceMotion = useMediaQuery('(prefers-reduced-motion: reduce)');\n return useCallback((element: HTMLElement | null) => {\n if (isAnimating && !animationRef.current && element && !reduceMotion) {\n // Use web animation API instead of CSS animations so that we can\n // synchronize it between all loading elements on the page (via startTime).\n animationRef.current = element.animate(\n [\n {backgroundPosition: '100%'},\n {backgroundPosition: '0%'}\n ],\n {\n duration: 2000,\n iterations: Infinity,\n easing: 'ease-in-out'\n }\n );\n animationRef.current.startTime = 0;\n } else if (!isAnimating && animationRef.current) {\n animationRef.current.cancel();\n animationRef.current = null;\n }\n }, [isAnimating]);\n}\n\nexport type SkeletonElement = ReactElement<{\n children: ReactNode,\n className?: string,\n ref?: Ref<HTMLElement>,\n inert?: boolean | 'true'\n}>;\n\nexport const SkeletonContext = createContext<boolean | null>(null);\nexport function useIsSkeleton(): boolean {\n return useContext(SkeletonContext) || false;\n}\n\nexport interface SkeletonProps {\n children: ReactNode,\n isLoading: boolean\n}\n\n/**\n * A Skeleton wraps around content to render it as a placeholder.\n */\nexport function Skeleton({children, isLoading}: SkeletonProps): ReactNode {\n // Disable all form components inside a skeleton.\n return (\n <SkeletonContext.Provider value={isLoading}>\n {children}\n </SkeletonContext.Provider>\n );\n}\n\nexport const loadingStyle = raw(`\n background-image: linear-gradient(to right, ${color('gray-100')} 33%, light-dark(${color('gray-25')}, ${color('gray-300')}), ${color('gray-100')} 66%);\n background-size: 300%;\n * {\n visibility: hidden;\n }\n`, 'L'); // add to a separate layer so it overrides default style macro styles\n\nexport function useSkeletonText(children: ReactNode, style: CSSProperties | undefined): [ReactNode, CSSProperties | undefined] {\n let isSkeleton = useContext(SkeletonContext);\n if (isSkeleton) {\n children = <SkeletonText>{children}</SkeletonText>;\n style = {\n ...style,\n // This ensures the ellipsis on truncated text is also hidden.\n // -webkit-text-fill-color overrides any `color` property that is also set.\n WebkitTextFillColor: 'transparent'\n };\n }\n return [children, style];\n}\n\n// Rendered inside <Text> to create skeleton line boxes via box-decoration-break.\nexport function SkeletonText({children}: {children: ReactNode}): ReactNode {\n return (\n <span\n // @ts-ignore - compatibility with React < 19\n inert={inertValue(true)}\n ref={useLoadingAnimation(true)}\n className={loadingStyle + style({\n color: 'transparent',\n boxDecorationBreak: 'clone',\n borderRadius: 'sm'\n })}>\n {children}\n </span>\n );\n}\n\n// Clones the child element and displays it with skeleton styling.\nexport function SkeletonWrapper({children}: {children: SkeletonElement}): ReactNode {\n let isLoading = useContext(SkeletonContext);\n let animation = useLoadingAnimation(isLoading || false);\n if (isLoading == null) {\n return children;\n }\n\n let childRef = 'ref' in children ? children.ref as any : children.props.ref;\n return (\n <SkeletonContext.Provider value={null}>\n {isLoading ? cloneElement(children, {\n ref: mergeRefs(childRef, animation),\n className: (children.props.className || '') + ' ' + loadingStyle,\n // @ts-ignore - compatibility with React < 19\n inert: inertValue(true)\n }) : children}\n </SkeletonContext.Provider>\n );\n}\n\n// Adds default border radius around icons when displayed in a skeleton.\nexport function useSkeletonIcon(styles: StyleString): StyleString {\n let isSkeleton = useContext(SkeletonContext);\n if (isSkeleton) {\n return mergeStyles(style({borderRadius: 'sm'}), styles);\n }\n return styles || '' as StyleString;\n}\n"],"names":[],"version":3,"file":"Skeleton.mjs.map"}