import { g as getOrThrowWith, r as right, l as left, i as identity, a as isRight, b as getRight, m as match, t as try_, T as TaggedError, c as runPromise } from './logger-fiRXhuXK.js';

/**
 * This module provides types and utility functions to create and work with branded types,
 * which are TypeScript types with an added type tag to prevent accidental usage of a value in the wrong context.
 *
 * The `refined` and `nominal` functions are both used to create branded types in TypeScript.
 * The main difference between them is that `refined` allows for validation of the data, while `nominal` does not.
 *
 * The `nominal` function is used to create a new branded type that has the same underlying type as the input, but with a different name.
 * This is useful when you want to distinguish between two values of the same type that have different meanings.
 * The `nominal` function does not perform any validation of the input data.
 *
 * On the other hand, the `refined` function is used to create a new branded type that has the same underlying type as the input,
 * but with a different name, and it also allows for validation of the input data.
 * The `refined` function takes a predicate that is used to validate the input data.
 * If the input data fails the validation, a `BrandErrors` is returned, which provides information about the specific validation failure.
 *
 * @since 2.0.0
 */
/**
 * @since 2.0.0
 * @category symbols
 */
const RefinedConstructorsTypeId = /*#__PURE__*/Symbol.for("effect/Brand/Refined");
/**
 * Returns a `BrandErrors` that contains a single `RefinementError`.
 *
 * @since 2.0.0
 * @category constructors
 */
const error = (message, meta) => [{
  message,
  meta
}];
function refined(...args) {
  const either = args.length === 2 ? unbranded => args[0](unbranded) ? right(unbranded) : left(args[1](unbranded)) : unbranded => {
    return match(args[0](unbranded), {
      onNone: () => right(unbranded),
      onSome: left
    });
  };
  return Object.assign(unbranded => getOrThrowWith(either(unbranded), identity), {
    [RefinedConstructorsTypeId]: RefinedConstructorsTypeId,
    option: args => getRight(either(args)),
    either,
    is: args => isRight(either(args))
  });
}

const SVGString = refined(isValidSVG, () => error('SVG data is malformed'));
class BrandValidationError extends TaggedError('BrandValidationError') {
    constructor(error, type) {
        super(new Error(`Brand validation failed for type ${type}.`, { cause: error }));
    }
}
const createValidSVGString = (svg) => try_({
    try: () => SVGString(svg),
    catch: (error) => new BrandValidationError(error, 'SVGString'),
});
function isValidSVG(svg) {
    if (typeof svg !== 'string') {
        return false;
    }
    try {
        const parser = new DOMParser();
        const doc = parser.parseFromString(svg, 'image/svg+xml');
        return doc.documentElement.nodeName === 'svg';
    }
    catch {
        return false;
    }
}

const IconProviderRegistryKey = Symbol.for('LMVZ__iconProviderRegistry');
const inMemoryRegistry = {};
function getRegistry() {
    if (typeof window === 'undefined') {
        return inMemoryRegistry;
    }
    return window[IconProviderRegistryKey] ?? (window[IconProviderRegistryKey] = {});
}
function registerIconProvider(id, provider) {
    const registry = getRegistry();
    const providerName = id;
    if (Object.prototype.hasOwnProperty.call(registry, providerName)) {
        console.warn(`Icon provider with name "${providerName}" is already registered. Overwriting existing provider.`);
    }
    registry[providerName] = provider;
}
function getRegisteredIconProvider(id) {
    const registry = getRegistry();
    if (id) {
        return registry[id];
    }
    const providerNames = Object.keys(registry);
    if (providerNames.length === 0) {
        return undefined;
    }
    if (providerNames.length > 1) {
        console.warn(`Multiple icon providers registered (${providerNames.join(', ')}). Using the first one: "${providerNames[0]}".`);
    }
    const firstProviderName = providerNames[0];
    if (!firstProviderName) {
        return undefined;
    }
    return registry[firstProviderName];
}

const emptyDefaultSvg = () => SVGString(`<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"></svg>`);
async function toValidSvgStringWithFallback(value) {
    try {
        return await runPromise(createValidSVGString(value));
    }
    catch {
        console.error('Invalid SVG string:', value);
        return emptyDefaultSvg();
    }
}
async function resolveIconSvg(options) {
    const { icon, iconset } = options;
    const iconSvg = await (async () => {
        const provider = getRegisteredIconProvider(iconset);
        if (!provider) {
            console.warn(`No icon provider registered. Unable to resolve icon "${icon}"${iconset ? ` from set "${iconset}"` : ''}. Using default icon.`);
            return;
        }
        try {
            const resolved = await Promise.resolve(provider.resolve(icon));
            if (!resolved?.svg) {
                console.warn(`Icon "${icon}"${iconset ? ` from set "${iconset}"` : ''} not found in provider. Using default icon.`);
                return;
            }
            const validated = await toValidSvgStringWithFallback(resolved.svg);
            if (validated) {
                return validated;
            }
        }
        catch (error) {
            console.error(`Error resolving icon "${icon}" with provider:`, error);
            return;
        }
        return;
    })();
    if (iconSvg)
        return iconSvg;
    console.error(`Icon "${icon}" not found${iconset ? ` in set "${iconset}"` : ''}. Using default icon.`);
    return emptyDefaultSvg();
}
function typedIconFromSet(iconset, icon) {
    return {
        iconset,
        icon,
    };
}

export { resolveIconSvg as a, getRegisteredIconProvider as g, isValidSVG as i, registerIconProvider as r, typedIconFromSet as t };
