import { r as registerInstance, h, H as Host, a as getElement } from './index-B2f84Zog.js';

let missingAssetPathWarning = false;
/**
 *
 * Reads the component asset path config from meta tag or a global variable.
 * This is a temporary workaround until these issues have been addressed:
 *
 * https://github.com/ionic-team/stencil/issues/2826/
 * https://github.com/ionic-team/stencil/issues/3470
 * https://github.com/ionic-team/stencil-ds-output-targets/issues/186
 */
const getAssetPath = (path) => {
    var _a;
    const metaPineAssetPath = (_a = document.head.querySelector('meta[data-pine-asset-path]')) === null || _a === void 0 ? void 0 : _a.dataset.pineAssetPath;
    // Get the asset path from the window object if available
    const windowAssetPath = window.__PINE_ASSET_PATH__;
    // Set the CDN Asset path using the latest version
    const cdnAssetPath = 'https://cdn.jsdelivr.net/npm/@pine-ds/icons/dist/';
    const assetBasePath = metaPineAssetPath || windowAssetPath || cdnAssetPath;
    // Display a warning if the assets are fetched from the CDN.
    if (assetBasePath.startsWith('https://cdn.jsdelivr.net/npm/') && !missingAssetPathWarning) {
        missingAssetPathWarning = true;
        console.warn(`
      Fetching Pine assets from jsDelivr CDN.\n\n It's recommended that you bundle Pine Assets with your application and set the path accordingly.\n\nFor more information, read the documentation: \nhttps://pine-design-system.netlify.app/?path=/docs/resources-assets--docs
    `);
    }
    let assetPath = path;
    if (path.startsWith('./')) {
        assetPath = path.substring(2);
    }
    if (!assetBasePath.endsWith('/')) {
        assetPath = '/' + assetPath;
    }
    return assetBasePath + assetPath;
};

let CACHED_MAP;
const getIconMap = () => {
    if (typeof window === 'undefined') {
        return new Map();
    }
    else {
        if (!CACHED_MAP) {
            const win = window; // eslint-disable-line @typescript-eslint/no-explicit-any
            win.PdsIcons = win.PdsIcons || {};
            CACHED_MAP = win.PdsIcons.map = win.PdsIcons.map || new Map();
        }
        return CACHED_MAP;
    }
};
const getName = (iconName, icon) => {
    if (!iconName && icon && !isSrc(icon)) {
        iconName = icon;
    }
    if (isStr(iconName)) {
        iconName = toLower(iconName);
    }
    if (!isStr(iconName) || iconName.trim() === '') {
        return null;
    }
    const invalidChars = iconName.replace(/[a-z]|-|\d/gi, '');
    if (invalidChars != '') {
        return null;
    }
    return iconName;
};
const getNamedUrl = (iconName) => {
    const url = getIconMap().get(iconName);
    if (url) {
        return url;
    }
    return getAssetPath(`svg/${iconName}.svg`);
};
const getSrc = (src) => {
    if (isStr(src)) {
        src = src.trim();
        if (isSrc(src)) {
            return src;
        }
    }
    return null;
};
const getUrl = (pdsIcon) => {
    let url = getSrc(pdsIcon.src);
    if (url) {
        return url;
    }
    url = getName(pdsIcon.name, pdsIcon.icon);
    if (url) {
        return getNamedUrl(url);
    }
    if (pdsIcon.icon) {
        url = getSrc(pdsIcon.icon);
        if (url) {
            return url;
        }
    }
    return null;
};
/**
 * Returns `true` if the document or host element
 * has a `dir` set to `rtl`. The host value will always
 * take priority over the root document value.
 */
