{"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;;;;;;;;;;CAUC;;;;;AAUM,SAAS,0CAAoB,WAAoB;IACtD,IAAI,eAAe,CAAA,GAAA,mBAAK,EAAoB;IAC5C,IAAI,eAAe,CAAA,GAAA,uCAAY,EAAE;IACjC,OAAO,CAAA,GAAA,wBAAU,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,0BAAY,EAAkB;AACtD,SAAS;IACd,OAAO,CAAA,GAAA,uBAAS,EAAE,8CAAoB;AACxC;AAUO,SAAS,0CAAS,YAAC,QAAQ,aAAE,SAAS,EAAgB;IAC3D,iDAAiD;IACjD,qBACE,gCAAC,0CAAgB,QAAQ;QAAC,OAAO;kBAC9B;;AAGP;AAEO,MAAM,sDAMJ,qEAAqE;AAEvE,SAAS,0CAAgB,QAAmB,EAAE,KAAgC;IACnF,IAAI,aAAa,CAAA,GAAA,uBAAS,EAAE;IAC5B,IAAI,YAAY;QACd,yBAAW,gCAAC;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,gCAAC;QACC,6CAA6C;QAC7C,OAAO,CAAA,GAAA,gCAAS,EAAE;QAClB,KAAK,0CAAoB;QACzB,WAAW;kBAKV;;AAGP;AAGO,SAAS,0CAAgB,YAAC,QAAQ,EAA8B;IACrE,IAAI,YAAY,CAAA,GAAA,uBAAS,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,gCAAC,0CAAgB,QAAQ;QAAC,OAAO;kBAC9B,0BAAY,CAAA,GAAA,yBAAW,EAAE,UAAU;YAClC,KAAK,CAAA,GAAA,+BAAQ,EAAE,UAAU;YACzB,WAAW,AAAC,CAAA,SAAS,KAAK,CAAC,SAAS,IAAI,EAAC,IAAK,MAAM;YACpD,OAAO;QACT,KAAK;;AAGX;AAGO,SAAS,0CAAgB,MAAmB;IACjD,IAAI,aAAa,CAAA,GAAA,uBAAS,EAAE;IAC5B,IAAI,YACF,OAAO,CAAA,GAAA,qCAAU,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        inert: '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.cjs.map"}