'use strict';

var jsxRuntime = require('react/jsx-runtime');
var React = require('react');
var reactI18next = require('react-i18next');
var reactColorful = require('react-colorful');
var primitives_Button = require('./primitives/Button.js');
var primitives_Popover = require('./primitives/Popover.js');
var utils = require('./utils-CTr7wn5d.js');
var index = require('./index-BZhTddX0.js');
var chevronDown = require('./chevron-down-CPsWSS51.js');
var createLucideIcon = require('./createLucideIcon-D0tRgV6l.js');

/**
 * @license lucide-react v0.577.0 - ISC
 *
 * This source code is licensed under the ISC license.
 * See the LICENSE file in the root directory of this source tree.
 */


const __iconNode = [
  [
    "path",
    {
      d: "m12 9-8.414 8.414A2 2 0 0 0 3 18.828v1.344a2 2 0 0 1-.586 1.414A2 2 0 0 1 3.828 21h1.344a2 2 0 0 0 1.414-.586L15 12",
      key: "1y3wsu"
    }
  ],
  [
    "path",
    {
      d: "m18 9 .4.4a1 1 0 1 1-3 3l-3.8-3.8a1 1 0 1 1 3-3l.4.4 3.4-3.4a1 1 0 1 1 3 3z",
      key: "110lr1"
    }
  ],
  ["path", { d: "m2 22 .414-.414", key: "jhxm08" }]
];
const Pipette = createLucideIcon.createLucideIcon("pipette", __iconNode);

const isSupported = typeof window !== "undefined" && "EyeDropper" in window;
const useEyeDropper = () => {
    const open = React.useCallback(async () => {
        if (!window.EyeDropper)
            throw new Error("EyeDropper API not supported");
        const dropper = new window.EyeDropper();
        const result = await dropper.open();
        return result.sRGBHex;
    }, []);
    return { isSupported, open };
};

const DEFAULT_PALETTE_COLORS = [
    { hex: "#FFFFFF" },
    { hex: "#D6D6D6" },
    { hex: "#0A0E13" },
    { hex: "#FECE1E" },
    { hex: "#F32E48" },
    { hex: "#02C39A" },
    { hex: "#2A79C4" },
    { hex: "#B3E5FC" },
    { hex: "#C3C6F9" },
    { hex: "#8064CE" },
    { hex: "#FE861E" },
    { hex: "#FF7DC9" },
    { hex: "#028090" },
    { hex: "#095482" },
];
const RECENTLY_USED_STORAGE_KEY = "recently-used-colors";
const PICKER_HEIGHT = {
    small: "100px",
    medium: "120px",
    large: "140px",
};

const getFromStorage = (key, fallback) => {
    try {
        const stored = localStorage.getItem(key);
        return stored ? JSON.parse(stored) : fallback;
    }
    catch {
        return fallback;
    }
};
const setToStorage = (key, value) => {
    try {
        localStorage.setItem(key, JSON.stringify(value));
    }
    catch {
        // Silently fail if storage is unavailable
    }
};
const createSyncedStore = (storageKey) => {
    const listeners = new Set();
    const store = {
        value: getFromStorage(storageKey, []),
        getSnapshot: () => store.value,
        getServerSnapshot: () => [],
        setValue: (newValue) => {
            store.value = newValue;
            setToStorage(storageKey, newValue);
            listeners.forEach(listener => listener());
        },
        subscribe: (callback) => {
            listeners.add(callback);
            const storageEventHandler = (event) => {
                if (event.key !== storageKey)
                    return;
                store.value = getFromStorage(storageKey, []);
                listeners.forEach(listener => listener());
            };
            if (listeners.size === 1) {
                window.addEventListener("storage", storageEventHandler);
            }
            return () => {
                listeners.delete(callback);
                if (listeners.size === 0) {
                    window.removeEventListener("storage", storageEventHandler);
                }
            };
        },
    };
    return store;
};
const store = createSyncedStore(RECENTLY_USED_STORAGE_KEY);
const useRecentlyUsedColors = () => [
    React.useSyncExternalStore(store.subscribe, store.getSnapshot, store.getServerSnapshot),
    store.setValue,
];

/**
 * Validates a hex color string (3, 4, 6, or 8 digits with optional #).
 */
const isValidHex = (hex) => /^#?([0-9A-Fa-f]{3}|[0-9A-Fa-f]{4}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/.test(hex);
/**
 * Parses a hex color string into RGBA components.
 * Returns { r: 0, g: 0, b: 0, a: 1 } for invalid inputs.
 */
