// #region Imports
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
import { HTMLElementEventEmitter } from '@breadstone/mosaik-elements';
import chroma from 'chroma-js';
import { Emit } from '../../../../events/Decorators/EmitDecorator';
import { Disableable } from '../../../Behaviors/Disableable';
import { Focusable } from '../../../Behaviors/Focusable';
import { Themeable } from '../../../Behaviors/Themeable';
import { Attribute } from '../../../Decorators/AttributeDecorator';
import { Component } from '../../../Decorators/ComponentDecorator';
import { Property } from '../../../Decorators/PropertyDecorator';
import { CustomElement } from '../../Abstracts/CustomElement';
import { ColorEditorAlphaSliderElement } from './ColorEditorAlphaSliderElement';
import { ColorEditorAreaElement } from './ColorEditorAreaElement';
import { colorEditorElementTemplate } from './ColorEditorElementTemplate';
import { ColorEditorHueSliderElement } from './ColorEditorHueSliderElement';
import { ColorEditorInputsElement } from './ColorEditorInputsElement';
import { ColorEditorPaletteElement } from './ColorEditorPaletteElement';
import { ColorEditorSwatchElement } from './ColorEditorSwatchElement';
import { IColorPalette } from './IColorPalette';
import { colorEditorElementCosmopolitanStyle } from './Themes/ColorEditorElement.Cosmopolitan';
import { colorEditorElementJoyStyle } from './Themes/ColorEditorElement.Joy';
import { colorEditorElementMemphisStyle } from './Themes/ColorEditorElement.Memphis';
// #endregion
/**
 * Color Editor - A comprehensive color picker component with area, sliders, inputs, and palette.
 *
 * @description
 * The Color Editor component is a complete color picker solution that combines multiple
 * sub-components to provide a rich color selection experience. It includes:
 * - A 2D saturation/value area for fine-tuning color
 * - A hue slider for selecting the base hue
 * - An optional alpha slider for transparency
 * - A color swatch preview
 * - Input fields for precise color entry in multiple formats
 * - Optional color palettes for quick selection
 *
 * All sub-components can be enabled or disabled individually, allowing for
 * customizable color picker configurations.
 *
 * @name ColorEditor
 * @element mosaik-color-editor
 * @category Media
 *
 * @slot alpha-slider - Custom alpha slider component
 * @slot area - Custom color area component
 * @slot eye-dropper - The eye-dropper slot.
 * @slot hue-slider - Custom hue slider component
 * @slot inputs - Custom inputs component
 * @slot palette - Custom palette component
 * @slot swatch - Custom color swatch component
 *
 * @csspart tools - The main tools container
 * @csspart eye-dropper-button - The eye-dropper-button part.
 * @csspart inputs - Container for input fields
 * @csspart palette - Container for color palette
 * @csspart sliders - Container for hue and alpha sliders
 * @csspart tools - The tools part.
 * @csspart tools-row - Row container for sliders and swatch
 *
 * @cssprop {String} --color-editor-background-color - The editor background color CSS custom property.
 * @cssprop {String} --color-editor-border-color - The editor border color CSS custom property.
 * @cssprop {String} --color-editor-border-radius - The editor border radius CSS custom property.
 * @cssprop {String} --color-editor-border-style - The editor border style CSS custom property.
 * @cssprop {String} --color-editor-border-width - The editor border width CSS custom property.
 * @cssprop {String} --color-editor-focus-ring-active-width - The editor focus ring active width CSS custom property.
 * @cssprop {String} --color-editor-focus-ring-color - The editor focus ring color CSS custom property.
 * @cssprop {String} --color-editor-focus-ring-inward-offset - The editor focus ring inward offset CSS custom property.
 * @cssprop {String} --color-editor-focus-ring-outward-offset - The editor focus ring outward offset CSS custom property.
 * @cssprop {String} --color-editor-font-family - The editor font family CSS custom property.
 * @cssprop {String} --color-editor-font-letter-spacing - The editor font letter spacing CSS custom property.
 * @cssprop {String} --color-editor-font-line-height - The editor font line height CSS custom property.
 * @cssprop {String} --color-editor-font-size - The editor font size CSS custom property.
 * @cssprop {String} --color-editor-font-text-decoration - The editor font text decoration CSS custom property.
 * @cssprop {String} --color-editor-font-text-transform - The editor font text transform CSS custom property.
 * @cssprop {String} --color-editor-font-weight - The editor font weight CSS custom property.
 * @cssprop {String} --color-editor-foreground-color - The editor foreground color CSS custom property.
 * @cssprop {String} --color-editor-gap - The editor gap CSS custom property.
 * @cssprop {String} --color-editor-height - The editor height CSS custom property.
 * @cssprop {String} --color-editor-padding-bottom - The editor padding bottom CSS custom property.
 * @cssprop {String} --color-editor-padding-left - The editor padding left CSS custom property.
 * @cssprop {String} --color-editor-padding-right - The editor padding right CSS custom property.
 * @cssprop {String} --color-editor-padding-top - The editor padding top CSS custom property.
 * @cssprop {String} --color-editor-shadow - The editor shadow CSS custom property.
 * @cssprop {String} --color-editor-shadow-blur - The editor shadow blur CSS custom property.
 * @cssprop {String} --color-editor-shadow-color - The editor shadow color CSS custom property.
 * @cssprop {String} --color-editor-shadow-offset-x - The editor shadow offset x CSS custom property.
 * @cssprop {String} --color-editor-shadow-offset-y - The editor shadow offset y CSS custom property.
 * @cssprop {String} --color-editor-shadow-spread - The editor shadow spread CSS custom property.
 * @cssprop {String} --color-editor-transition-duration - The editor transition duration CSS custom property.
 * @cssprop {String} --color-editor-transition-mode - The editor transition mode CSS custom property.
 * @cssprop {String} --color-editor-transition-property - The editor transition property CSS custom property.
 * @cssprop {String} --color-editor-translate - The editor translate CSS custom property.
 * @cssprop {String} --color-editor-width - The editor width CSS custom property.
 *
 * @fires colorChanged {ColorChangedEvent} - Fired when the color value changes
 * @fires colorFormatChanged {ColorFormatChangedEvent} - Fired when the color format is changed
 * @fires paletteChanged {PaletteChangedEvent} - Fired when custom palette colors change
 *
 * @dependency mosaik-button - The Button element.
 * @dependency mosaik-color-editor-alpha-slider - The Color Editor Alpha Slider element.
 * @dependency mosaik-color-editor-area - The Color Editor Area element.
 * @dependency mosaik-color-editor-hue-slider - The Color Editor Hue Slider element.
 * @dependency mosaik-color-editor-inputs - The Color Editor Inputs element.
 * @dependency mosaik-color-editor-palette - The Color Editor Palette element.
 * @dependency mosaik-color-editor-swatch - The Color Editor Swatch element.
 *
 * @example
 * Basic usage:
 * ```html
 * <mosaik-color-editor></mosaik-color-editor>
 * ```
 *
 * @example
 * With an initial color and format:
 * ```html
 * <mosaik-color-editor color="#4a90d9" format="hex"></mosaik-color-editor>
 * ```
 *
 * @example
 * Disabled state:
 * ```html
 * <mosaik-color-editor color="#ff0000" disabled></mosaik-color-editor>
 * ```
 *
 * @public
 */