const isRTL = (hostEl) => {
    if (hostEl) {
        if (hostEl.dir !== '') {
            return hostEl.dir.toLowerCase() === 'rtl';
        }
    }
    return (document === null || document === void 0 ? void 0 : document.dir.toLowerCase()) === 'rtl';
};
const isSrc = (str) => str.length > 0 && /(\/|\.)/.test(str);
const isStr = (val) => typeof val === 'string'; // eslint-disable-line @typescript-eslint/no-explicit-any
const toLower = (val) => val.toLowerCase();
/**
 * Elements inside of web components sometimes need to inherit global attributes
 * set on the host. For example, the inner input in `pds-input` should inherit
 * the `title` attribute that developers set directly on `pds-input`. This
 * helper function should be called in componentWillLoad and assigned to a variable
 * that is later used in the render function.
 *
 * This does not need to be reactive as changing attributes on the host element
 * does not trigger a re-render.
 */
const inheritAttributes = (el, attributes = []) => {
    const attributeObject = {}; // eslint-disable-line @typescript-eslint/no-explicit-any
    attributes.forEach(attr => {
        if (el.hasAttribute(attr)) {
            const value = el.getAttribute(attr);
            if (value !== null) {
                attributeObject[attr] = el.getAttribute(attr);
            }
            el.removeAttribute(attr);
        }
    });
    return attributeObject;
};
/**
 * Determines if an icon should be flipped when RTL is enabled
 * @param iconName - The name of the icon to check
 * @param hostEl - Optional host element to check for RTL direction
 * @returns {boolean} - True if the icon should be flipped in RTL mode, false otherwise
 */
const shouldRtlFlipIcon = (iconName, hostEl) => {
    // First check if we're in RTL mode
    const rtlEnabled = isRTL(hostEl);
    // Only flip if we're in RTL mode and the icon is in the flip list
    return rtlEnabled && ICONS_TO_FLIP.includes(iconName);
};
/**
 * Array of available icon names
 */
const ICONS_TO_FLIP = [
    'align-horizontal-bottom',
    'align-horizontal-center',
    'align-horizontal-top',
    'align-left',
    'align-right',
    'align-vertical-left',
    'align-vertical-right',
    'arrow-corner',
    'arrow-left',
    'arrow-right',
    'calendar-schedule',
    'caret-left',
    'caret-right',
    'cart',
    'cart-add',
    'comment',
    'comment-no',
    'conversation',
    'copy',
    'copy-07',
    'delete-key',
    'delete-x',
    'downsell',
    'drawer-collapse',
    'drawer-expand',
    'duplicate',
    'feedback',
    'file-lock',
    'file-search',
    'form-field',
    'form-filled',
    'left-small',
    'launch',
    'list-bullet',
    'list-numbers',
    'margin-left',
    'margin-right',
    'move-left',
    'move-right',
    'newsletter-2',
    'one-off-session',
    'quote',
    'redo',
    'reset-password',
    'right-small',
    'send-message',
    'share',
    'super-admin',
    'tablet-landscape',
    'undo',
    'user-star',
    'user-star-filled',
    'users',
    'users-filled',
    'users-tone'
];

const validateContent = (svgContent) => {
    const div = document.createElement('div');
    div.innerHTML = svgContent;
    // setup this way to ensure it works on our buddy IE
    for (let i = div.childNodes.length - 1; i >= 0; i--) {
        if (div.childNodes[i].nodeName.toLowerCase() !== 'svg') {
            div.removeChild(div.childNodes[i]);
        }
    }
    // must only have 1 root element
    const svgElm = div.firstElementChild;
    if (svgElm && svgElm.nodeName.toLowerCase() === 'svg') {
        const svgClass = svgElm.getAttribute('class') || '';
        svgElm.setAttribute('class', (svgClass + ' s-pds-icon').trim());
        // root element must be an svg
        // lets double check we've got valid elements
        // do not allow scripts
        if (isValid(svgElm)) {
            return div.innerHTML;
        }
    }
    return '';
};
const isValid = (elm) => {
    if (elm.nodeType === 1) {
        if (elm.nodeName.toLowerCase() === 'script') {
            return false;
        }
        for (let i = 0; i < elm.attributes.length; i++) {
            const name = elm.attributes[i].name;
            if (isStr(name) && name.toLowerCase().indexOf('on') === 0) {
                return false;
            }
        }
        for (let i = 0; i < elm.childNodes.length; i++) {
            if (!isValid(elm.childNodes[i])) {
                return false;
            }
        }
    }
    return true;
};
const isSvgDataUrl = (url) => url.startsWith('data:image/svg+xml');
const isEncodedDataUrl = (url) => url.indexOf(';utf8,') !== -1;

