@oruga-ui/oruga-next
Version:
UI components for Vue.js and CSS framework agnostic
1 lines • 1.63 MB
Source Map (JSON)
{"version":3,"file":"index.umd.cjs","names":["$attrs","$slots","$attrs","$emit","$slots","$slots","$slots","$emit","$emit","$emit","$slots","$emit","$slots","$attrs","$emit","$slots","$attrs","$slots","$props","$slots","$slots","$attrs","$slots","$slots","$attrs","$props","$slots","$attrs","$slots","$attrs","$props","$slots","$attrs","$props","$attrs","$slots","$attrs","$props","$slots","$attrs","$emit","$attrs","$slots","$attrs","$props","$slots","$emit","$slots","$slots","$slots"],"sources":["../src/utils/helpers.ts","../src/utils/ssr.ts","../src/utils/plugins.ts","../src/utils/config.ts","../src/utils/icons.ts","../src/composables/unrefElement.ts","../src/composables/defineClasses.ts","../src/composables/useEventListener.ts","../src/composables/useMatchMedia.ts","../src/components/field/fieldInjection.ts","../src/composables/useInputHandler.ts","../src/composables/useDebounce.ts","../src/composables/useIndexer.ts","../src/composables/useParentProvider.ts","../src/composables/useClickOutside.ts","../src/composables/useOptions.ts","../src/composables/usePreventScrolling.ts","../src/composables/useScrollHelper.ts","../src/composables/useConfig.ts","../src/composables/useTrapFocus.ts","../src/components/icon/Icon.vue","../src/components/icon/Icon.vue","../src/components/input/Input.vue","../src/components/input/Input.vue","../src/components/dropdown/DropdownItem.vue","../src/components/dropdown/DropdownItem.vue","../src/components/utils/PositionWrapper.vue","../src/components/utils/PositionWrapper.vue","../src/components/dropdown/Dropdown.vue","../src/components/dropdown/Dropdown.vue","../src/components/autocomplete/Autocomplete.vue","../src/components/autocomplete/Autocomplete.vue","../src/components/autocomplete/index.ts","../src/components/breadcrumb/Breadcrumb.vue","../src/components/breadcrumb/Breadcrumb.vue","../src/components/breadcrumb/BreadcrumbItem.vue","../src/components/breadcrumb/BreadcrumbItem.vue","../src/components/breadcrumb/index.ts","../src/components/button/Button.vue","../src/components/button/Button.vue","../src/components/button/index.ts","../src/components/carousel/CarouselItem.vue","../src/components/carousel/CarouselItem.vue","../src/components/carousel/Carousel.vue","../src/components/carousel/Carousel.vue","../src/components/carousel/index.ts","../src/components/checkbox/Checkbox.vue","../src/components/checkbox/Checkbox.vue","../src/components/checkbox/index.ts","../src/components/collapse/Collapse.vue","../src/components/collapse/Collapse.vue","../src/components/collapse/index.ts","../src/components/select/Select.vue","../src/components/select/Select.vue","../src/components/utils/PickerWrapper.vue","../src/components/utils/PickerWrapper.vue","../src/components/datepicker/utils.ts","../src/components/datepicker/useDatepickerMixins.ts","../src/components/datepicker/DatepickerTableRow.vue","../src/components/datepicker/DatepickerTableRow.vue","../src/components/datepicker/DatepickerTable.vue","../src/components/datepicker/DatepickerTable.vue","../src/components/datepicker/DatepickerMonth.vue","../src/components/datepicker/DatepickerMonth.vue","../src/components/datepicker/Datepicker.vue","../src/components/datepicker/Datepicker.vue","../src/components/datepicker/index.ts","../src/components/timepicker/useTimepickerMixins.ts","../src/components/timepicker/Timepicker.vue","../src/components/timepicker/Timepicker.vue","../src/components/datetimepicker/useDatetimepickerMixin.ts","../src/components/datetimepicker/Datetimepicker.vue","../src/components/datetimepicker/Datetimepicker.vue","../src/components/datetimepicker/index.ts","../src/components/loading/Loading.vue","../src/components/loading/Loading.vue","../src/components/utils/CloseButton.vue","../src/components/utils/CloseButton.vue","../src/components/dialog/Dialog.vue","../src/components/dialog/Dialog.vue","../src/components/programmatic/InstanceRegistry.ts","../src/components/programmatic/ProgrammaticComponent.ts","../src/components/programmatic/useProgrammatic.ts","../src/components/programmatic/index.ts","../src/components/dialog/useDialogProgrammatic.ts","../src/components/dialog/index.ts","../src/components/dropdown/index.ts","../src/components/field/Field.vue","../src/components/field/Field.vue","../src/components/field/index.ts","../src/components/icon/index.ts","../src/components/input/index.ts","../src/components/listbox/ListItem.vue","../src/components/listbox/ListItem.vue","../src/components/listbox/Listbox.vue","../src/components/listbox/Listbox.vue","../src/components/listbox/index.ts","../src/components/loading/useLoadingProgrammatic.ts","../src/components/loading/index.ts","../src/components/utils/PlainButton.ts","../src/components/menu/MenuItem.vue","../src/components/menu/MenuItem.vue","../src/components/menu/Menu.vue","../src/components/menu/Menu.vue","../src/components/menu/index.ts","../src/components/modal/Modal.vue","../src/components/modal/Modal.vue","../src/components/modal/useModalProgrammatic.ts","../src/components/modal/index.ts","../src/components/notification/Notification.vue","../src/components/notification/Notification.vue","../src/components/notification/NotificationNotice.vue","../src/components/notification/NotificationNotice.vue","../src/components/notification/useNotificationProgrammatic.ts","../src/components/notification/index.ts","../src/components/pagination/Pagination.vue","../src/components/pagination/Pagination.vue","../src/components/pagination/index.ts","../src/components/radio/Radio.vue","../src/components/radio/Radio.vue","../src/components/radio/index.ts","../src/components/select/index.ts","../src/components/skeleton/Skeleton.vue","../src/components/skeleton/Skeleton.vue","../src/components/skeleton/index.ts","../src/components/sidebar/Sidebar.vue","../src/components/sidebar/Sidebar.vue","../src/components/sidebar/useSidebarProgrammatic.ts","../src/components/sidebar/index.ts","../src/components/tooltip/Tooltip.vue","../src/components/tooltip/Tooltip.vue","../src/components/slider/SliderThumb.vue","../src/components/slider/SliderThumb.vue","../src/components/slider/SliderTick.vue","../src/components/slider/SliderTick.vue","../src/components/slider/Slider.vue","../src/components/slider/Slider.vue","../src/components/slider/index.ts","../src/components/steps/StepItem.vue","../src/components/steps/StepItem.vue","../src/components/steps/Steps.vue","../src/components/steps/Steps.vue","../src/components/steps/index.ts","../src/components/switch/Switch.vue","../src/components/switch/Switch.vue","../src/components/switch/index.ts","../src/components/utils/SlotComponent.ts","../src/components/table/TableMobileSort.vue","../src/components/table/TableMobileSort.vue","../src/components/table/TableColumn.vue","../src/components/table/TableColumn.vue","../src/components/table/TablePagination.vue","../src/components/table/TablePagination.vue","../src/components/table/Table.vue","../src/components/table/Table.vue","../src/components/table/index.ts","../src/components/tabs/TabItem.vue","../src/components/tabs/TabItem.vue","../src/components/tabs/Tabs.vue","../src/components/tabs/Tabs.vue","../src/components/tabs/index.ts","../src/components/tag/Tag.vue","../src/components/tag/Tag.vue","../src/components/tag/index.ts","../src/components/taginput/Taginput.vue","../src/components/taginput/Taginput.vue","../src/components/taginput/index.ts","../src/components/timepicker/index.ts","../src/components/tooltip/index.ts","../src/components/tree/TreeItem.vue","../src/components/tree/TreeItem.vue","../src/components/tree/Tree.vue","../src/components/tree/Tree.vue","../src/components/tree/index.ts","../src/components/upload/Upload.vue","../src/components/upload/Upload.vue","../src/components/upload/index.ts","../src/components/plugins.ts","../src/index.ts"],"sourcesContent":["import { Comment, Fragment, Text } from \"vue\";\nimport type { DeepKeys, DeepType, Numberish } from \"@/types\";\n\n/**\n * +/- function to native math sign\n */\nfunction signPoly(value: number): number {\n if (value < 0) return -1;\n return value > 0 ? 1 : 0;\n}\nexport const sign = Math.sign || signPoly;\n\n/**\n * Native modulo bug with negative numbers\n * @param n\n * @param mod\n * @returns {number}\n */\nexport const mod = (n: number, mod: number): number => ((n % mod) + mod) % mod;\n\n/** add a prefix `0` to a 1 digit number */\nexport const pad = (value: number): string => (value < 10 ? \"0\" : \"\") + value;\n\n/**\n * Asserts a value is beetween min and max\n * @param val\n * @param min\n * @param max\n * @returns {number}\n */\nexport function bound(val: number, min: number, max: number): number {\n return Math.max(min, Math.min(max, val));\n}\n\n/**\n * checks if the value is of type object\n */\nexport const isObject = (value: unknown): value is object =>\n !!value && typeof value === \"object\" && !Array.isArray(value);\n\n/**\n * checks if the value is of type date\n */\nexport const isDate = (value: unknown): value is Date =>\n !!value && value instanceof Date && !isNaN(value.getTime());\n\n/**\n * checks if the value is not null or undefined\n */\nexport const isDefined = <T>(value: T | undefined | null): value is T =>\n value !== null && typeof value !== \"undefined\";\n\n/**\n * Determines if the value of a prop that is either present (true) or not\n * present (undefined). For example, the prop disabled should disable\n * by just existing, but what if it is set to the string \"false\" — then it\n * should not be disabled.\n *\n * @param value - Value to check for undefined.\n * @returns boolean\n */\nexport const isTrueish = (value: unknown): boolean =>\n isDefined(value) && value !== \"false\" && value !== false;\n\nexport const blankIfUndefined = (value: string | null | undefined): string =>\n isDefined(value) ? value : \"\";\n\nexport const defaultIfUndefined = <T>(\n value: T | undefined,\n defaultValue: T,\n): T => (isDefined(value) ? value : defaultValue);\n\nexport const toCssDimension = (\n width: Numberish | undefined,\n dimension: string = \"px\",\n): string | undefined =>\n !isDefined(width)\n ? undefined\n : isNaN(width as number)\n ? String(width)\n : String(width) + dimension;\n\nexport function isEmpty(value: unknown): boolean {\n return (\n value === null ||\n value === undefined ||\n value === \"\" ||\n (Array.isArray(value) && value.length === 0) ||\n (!(value instanceof Date) &&\n typeof value === \"object\" &&\n Object.keys(value).length === 0)\n );\n}\n\nexport function isPrintableCharacter(char: string = \"\"): boolean {\n return !isEmpty(char) && char.length === 1 && !!char.match(/\\S| /);\n}\n\n/**\n * Reorders an array starting from a given index, alternating between\n * the next and previous elements in a zigzag pattern.\n *\n * For example, given [10, 20, 30, 40, 50, 60] and startIndex = 2,\n * the result will be: [30, 40, 20, 50, 10, 60]\n *\n * @param {Array} arr - The input array to reorder.\n * @param {number} startIndex - The index to start the reordering from.\n * @returns {Array} A new array reordered around the start index.\n */\nexport function alternateArray<T>(arr: T[], startIndex: number): T[] {\n const result: T[] = [];\n const len = arr.length;\n\n for (let offset = 0; offset < len; offset++) {\n const index =\n offset % 2 === 0\n ? startIndex + Math.floor(offset / 2)\n : startIndex - Math.ceil(offset / 2);\n\n if (index >= 0 && index < len) result.push(arr[index]);\n }\n\n return result;\n}\n\n/**\n * Sort an array by the given `key`.\n * The `key` can be a path to a nested property, when array items are objects.\n * A custom sort function can be provided.\n * By default the original array is not mutated. Set `mutate` to true to sort in place.\n * @param array - Array to sort.\n * @param key - Key or path to sort by.\n * @param fn - Custom sort function.\n * @param isAsc - Whether to sort in ascending order.\n * @param mutate - Whether to mutate the original array.\n * @returns Sorted array.\n */\nexport function sortBy<T extends object, K extends string = DeepKeys<T>>(\n array: T[],\n key: K,\n fn?: (a: T, b: T, asc: boolean) => number,\n isAsc: boolean = false,\n mutate: boolean = false,\n): T[] {\n // Sorting without mutating original data\n if (fn && typeof fn === \"function\") {\n return (mutate ? array : [...array]).sort((a, b) => fn(a, b, isAsc));\n } else {\n return (mutate ? array : [...array]).sort((a, b) => {\n // Get nested values from objects\n let newA: any = isObject(a) ? getValueByPath(a, key) : a;\n let newB: any = isObject(b) ? getValueByPath(b, key) : b;\n\n // sort boolean type\n if (typeof newA === \"boolean\" && typeof newB === \"boolean\") {\n return isAsc ? (newA > newB ? 1 : -1) : newA > newB ? -1 : 1;\n }\n\n if (!newA && newA !== 0) return 1;\n if (!newB && newB !== 0) return -1;\n if (newA === newB) return 0;\n\n newA = typeof newA === \"string\" ? newA.toUpperCase() : newA;\n newB = typeof newB === \"string\" ? newB.toUpperCase() : newB;\n\n return isAsc ? (newA > newB ? 1 : -1) : newA > newB ? -1 : 1;\n });\n }\n}\n\n/**\n * Deeply check if two values are equal\n */\nexport function isEqual(valueA: unknown, valueB: unknown): boolean {\n // Check if only one value is empty.\n if ((!valueA && !!valueB) || (!!valueA && !valueB)) return false;\n\n // If both objects are identical, return true.\n if (valueA === valueB) return true;\n\n // Check if both values are objecs.\n if (isObject(valueA) && isObject(valueB)) {\n // Get the keys of both objects.\n const keys1 = Object.keys(valueA);\n const keys2 = Object.keys(valueB);\n\n // Check if the number of keys is the same.\n if (keys1.length !== keys2.length) return false;\n\n // Iterate through the keys and compare their values recursively.\n for (const key of keys1) {\n const val1 = valueA[key];\n const val2 = valueB[key];\n if (!isEqual(val1, val2)) return false;\n }\n // If all checks pass, the objects are deep equal.\n return true;\n }\n\n // Check if both values are arrays.\n if (Array.isArray(valueA) && Array.isArray(valueB)) {\n // Check if the number of keys is the same.\n if (valueA.length !== valueB.length) return false;\n // Check if each value of the array is the same.\n if (!valueA.every((val, index) => isEqual(val, valueB[index])))\n return false;\n // If all checks pass, the arrays are deep equal.\n return true;\n }\n\n return false;\n}\n\n/**\n * Merge function to replace Object.assign with deep merging possibility\n */\nexport function merge(target: any, source: any, deep = false): any {\n if (!isObject(target) || !isObject(source)) return source;\n if (!deep) return Object.assign(target, source);\n else return mergeDeep(target, source);\n}\n\n/**\n * Performs a deep merge of `source` into `target`.\n * Mutates `target` only but not its objects and arrays.\n *\n * @author inspired by [jhildenbiddle](https://stackoverflow.com/a/48218209).\n */\nexport function mergeDeep(target: any, source: any): any {\n if (!isObject(target) || !isObject(source)) return source;\n\n Object.getOwnPropertyNames(source).forEach((key) => {\n const targetValue = target[key];\n const sourceValue = source[key];\n\n if (Array.isArray(targetValue) && Array.isArray(sourceValue)) {\n target[key] = targetValue.concat(sourceValue);\n } else if (isObject(targetValue) && isObject(sourceValue)) {\n target[key] = mergeDeep(\n Object.assign({}, targetValue),\n sourceValue,\n );\n } else {\n target[key] = sourceValue;\n }\n });\n\n return target;\n}\n\n/**\n * Return display text for an option.\n * If option is an object, get the property from path based on given field, or else just the property.\n * Apply a formatter function to the property if given.\n * Return the display label.\n *\n * @param obj Object to get the label for\n * @param field Property path of the object to use as display text\n * @param formatter Function to format the property to a string\n */\nexport function getPropertyValue<\n O,\n K extends DeepKeys<O>,\n D extends DeepType<O, K>,\n>(obj: O, field?: K, formatter?: (value: D, option: O) => string): string {\n if (!obj) return \"\";\n\n const property = (field ? getValueByPath<O, K, D>(obj, field) : obj) as D;\n\n const label =\n typeof formatter === \"function\" ? formatter(property, obj) : property;\n\n return String(label || \"\");\n}\n\n/**\n * Get a value of an object property/path even if it's nested\n */\nexport function getValueByPath<\n O,\n K extends DeepKeys<O>,\n D extends DeepType<O, K>,\n>(obj: O, path: K | (string & {})): D | undefined;\nexport function getValueByPath<\n O,\n K extends DeepKeys<O>,\n D extends DeepType<O, K>,\n>(obj: O, path: K | (string & {}), defaultValue: D): D;\nexport function getValueByPath<\n O,\n K extends DeepKeys<O>,\n D extends DeepType<O, K>,\n>(obj: O, path: K | (string & {}), defaultValue?: D): D | undefined;\nexport function getValueByPath<\n O,\n K extends DeepKeys<O>,\n D extends DeepType<O, K>,\n>(obj: O, path: K | (string & {}), defaultValue?: D): D | undefined {\n if (!obj || typeof obj !== \"object\" || typeof path !== \"string\")\n return defaultValue;\n\n const value: any = path\n .split(\".\")\n .reduce((o, i) => (typeof o !== \"undefined\" ? o[i] : undefined), obj);\n\n return typeof value !== \"undefined\" ? value : defaultValue;\n}\n\n/**\n * Set a value of an object property/path even if it's nested\n */\nexport function setValueByPath<O, K extends DeepKeys<O>>(\n obj: O,\n path: K,\n value: DeepType<O, K>,\n): void {\n if (typeof path !== \"string\") return;\n\n const p = path.split(\".\");\n if (p.length === 1) {\n obj[p[0]] = value;\n return;\n }\n const field = p[0];\n if (typeof obj[field] === \"undefined\") obj[field] = {};\n return setValueByPath(obj[field], p.slice(1).join(\".\"), value);\n}\n\nexport function removeElement(el: Element): void {\n if (typeof el.remove !== \"undefined\") {\n el.remove();\n } else if (typeof el.parentNode !== \"undefined\" && el.parentNode !== null) {\n el.parentNode.removeChild(el);\n }\n}\n\n/**\n * Escape regex characters\n * http://stackoverflow.com/a/6969486\n */\nexport function escapeRegExpChars(value: string): string {\n if (!value) return value;\n\n // eslint-disable-next-line no-useless-escape\n return value.replace(/[\\-\\[\\]\\/\\{\\}\\(\\)\\*\\+\\?\\.\\\\\\^\\$\\|]/g, \"\\\\$&\");\n}\n\n/**\n * Remove accents/diacritics in a string\n * https://stackoverflow.com/a/37511463\n */\nexport function removeDiacriticsFromString(value: string): string {\n if (!value) return value;\n return value.normalize(\"NFD\").replace(/[\\u0300-\\u036f]/g, \"\");\n}\n\n/** checks if a vue vnode is empty */\nexport function isVNodeEmpty(vnode): boolean {\n if (!vnode) return true;\n if (vnode.type === Comment) return true;\n if (vnode.type === Text && !vnode.children.trim()) return true;\n if (vnode.type === Fragment && isVNodeEmpty(vnode.children)) return true;\n return false;\n}\n\n/**\n * Mobile detection\n * https://www.abeautifulsite.net/detecting-mobile-devices-with-javascript\n */\nexport const isMobileAgent = {\n Android: (): boolean =>\n typeof window !== \"undefined\" &&\n !!window.navigator.userAgent.match(/Android/i),\n BlackBerry: (): boolean =>\n typeof window !== \"undefined\" &&\n !!window.navigator.userAgent.match(/BlackBerry/i),\n iOS: (): boolean =>\n typeof window !== \"undefined\" &&\n !!window.navigator.userAgent.match(/iPhone|iPad|iPod/i),\n Opera: (): boolean =>\n typeof window !== \"undefined\" &&\n !!window.navigator.userAgent.match(/Opera Mini/i),\n Windows: (): boolean =>\n typeof window !== \"undefined\" &&\n !!window.navigator.userAgent.match(/IEMobile/i),\n any: (): boolean =>\n isMobileAgent.Android() ||\n isMobileAgent.BlackBerry() ||\n isMobileAgent.iOS() ||\n isMobileAgent.Opera() ||\n isMobileAgent.Windows(),\n};\n","// Polyfills for SSR\n\nexport const isClient = typeof window !== \"undefined\";\n\nexport const HTMLElement = isClient ? window.HTMLElement : Object;\nexport const HTMLInputElement = isClient ? window.HTMLInputElement : Object;\nexport const File = isClient ? window.File : Object;\n","import type { App, defineComponent } from \"vue\";\nimport type { ProgrammaticFactory } from \"@/components/programmatic/useProgrammatic\";\nimport { type Oruga } from \"./config\";\n\n/**\n * Register a component to the vue app instance.\n * @internal\n */\nexport const registerComponent = (\n app: App,\n component: ReturnType<typeof defineComponent>, // type Component isn't correct since vue 3.5 any more\n): void => {\n app.component(component.name, component);\n};\n\n/**\n * Register a global programmatic component factory interface to the oruga object.\n * @internal\n */\nexport const registerProgrammatic = (\n oruga: Oruga,\n component: string,\n Factory: new () => ProgrammaticFactory,\n): void => {\n // add new programmatic component factory to the programmatic oruga object\n addProgrammatic(oruga, component, new Factory());\n};\n\n/**\n * Add components programmatic interfaces to the current oruga instance.\n * @internal\n */\nexport function addProgrammatic(\n oruga: Oruga,\n property: string,\n component: object,\n): void {\n // add the component on the property to the programmatic interface\n oruga._programmatic[property] = component;\n}\n","import {\n hasInjectionContext,\n inject,\n type App,\n type InjectionKey,\n type ObjectPlugin,\n} from \"vue\";\nimport { getValueByPath, merge, setValueByPath } from \"./helpers\";\nimport { isClient } from \"./ssr\";\nimport { addProgrammatic } from \"./plugins\";\nimport type { DeepKeys, DeepType, OrugaConfig } from \"@/types\";\n\n// extend the OrugaProgrammatic interface with `config` programmatic interface\ndeclare module \"../index\" {\n interface OrugaProgrammatic {\n config: typeof ConfigProgrammatic;\n }\n}\n\n/** Interface of the programmtic component. interfaces. */\nexport interface OrugaProgrammatic {\n [key: string]: Record<string, any>;\n}\n\nexport type OrugaComponentPlugin = ObjectPlugin<{ oruga: Oruga }>;\n\n/** Oruga Vue Plugin Object */\nexport interface Oruga {\n install(app: App, options?: OrugaConfig): void;\n\n /**\n * The vue instance oruga got registered into.\n * @internal\n */\n _app: App;\n\n /**\n * The global config object for this instance.\n * @internal\n */\n _config: OrugaConfig;\n\n /**\n * All registered components programmatic interfaces.\n * @internal\n */\n _programmatic: OrugaProgrammatic;\n\n /**\n * Defines if this oruga instance is a testing instance.\n * @internal\n */\n _testing?: boolean;\n\n /**\n * Adds a Oruga component plugin.\n *\n * @param plugin - Oruga component plugin to add\n * @returns Oruga plugin instance\n */\n use(plugin: OrugaComponentPlugin): Oruga;\n use(...plugins: OrugaComponentPlugin[]): Oruga;\n\n /**\n * Provides the oruga instance to the app context.\n * This is useful when you need to use `useOruga()` in a different app instance than the one Oruga got installed in.\n * @param app - The app instance to provide the oruga instance to.\n */\n provide(app: App): void;\n}\n\n/** provide/inject oruga key symbol */\nconst $ORUGA_SYMBOL = Symbol(\"$oruga\") as InjectionKey<Oruga>;\n\n/**\n * The global oruga instance which allows colling `useOruga()` outside of a component setup\n * after the oruga plugin got installed.\n */\nlet globalOruga: Oruga | undefined;\n\nexport function setActiveOruga(oruga: Oruga | undefined): void {\n globalOruga = oruga;\n}\n\n/**\n * Get the currently active oruga instance if there is any.\n */\nexport function getActiveOruga(): Oruga | undefined {\n return (hasInjectionContext() && inject($ORUGA_SYMBOL)) || globalOruga;\n}\n\n/**\n * Create a new Oruga Vue plugin which sets the oruga config options.\n * @param config - Override or extend the default oruga config.\n * @param plugins - A list of component plugins to register them globally. By default, no components will be registered globally.\n * @returns A new Oruga instance.\n */\nexport function createOruga(\n config: OrugaConfig = {},\n plugins: OrugaComponentPlugin[] = [],\n): Oruga {\n const _plugins: OrugaComponentPlugin[] = [];\n\n const oruga: Oruga = {\n // the vue instance Oruga gets installed in, it will be set in the install function\n // @ts-expect-error it's actually empty here\n _app: null,\n // default config is defined here\n _config: {\n override: false,\n iconPack: \"mdi\",\n useHtml5Validation: true,\n statusIcon: true,\n transformClasses: undefined,\n mobileBreakpoint: \"1023px\",\n teleportTarget: () => (isClient ? document.body : \"body\"),\n ...config,\n },\n // map of all registered programmatic interfaces\n // @ts-expect-error it's empty at first\n _programmatic: {},\n\n // vue plugin install function\n install(app: App, options: OrugaConfig = {}): void {\n // set global vue instance for programmatic usage\n oruga._app = app;\n // merge additional options with the base config\n oruga._config = merge(oruga._config, options, true);\n\n // set the global oruga instance\n setActiveOruga(oruga);\n\n // provide the oruga instance to the app context\n this.provide(app);\n\n // register the programmatic config interface to the programmatic oruga object\n addProgrammatic(oruga, \"config\", ConfigProgrammatic);\n\n // register oruga component plugins\n _plugins.forEach((p) => app.use(p, { oruga }));\n },\n // helper to register component plugins on install\n use(...plugins: OrugaComponentPlugin[]): Oruga {\n plugins.forEach((p) => _plugins.push(p));\n return oruga;\n },\n // helper to provide the oruga instance to another app instance\n provide(app: App): void {\n // provide the oruga instance\n app.provide($ORUGA_SYMBOL, oruga);\n // set the oruga instance as globalProperties\n app.config.globalProperties.$oruga = oruga;\n },\n };\n\n // register global components\n oruga.use(...plugins);\n\n return oruga;\n}\n\n/**\n * Create a new oruga instance and set it as active even the plugin got not installed yet.\n * @param config - Override or extend the default oruga config.\n * @returns A new Oruga instance.\n */\nexport function createTestingOruga(config: OrugaConfig = {}): Oruga {\n const oruga = createOruga(config);\n oruga._testing = true;\n setActiveOruga(oruga);\n return oruga;\n}\n\n/**\n * Get the oruga instence by injecting from the current context.\n * Throws an error when no inject context or no oruga instance is available.\n * @internal\n */\nfunction getOruga(): Oruga {\n // inject the current active oruga instance\n const oruga = getActiveOruga();\n if (!oruga)\n throw new Error(\n \"No Oruga instance available. Have you installed the Oruga plugin yet?\",\n );\n\n return oruga;\n}\n\n/**\n * Composable for internal and external usage of programmatic components.\n * It returns the programmatic interface of the current active oruga instance if there is any.\n */\nexport function useOruga(): OrugaProgrammatic {\n return getActiveOruga()?._programmatic ?? ({} as OrugaProgrammatic);\n}\n\n/**\n * Get the config of the current active oruga instance if there is any.\n */\nexport function getConfig(): OrugaConfig {\n return getActiveOruga()?._config ?? {};\n}\n\n/**\n * Override the config of the current active Oruga instance.\n * The given config will be mergen in the existing one.\n * Throws an error when no inject context or no oruga instance is available.\n *\n * @param config - The new config to be mergen into the existing one.\n */\nexport function setConfig(config: OrugaConfig): void {\n const oruga = getOruga();\n const _config = merge(oruga._config, config, true);\n oruga._config = _config;\n}\n\n/**\n * Get a config option by an option path\n * with an optional default value as fallback when no config is set.\n */\nexport function getOption<\n K extends DeepKeys<OrugaConfig>,\n D extends DeepType<OrugaConfig, K>,\n>(path: K | (string & {}), defaultValue: D): D;\nexport function getOption<\n K extends DeepKeys<OrugaConfig>,\n D extends DeepType<OrugaConfig, K>,\n>(path: K | (string & {}), defaultValue?: D): D | undefined;\nexport function getOption<\n K extends DeepKeys<OrugaConfig>,\n D extends DeepType<OrugaConfig, K>,\n>(path: K | (string & {}), defaultValue?: D): D | undefined {\n const config = getConfig();\n return getValueByPath<OrugaConfig, K, D>(config, path, defaultValue);\n}\n\n/** Add a config option to the config object. */\nfunction setOption<K extends DeepKeys<OrugaConfig>>(\n path: K,\n value: DeepType<OrugaConfig, K>,\n): void {\n const oruga = getOruga();\n setValueByPath(oruga._config, path, value);\n}\n\n/**\n * Less type strict version of getOption for component props defaults.\n * @internal\n */\nexport function getDefault<T>(\n path: DeepKeys<OrugaConfig>,\n defaultValue?: T,\n): T {\n const config = getConfig();\n return getValueByPath(config, path, defaultValue) as T & {};\n}\n\n/**\n * less type strict version of getOption for component prop default with type function\n * @internal\n */\nexport function getDefaultFunction<T>(\n path: DeepKeys<OrugaConfig>,\n defaultValue?: T,\n): (...args) => any {\n return (...args) => {\n const f = getDefault(path, defaultValue);\n if (typeof f === \"function\") return f(...args);\n };\n}\n\nconst ConfigProgrammatic = {\n getOption,\n setOption,\n getConfig,\n setConfig,\n};\n\nexport function useConfigProgrammatic(): typeof ConfigProgrammatic {\n return ConfigProgrammatic;\n}\n","import { getOption } from \"./config\";\nimport { merge } from \"./helpers\";\n\nexport type IconConfig = {\n sizes?: { default: string; [key: string]: string };\n iconPrefix?: string;\n internalIcons?: Record<string, string>;\n};\n\nconst mdiIcons = {\n iconPrefix: \"mdi-\",\n sizes: {\n default: \"mdi-24px\",\n small: \"\",\n medium: \"mdi-36px\",\n large: \"mdi-48px\",\n },\n} as const;\n\nfunction getFaIcons(): IconConfig {\n const iconComponent = getOption(\"iconComponent\");\n const faIconPrefix = iconComponent ? \"\" : \"fa-\";\n return {\n iconPrefix: faIconPrefix,\n sizes: {\n default: \"\",\n small: \"sm\",\n medium: \"lg\",\n large: \"xl\",\n },\n internalIcons: {\n check: \"check\",\n information: \"info-circle\",\n alert: \"exclamation-triangle\",\n \"alert-circle\": \"exclamation-circle\",\n \"arrow-up\": \"arrow-up\",\n \"chevron-right\": \"angle-right\",\n \"chevron-left\": \"angle-left\",\n \"chevron-down\": \"angle-down\",\n \"chevron-up\": \"angle-up\",\n eye: \"eye\",\n \"eye-off\": \"eye-slash\",\n \"caret-down\": \"caret-down\",\n \"caret-up\": \"caret-up\",\n \"close-circle\": \"times-circle\",\n close: \"times\",\n loading: \"circle-notch\",\n \"emoticon-sad\": \"frown\",\n },\n } as const;\n}\n\nfunction getIcons(): Record<string, IconConfig> {\n const faIcons = getFaIcons();\n let icons: Record<string, IconConfig> = {\n mdi: mdiIcons,\n fa: faIcons,\n fas: faIcons,\n far: faIcons,\n fad: faIcons,\n fab: faIcons,\n fal: faIcons,\n };\n\n const customIconPacks = getOption(\"customIconPacks\");\n if (customIconPacks) icons = merge(icons, customIconPacks, true);\n\n return icons;\n}\n\nexport default getIcons;\n","import {\n toValue,\n type ComponentPublicInstance,\n type MaybeRefOrGetter,\n type MaybeRef,\n type Component,\n} from \"vue\";\n\nexport type MaybeElement =\n | HTMLElement\n | Component\n | ComponentPublicInstance\n | undefined\n | null;\n\nexport type UnRefElementReturn<T extends MaybeElement> = T extends\n | ComponentPublicInstance\n | Component\n ? HTMLElement\n : T;\n\n/** Get the dom element of a ref of element or Vue component instance */\nexport function unrefElement<T extends MaybeElement>(\n elRef: MaybeRefOrGetter<T> | MaybeRef<T>,\n): UnRefElementReturn<T> {\n const plain = toValue(elRef);\n return (plain as ComponentPublicInstance)?.$el ?? plain;\n}\n\n/** Resolve an HTML element based on query selector or an explizit dom element */\nexport function resolveElement(\n target: MaybeRefOrGetter<HTMLElement | string>,\n): HTMLElement | null {\n const targetQuery = toValue(target);\n // query element if target is a string\n if (typeof targetQuery === \"string\")\n return document.querySelector<HTMLElement>(targetQuery);\n // else unwrap element\n else return unrefElement(targetQuery);\n}\n","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 { getConfig } from \"@/utils/config\";\nimport {\n isDefined,\n blankIfUndefined,\n getValueByPath,\n isTrueish,\n} from \"@/utils/helpers\";\n\nimport type { ClassBinding, ComponentClass, TransformFunction } 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<ClassBinding[]>,\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 * Pass a custom component instance.\n * By default the current component instance is used.\n */\n vm?: ComponentInternalInstance;\n};\n\nexport function defineClasses(\n ...args: [...ComputedClass[], DefineClassesOptions]\n): Ref<ClassBinding[]>;\n\nexport function defineClasses(\n ...args: [...ComputedClass[]]\n): Ref<ClassBinding[]>;\n\n/**\n * Calculate dynamic classes based on class definitions\n */\nexport function defineClasses(\n ...args: ComputedClass[] | [...ComputedClass[], DefineClassesOptions]\n): Ref<ClassBinding[]> {\n // extract last argument if its the option object\n const options = Array.isArray(args[args.length - 1])\n ? undefined\n : (args[args.length - 1] as DefineClassesOptions);\n\n // get class defintion list based on options are given or not\n const classDefinitions = (\n Array.isArray(args[args.length - 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 = options?.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<ClassBinding[]>([]);\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(): ClassBinding {\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 instance 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 the component config if it's not overridden by current instance\n const config = isTrueish(props.override) ? {} : getConfig();\n\n // --- Override Definition ---\n\n // define instance override\n const instanceOverride: boolean = isTrueish(props.override);\n\n // define config override\n const configOverride =\n // do not have to check if config is already overridden\n instanceOverride ||\n // check root config override property\n getValueByPath(config, \"override\") ||\n // check component field config override property\n getValueByPath(config, `${componentKey}.${field}.override`) ||\n // check component config override property\n getValueByPath(config, `${componentKey}.override`);\n\n // --- Class Definition ---\n\n let instanceClassString: string | undefined = undefined;\n let configClassString: string | undefined = undefined;\n let defaultClassString: string | undefined = undefined;\n\n // procsess instance class definition if available\n const instanceClass: ComponentClass | undefined =\n // get instance class definition\n getValueByPath(props, field);\n // compile instance class\n instanceClassString = compileClass(instanceClass, props, suffix);\n\n if (!instanceOverride) {\n if (!configOverride) {\n // process default class definition if not overridden by instance or config\n defaultClassString = applySuffix(defaultValue, suffix);\n }\n\n // process config class definition if not overriden by instance\n const configClass: ComponentClass | undefined =\n // get config class definition\n getValueByPath(config, `${componentKey}.${field}.class`) ||\n getValueByPath(config, `${componentKey}.${field}`);\n // compile config class\n configClassString = compileClass(configClass, props, suffix);\n }\n\n // --- Define Applied Classes ---\n\n // add default classes if available\n // add config classes if available\n // add instance classes if available\n let appliedClasses = [\n defaultClassString ?? \"\",\n configClassString ?? \"\",\n instanceClassString ?? \"\",\n ]\n .join(\" \")\n .trim()\n .replace(/\\s\\s+/g, \" \");\n\n // --- Tranform Classes ---\n\n // get component config transform function\n let transformClasses: TransformFunction | undefined = getValueByPath(\n config,\n `${componentKey}.transformClasses`,\n );\n if (!transformClasses)\n // get root config transform function\n transformClasses = getValueByPath(config, \"transformClasses\");\n\n // apply transform function if available\n if (typeof transformClasses === \"function\")\n appliedClasses = transformClasses(appliedClasses);\n\n return appliedClasses;\n}\n\n/** Compile a component class definition into a string. */\nfunction compileClass(\n classDefinition: ComponentClass | undefined,\n props: ReturnType<typeof getProps>,\n suffix: string,\n): string {\n // if definiton is undefined return empty class string\n if (typeof classDefinition === \"undefined\") return \"\";\n\n let classBinding: ClassBinding | ClassBinding[];\n\n if (typeof classDefinition === \"function\")\n // call class definition function\n classBinding = classDefinition(suffix, props) ?? \"\";\n else classBinding = classDefinition;\n\n let classString = \"\";\n if (Array.isArray(classBinding)) {\n classString = classBinding\n // transform the classBinding into a string\n .map(processClassBinding)\n // join all classes into one string\n .join(\" \");\n } else if (classBinding) {\n // transform the classBinding into a string\n classString = processClassBinding(classBinding);\n }\n\n // if suffix is not already applied by the classFunction\n if (typeof classDefinition !== \"function\")\n // apply suffix to the class string\n classString = applySuffix(classString, suffix);\n\n return classString;\n}\n\n/** Transform a classBinding object into a string. */\nfunction processClassBinding(classBinding: ClassBinding): string {\n if (typeof classBinding === \"string\") return classBinding;\n\n if (typeof classBinding === \"object\")\n return (\n Object.keys(classBinding)\n // filter by the truthiness of the data property\n .filter((key) => classBinding[key])\n // join all classes into one string\n .join(\" \")\n );\n\n return \"\";\n}\n\n/** Add a suffix to each word of an input string. */\nfunction applySuffix(value: string, suffix: string): string {\n return blankIfUndefined(value)\n .split(\" \")\n .map((cls) => {\n if (cls.includes(\"{*}\")) {\n return cls.replace(/\\{\\*\\}/g, blankIfUndefined(suffix));\n } else {\n return cls + blankIfUndefined(suffix);\n }\n })\n .join(\" \");\n}\n\n/** Get all props form an component instance. */\nfunction getProps(vm: ComponentInternalInstance): Record<string, any> {\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","import {\n onMounted,\n watch,\n getCurrentScope,\n onScopeDispose,\n type MaybeRefOrGetter,\n type Component,\n type WatchSource,\n toValue,\n} from \"vue\";\nimport { isObject } from \"@/utils/helpers\";\nimport { unrefElement } from \"./unrefElement\";\n\nexport type EventTarget = Element | Document | Window | Component;\nexport type EventListenerOptions = AddEventListenerOptions & {\n /** Register event listener immediate or on mounted hook. */\n immediate?: boolean;\n /** Trigger when the listener get registered and removed */\n trigger?: WatchSource<boolean>;\n};\n\n/**\n * Register DOM events using addEventListener on mounted, and removeEventListener automatically on unmounted.\n * Adaption of {@link https://vueuse.org/core/useEventListener}\n *\n * @param element DOM element to add the listener to\n * @param event Event name\n * @param handler Event handler function\n * @param options EventListenerOptions\n * @return stop function\n */\nexport function useEventListener(\n element: MaybeRefOrGetter<EventTarget>,\n event: string,\n handler: (evt?: any) => void,\n options?: EventListenerOptions,\n): () => void {\n let cleanup: () => void;\n\n const register = (): void => {\n if (!element) return;\n\n const target = unrefElement(element);\n // create a clone of options, to avoid it being changed reactively on removal\n const optionsClone = isObject(options) ? { ...options } : options;\n // register listener with timeout to prevent animation collision\n setTimeout(() => {\n target.addEventListener(event, handler, optionsClone);\n cleanup = (): void => {\n target.removeEventListener(event, handler, optionsClone);\n };\n });\n };\n\n let stopWatch: () => void;\n\n if (typeof options?.trigger !== \"undefined\") {\n stopWatch = watch(\n options.trigger,\n (value) => {\n // toggle listener\n if (value) register();\n else if (typeof cleanup === \"function\") cleanup();\n },\n { flush: \"post\" },\n );\n }\n\n if (options?.immediate) register();\n else if (getCurrentScope()) {\n // register listener on mount\n onMounted(() => {\n if (\n typeof options?.trigger === \"undefined\" ||\n toValue(options.trigger)\n )\n register();\n });\n }\n\n const stop = (): void => {\n // remove listener before unmounting\n if (typeof stopWatch === \"function\") stopWatch();\n if (typeof cleanup === \"function\") cleanup();\n };\n\n if (getCurrentScope(