{"version":3,"file":"skeleton.cjs","names":[],"sources":["../src/feedback/skeleton/skeleton.ts"],"sourcesContent":["import { bind, define, getHost, html, onCleanup, onMounted, prop } from '@vielzeug/ore';\nimport { computed, signal, watch } from '@vielzeug/ripple';\nimport { createIntersection } from '@vielzeug/sentinel';\nimport { sizableBundle } from '../../shared';\nimport { reducedMotionMixin } from '../../styles';\nimport type { ComponentSize } from '../../types';\nimport { safeCSSLength } from '../../utils';\nimport componentStyles from './skeleton.css?inline';\n\n/** Skeleton loader component properties */\nexport type OreSkeletonProps = {\n  /** Toggle shimmer animation */\n  animated?: boolean;\n  /** Height override (e.g. '1rem', '3rem') */\n  height?: string;\n  /** Number of text lines for `variant='text'` */\n  lines?: number;\n  /** Radius override (e.g. '9999px', 'var(--rounded-xl)') */\n  radius?: string;\n  /** Size preset controlling line height and circle size */\n  size?: ComponentSize;\n  /** Render diagonal stripes instead of the shimmer — useful as a design-mode placeholder */\n  striped?: boolean;\n  /** Visual variant: 'rect' (default), 'circle', or 'text' */\n  variant?: 'rect' | 'circle' | 'text';\n  /** Width override (e.g. '12rem', '70%') */\n  width?: string;\n};\n\n/**\n * A shimmer placeholder that represents loading content.\n * Control dimensions via the `--skeleton-width` and `--skeleton-height` CSS custom properties,\n * or via `width` / `height` inline styles.\n *\n * @element ore-skeleton\n *\n * @attr {string}  variant  - Shape: 'rect' (default) | 'circle' | 'text'\n * @attr {string}  size     - Height/circle preset: 'sm' | 'md' | 'lg'\n * @attr {string}  width    - Width override (CSS length/percentage)\n * @attr {string}  height   - Height override (CSS length)\n * @attr {string}  radius   - Radius override\n * @attr {boolean} animated - Disable with `animated=\"false\"`\n * @attr {number}  lines    - Text line count (only for `variant='text'`)\n * @attr {boolean} striped  - Replace shimmer with diagonal stripes\n *\n * @cssprop --skeleton-bg          - Base shimmer color\n * @cssprop --skeleton-highlight - Shimmer highlight color\n * @cssprop --skeleton-radius    - Border radius\n * @cssprop --skeleton-size      - Circle fallback size\n * @cssprop --skeleton-width     - Width (default: 100%)\n * @cssprop --skeleton-height    - Height (default: var(--size-4))\n * @cssprop --skeleton-line-gap  - Vertical gap between text lines\n * @cssprop --skeleton-last-line-width - Width of the final text line\n * @cssprop --skeleton-duration    - Shimmer animation duration\n * @cssprop --skeleton-stripe-size  - Width of each diagonal stripe (default: 6px)\n *\n * @part stack - Stack container.\n * @part bone - Skeleton bone element.\n * @example\n * ```html\n * <!-- Paragraph lines -->\n * <ore-skeleton variant=\"text\" lines=\"3\" width=\"100%\"></ore-skeleton>\n *\n * <!-- Avatar -->\n * <ore-skeleton variant=\"circle\" size=\"md\"></ore-skeleton>\n *\n * <!-- Card image -->\n * <ore-skeleton width=\"100%\" height=\"10rem\"></ore-skeleton>\n * ```\n */\nexport const SKELETON_TAG = 'ore-skeleton' as const;\ndefine<OreSkeletonProps>(SKELETON_TAG, {\n  props: {\n    ...sizableBundle,\n    animated: prop.bool(true),\n    height: prop.string(),\n    lines: prop.number(1),\n    radius: prop.string(),\n    striped: prop.bool(false),\n    variant: prop.oneOf(['rect', 'circle', 'text'] as const, 'rect'),\n    width: prop.string(),\n  },\n  setup(props) {\n    const el = getHost();\n\n    const isPaused = signal(false);\n    const lineCount = () => {\n      const value = Math.floor(Number(props.lines.value));\n\n      return Number.isFinite(value) && value > 0 ? value : 1;\n    };\n    const renderLineCount = () => (props.variant.value === 'text' ? lineCount() : 1);\n    const styleDeps = () =>\n      `${props.width.value ?? ''}|${props.height.value ?? ''}|${props.radius.value ?? ''}|${props.animated.value === false ? '0' : '1'}`;\n\n    watch(\n      computed(styleDeps),\n      () => {\n        const safeWidth = safeCSSLength(props.width.value);\n        const safeHeight = safeCSSLength(props.height.value);\n        const safeRadius = safeCSSLength(props.radius.value);\n\n        if (safeWidth) el.style.setProperty('--skeleton-width', safeWidth);\n        else el.style.removeProperty('--skeleton-width');\n\n        if (safeHeight) el.style.setProperty('--skeleton-height', safeHeight);\n        else el.style.removeProperty('--skeleton-height');\n\n        if (safeRadius) el.style.setProperty('--skeleton-radius', safeRadius);\n        else el.style.removeProperty('--skeleton-radius');\n\n        const rawAnimated = el.getAttribute('animated');\n        const isAnimated = rawAnimated !== 'false' && props.animated.value !== false;\n\n        el.setAttribute('data-animated', isAnimated ? 'true' : 'false');\n      },\n      { immediate: true },\n    );\n\n    bind({\n      attr: {\n        'data-paused': () => (isPaused.value ? true : undefined),\n      },\n    });\n\n    onMounted(() => {\n      const intersection = createIntersection(el, { threshold: 0 });\n\n      onCleanup(() => intersection.dispose());\n\n      watch(intersection, (state) => {\n        const paused = state === null ? false : !state.isIntersecting;\n        isPaused.value = paused;\n      });\n    });\n\n    return html`\n      <div class=\"stack\" part=\"stack\">\n        ${() =>\n          Array.from({ length: renderLineCount() }, (_, index) => {\n            const isLastLine =\n              props.variant.value === 'text' && renderLineCount() > 1 && index === renderLineCount() - 1;\n\n            return html`\n              <div class=\"bone\" part=\"bone\" aria-hidden=\"true\" data-last=\"${() => (isLastLine ? 'true' : null)}\"></div>\n            `;\n          })}\n      </div>\n    `;\n  },\n  styles: [reducedMotionMixin, componentStyles],\n});\n"],"mappings":"+UAsEA,IAAa,EAAe,gBAC5B,EAAA,EAAA,OAAA,CAAyB,EAAc,CACrC,MAAO,CACL,GAAG,EAAA,cACH,SAAU,EAAA,KAAK,KAAK,EAAI,EACxB,OAAQ,EAAA,KAAK,OAAO,EACpB,MAAO,EAAA,KAAK,OAAO,CAAC,EACpB,OAAQ,EAAA,KAAK,OAAO,EACpB,QAAS,EAAA,KAAK,KAAK,EAAK,EACxB,QAAS,EAAA,KAAK,MAAM,CAAC,OAAQ,SAAU,MAAM,EAAY,MAAM,EAC/D,MAAO,EAAA,KAAK,OAAO,CACrB,EACA,MAAM,EAAO,CACX,IAAM,GAAA,EAAK,EAAA,QAAA,CAAQ,EAEb,GAAA,EAAW,EAAA,OAAA,CAAO,EAAK,EACvB,MAAkB,CACtB,IAAM,EAAQ,KAAK,MAAM,OAAO,EAAM,MAAM,KAAK,CAAC,EAElD,OAAO,OAAO,SAAS,CAAK,GAAK,EAAQ,EAAI,EAAQ,CACvD,EACM,MAAyB,EAAM,QAAQ,QAAU,OAAS,EAAU,EAAI,EA6C9E,OAzCA,EAAA,EAAA,MAAA,EAAA,EACE,EAAA,SAAA,KAHA,GAAG,EAAM,MAAM,OAAS,GAAG,GAAG,EAAM,OAAO,OAAS,GAAG,GAAG,EAAM,OAAO,OAAS,GAAG,GAAG,EAAM,SAAS,QAAU,GAAQ,IAAM,KAG3G,MACZ,CACJ,IAAM,EAAY,EAAA,cAAc,EAAM,MAAM,KAAK,EAC3C,EAAa,EAAA,cAAc,EAAM,OAAO,KAAK,EAC7C,EAAa,EAAA,cAAc,EAAM,OAAO,KAAK,EAE/C,EAAW,EAAG,MAAM,YAAY,mBAAoB,CAAS,EAC5D,EAAG,MAAM,eAAe,kBAAkB,EAE3C,EAAY,EAAG,MAAM,YAAY,oBAAqB,CAAU,EAC/D,EAAG,MAAM,eAAe,mBAAmB,EAE5C,EAAY,EAAG,MAAM,YAAY,oBAAqB,CAAU,EAC/D,EAAG,MAAM,eAAe,mBAAmB,EAGhD,IAAM,EADc,EAAG,aAAa,UACjB,IAAgB,SAAW,EAAM,SAAS,QAAU,GAEvE,EAAG,aAAa,gBAAiB,EAAa,OAAS,OAAO,CAChE,EACA,CAAE,UAAW,EAAK,CACpB,GAEA,EAAA,EAAA,KAAA,CAAK,CACH,KAAM,CACJ,kBAAsB,EAAS,MAAQ,GAAO,IAAA,EAChD,CACF,CAAC,GAED,EAAA,EAAA,UAAA,KAAgB,CACd,IAAM,GAAA,EAAe,EAAA,mBAAA,CAAmB,EAAI,CAAE,UAAW,CAAE,CAAC,GAE5D,EAAA,EAAA,UAAA,KAAgB,EAAa,QAAQ,CAAC,GAEtC,EAAA,EAAA,MAAA,CAAM,EAAe,GAAU,CAC7B,IAAM,EAAS,IAAU,MAAe,CAAC,EAAM,eAC/C,EAAS,MAAQ,CACnB,CAAC,CACH,CAAC,EAEM,EAAA,IAAI;;cAGL,MAAM,KAAK,CAAE,OAAQ,EAAgB,CAAE,GAAI,EAAG,IAAU,CACtD,IAAM,EACJ,EAAM,QAAQ,QAAU,QAAU,EAAgB,EAAI,GAAK,IAAU,EAAgB,EAAI,EAE3F,MAAO,GAAA,IAAI;gFAC4D,EAAa,OAAS,KAAM;aAErG,CAAC,EAAE;;KAGX,EACA,OAAQ,CAAC,EAAA,mBAAoB,EAAA,OAAe,CAC9C,CAAC"}