{
  "name": "Progress",
  "category": "Feedback",
  "subcategory": null,
  "description": "Linear progress bar with determinate + indeterminate modes.",
  "thumbnail": "/preview-cards/progress.png",
  "hasDocsPage": true,
  "nugetPackage": "Lumeo",
  "files": [
    "UI/Progress/CircularProgress.razor",
    "UI/Progress/Progress.razor",
    "UI/Progress/StepsProgress.razor"
  ],
  "dependencies": [],
  "packageDependencies": [
    "Blazicons.Lucide"
  ],
  "cssVars": [
    "--color-destructive",
    "--color-foreground",
    "--color-muted",
    "--color-muted-foreground",
    "--color-primary",
    "--color-primary-foreground",
    "--radius"
  ],
  "api": {
    "name": "Progress",
    "category": "Feedback",
    "subcategory": null,
    "description": "Linear progress bar with determinate + indeterminate modes.",
    "nugetPackage": "Lumeo",
    "files": [
      "UI/Progress/CircularProgress.razor",
      "UI/Progress/Progress.razor",
      "UI/Progress/StepsProgress.razor"
    ],
    "namespace": "Lumeo",
    "inheritsFrom": null,
    "implements": [],
    "parameters": [
      {
        "name": "Value",
        "type": "int",
        "default": null,
        "description": null,
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "Max",
        "type": "int",
        "default": "100",
        "description": null,
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "Variant",
        "type": "ProgressVariant",
        "default": "ProgressVariant.Default",
        "description": null,
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "Shape",
        "type": "ProgressShape",
        "default": "ProgressShape.Linear",
        "description": null,
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "IsIndeterminate",
        "type": "bool",
        "default": null,
        "description": null,
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "ShowLabel",
        "type": "bool",
        "default": null,
        "description": null,
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "ShowValue",
        "type": "bool",
        "default": null,
        "description": null,
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "Label",
        "type": "string?",
        "default": null,
        "description": null,
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "Striped",
        "type": "bool",
        "default": null,
        "description": null,
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "Animated",
        "type": "bool",
        "default": null,
        "description": null,
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "Animation",
        "type": "ProgressAnimation",
        "default": "ProgressAnimation.None",
        "description": "Opt-in animation variant for the linear progress fill. None (default) leaves existing behaviour untouched. Stripe overlays translucent diagonal stripes that sweep across the bar.",
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "GradientFrom",
        "type": "string?",
        "default": null,
        "description": null,
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "GradientTo",
        "type": "string?",
        "default": null,
        "description": null,
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "Size",
        "type": "string",
        "default": "\"Default\"",
        "description": null,
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "StrokeWidth",
        "type": "int",
        "default": "4",
        "description": null,
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "Class",
        "type": "string?",
        "default": null,
        "description": null,
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "AdditionalAttributes",
        "type": "Dictionary<string, object>?",
        "default": null,
        "description": null,
        "isCascading": false,
        "captureUnmatched": true
      }
    ],
    "events": [],
    "enums": [
      {
        "name": "ProgressVariant",
        "values": [
          "Default",
          "Success",
          "Warning",
          "Destructive"
        ],
        "description": null
      },
      {
        "name": "ProgressShape",
        "values": [
          "Linear",
          "Circular"
        ],
        "description": null
      },
      {
        "name": "ProgressAnimation",
        "values": [
          "None",
          "Stripe",
          "Indeterminate",
          "Glow"
        ],
        "description": "Animation variants for linear progress."
      }
    ],
    "records": [],
    "cssVars": [
      "--color-destructive",
      "--color-foreground",
      "--color-muted",
      "--color-muted-foreground",
      "--color-primary",
      "--color-primary-foreground",
      "--radius"
    ],
    "examples": [
      {
        "title": "Default",
        "code": "<Progress Value=\"25\" />\n<Progress Value=\"50\" />\n<Progress Value=\"75\" />"
      },
      {
        "title": "Variants",
        "code": "<Progress Value=\"60\" />\n<Progress Value=\"100\" Variant=\"Progress.ProgressVariant.Success\" />\n<Progress Value=\"45\" Variant=\"Progress.ProgressVariant.Warning\" />\n<Progress Value=\"80\" Variant=\"Progress.ProgressVariant.Destructive\" />"
      },
      {
        "title": "Interactive",
        "code": "<Progress Value=\"@_value\" />\n<Flex Align=\"center\" Gap=\"2\">\n    <Button OnClick=\"Decrease\">-10</Button>\n    <Lumeo.Text As=\"span\" Size=\"sm\" Weight=\"medium\">@_value%</Lumeo.Text>\n    <Button OnClick=\"Increase\">+10</Button>\n</Flex>\n\n@code {\n    private int _value = 50;\n    private void Increase() => _value = Math.Min(100, _value + 10);\n    private void Decrease() => _value = Math.Max(0, _value - 10);\n}"
      },
      {
        "title": "Indeterminate",
        "code": "<Progress IsIndeterminate=\"true\" />\n<Progress IsIndeterminate=\"true\" Variant=\"Progress.ProgressVariant.Success\" />"
      }
    ],
    "subComponents": {
      "CircularProgress": {
        "componentName": "CircularProgress",
        "fileName": "CircularProgress.razor",
        "namespace": "Lumeo",
        "inheritsFrom": null,
        "implements": [],
        "parameters": [
          {
            "name": "Value",
            "type": "double",
            "default": null,
            "description": null,
            "isCascading": false,
            "captureUnmatched": false
          },
          {
            "name": "Max",
            "type": "double",
            "default": "100",
            "description": null,
            "isCascading": false,
            "captureUnmatched": false
          },
          {
            "name": "Size",
            "type": "int",
            "default": "64",
            "description": null,
            "isCascading": false,
            "captureUnmatched": false
          },
          {
            "name": "StrokeWidth",
            "type": "int",
            "default": "4",
            "description": null,
            "isCascading": false,
            "captureUnmatched": false
          },
          {
            "name": "ShowValue",
            "type": "bool",
            "default": "true",
            "description": null,
            "isCascading": false,
            "captureUnmatched": false
          },
          {
            "name": "Format",
            "type": "string?",
            "default": null,
            "description": null,
            "isCascading": false,
            "captureUnmatched": false
          },
          {
            "name": "ChildContent",
            "type": "RenderFragment?",
            "default": null,
            "description": null,
            "isCascading": false,
            "captureUnmatched": false
          },
          {
            "name": "Class",
            "type": "string?",
            "default": null,
            "description": null,
            "isCascading": false,
            "captureUnmatched": false
          },
          {
            "name": "AdditionalAttributes",
            "type": "Dictionary<string, object>?",
            "default": null,
            "description": null,
            "isCascading": false,
            "captureUnmatched": true
          }
        ],
        "events": [],
        "enums": [],
        "records": [],
        "parseFailed": false,
        "parseError": null
      },
      "StepsProgress": {
        "componentName": "StepsProgress",
        "fileName": "StepsProgress.razor",
        "namespace": "Lumeo",
        "inheritsFrom": null,
        "implements": [],
        "parameters": [
          {
            "name": "CurrentStep",
            "type": "int",
            "default": null,
            "description": null,
            "isCascading": false,
            "captureUnmatched": false
          },
          {
            "name": "Steps",
            "type": "List<string>?",
            "default": null,
            "description": null,
            "isCascading": false,
            "captureUnmatched": false
          },
          {
            "name": "Orientation",
            "type": "string",
            "default": "\"Horizontal\"",
            "description": null,
            "isCascading": false,
            "captureUnmatched": false
          },
          {
            "name": "Class",
            "type": "string?",
            "default": null,
            "description": null,
            "isCascading": false,
            "captureUnmatched": false
          },
          {
            "name": "AdditionalAttributes",
            "type": "Dictionary<string, object>?",
            "default": null,
            "description": null,
            "isCascading": false,
            "captureUnmatched": true
          }
        ],
        "events": [],
        "enums": [],
        "records": [],
        "parseFailed": false,
        "parseError": null
      }
    },
    "parseFailed": false,
    "parseError": null
  },
  "$schema": "https://lumeo.nativ.sh/registry-component-schema.json",
  "key": "progress",
  "docsUrl": "https://lumeo.nativ.sh/components/progress",
  "sourceUrl": [
    {
      "file": "UI/Progress/CircularProgress.razor",
      "url": "https://github.com/Brain2k-0005/Lumeo/tree/master/src/Lumeo/UI/Progress/CircularProgress.razor"
    },
    {
      "file": "UI/Progress/Progress.razor",
      "url": "https://github.com/Brain2k-0005/Lumeo/tree/master/src/Lumeo/UI/Progress/Progress.razor"
    },
    {
      "file": "UI/Progress/StepsProgress.razor",
      "url": "https://github.com/Brain2k-0005/Lumeo/tree/master/src/Lumeo/UI/Progress/StepsProgress.razor"
    }
  ],
  "source": [
    {
      "path": "UI/Progress/CircularProgress.razor",
      "content": "@namespace Lumeo\n\n<div class=\"@($\"inline-flex items-center justify-center {Class}\".Trim())\" @attributes=\"AdditionalAttributes\">\n    <svg width=\"@Size\" height=\"@Size\" viewBox=\"0 0 @Size @Size\" class=\"transform -rotate-90\">\n        <circle\n            cx=\"@Center\"\n            cy=\"@Center\"\n            r=\"@Radius\"\n            fill=\"none\"\n            stroke=\"currentColor\"\n            stroke-width=\"@StrokeWidth\"\n            class=\"text-muted/20\" />\n        <circle\n            cx=\"@Center\"\n            cy=\"@Center\"\n            r=\"@Radius\"\n            fill=\"none\"\n            stroke=\"currentColor\"\n            stroke-width=\"@StrokeWidth\"\n            stroke-dasharray=\"@Circumference\"\n            stroke-dashoffset=\"@DashOffset\"\n            stroke-linecap=\"round\"\n            class=\"text-primary transition-all duration-300\" />\n    </svg>\n    @if (ChildContent is not null)\n    {\n        <div class=\"absolute flex items-center justify-center\" style=\"width: @(Size)px; height: @(Size)px;\">\n            @ChildContent\n        </div>\n    }\n    else if (ShowValue)\n    {\n        <div class=\"absolute flex items-center justify-center\" style=\"width: @(Size)px; height: @(Size)px;\">\n            <span class=\"text-sm font-medium text-foreground\">@DisplayValue</span>\n        </div>\n    }\n</div>\n\n@code {\n    [Parameter] public double Value { get; set; }\n    [Parameter] public double Max { get; set; } = 100;\n    [Parameter] public int Size { get; set; } = 64;\n    [Parameter] public int StrokeWidth { get; set; } = 4;\n    [Parameter] public bool ShowValue { get; set; } = true;\n    [Parameter] public string? Format { get; set; }\n    [Parameter] public RenderFragment? ChildContent { get; set; }\n    [Parameter] public string? Class { get; set; }\n    [Parameter(CaptureUnmatchedValues = true)] public Dictionary<string, object>? AdditionalAttributes { get; set; }\n\n    private double Center => Size / 2.0;\n    private double Radius => (Size - StrokeWidth) / 2.0;\n    private double Circumference => 2 * Math.PI * Radius;\n    private double Percentage => Max > 0 ? Math.Clamp(Value / Max, 0, 1) : 0;\n    private double DashOffset => Circumference * (1 - Percentage);\n\n    private string DisplayValue => Format is not null\n        ? string.Format(Format, Value)\n        : $\"{(int)(Percentage * 100)}%\";\n}\n"
    },
    {
      "path": "UI/Progress/Progress.razor",
      "content": "@namespace Lumeo\n\n@if (IsIndeterminate && Shape == ProgressShape.Linear)\n{\n    <style>\n        @@keyframes progress-indeterminate {\n            0% { left: -35%; right: 100%; }\n            60% { left: 100%; right: -90%; }\n            100% { left: 100%; right: -90%; }\n        }\n        .animate-progress-indeterminate {\n            position: absolute;\n            top: 0;\n            bottom: 0;\n            width: 30%;\n            animation: progress-indeterminate 1.5s ease-in-out infinite;\n        }\n    </style>\n}\n\n@if (IsIndeterminate && Shape == ProgressShape.Circular)\n{\n    <style>\n        @@keyframes circular-indeterminate {\n            0% { transform: rotate(0deg); }\n            100% { transform: rotate(360deg); }\n        }\n        .animate-circular-indeterminate {\n            animation: circular-indeterminate 1.5s linear infinite;\n            transform-origin: center;\n        }\n    </style>\n}\n\n@if ((Striped || Animated) && Shape == ProgressShape.Linear)\n{\n    <style>\n        @@keyframes progress-stripes {\n            0% { background-position: 1rem 0; }\n            100% { background-position: 0 0; }\n        }\n        .progress-striped {\n            background-image: linear-gradient(\n                45deg,\n                var(--color-progress-stripe) 25%,\n                transparent 25%,\n                transparent 50%,\n                var(--color-progress-stripe) 50%,\n                var(--color-progress-stripe) 75%,\n                transparent 75%,\n                transparent\n            );\n            background-size: 1rem 1rem;\n        }\n        .progress-animated {\n            animation: progress-stripes 1s linear infinite;\n        }\n    </style>\n}\n\n@if (Shape == ProgressShape.Circular)\n{\n    @if (ShowLabel)\n    {\n        <div class=\"flex items-center gap-2\">\n            <div class=\"@CircularWrapperClass\" role=\"progressbar\" aria-valuenow=\"@(IsIndeterminate ? null : Value)\" aria-valuemin=\"0\" aria-valuemax=\"@Max\" @attributes=\"AdditionalAttributes\">\n                <svg viewBox=\"0 0 36 36\" class=\"@CircularSvgClass\" style=\"@CircularSizeStyle\">\n                    <circle cx=\"18\" cy=\"18\" r=\"@CircularRadius\" fill=\"none\" stroke=\"currentColor\" class=\"text-primary/20\" stroke-width=\"@StrokeWidth\" />\n                    <circle cx=\"18\" cy=\"18\" r=\"@CircularRadius\" fill=\"none\" stroke=\"currentColor\" class=\"@CircularStrokeColor\"\n                        stroke-width=\"@StrokeWidth\"\n                        stroke-dasharray=\"@Circumference.ToString(System.Globalization.CultureInfo.InvariantCulture)\"\n                        stroke-dashoffset=\"@DashOffset.ToString(System.Globalization.CultureInfo.InvariantCulture)\"\n                        stroke-linecap=\"round\"\n                        transform=\"rotate(-90 18 18)\"\n                        style=\"transition: stroke-dashoffset 0.3s ease\" />\n                </svg>\n                @if (ShowValue)\n                {\n                    <span class=\"absolute inset-0 flex items-center justify-center text-foreground @CircularTextSize\">@(Label ?? $\"{Percentage}%\")</span>\n                }\n            </div>\n            @if (!ShowValue)\n            {\n                <span class=\"text-sm text-muted-foreground whitespace-nowrap\">@(Label ?? $\"{Percentage}%\")</span>\n            }\n        </div>\n    }\n    else\n    {\n        <div class=\"@CircularWrapperClass\" role=\"progressbar\" aria-valuenow=\"@(IsIndeterminate ? null : Value)\" aria-valuemin=\"0\" aria-valuemax=\"@Max\" @attributes=\"AdditionalAttributes\">\n            <svg viewBox=\"0 0 36 36\" class=\"@CircularSvgClass\" style=\"@CircularSizeStyle\">\n                <circle cx=\"18\" cy=\"18\" r=\"@CircularRadius\" fill=\"none\" stroke=\"currentColor\" class=\"text-primary/20\" stroke-width=\"@StrokeWidth\" />\n                <circle cx=\"18\" cy=\"18\" r=\"@CircularRadius\" fill=\"none\" stroke=\"currentColor\" class=\"@CircularStrokeColor\"\n                    stroke-width=\"@StrokeWidth\"\n                    stroke-dasharray=\"@Circumference.ToString(System.Globalization.CultureInfo.InvariantCulture)\"\n                    stroke-dashoffset=\"@DashOffset.ToString(System.Globalization.CultureInfo.InvariantCulture)\"\n                    stroke-linecap=\"round\"\n                    transform=\"rotate(-90 18 18)\"\n                    style=\"transition: stroke-dashoffset 0.3s ease\" />\n            </svg>\n            @if (ShowValue)\n            {\n                <span class=\"absolute inset-0 flex items-center justify-center text-foreground @CircularTextSize\">@(Label ?? $\"{Percentage}%\")</span>\n            }\n        </div>\n    }\n}\nelse\n{\n    @if (ShowLabel)\n    {\n        <div class=\"flex items-center gap-2\">\n            <div class=\"@CssClass\" role=\"progressbar\" aria-valuenow=\"@(IsIndeterminate ? null : Value)\" aria-valuemin=\"0\" aria-valuemax=\"@Max\" @attributes=\"AdditionalAttributes\">\n                @if (IsIndeterminate)\n                {\n                    <div class=\"@($\"animate-progress-indeterminate rounded-[var(--radius)] {VariantClasses}\")\"></div>\n                }\n                else\n                {\n                    <div class=\"@IndicatorClasses\" style=\"@IndicatorStyle\"></div>\n                }\n            </div>\n            <span class=\"text-sm text-muted-foreground whitespace-nowrap\">@(Label ?? $\"{Percentage}%\")</span>\n        </div>\n    }\n    else\n    {\n        <div class=\"@CssClass\" role=\"progressbar\" aria-valuenow=\"@(IsIndeterminate ? null : Value)\" aria-valuemin=\"0\" aria-valuemax=\"@Max\" @attributes=\"AdditionalAttributes\">\n            @if (IsIndeterminate)\n            {\n                <div class=\"@($\"animate-progress-indeterminate rounded-[var(--radius)] {VariantClasses}\")\"></div>\n            }\n            else\n            {\n                <div class=\"@IndicatorClasses\" style=\"@IndicatorStyle\"></div>\n            }\n        </div>\n    }\n}\n\n@code {\n    [Parameter] public int Value { get; set; }\n    [Parameter] public int Max { get; set; } = 100;\n    [Parameter] public ProgressVariant Variant { get; set; } = ProgressVariant.Default;\n    [Parameter] public ProgressShape Shape { get; set; } = ProgressShape.Linear;\n    [Parameter] public bool IsIndeterminate { get; set; }\n    [Parameter] public bool ShowLabel { get; set; }\n    [Parameter] public bool ShowValue { get; set; }\n    [Parameter] public string? Label { get; set; }\n    [Parameter] public bool Striped { get; set; }\n    [Parameter] public bool Animated { get; set; }\n\n    /// <summary>\n    /// Opt-in animation variant for the linear progress fill. <c>None</c> (default)\n    /// leaves existing behaviour untouched. <c>Stripe</c> overlays translucent\n    /// diagonal stripes that sweep across the bar.\n    /// </summary>\n    [Parameter] public ProgressAnimation Animation { get; set; } = ProgressAnimation.None;\n    [Parameter] public string? GradientFrom { get; set; }\n    [Parameter] public string? GradientTo { get; set; }\n    [Parameter] public string Size { get; set; } = \"Default\";\n    [Parameter] public int StrokeWidth { get; set; } = 4;\n    [Parameter] public string? Class { get; set; }\n    [Parameter(CaptureUnmatchedValues = true)] public Dictionary<string, object>? AdditionalAttributes { get; set; }\n\n    private int Percentage => Max > 0 ? Math.Min(100, (int)((double)Value / Max * 100)) : 0;\n\n    // --- Linear progress ---\n    private string SizeClass => Size switch\n    {\n        \"Small\" => \"h-1\",\n        \"Large\" => \"h-4\",\n        _ => \"h-2\"\n    };\n\n    private string CssClass => string.Join(\" \", new[] { \"relative\", SizeClass, \"w-full overflow-hidden rounded-[var(--radius)] bg-primary/20\", Class }.Where(s => !string.IsNullOrWhiteSpace(s)));\n\n    private string IndicatorClasses\n    {\n        get\n        {\n            var stripeClasses = Striped || Animated ? \"progress-striped\" : null;\n            var animClasses = Animated ? \"progress-animated\" : null;\n            var enumStripeClass = Animation == ProgressAnimation.Stripe ? \"lumeo-progress-stripes\" : null;\n            var enumIndeterminateClass = Animation == ProgressAnimation.Indeterminate ? \"lumeo-progress-indeterminate\" : null;\n            var enumGlowClass = Animation == ProgressAnimation.Glow ? \"lumeo-progress-glow\" : null;\n            // Indeterminate sweep uses currentColor for its ::before pseudo — swap bg-* → text-* so the variant color feeds through.\n            var colorClasses = (GradientFrom is not null && GradientTo is not null)\n                ? null\n                : (Animation == ProgressAnimation.Indeterminate ? IndeterminateColorClasses : VariantClasses);\n            return string.Join(\" \", new[] { \"h-full rounded-[var(--radius)] transition-all duration-300\", colorClasses, stripeClasses, animClasses, enumStripeClass, enumIndeterminateClass, enumGlowClass }.Where(s => !string.IsNullOrWhiteSpace(s)));\n        }\n    }\n\n    private string IndeterminateColorClasses => Variant switch\n    {\n        ProgressVariant.Default => \"text-primary\",\n        ProgressVariant.Success => \"text-success\",\n        ProgressVariant.Warning => \"text-warning\",\n        ProgressVariant.Destructive => \"text-destructive\",\n        _ => \"text-primary\"\n    };\n\n    private string IndicatorStyle\n    {\n        get\n        {\n            // `Indeterminate` animation hides the fill and lets a narrow\n            // pseudo-element slide across the track — so force 100% width and\n            // fully transparent background so only the ::before sweep shows.\n            if (Animation == ProgressAnimation.Indeterminate)\n            {\n                return \"width: 100%; background: transparent\";\n            }\n            var width = $\"width: {Percentage}%\";\n            if (GradientFrom is not null && GradientTo is not null)\n            {\n                return $\"{width}; background: linear-gradient(90deg, {GradientFrom}, {GradientTo})\";\n            }\n            return width;\n        }\n    }\n\n    private string VariantClasses => Variant switch\n    {\n        ProgressVariant.Default => \"bg-primary\",\n        ProgressVariant.Success => \"bg-success\",\n        ProgressVariant.Warning => \"bg-warning\",\n        ProgressVariant.Destructive => \"bg-destructive\",\n        _ => \"bg-primary\"\n    };\n\n    // --- Circular progress ---\n    private const double CircularRadius = 16;\n    private double Circumference => 2 * Math.PI * CircularRadius;\n    private double DashOffset => IsIndeterminate ? Circumference * 0.75 : Circumference * (1.0 - Percentage / 100.0);\n\n    private string CircularSizeStyle => Size switch\n    {\n        \"Small\" => \"width: 40px; height: 40px\",\n        \"Large\" => \"width: 80px; height: 80px\",\n        _ => \"width: 56px; height: 56px\"\n    };\n\n    private string CircularTextSize => Size switch\n    {\n        \"Small\" => \"text-[10px] font-medium\",\n        \"Large\" => \"text-sm font-semibold\",\n        _ => \"text-xs font-medium\"\n    };\n\n    private string CircularWrapperClass => string.Join(\" \", new[] { \"relative inline-flex items-center justify-center\", Class }.Where(s => !string.IsNullOrWhiteSpace(s)));\n\n    private string CircularSvgClass => IsIndeterminate ? \"animate-circular-indeterminate\" : \"\";\n\n    private string CircularStrokeColor => Variant switch\n    {\n        ProgressVariant.Default => \"text-primary\",\n        ProgressVariant.Success => \"text-success\",\n        ProgressVariant.Warning => \"text-warning\",\n        ProgressVariant.Destructive => \"text-destructive\",\n        _ => \"text-primary\"\n    };\n\n    public enum ProgressVariant { Default, Success, Warning, Destructive }\n    public enum ProgressShape { Linear, Circular }\n\n    /// <summary>Animation variants for linear progress.</summary>\n    /// <remarks>\n    /// <list type=\"bullet\">\n    /// <item><c>None</c> — no animation (default).</item>\n    /// <item><c>Stripe</c> — translucent diagonal stripes sweep across the fill.</item>\n    /// <item><c>Indeterminate</c> — a narrow bright segment slides continuously.\n    /// The bound <c>Value</c> is visually ignored while this plays.</item>\n    /// <item><c>Glow</c> — the fill bar's box-shadow breathes, suggesting activity.</item>\n    /// </list>\n    /// </remarks>\n    public enum ProgressAnimation { None, Stripe, Indeterminate, Glow }\n}\n"
    },
    {
      "path": "UI/Progress/StepsProgress.razor",
      "content": "@namespace Lumeo\n\n@if (Steps is not null && Steps.Count > 0)\n{\n    @if (Orientation == \"Vertical\")\n    {\n        <div class=\"@($\"flex flex-col {Class}\".Trim())\" @attributes=\"AdditionalAttributes\">\n            @for (var i = 0; i < Steps.Count; i++)\n            {\n                var index = i;\n                var isCompleted = index < CurrentStep;\n                var isCurrent = index == CurrentStep;\n                <div class=\"flex items-start gap-3\">\n                    <div class=\"flex flex-col items-center\">\n                        <div class=\"@StepCircleClasses(isCompleted, isCurrent)\">\n                            @if (isCompleted)\n                            {\n                                <Blazicon Svg=\"Lucide.Check\" class=\"h-3.5 w-3.5\" />\n                            }\n                            else\n                            {\n                                <span class=\"text-xs font-medium\">@(index + 1)</span>\n                            }\n                        </div>\n                        @if (index < Steps.Count - 1)\n                        {\n                            <div class=\"@($\"w-0.5 min-h-[2rem] flex-1 {(isCompleted ? \"bg-primary\" : \"bg-muted\")}\")\"></div>\n                        }\n                    </div>\n                    <div class=\"pb-6\">\n                        <p class=\"@($\"text-sm font-medium {(isCompleted || isCurrent ? \"text-foreground\" : \"text-muted-foreground\")}\")\">@Steps[index]</p>\n                    </div>\n                </div>\n            }\n        </div>\n    }\n    else\n    {\n        <div class=\"@($\"flex w-full items-center {Class}\".Trim())\" @attributes=\"AdditionalAttributes\">\n            @for (var i = 0; i < Steps.Count; i++)\n            {\n                var index = i;\n                var isCompleted = index < CurrentStep;\n                var isCurrent = index == CurrentStep;\n                <div class=\"flex flex-1 flex-col items-center gap-2\">\n                    <div class=\"flex w-full items-center\">\n                        @if (index > 0)\n                        {\n                            <div class=\"@($\"h-0.5 flex-1 {(index <= CurrentStep ? \"bg-primary\" : \"bg-muted\")}\")\"></div>\n                        }\n                        else\n                        {\n                            <div class=\"flex-1\"></div>\n                        }\n                        <div class=\"@StepCircleClasses(isCompleted, isCurrent)\">\n                            @if (isCompleted)\n                            {\n                                <Blazicon Svg=\"Lucide.Check\" class=\"h-3.5 w-3.5\" />\n                            }\n                            else\n                            {\n                                <span class=\"text-xs font-medium\">@(index + 1)</span>\n                            }\n                        </div>\n                        @if (index < Steps.Count - 1)\n                        {\n                            <div class=\"@($\"h-0.5 flex-1 {(isCompleted ? \"bg-primary\" : \"bg-muted\")}\")\"></div>\n                        }\n                        else\n                        {\n                            <div class=\"flex-1\"></div>\n                        }\n                    </div>\n                    <span class=\"@($\"text-xs text-center {(isCompleted || isCurrent ? \"text-foreground font-medium\" : \"text-muted-foreground\")}\")\">@Steps[index]</span>\n                </div>\n            }\n        </div>\n    }\n}\n\n@code {\n    [Parameter] public int CurrentStep { get; set; }\n    [Parameter] public List<string>? Steps { get; set; }\n    [Parameter] public string Orientation { get; set; } = \"Horizontal\";\n    [Parameter] public string? Class { get; set; }\n    [Parameter(CaptureUnmatchedValues = true)] public Dictionary<string, object>? AdditionalAttributes { get; set; }\n\n    private string StepCircleClasses(bool isCompleted, bool isCurrent)\n    {\n        var baseClasses = \"flex h-8 w-8 shrink-0 items-center justify-center rounded-full text-sm transition-colors\";\n        if (isCompleted)\n            return $\"{baseClasses} bg-primary text-primary-foreground\";\n        if (isCurrent)\n            return $\"{baseClasses} border-2 border-primary text-primary\";\n        return $\"{baseClasses} bg-muted text-muted-foreground\";\n    }\n}\n"
    }
  ],
  "slots": [
    {
      "name": "ChildContent",
      "owner": "CircularProgress",
      "type": "RenderFragment?",
      "description": null
    }
  ],
  "serviceDependencies": [],
  "cascadingDependencies": [],
  "relatedComponents": [
    {
      "name": "CircularProgress",
      "reason": "sub-component"
    },
    {
      "name": "StepsProgress",
      "reason": "sub-component"
    }
  ],
  "keyboardInteractions": [],
  "tests": [
    "tests/Lumeo.Tests/Components/Progress/ProgressAnimatedTests.cs",
    "tests/Lumeo.Tests/Components/Progress/ProgressAnimationVariantsTests.cs",
    "tests/Lumeo.Tests/Components/Progress/ProgressTests.cs",
    "tests/Lumeo.Tests/Contract/ComponentContractTests.cs"
  ],
  "mdSummary": "# Progress\n\nLinear progress bar with determinate + indeterminate modes.\n\n**Package:** `Lumeo` · **Category:** Feedback\n**Docs:** https://lumeo.nativ.sh/components/progress\n\n## Parameters\n| Owner | Name | Type | Default | Description |\n|---|---|---|---|---|\n| Progress | Value | `int` | `` |  |\n| Progress | Max | `int` | `100` |  |\n| Progress | Variant | `ProgressVariant` | `ProgressVariant.Default` |  |\n| Progress | Shape | `ProgressShape` | `ProgressShape.Linear` |  |\n| Progress | IsIndeterminate | `bool` | `` |  |\n| Progress | ShowLabel | `bool` | `` |  |\n| Progress | ShowValue | `bool` | `` |  |\n| Progress | Label | `string?` | `` |  |\n| Progress | Striped | `bool` | `` |  |\n| Progress | Animated | `bool` | `` |  |\n| Progress | Animation | `ProgressAnimation` | `ProgressAnimation.None` | Opt-in animation variant for the linear progress fill. None (default) leaves existing behaviour untouched. Stripe overlays translucent diagonal stripes that sweep across the bar. |\n| Progress | GradientFrom | `string?` | `` |  |\n| Progress | GradientTo | `string?` | `` |  |\n| Progress | Size | `string` | `\"Default\"` |  |\n| Progress | StrokeWidth | `int` | `4` |  |\n| Progress | Class | `string?` | `` |  |\n| Progress | AdditionalAttributes | `Dictionary<string, object>?` | `` |  |\n| CircularProgress | Value | `double` | `` |  |\n| CircularProgress | Max | `double` | `100` |  |\n| CircularProgress | Size | `int` | `64` |  |\n| CircularProgress | StrokeWidth | `int` | `4` |  |\n| CircularProgress | ShowValue | `bool` | `true` |  |\n| CircularProgress | Format | `string?` | `` |  |\n| CircularProgress | ChildContent | `RenderFragment?` | `` |  |\n| CircularProgress | Class | `string?` | `` |  |\n| CircularProgress | AdditionalAttributes | `Dictionary<string, object>?` | `` |  |\n| StepsProgress | CurrentStep | `int` | `` |  |\n| StepsProgress | Steps | `List<string>?` | `` |  |\n| StepsProgress | Orientation | `string` | `\"Horizontal\"` |  |\n| StepsProgress | Class | `string?` | `` |  |\n| StepsProgress | AdditionalAttributes | `Dictionary<string, object>?` | `` |  |\n\n## Slots\n- `ChildContent` (CircularProgress) — RenderFragment slot\n\n## Events\n- (none)\n\n## Sub-components\n- `CircularProgress`, `StepsProgress`\n\n## Cascading values it expects\n- (none)\n\n## Services it injects\n- (none)\n\n## Keyboard\n—\n\n## Example\n```razor\n<Progress />\n```\n\n## CSS variables\n`--color-destructive`, `--color-foreground`, `--color-muted`, `--color-muted-foreground`, `--color-primary`, `--color-primary-foreground`, `--radius`\n\n## Files\n- `UI/Progress/CircularProgress.razor`\n- `UI/Progress/Progress.razor`\n- `UI/Progress/StepsProgress.razor`\n"
}