const hexToRgb = (hex) => {
    const raw = hex.replace(/^#/, "");
    if (!/^([0-9A-Fa-f]{3}|[0-9A-Fa-f]{4}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/.test(raw)) {
        return { r: 0, g: 0, b: 0, a: 1 };
    }
    let r, g, b, a = 255;
    if (raw.length === 3 || raw.length === 4) {
        r = parseInt(raw[0] + raw[0], 16);
        g = parseInt(raw[1] + raw[1], 16);
        b = parseInt(raw[2] + raw[2], 16);
        if (raw.length === 4)
            a = parseInt(raw[3] + raw[3], 16);
    }
    else {
        r = parseInt(raw.slice(0, 2), 16);
        g = parseInt(raw.slice(2, 4), 16);
        b = parseInt(raw.slice(4, 6), 16);
        if (raw.length === 8)
            a = parseInt(raw.slice(6, 8), 16);
    }
    return { r, g, b, a: Math.round((a / 255) * 100) / 100 };
};
/**
 * Converts a hex color to an 8-digit hex string (#RRGGBBAA).
 */
const hexToHex8 = (hex) => {
    const { r, g, b, a } = hexToRgb(hex);
    const alpha = Math.round(a * 255);
    return `#${[r, g, b, alpha].map(v => v.toString(16).padStart(2, "0")).join("")}`;
};
/**
 * Converts a color value to a normalized { hex, rgb } object.
 * Handles transparency and validity checks.
 */
const getColor = (colorValue, showTransparencyControl) => {
    if (!isValidHex(colorValue)) {
        return { hex: colorValue, rgb: { r: 0, g: 0, b: 0, a: 1 } };
    }
    const rgb = hexToRgb(colorValue);
    if (rgb.a === 0) {
        return { hex: colorValue, rgb };
    }
    const hex = showTransparencyControl
        ? hexToHex8(colorValue)
        : `#${colorValue.replace(/^#/, "").slice(0, 6)}`;
    return { hex, rgb: hexToRgb(hex) };
};

const Palette = React.forwardRef(({ color, colorList = DEFAULT_PALETTE_COLORS, onChange, className, ...props }, ref) => (jsxRuntime.jsx("div", { ref: ref, className: utils.cn("flex flex-row flex-wrap items-start justify-start gap-1", className), ...props, children: colorList.map(item => {
        const rgbValue = "rgb" in item && typeof item.rgb === "string" ? item.rgb : undefined;
        const value = item.hex ?? rgbValue ?? "";
        const isActive = !!color && !!value && color.toLowerCase() === value.toLowerCase();
        return (jsxRuntime.jsx("button", { type: "button", "data-testid": "color-palette-item", className: utils.cn("size-6 rounded-[5px] border cursor-pointer overflow-hidden transition-colors", isActive
                ? "border-muted-foreground"
                : "border-border hover:border-muted-foreground/50"), onClick: () => onChange?.(value), children: jsxRuntime.jsx("span", { className: utils.cn("block size-full", isValidHex(value)
                    ? ""
                    : "bg-[repeating-conic-gradient(#ccc_0_25%,transparent_0_50%)] bg-[length:8px_8px]"), style: isValidHex(value) ? { backgroundColor: value } : undefined }) }, value));
    }) })));
Palette.displayName = "ColorPicker.Palette";

const targetVariants = index.cva("inline-flex items-center justify-between rounded-md border border-input bg-background transition-colors hover:border-muted-foreground focus-visible:outline-none focus-visible:border-primary focus-visible:ring-3 focus-visible:ring-primary/15 cursor-pointer", {
    variants: {
        size: {
            small: "h-7 p-0.5 gap-2",
            medium: "h-8 p-1 gap-2",
            large: "h-10 p-1.5 gap-3",
        },
    },
    defaultVariants: {
        size: "large",
    },
});
const Target = React.forwardRef(({ size = "large", showHexValue, color, colorValue, className, ...props }, ref) => (jsxRuntime.jsxs("button", { ref: ref, type: "button", "data-testid": "color-picker-target", className: utils.cn(targetVariants({ size }), className), ...props, children: [showHexValue && (jsxRuntime.jsx("span", { className: "text-sm font-medium text-foreground min-w-[4.5rem] ps-1", children: color })), jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-2", children: [jsxRuntime.jsx("span", { className: "block size-5 rounded-md border border-border", style: { backgroundColor: colorValue } }), jsxRuntime.jsx(chevronDown.ChevronDown, { className: "size-4 text-muted-foreground" })] })] })));
Target.displayName = "ColorPicker.Target";

const ColorPicker = React.forwardRef(({ color = "", size = "large", onChange, dropdownProps, showEyeDropper = true, showHexValue = false, showTransparencyControl = false, showPicker = true, showHexPicker = true, colorPalette, showRecentlyUsedColors = showPicker, className, }, ref) => {
    const { t } = reactI18next.useTranslation();
    const [colorInternal, setColorInternal] = React.useState(color);
    const [isColorSelected, setIsColorSelected] = React.useState(false);
    const [open, setOpen] = React.useState(false);
    const hexColorInputValue = React.useRef("");
    const { isSupported: eyeDropperSupported, open: openEyeDropper } = useEyeDropper();
    const [recentlyUsedColors, setRecentlyUsedColors] = useRecentlyUsedColors();
    const PickerComponent = showTransparencyControl
        ? reactColorful.HexAlphaColorPicker
        : reactColorful.HexColorPicker;
    const colorValue = color ?? colorInternal ?? "";
    const onColorChange = (value) => {
        setIsColorSelected(true);
        if (onChange) {
            onChange(getColor(value, showTransparencyControl));
        }
        else {
            setColorInternal(value);
        }
    };
    const onColorInputChange = (hex) => {
        hexColorInputValue.current = hex;
        const expectedLength = showTransparencyControl ? 9 : 7;
        if (hex.length !== expectedLength)
            return;
        onColorChange(hex);
        hexColorInputValue.current = "";
    };
    const onBlur = () => {
        if (!hexColorInputValue.current)
            return;
        onColorChange(hexColorInputValue.current);
        hexColorInputValue.current = "";
    };
    const pickColor = async () => {
        try {
            const hex = await openEyeDropper();
            onColorChange(hex);
        }
        catch {
            // User cancelled or API unavailable
        }
    };
    const onOpenChange = (nextOpen) => {
        if (!nextOpen && showRecentlyUsedColors && isColorSelected) {
            const newColor = getColor(colorValue, showTransparencyControl);
            const filtered = recentlyUsedColors.filter(({ hex }) => hex !== newColor.hex);
            const updated = [newColor, ...filtered];
            if (updated.length > 14)
                updated.pop();
            setRecentlyUsedColors(updated);
            setIsColorSelected(false);
        }
        setOpen(nextOpen);
    };
    return (jsxRuntime.jsxs(primitives_Popover.Popover, { open: open, onOpenChange: onOpenChange, children: [jsxRuntime.jsx(primitives_Popover.PopoverTrigger, { asChild: true, children: jsxRuntime.jsx(Target, { color: color, colorValue: colorValue, showHexValue: showHexValue, size: size }) }), jsxRuntime.jsx(primitives_Popover.PopoverContent, { ref: ref, align: "start", side: "bottom", className: utils.cn("w-auto p-3", className), ...dropdownProps, children: jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 w-56", children: [showPicker && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [showHexPicker && (jsxRuntime.jsx("div", { "data-testid": "neeto-color-picker-section", style: {
                                        ["--react-colorful-height"]: PICKER_HEIGHT[size] ?? "140px",
                                    }, children: jsxRuntime.jsx(PickerComponent, { color: colorValue, onChange: onColorChange, style: {
                                            width: "100%",
                                            height: PICKER_HEIGHT[size] ?? "140px",
                                        } }) })), jsxRuntime.jsxs("div", { className: "flex items-center justify-center gap-2", children: [showEyeDropper && eyeDropperSupported && (jsxRuntime.jsx(primitives_Button.Button, { type: "button", variant: "ghost", size: "icon-sm", onClick: pickColor, "aria-label": t("neetoatoms.colorPicker.pickColor", "Pick color from screen"), children: jsxRuntime.jsx(Pipette, { className: "size-4" }) })), jsxRuntime.jsx("div", { className: "flex-1", "data-testid": "colorpicker-editable-input", children: jsxRuntime.jsx(reactColorful.HexColorInput, { prefixed: true, alpha: !!showTransparencyControl, color: colorValue, "data-testid": "colorpicker-editable-input-textbox", onChange: onColorInputChange, onBlur: onBlur, className: "h-8 w-full rounded-lg border border-input bg-transparent px-2.5 text-sm outline-none focus-visible:border-primary focus-visible:ring-3 focus-visible:ring-primary/15" }) })] })] })), jsxRuntime.jsx("div", { "data-testid": "color-palette", className: utils.cn(showPicker && "border-t border-border pt-3"), children: jsxRuntime.jsx(Palette, { color: color, colorList: colorPalette, onChange: onColorChange }) }), showRecentlyUsedColors && recentlyUsedColors.length > 0 && (jsxRuntime.jsxs("div", { className: "border-t border-border pt-3", "data-testid": "color-palette-recently-used", children: [jsxRuntime.jsx("p", { className: "text-xs font-medium text-muted-foreground mb-2", children: t("neetoatoms.colorPicker.recentlyUsed", "Recently used") }), jsxRuntime.jsx(Palette, { colorList: recentlyUsedColors, onChange: onColorChange })] }))] }) })] }));
});
ColorPicker.displayName = "ColorPicker";

exports.ColorPicker = ColorPicker;
//# sourceMappingURL=ColorPicker-Uxgn8U0h.js.map
