{
  "name": "ImageCompare",
  "category": "Data Display",
  "subcategory": "Cards & Layout",
  "description": "Before/after slider comparison for two images.",
  "thumbnail": "/preview-cards/image-compare.png",
  "hasDocsPage": true,
  "nugetPackage": "Lumeo",
  "files": [
    "UI/ImageCompare/ImageCompare.razor"
  ],
  "dependencies": [],
  "packageDependencies": [],
  "cssVars": [
    "--color-background",
    "--color-foreground",
    "--radius"
  ],
  "api": {
    "name": "ImageCompare",
    "category": "Data Display",
    "subcategory": "Cards & Layout",
    "description": "Before/after slider comparison for two images.",
    "nugetPackage": "Lumeo",
    "files": [
      "UI/ImageCompare/ImageCompare.razor"
    ],
    "namespace": "Lumeo",
    "inheritsFrom": null,
    "implements": [],
    "parameters": [
      {
        "name": "BeforeSrc",
        "type": "string",
        "default": "\"\"",
        "description": null,
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "AfterSrc",
        "type": "string",
        "default": "\"\"",
        "description": null,
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "BeforeLabel",
        "type": "string?",
        "default": "\"Before\"",
        "description": null,
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "AfterLabel",
        "type": "string?",
        "default": "\"After\"",
        "description": null,
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "InitialPosition",
        "type": "int",
        "default": "50",
        "description": null,
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "Width",
        "type": "string",
        "default": "\"100%\"",
        "description": null,
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "Height",
        "type": "string",
        "default": "\"400px\"",
        "description": null,
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "Orientation",
        "type": "ImageCompareOrientation",
        "default": "ImageCompareOrientation.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": [
      {
        "name": "ImageCompareOrientation",
        "values": [
          "Horizontal",
          "Vertical"
        ],
        "description": null
      }
    ],
    "records": [],
    "cssVars": [
      "--color-background",
      "--color-foreground",
      "--radius"
    ],
    "examples": [
      {
        "title": "Horizontal Comparison",
        "code": "<ImageCompare BeforeSrc=\"before.jpg\" AfterSrc=\"after.jpg\"\n             BeforeLabel=\"Before\" AfterLabel=\"After\" Height=\"320px\" />"
      },
      {
        "title": "Vertical Comparison",
        "code": "<ImageCompare BeforeSrc=\"img1.jpg\" AfterSrc=\"img2.jpg\"\n             Orientation=\"ImageCompare.ImageCompareOrientation.Vertical\"\n             Height=\"320px\" />"
      },
      {
        "title": "Orientation (interactive)",
        "code": "<Segmented @bind-Value=\"_orientation\">\n    <SegmentedItem Value=\"@ImageCompare.ImageCompareOrientation.Horizontal\">Horizontal</SegmentedItem>\n    <SegmentedItem Value=\"@ImageCompare.ImageCompareOrientation.Vertical\">Vertical</SegmentedItem>\n</Segmented>\n<ImageCompare BeforeSrc=\"before.jpg\" AfterSrc=\"after.jpg\"\n             BeforeLabel=\"Before\" AfterLabel=\"After\"\n             Orientation=\"@_orientation\" Height=\"280px\" />\n\n@code { private ImageCompare.ImageCompareOrientation _orientation = ImageCompare.ImageCompareOrientation.Horizontal; }"
      },
      {
        "title": "Custom Initial Position",
        "code": "<ImageCompare BeforeSrc=\"before.jpg\" AfterSrc=\"after.jpg\"\n             InitialPosition=\"25\" Height=\"280px\" />"
      }
    ],
    "subComponents": {},
    "parseFailed": false,
    "parseError": null
  },
  "$schema": "https://lumeo.nativ.sh/registry-component-schema.json",
  "key": "image-compare",
  "docsUrl": "https://lumeo.nativ.sh/components/image-compare",
  "sourceUrl": [
    {
      "file": "UI/ImageCompare/ImageCompare.razor",
      "url": "https://github.com/Brain2k-0005/Lumeo/tree/master/src/Lumeo/UI/ImageCompare/ImageCompare.razor"
    }
  ],
  "source": [
    {
      "path": "UI/ImageCompare/ImageCompare.razor",
      "content": "@namespace Lumeo\n\n@* Uses a transparent <input type=\"range\"> for drag handling — the browser does all the math,\n   so the slider tracks the pointer exactly whether the container is fixed px or fluid %. *@\n<div class=\"@CssClass\"\n     style=\"width: @Width; height: @Height; position: relative; overflow: hidden; user-select: none;\"\n     @attributes=\"AdditionalAttributes\">\n\n    @* After image (full size, behind) *@\n    <img src=\"@AfterSrc\" alt=\"@AfterLabel\" draggable=\"false\"\n         style=\"position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; pointer-events: none;\" />\n\n    @* Before image (clipped via clip-path — no scaling tricks, exact pixel-for-pixel reveal) *@\n    <img src=\"@BeforeSrc\" alt=\"@BeforeLabel\" draggable=\"false\"\n         style=\"position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; pointer-events: none; clip-path: @ClipPath;\" />\n\n    @* Divider line *@\n    @if (Orientation == ImageCompareOrientation.Horizontal)\n    {\n        <div class=\"bg-background/90 pointer-events-none\" style=\"position: absolute; top: 0; bottom: 0; left: @(PositionPct); transform: translateX(-50%); width: 2px;\"></div>\n    }\n    else\n    {\n        <div class=\"bg-background/90 pointer-events-none\" style=\"position: absolute; left: 0; right: 0; top: @(PositionPct); transform: translateY(-50%); height: 2px;\"></div>\n    }\n\n    @* Handle *@\n    @if (Orientation == ImageCompareOrientation.Horizontal)\n    {\n        <div class=\"bg-background text-foreground shadow-md pointer-events-none flex items-center justify-center rounded-full\" style=\"position: absolute; top: 50%; left: @(PositionPct); transform: translate(-50%, -50%); width: 36px; height: 36px;\">\n            <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\"\n                 stroke=\"currentColor\" stroke-width=\"2.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n                <path d=\"M9 6 3 12l6 6\" />\n                <path d=\"m15 6 6 6-6 6\" />\n            </svg>\n        </div>\n    }\n    else\n    {\n        <div class=\"bg-background text-foreground shadow-md pointer-events-none flex items-center justify-center rounded-full\" style=\"position: absolute; left: 50%; top: @(PositionPct); transform: translate(-50%, -50%); width: 36px; height: 36px;\">\n            <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\"\n                 stroke=\"currentColor\" stroke-width=\"2.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n                <path d=\"m6 9 6-6 6 6\" />\n                <path d=\"m6 15 6 6 6-6\" />\n            </svg>\n        </div>\n    }\n\n    @* Labels *@\n    @if (!string.IsNullOrEmpty(BeforeLabel))\n    {\n        <span class=\"bg-foreground/60 text-background pointer-events-none\" style=\"position: absolute; top: 10px; left: 10px; font-size: 12px; font-weight: 500; padding: 2px 8px; border-radius: 4px;\">\n            @BeforeLabel\n        </span>\n    }\n    @if (!string.IsNullOrEmpty(AfterLabel))\n    {\n        <span class=\"bg-foreground/60 text-background pointer-events-none\" style=\"position: absolute; top: 10px; right: 10px; font-size: 12px; font-weight: 500; padding: 2px 8px; border-radius: 4px;\">\n            @AfterLabel\n        </span>\n    }\n\n    @* Transparent range input layered on top — the browser handles drag math. *@\n    <input type=\"range\" min=\"0\" max=\"100\" step=\"0.1\"\n           value=\"@_position.ToString(\"F2\", System.Globalization.CultureInfo.InvariantCulture)\"\n           @oninput=\"OnInput\"\n           aria-label=\"Image compare slider\"\n           class=\"lumeo-image-compare-slider\"\n           style=\"@SliderStyle\" />\n</div>\n\n@code {\n    [Parameter] public string BeforeSrc { get; set; } = \"\";\n    [Parameter] public string AfterSrc { get; set; } = \"\";\n    [Parameter] public string? BeforeLabel { get; set; } = \"Before\";\n    [Parameter] public string? AfterLabel { get; set; } = \"After\";\n    [Parameter] public int InitialPosition { get; set; } = 50;\n    [Parameter] public string Width { get; set; } = \"100%\";\n    [Parameter] public string Height { get; set; } = \"400px\";\n    [Parameter] public ImageCompareOrientation Orientation { get; set; } = ImageCompareOrientation.Horizontal;\n    [Parameter] public string? Class { get; set; }\n    [Parameter(CaptureUnmatchedValues = true)] public Dictionary<string, object>? AdditionalAttributes { get; set; }\n\n    private double _position;\n\n    private string CssClass => $\"rounded-lg overflow-hidden {Class}\".Trim();\n\n    private string PositionPct => $\"{_position.ToString(\"F2\", System.Globalization.CultureInfo.InvariantCulture)}%\";\n\n    private string ClipPath => Orientation == ImageCompareOrientation.Horizontal\n        ? $\"inset(0 {(100 - _position).ToString(\"F2\", System.Globalization.CultureInfo.InvariantCulture)}% 0 0)\"\n        : $\"inset(0 0 {(100 - _position).ToString(\"F2\", System.Globalization.CultureInfo.InvariantCulture)}% 0)\";\n\n    private string SliderStyle =>\n        Orientation == ImageCompareOrientation.Horizontal\n            ? \"position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: ew-resize; appearance: none; -webkit-appearance: none; background: transparent; margin: 0;\"\n            : \"position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: ns-resize; appearance: none; -webkit-appearance: none; background: transparent; margin: 0; writing-mode: vertical-lr; direction: ltr;\";\n\n    public enum ImageCompareOrientation { Horizontal, Vertical }\n\n    protected override void OnInitialized()\n    {\n        _position = Math.Clamp(InitialPosition, 1, 99);\n    }\n\n    private void OnInput(ChangeEventArgs e)\n    {\n        if (e.Value is string s && double.TryParse(s, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out var v))\n        {\n            _position = Math.Clamp(v, 1, 99);\n        }\n    }\n}\n"
    }
  ],
  "slots": [],
  "serviceDependencies": [],
  "cascadingDependencies": [],
  "relatedComponents": [],
  "keyboardInteractions": [],
  "tests": [
    "tests/Lumeo.Tests/Components/ImageCompare/ImageCompareTests.cs"
  ],
  "mdSummary": "# ImageCompare\n\nBefore/after slider comparison for two images.\n\n**Package:** `Lumeo` · **Category:** Data Display/Cards & Layout\n**Docs:** https://lumeo.nativ.sh/components/image-compare\n\n## Parameters\n| Owner | Name | Type | Default | Description |\n|---|---|---|---|---|\n| ImageCompare | BeforeSrc | `string` | `\"\"` |  |\n| ImageCompare | AfterSrc | `string` | `\"\"` |  |\n| ImageCompare | BeforeLabel | `string?` | `\"Before\"` |  |\n| ImageCompare | AfterLabel | `string?` | `\"After\"` |  |\n| ImageCompare | InitialPosition | `int` | `50` |  |\n| ImageCompare | Width | `string` | `\"100%\"` |  |\n| ImageCompare | Height | `string` | `\"400px\"` |  |\n| ImageCompare | Orientation | `ImageCompareOrientation` | `ImageCompareOrientation.Horizontal` |  |\n| ImageCompare | Class | `string?` | `` |  |\n| ImageCompare | AdditionalAttributes | `Dictionary<string, object>?` | `` |  |\n\n## Slots\n- (none)\n\n## Events\n- (none)\n\n## Sub-components\n- (none)\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<ImageCompare />\n```\n\n## CSS variables\n`--color-background`, `--color-foreground`, `--radius`\n\n## Files\n- `UI/ImageCompare/ImageCompare.razor`\n"
}