{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "progress",
  "title": "Progress",
  "type": "registry:ui",
  "description": "Linear progress bar — determinate or indeterminate. Two visual densities (slim, default), four tones, and an optional inline percentage label.",
  "categories": [
    "feedback"
  ],
  "files": [
    {
      "path": "packages/elements-lit/src/components/progress/progress.ts",
      "content": "import { LitElement, css, html } from 'lit'\nimport { styleMap } from 'lit/directives/style-map.js'\nimport { tailwind } from '../../lib/styles'\nimport { ThemeController } from '../../lib/theme'\n\n/**\n * <uip-progress> — the registry Progress (Radix Progress Root + Indicator).\n *\n * The track (`part=\"base\"`, role=progressbar) and the indicator\n * (`part=\"indicator\"`) carry React's class strings and Radix's ARIA/data\n * attributes. `value` is clamped to 0–100 like React. The host's\n * `aria-label` is forwarded to the progressbar (default \"Progress\").\n *\n * React's `className` → style the parts from outside, e.g.\n * `class=\"[&::part(base)]:h-3 [&::part(indicator)]:bg-success\"`.\n */\nexport class UipProgress extends LitElement {\n  // :host display can't be a utility class (the host has no template of its own).\n  static styles = [tailwind, css`:host { display: block; }`]\n\n  static properties = {\n    value: { type: Number },\n    max: { type: Number },\n    accessibleLabel: { attribute: 'aria-label' },\n  }\n\n  value?: number | null\n  max = 100\n  accessibleLabel?: string\n\n  constructor() {\n    super()\n    new ThemeController(this)\n  }\n\n  connectedCallback() {\n    super.connectedCallback()\n    this.setAttribute('data-uipkge', '')\n    this.setAttribute('data-slot', 'progress')\n  }\n\n  render() {\n    // Clamp so out-of-range value cannot push the indicator past the track.\n    const clamped = Math.min(100, Math.max(0, this.value ?? 0))\n    // Radix: an invalid max falls back to 100.\n    const max = this.max > 0 ? this.max : 100\n    const state = clamped === max ? 'complete' : 'loading'\n    return html`<div\n      part=\"base\"\n      role=\"progressbar\"\n      aria-valuemax=${max}\n      aria-valuemin=\"0\"\n      aria-valuenow=${clamped}\n      aria-valuetext=${`${Math.round((clamped / max) * 100)}%`}\n      aria-label=${this.accessibleLabel ?? 'Progress'}\n      data-state=${state}\n      data-value=${clamped}\n      data-max=${max}\n      data-uipkge=\"\"\n      data-slot=\"progress\"\n      class=\"bg-primary/20 relative h-2 w-full overflow-hidden rounded-full\"\n    >\n      <div\n        part=\"indicator\"\n        data-state=${state}\n        data-value=${clamped}\n        data-max=${max}\n        data-uipkge=\"\"\n        data-slot=\"progress-indicator\"\n        class=\"bg-primary h-full w-full flex-1 transition-transform duration-500 ease-out motion-reduce:transition-none\"\n        style=${styleMap({ transform: `translateX(-${100 - clamped}%)` })}\n      ></div>\n    </div>`\n  }\n}\n\ncustomElements.get('uip-progress') || customElements.define('uip-progress', UipProgress)\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'uip-progress': UipProgress\n  }\n}\n",
      "type": "registry:file",
      "target": "src/uip/components/progress/progress.ts"
    }
  ],
  "dependencies": [
    "lit"
  ],
  "registryDependencies": [
    "https://uipkge.dev/r/lit/lit-core.json"
  ]
}