let ColorEditorElement = class ColorEditorElement extends Themeable(Disableable(Focusable(CustomElement))) {
    // #region Fields
    _colorChanged;
    _colorFormatChanged;
    _paletteChanged;
    _color;
    _format;
    _showAlpha;
    _showInputs;
    _showPalette;
    _showEyeDropper;
    _showSwatch;
    _palettes;
    _selectedPalette;
    _hue;
    _saturation;
    _value;
    _alpha;
    // #endregion
    // #region Ctor
    /**
     * Constructs a new instance of the ColorEditorElement class.
     *
     * @public
     */
    constructor() {
        super();
        this._colorChanged = new HTMLElementEventEmitter(this, 'colorChanged');
        this._colorFormatChanged = new HTMLElementEventEmitter(this, 'colorFormatChanged');
        this._paletteChanged = new HTMLElementEventEmitter(this, 'paletteChanged');
        this._color = '#ff0000';
        this._format = 'hex';
        this._showAlpha = true;
        this._showInputs = true;
        this._showPalette = true;
        this._showEyeDropper = false;
        this._showSwatch = true;
        this._palettes = IColorPalette.allPalettes();
        this._selectedPalette = IColorPalette.MATERIAL_PALETTE.title;
        this._hue = 0;
        this._saturation = 1;
        this._value = 1;
        this._alpha = 1;
        this.syncHsvFromColor();
    }
    // #endregion
    // #region Properties
    /**
     * Returns the `is` property.
     * The `is` property represents natural name of this element.
     *
     * @public
     * @static
     * @readonly
     */
    static get is() {
        return 'mosaik-color-editor';
    }
    /**
     * Gets or sets the color value.
     *
     * @public
     * @attr
     */
    get color() {
        return this._color;
    }
    set color(value) {
        if (this._color !== value) {
            this._color = value;
            this.syncHsvFromColor();
            this.requestUpdate('color');
        }
    }
    /**
     * Gets or sets the color format for the inputs.
     *
     * @public
     * @attr
     */
    get format() {
        return this._format;
    }
    set format(value) {
        if (this._format !== value) {
            this._format = value;
            this.requestUpdate('format');
        }
    }
    /**
     * Gets or sets whether to show the alpha slider and input.
     *
     * @public
     */
    get showAlpha() {
        return this._showAlpha;
    }
    set showAlpha(value) {
        if (this._showAlpha !== value) {
            this._showAlpha = value;
            this.requestUpdate('showAlpha');
        }
    }
    /**
     * Gets or sets whether to show the color inputs.
     *
     * @public
     */
    get showInputs() {
        return this._showInputs;
    }
    set showInputs(value) {
        if (this._showInputs !== value) {
            this._showInputs = value;
            this.requestUpdate('showInputs');
        }
    }
    /**
     * Gets or sets whether to show the color palette.
     *
     * @public
     */
    get showPalette() {
        return this._showPalette;
    }
    set showPalette(value) {
        if (this._showPalette !== value) {
            this._showPalette = value;
            this.requestUpdate('showPalette');
        }
    }
    /**
     * Gets or sets whether to show the eye dropper button.
     *
     * @public
     */
    get showEyeDropper() {
        return this._showEyeDropper;
    }
    set showEyeDropper(value) {
        if (this._showEyeDropper !== value) {
            this._showEyeDropper = value;
            this.requestUpdate('showEyeDropper');
        }
    }
    /**
     * Gets or sets whether to show the color swatch preview.
     *
     * @public
     */
    get showSwatch() {
        return this._showSwatch;
    }
    set showSwatch(value) {
        if (this._showSwatch !== value) {
            this._showSwatch = value;
            this.requestUpdate('showSwatch');
        }
    }
    /**
     * Gets or sets the available color palettes.
     *
     * @public
     */
    get palettes() {
        return this._palettes;
    }
    set palettes(value) {
        if (this._palettes !== value) {
            this._palettes = value;
            this.requestUpdate('palettes');
        }
    }
    /**
     * Gets or sets the currently selected palette name.
     *
     * @public
     * @attr
     */
    get selectedPalette() {
        return this._selectedPalette;
    }
    set selectedPalette(value) {
        if (this._selectedPalette !== value) {
            this._selectedPalette = value;
            this.requestUpdate('selectedPalette');
        }
    }
    /**
     * Called when the color value changes.
     * Provides reference to `IColorChangedEventDetail` as event detail.
     *
     * @public
     * @readonly
     * @eventProperty
     */
    get colorChanged() {
        return this._colorChanged;
    }
    /**
     * Called when the color format is changed.
     * Provides reference to `IColorFormatChangedEventDetail` as event detail.
     *
     * @public
     * @readonly
     * @eventProperty
     */
    get colorFormatChanged() {
        return this._colorFormatChanged;
    }
    /**
     * Called when custom palette colors change.
     * Provides reference to `IPaletteChangedEventDetail` as event detail.
     *
     * @public
     * @readonly
     * @eventProperty
     */
    get paletteChanged() {
        return this._paletteChanged;
    }
    // #endregion
    // #region Properties (Additional)
    /**
     * Gets the current hue value.
     *
     * @public
     * @readonly
     */
    get hue() {
        return this._hue;
    }
    /**
     * Gets the current saturation value.
     *
     * @public
     * @readonly
     */
    get saturation() {
        return this._saturation;
    }
    /**
     * Gets the current value (brightness).
     *
     * @public
     * @readonly
     */
    get value() {
        return this._value;
    }
    /**
     * Gets the current alpha value.
     *
     * @public
     * @readonly
     */
    get alpha() {
        return this._alpha;
    }
    // #endregion
    // #region Methods
    /**
     * Gets the display color for templates.
     *
     * @public
     */
    getDisplayColor() {
        return this.buildColorFromHsv();
    }
    /**
     * Handles area change events.
     *
     * @private
     */
    onAreaChange(event) {
        this._saturation = event.detail.saturation;
        this._value = event.detail.value;
        this.updateColorAndEmit();
    }
    /**
     * Handles hue slider change events.
     *
     * @private
     */
    onHueChange(event) {
        this._hue = event.detail.hue;
        this.updateColorAndEmit();
    }
    /**
     * Handles alpha slider change events.
     *
     * @private
     */
    onAlphaChange(event) {
        this._alpha = event.detail.alpha;
        this.updateColorAndEmit();
    }
    /**
     * Handles inputs change events.
     *
     * @private
     */
    onInputsChange(event) {
        this._color = event.detail.color;
        this.syncHsvFromColor();
        this.requestUpdate();
        this._colorChanged.emit({
            color: this._color,
            hue: this._hue,
            saturation: this._saturation,
            value: this._value,
            alpha: this._alpha
        });
    }
    /**
     * Handles inputs format change events.
     *
     * @private
     */
    onInputsFormatChange(event) {
        this._format = event.detail.format;
        this.requestUpdate('format');
        this._colorFormatChanged.emit({
            format: this._format
        });
    }
    /**
     * Handles palette color selection.
     *
     * @private
     */
    onPaletteSelect(event) {
        this._color = event.detail.color;
        this.syncHsvFromColor();
        this.requestUpdate();
        this._colorChanged.emit({
            color: this._color,
            hue: this._hue,
            saturation: this._saturation,
            value: this._value,
            alpha: this._alpha
        });
    }
    /**
     * Handles palette add button click.
     *
     * @private
     */
    onPaletteAdd(event) {
        const color = event.detail.color;
        const customPalette = this._palettes.find((p) => p.mutable === true);
        if (customPalette && !customPalette.colors.includes(color)) {
            customPalette.colors.push(color);
            this.requestUpdate('palettes');
            const found = this._palettes.find((p) => p.mutable === true);
            this._paletteChanged.emit({
                colors: found ? [...found.colors] : []
            });
        }
    }
    /**
     * Handles palette change.
     *
     * @private
     */
    onPaletteChange(event) {
        this._selectedPalette = event.detail.palette ?? '';
    }
    /**
     * Opens the native eye dropper tool (if supported).
     *
     * @private
     */
    async onOpenEyeDropper() {
        if (!('EyeDropper' in window)) {
            console.warn('EyeDropper API is not supported in this browser.');
            return;
        }
        try {
            // @ts-expect-error EyeDropper is not typed in all TS versions
            const eyeDropper = new window.EyeDropper();
            const result = await eyeDropper.open();
            if (result?.sRGBHex) {
                this.color = result.sRGBHex;
                this._colorChanged.emit({
                    color: this._color,
                    hue: this._hue,
                    saturation: this._saturation,
                    value: this._value,
                    alpha: this._alpha
                });
            }
        }
        catch (error) {
            // User canceled or error occurred
            console.debug('EyeDropper operation canceled or failed:', error);
        }
    }
    /**
     * Syncs internal HSV state from the color property.
     *
     * @private
     */
    syncHsvFromColor() {
        try {
            const chromaColor = chroma(this._color);
            const [h, s, v] = chromaColor.hsv();
            this._hue = isNaN(h) ? this._hue : h;
            this._saturation = s;
            this._value = v;
            this._alpha = chromaColor.alpha();
        }
        catch {
            // Keep current HSV values if color is invalid
        }
    }
    /**
     * Builds a color string from internal HSV state.
     *
     * @private
     */
    buildColorFromHsv() {
        const chromaColor = chroma.hsv(this._hue, this._saturation, this._value).alpha(this._alpha);
        if (this._alpha < 1) {
            return chromaColor.css();
        }
        return chromaColor.hex();
    }
    /**
     * Updates the color property from HSV state and emits change event.
     *
     * @private
     */
    updateColorAndEmit() {
        this._color = this.buildColorFromHsv();
        this.requestUpdate();
        this._colorChanged.emit({
            color: this._color,
            hue: this._hue,
            saturation: this._saturation,
            value: this._value,
            alpha: this._alpha
        });
    }
};
__decorate([
    Attribute({ type: String }),
    __metadata("design:type", String),
    __metadata("design:paramtypes", [String])
], ColorEditorElement.prototype, "color", null);
__decorate([
    Attribute({ type: String }),
    __metadata("design:type", String),
    __metadata("design:paramtypes", [String])
], ColorEditorElement.prototype, "format", null);
__decorate([
    Property({
        type: Boolean,
        useDefault: true
    }),
    __metadata("design:type", Boolean),
    __metadata("design:paramtypes", [Boolean])
], ColorEditorElement.prototype, "showAlpha", null);
__decorate([
    Property({
        type: Boolean,
        useDefault: true
    }),
    __metadata("design:type", Boolean),
    __metadata("design:paramtypes", [Boolean])
], ColorEditorElement.prototype, "showInputs", null);
__decorate([
    Property({
        type: Boolean,
        useDefault: true
    }),
    __metadata("design:type", Boolean),
    __metadata("design:paramtypes", [Boolean])
], ColorEditorElement.prototype, "showPalette", null);
__decorate([
    Property({
        type: Boolean,
        useDefault: true
    }),
    __metadata("design:type", Boolean),
    __metadata("design:paramtypes", [Boolean])
], ColorEditorElement.prototype, "showEyeDropper", null);
__decorate([
    Property({
        type: Boolean,
        useDefault: true
    }),
    __metadata("design:type", Boolean),
    __metadata("design:paramtypes", [Boolean])
], ColorEditorElement.prototype, "showSwatch", null);
__decorate([
    Property({ type: Array }),
    __metadata("design:type", Array),
    __metadata("design:paramtypes", [Array])
], ColorEditorElement.prototype, "palettes", null);
__decorate([
    Attribute({ type: String }),
    __metadata("design:type", String),
    __metadata("design:paramtypes", [String])
], ColorEditorElement.prototype, "selectedPalette", null);
__decorate([
    Emit({ eventName: 'colorChanged' }),
    __metadata("design:type", Object),
    __metadata("design:paramtypes", [])
], ColorEditorElement.prototype, "colorChanged", null);
__decorate([
    Emit({ eventName: 'colorFormatChanged' }),
    __metadata("design:type", Object),
    __metadata("design:paramtypes", [])
], ColorEditorElement.prototype, "colorFormatChanged", null);
__decorate([
    Emit({ eventName: 'paletteChanged' }),
    __metadata("design:type", Object),
    __metadata("design:paramtypes", [])
], ColorEditorElement.prototype, "paletteChanged", null);
ColorEditorElement = __decorate([
    Component({
        selector: 'mosaik-color-editor',
        template: colorEditorElementTemplate,
        themes: {
            joy: colorEditorElementJoyStyle,
            memphis: colorEditorElementMemphisStyle,
            cosmopolitan: colorEditorElementCosmopolitanStyle
        },
        imports: [
            ColorEditorAreaElement,
            ColorEditorHueSliderElement,
            ColorEditorAlphaSliderElement,
            ColorEditorSwatchElement,
            ColorEditorInputsElement,
            ColorEditorPaletteElement
        ]
    }),
    __metadata("design:paramtypes", [])
], ColorEditorElement);
export { ColorEditorElement };
//# sourceMappingURL=ColorEditorElement.js.map