const pdsIconContent = new Map();
const requests = new Map(); // eslint-disable-line @typescript-eslint/no-explicit-any
let parser;
const getSvgContent = (url, sanitize = false) => {
    let req = requests.get(url);
    if (!req) {
        if (typeof fetch != 'undefined' && typeof document !== 'undefined') {
            if (isSvgDataUrl(url) && isEncodedDataUrl(url)) {
                if (!parser) {
                    parser = new DOMParser();
                }
                try {
                    const doc = parser.parseFromString(url, 'text/html');
                    const svg = doc.querySelector('svg');
                    if (svg) {
                        pdsIconContent.set(url, svg.outerHTML);
                    }
                    else {
                        pdsIconContent.set(url, '');
                    }
                }
                catch (error) {
                    pdsIconContent.set(url, '');
                }
                return Promise.resolve();
            }
            else {
                // we don't have a request
                req = fetch(url).then((rsp) => {
                    if (rsp.ok) {
                        return rsp.text().then((svgContent) => {
                            if (svgContent && sanitize !== false) {
                                try {
                                    svgContent = validateContent(svgContent);
                                }
                                catch (validationError) {
                                    svgContent = '';
                                }
                            }
                            pdsIconContent.set(url, svgContent || '');
                        });
                    }
                    else {
                        // Handle HTTP errors
                        throw new Error(`Failed to load SVG: ${rsp.status} ${rsp.statusText}`);
                    }
                }).catch((error) => {
                    // Handle all fetch errors gracefully
                    console.warn('Failed to load SVG:', url, error);
                    pdsIconContent.set(url, '');
                    // Don't re-throw to prevent unhandled promise rejections
                });
                requests.set(url, req);
            }
        }
        else {
            pdsIconContent.set(url, '');
            return Promise.resolve();
        }
    }
    return req;
};

const pdsIconCss = ":host{--dimension-icon-height:16px;--dimension-icon-width:16px;--color-icon-fill:currentColor;contain:strict;display:inline-block;fill:var(--color-icon-fill);-ms-flex-negative:0;flex-shrink:0;height:var(--dimension-icon-height);width:var(--dimension-icon-width)}:host .pdsicon{fill:var(--color-icon-fill)}.pds-icon-fill-none{fill:none}.icon-inner,.pds-icon,svg{display:block;height:100%;width:100%}:host(.flip-rtl):host-context([dir=rtl]) .icon-inner{-webkit-transform:scaleX(-1);transform:scaleX(-1)}:host(.flip-rtl:dir(rtl)) .icon-inner{-webkit-transform:scaleX(-1);transform:scaleX(-1)}:host(.flip-rtl:dir(ltr)) .icon-inner{-webkit-transform:scaleX(1);transform:scaleX(1)}";

