{"version":3,"file":"defineClasses-Cqhbv-UT.cjs","sources":["../../src/composables/defineClasses.ts"],"sourcesContent":["import {\n    ref,\n    watch,\n    isRef,\n    toValue,\n    getCurrentInstance,\n    effectScope,\n    onScopeDispose,\n    getCurrentScope,\n    type MaybeRefOrGetter,\n    type Ref,\n    type ComponentInternalInstance,\n    type EffectScope,\n} from \"vue\";\n\nimport { getOptions } from \"@/utils/config\";\nimport { isDefined, blankIfUndefined, getValueByPath } from \"@/utils/helpers\";\n\nimport type {\n    ClassBind,\n    ComponentClass,\n    ComponentProps,\n    TransformFunction,\n} from \"@/types\";\n\n// named tuple as prop definition\ntype ComputedClass = readonly [\n    className: string,\n    defaultClass: string,\n    suffix?: MaybeRefOrGetter<string | undefined> | null,\n    apply?: MaybeRefOrGetter<boolean> | null,\n];\n\n/** Helper function to get all active classes from a class binding list */\nexport const getActiveClasses = (\n    classes: MaybeRefOrGetter<ClassBind[]>,\n): string[] => {\n    const values = toValue(classes);\n    if (!values) return [];\n    return values.flatMap((bind) =>\n        Object.keys(bind)\n            .filter((key) => key && bind[key])\n            .flatMap((v) => v.split(\" \")),\n    );\n};\n\ntype DefineClassesOptions = {\n    /**\n     * Pass a custom effect scope.\n     * By default a new effect scope is created.\n     * An error will be thrown if no current scope or a custom scope is given.\n     * @default effectScope()\n     */\n    scope?: EffectScope;\n    /**\n     * Pass a custom props object which will be watched on additionaly to the current component instance props.\n     * this will recompute the class bind property when the class property change.\n     * @default vm.proxy?.$props\n     */\n    props?: Record<string, any>;\n};\n\nexport function defineClasses(\n    ...args: [...ComputedClass[], DefineClassesOptions]\n): Ref<ClassBind[]>;\n\nexport function defineClasses(...args: [...ComputedClass[]]): Ref<ClassBind[]>;\n\n/**\n * Calculate dynamic classes based on class definitions\n */\nexport function defineClasses(\n    ...args: ComputedClass[] | [...ComputedClass[], DefineClassesOptions]\n): Ref<ClassBind[]> {\n    // extract last argument if its the option object\n    const options = Array.isArray(args.at(-1))\n        ? undefined\n        : (args.at(-1) as DefineClassesOptions);\n\n    // get class defintion list based on options are given or not\n    const classDefinitions = (\n        Array.isArray(args.at(-1)) ? args : args.slice(0, -1)\n    ) as ComputedClass[];\n\n    // getting a hold of the internal instance of the component in setup()\n    const vm = getCurrentInstance();\n    if (!vm)\n        throw new Error(\n            \"defineClasses must be called within a component setup function.\",\n        );\n    // check if there is no current active effect scope given\n    if (!getCurrentScope() && !options?.scope)\n        throw new Error(\n            \"defineClasses must be called within a current active effect scope.\",\n        );\n\n    // create an effect scope object to capture reactive effects\n    const scope = options?.scope || effectScope();\n\n    // check if there is a current active effect scope\n    if (getCurrentScope())\n        // Registers a dispose callback on the current active effect scope.\n        // The callback will be invoked when the associated effect scope is stopped.\n        onScopeDispose(() => {\n            // stop all effects when appropriate\n            if (scope) scope.stop();\n        });\n\n    // reactive classes container\n    const classes = ref<ClassBind[]>([]);\n\n    classes.value = classDefinitions.map((defintion, index) => {\n        const className = defintion[0];\n        const defaultClass = defintion[1];\n        const suffix = defintion[2];\n        const apply = defintion[3];\n\n        function getClassBind(): ClassBind {\n            // compute class based on definition parameter\n            const computedClass = computeClass(\n                vm!,\n                className,\n                defaultClass,\n                toValue(suffix) || undefined,\n            );\n\n            // if apply is not defined or true\n            const applied = !isDefined(apply) || toValue(apply);\n\n            // return class bind property\n            return { [computedClass]: applied };\n        }\n\n        // run all watcher and computed properties in an active effect scope\n        scope.run(() => {\n            // recompute the class bind property when the class property change\n            watch(\n                [\n                    () => vm.proxy?.$props[className],\n                    () => (options?.props ? options?.props[className] : null),\n                ],\n                () => {\n                    // recompute the class bind property\n                    const classBind = getClassBind();\n                    // update class binding property by class index\n                    classes.value[index] = classBind;\n                },\n            );\n\n            // if suffix is defined, watch suffix changed and recalculate class\n            if (isDefined(suffix) && isRef(suffix)) {\n                watch(suffix, (value, oldValue) => {\n                    // only recompute when value has really changed\n                    if (value === oldValue) return;\n                    // recompute the class bind property\n                    const classBind = getClassBind();\n                    // update class binding property by class index\n                    classes.value[index] = classBind;\n                });\n            }\n\n            // if apply is defined, watch apply changed and update apply state (no need of recalculation here)\n            if (isDefined(apply) && isRef(apply)) {\n                watch(apply, (applied, oldValue) => {\n                    // only change apply when value has really changed\n                    if (applied === oldValue) return;\n                    // get class binding property by class index\n                    const classBind = classes.value[index];\n                    // update the apply class binding state\n                    Object.keys(classBind).forEach(\n                        (key) => (classBind[key] = applied),\n                    );\n                    // update the class binding property by class index\n                    classes.value[index] = classBind;\n                });\n            }\n        });\n\n        // return computed class based on parameter\n        return getClassBind();\n    });\n\n    // return reactive classes\n    return classes;\n}\n\n/**\n * Compute a class by a field name\n */\nfunction computeClass(\n    vm: ComponentInternalInstance,\n    field: string,\n    defaultValue: string,\n    suffix = \"\",\n): string {\n    // get component props\n    const props = getProps(vm);\n\n    const componentKey: string = vm.proxy?.$options.configField;\n    if (!componentKey)\n        throw new Error(\"component must define the 'configField' option.\");\n\n    // get component instance override property\n    const config = props.override === true ? {} : getOptions();\n\n    // --- Classes Definition ---\n\n    // get component config class definition\n    let globalClass: ComponentClass | undefined =\n        getValueByPath(config, `${componentKey}.${field}.class`) ||\n        getValueByPath(config, `${componentKey}.${field}`);\n\n    // get instance class definition\n    let localClass: ComponentClass | undefined = getValueByPath(props, field);\n\n    // procsess local instance class\n    if (Array.isArray(localClass)) {\n        localClass = localClass.join(\" \");\n    }\n    if (typeof localClass === \"function\") {\n        const props = getProps(vm);\n        localClass = localClass(suffix, props);\n    } else {\n        localClass = suffixProcessor(localClass ?? \"\", suffix);\n    }\n\n    // process global config class\n    if (Array.isArray(globalClass)) {\n        globalClass = globalClass.join(\" \");\n    }\n    if (typeof globalClass === \"function\") {\n        const props = getProps(vm);\n        globalClass = globalClass(suffix, props);\n    } else {\n        globalClass = suffixProcessor(globalClass ?? \"\", suffix);\n    }\n\n    // process component instance default value\n    if (defaultValue.includes(\"{*}\")) {\n        defaultValue = defaultValue.replace(\n            /\\{\\*\\}/g,\n            blankIfUndefined(suffix),\n        );\n    } else {\n        defaultValue = defaultValue + blankIfUndefined(suffix);\n    }\n\n    // --- Override Definition ---\n\n    // get instance or global config override property\n    const globalOverride =\n        props.override || getValueByPath(config, \"override\", false);\n    // get component config override property\n    const localOverride = getValueByPath(\n        config,\n        `${componentKey}.override`,\n        globalOverride,\n    );\n    // get component field config override property\n    const overrideClass = getValueByPath(\n        config,\n        `${componentKey}.${field}.override`,\n        localOverride,\n    );\n\n    // --- Define Applied Classes ---\n\n    // if override is false add default value\n    // add global config classes\n    // add instance classes\n    let appliedClasses = (\n        `${!overrideClass ? defaultValue : \"\"} ` +\n        `${blankIfUndefined(globalClass)} ` +\n        `${blankIfUndefined(localClass)}`\n    )\n        .trim()\n        .replace(/\\s\\s+/g, \" \");\n\n    // --- Tranform Classes ---\n\n    // get global config tranform class\n    const globalTransformClasses: TransformFunction | undefined =\n        getValueByPath(config, \"transformClasses\");\n    // get component config tranform class\n    const localTransformClasses: TransformFunction | undefined = getValueByPath(\n        config,\n        `${componentKey}.transformClasses`,\n    );\n\n    // apply component local transformclass if available\n    if (localTransformClasses) {\n        appliedClasses = localTransformClasses(appliedClasses);\n    }\n    // else apply global transformclass if available\n    else if (globalTransformClasses) {\n        appliedClasses = globalTransformClasses(appliedClasses);\n    }\n\n    return appliedClasses;\n}\n\nfunction suffixProcessor(input: string, suffix: string): string {\n    return blankIfUndefined(input)\n        .split(\" \")\n        .filter((cls) => cls.length > 0)\n        .map((cls) => cls + blankIfUndefined(suffix))\n        .join(\" \");\n}\n\nconst getProps = (vm: ComponentInternalInstance): ComponentProps => {\n    let props = vm.proxy?.$props || {};\n\n    // get all props which ends with \"Props\", these are compressed parent props\n    // append these parent props as root level prop\n    props = Object.keys(props)\n        .filter((key) => key.endsWith(\"Props\"))\n        .map((key) => props[key])\n        .reduce((a, b) => ({ ...a, ...b }), props);\n\n    return props;\n};\n"],"names":["toValue","getCurrentInstance","getCurrentScope","effectScope","onScopeDispose","ref","isDefined","watch","isRef","config","getOptions","getValueByPath","props","blankIfUndefined"],"mappings":"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"}