{"version":3,"file":"defineClasses-CEpmGBsu.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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"}