const PdsIcon = class {
    constructor(hostRef) {
        registerInstance(this, hostRef);
        this.didLoadIcon = false;
        this.iconName = null;
        this.inheritedAttributes = {}; // eslint-disable-line @typescript-eslint/no-explicit-any
        this.isVisible = false;
        /**
         * The size of the icon. This can be
         * 'small', 'regular', 'medium', 'large', or a
         * custom value (40px, 1rem, etc)
         *
         */
        this.size = 'regular';
        this.hasAriaHidden = () => {
            const { el } = this;
            return el.hasAttribute('aria-hidden') && el.getAttribute('aria-hidden') === 'true';
        };
    }
    iconSize() {
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        const sizes = {
            small: '12px',
            regular: '16px',
            medium: '20px',
            large: '24px',
        };
        if (sizes[this.size]) {
            return sizes[this.size];
        }
        else {
            return this.size;
        }
    }
    componentDidLoad() {
        this.setCSSVariables();
        if (!this.didLoadIcon) {
            this.loadIcon();
        }
        // Fallback: Ensure icon loads even if IntersectionObserver doesn't fire
        setTimeout(() => {
            if (!this.svgContent && !this.isVisible) {
                this.isVisible = true;
                this.loadIcon();
            }
        }, 100);
        // Additional fallback for client-side navigation (React Router, etc.)
        // React's useLayoutEffect and rendering cycles can delay visibility detection
        setTimeout(() => {
            if (!this.svgContent && !this.isVisible) {
                this.isVisible = true;
                this.loadIcon();
            }
        }, 500);
    }
    componentWillLoad() {
        this.inheritedAttributes = inheritAttributes(this.el, ['aria-label']);
        this.setCSSVariables();
        this.setupInitialAriaLabel();
    }
    setCSSVariables() {
        this.el.style.setProperty(`--dimension-icon-height`, this.iconSize());
        this.el.style.setProperty(`--dimension-icon-width`, this.iconSize());
        this.el.style.setProperty(`--color-icon-fill`, typeof this.color !== 'undefined' ? this.color : 'currentColor');
    }
    connectedCallback() {
        // Handle re-connection during client-side navigation
        if (!this.isVisible && !this.svgContent) {
            this.waitUntilVisible(this.el, '50px', () => {
                this.isVisible = true;
                this.loadIcon();
            });
        }
        // Immediate load attempt if already visible (e.g., during React navigation)
        if (this.isElementInViewport(this.el)) {
            this.isVisible = true;
            this.loadIcon();
        }
    }
    disconnectedCallback() {
        if (this.io) {
            this.io.disconnect();
            this.io = undefined;
        }
    }
    updateStyles() {
        this.setCSSVariables();
    }
    onIconPropertyChange() {
        this.loadIcon();
        // Update aria-label when icon properties change
        this.setupInitialAriaLabel();
    }
    loadIcon() {
        // Reset load state when URL changes
        this.didLoadIcon = false;
        // Clear existing content to prevent stale content when switching icons
        this.svgContent = undefined;
        if (this.isVisible) {
            const url = getUrl(this);
            if (url) {
                if (pdsIconContent.has(url)) {
                    this.svgContent = pdsIconContent.get(url);
                }
                else {
                    // Fix: Ensure promise callback triggers re-render and handle errors
                    getSvgContent(url)
                        .then(() => {
                        // Force re-render by setting state in next tick
                        setTimeout(() => {
                            this.svgContent = pdsIconContent.get(url);
                        }, 0);
                    })
                        .catch(() => {
                        // Handle fetch errors gracefully
                        this.svgContent = '';
                    });
                }
                this.didLoadIcon = true;
            }
        }
        this.iconName = getName(this.name, this.icon);
    }
    render() {
        const { ariaLabel, flipRtl, iconName, inheritedAttributes } = this;
        const shouldIconAutoFlip = iconName
            ? shouldRtlFlipIcon(iconName, this.el) && flipRtl !== false
            : false;
        const shouldFlip = flipRtl || shouldIconAutoFlip;
        // Use inherited aria-label if provided, otherwise fall back to auto-generated one
        const finalAriaLabel = inheritedAttributes['aria-label'] || ariaLabel;
        return (h(Host, Object.assign({ key: '43aa73531314e6529a887468e69362430d006229', "aria-label": finalAriaLabel !== undefined && !this.hasAriaHidden() ? finalAriaLabel : null, alt: "", role: "img", class: Object.assign(Object.assign({}, createColorClasses(this.color)), { 'flip-rtl': shouldFlip, 'icon-rtl': shouldFlip && isRTL(this.el) }) }, inheritedAttributes), this.svgContent ? (h("div", { class: "icon-inner", innerHTML: this.svgContent })) : (h("div", { class: "icon-inner" }))));
    }
    /*****
     * Private Methods
     ****/
    setupInitialAriaLabel() {
        // Only set aria-label during initial load if one isn't already provided
        if (!this.inheritedAttributes['aria-label']) {
            const iconName = getName(this.name, this.icon);
            if (iconName) {
                this.ariaLabel = iconName.replace(/\-/g, ' ');
            }
        }
    }
    waitUntilVisible(el, rootMargin, cb) {
        if (typeof window !== 'undefined' && (window).IntersectionObserver) {
            const io = (this.io = new (window).IntersectionObserver((data) => {
                if (data[0].isIntersecting) {
                    io.disconnect();
                    this.io = undefined;
                    cb();
                }
            }, { rootMargin }));
            io.observe(el);
            // Safety timeout for client-side navigation scenarios
            // Sometimes IntersectionObserver doesn't fire during React navigation
            setTimeout(() => {
                if (this.io && !this.isVisible) {
                    // Check if element is actually visible in viewport
                    if (this.isElementInViewport(el)) {
                        this.io.disconnect();
                        this.io = undefined;
                        cb();
                    }
                }
            }, 1000);
        }
        else {
            // browser doesn't support IntersectionObserver
            // so just fallback to always show it
            cb();
        }
    }
    isElementInViewport(el) {
        if (!el || !el.isConnected)
            return false;
        const rect = el.getBoundingClientRect();
        const windowHeight = window.innerHeight || document.documentElement.clientHeight;
        const windowWidth = window.innerWidth || document.documentElement.clientWidth;
        return (rect.top >= 0 &&
            rect.left >= 0 &&
            rect.bottom <= windowHeight &&
            rect.right <= windowWidth) || (
        // Also consider partially visible elements
        rect.top < windowHeight &&
            rect.bottom > 0 &&
            rect.left < windowWidth &&
            rect.right > 0);
    }
    /**
     * Debug method to help diagnose loading issues
     * Call from browser console: document.querySelector('pds-icon').debugIconState()
     */
    debugIconState() {
        var _a;
        const url = getUrl(this);
        const rect = this.el.getBoundingClientRect();
        console.log('PdsIcon Debug State:', {
            name: this.name,
            src: this.src,
            icon: this.icon,
            iconName: this.iconName,
            url,
            isVisible: this.isVisible,
            didLoadIcon: this.didLoadIcon,
            hasSvgContent: !!this.svgContent,
            svgContentLength: ((_a = this.svgContent) === null || _a === void 0 ? void 0 : _a.length) || 0,
            isInCache: url ? pdsIconContent.has(url) : false,
            cachedContent: url ? pdsIconContent.get(url) : null,
            element: this.el,
            // Client-side navigation specific debug info
            isConnected: this.el.isConnected,
            isInViewport: this.isElementInViewport(this.el),
            hasIntersectionObserver: !!this.io,
            boundingClientRect: rect,
            windowDimensions: {
                width: window.innerWidth || document.documentElement.clientWidth,
                height: window.innerHeight || document.documentElement.clientHeight
            }
        });
    }
    static get assetsDirs() { return ["svg"]; }
    get el() { return getElement(this); }
    static get watchers() { return {
        "size": ["updateStyles"],
        "color": ["updateStyles"],
        "name": ["onIconPropertyChange"],
        "src": ["onIconPropertyChange"],
        "icon": ["onIconPropertyChange"]
    }; }
};
const createColorClasses = (color) => {
    return color
        ? {
            'pds-color': true,
            [`pds-color-${color}`]: true,
        }
        : null;
};
PdsIcon.style = pdsIconCss;

export { PdsIcon as pds_icon };
//# sourceMappingURL=pds-icon.entry.js.map
