import { defineComponent } from "vue"; import type { HTMLAttributes, LabelHTMLAttributes, ProgressHTMLAttributes, VNode, } from "vue"; import { v4 as uuid } from "uuid"; import generateProp from "@darwin-studio/vue-ui/src/utils/generate-prop"; import generateClass from "@darwin-studio/vue-ui/src/utils/generate-class"; import prepareHtmlSize from "@darwin-studio/vue-ui/src/utils/prepare-html-size"; import { DLoaderAsync as DLoader } from "@darwin-studio/vue-ui/src/components/atoms/d-loader/async"; import type { DLoaderProps } from "@darwin-studio/vue-ui/src/components/atoms/d-loader/types"; import type { DCaptionProps } from "@darwin-studio/vue-ui/src/components/atoms/d-caption/types"; import { TAG_NAME } from "@darwin-studio/vue-ui/src/constants/tag-name"; import useCaption from "@darwin-studio/vue-ui/src/compositions/caption"; import { Type } from "./types"; import config from "./config"; /** * Renders custom progress bar, linear or circular. */ export default defineComponent({ name: config.name, props: { /** * Defines id attr of the progress element.
* If you don't want to specify it, it will be generated automatically. */ id: generateProp.text(() => uuid()), /** * Defines content of the label element. */ label: generateProp.content(), /** Defines offset of .label */ labelOffset: generateProp.text(config.labelOffset), /** * Pass any attrs to customize label, f.e. { class: "someClass" } */ labelOptions: generateProp.options( config.labelOptions ), /** * Defines initial value attr of the input element */ value: generateProp.text(), /** * Defines type of the component: linear or circular */ type: generateProp.string(config.type), /** * Pass any attribute to the progress element */ progressOptions: generateProp.options( config.progressOptions ), /** * Plain string or VNode */ content: generateProp.content(), /** * Pass any attribute to the content element */ contentOptions: generateProp.options(config.contentOptions), /** * Plain string or VNode */ loader: generateProp.content(), /** * Pass any DLoader.props to customize it, f.e. { class: "someClass" } */ loaderOptions: generateProp.options(config.loaderOptions), /** * If not empty renders DCaption below the input element. */ caption: generateProp.content(), /** * Defines offset of DCaption */ captionOffset: generateProp.text(config.captionOffset), // TODO: move to captionOptions /** * Pass any DBackdrop.props to customize caption, f.e. { type: "error" } */ captionOptions: generateProp.options(config.captionOptions), /** * Defines appearance of the component */ colorScheme: generateProp.colorScheme(), /** * Defines corner rounding of the component */ rounding: generateProp.rounding(), /** * Defines size of the component */ size: generateProp.size(), /** * Defines transition type of the component */ transition: generateProp.transition(), /** * Defines container element type of the component */ tag: generateProp.tag(TAG_NAME.DIV), }, setup(props, { slots }) { return useCaption(props, slots, config.captionOptions); }, computed: { indeterminate(): boolean { if ( typeof this.progressOptions?.value === "undefined" && typeof this.value === "undefined" ) { return true; } return Number.isNaN(this.progressOptions?.value || this.value); }, renderLabel(): VNode | null { if (this.$slots.label || this.label) { return ( ); } return null; }, progressClasses(): (string | undefined)[] { return [ this.type === Type.linear ? config.linearClass : config.circularClass, generateClass.colorScheme(this.colorScheme), generateClass.rounding(this.rounding), this.type === Type.linear ? generateClass.minControlWidth(this.size) : undefined, generateClass.transition(this.transition), ]; }, renderLinear(): VNode { const Tag = TAG_NAME.PROGRESS; return ( {!this.indeterminate && `${this.progressOptions.value || this.value || 0}%`} ); }, renderCircular(): VNode { return (
); }, loaderClasses(): (string | undefined)[] { return [ config.loaderContainerClass, generateClass.rounding(this.rounding), ]; }, renderLoader(): VNode { return (
{this.$slots.loader?.() || this.loader || ( )}
); }, contentClasses(): (string | undefined)[] { return [ generateClass.colorScheme(this.colorScheme), this.type === Type.circular ? generateClass.rounding(this.rounding) : undefined, ]; }, renderContent(): VNode | null { if (!this.indeterminate && (this.$slots.default || this.content)) { return (
{this.$slots.default?.() || this.content}
); } if (this.indeterminate) { return this.renderLoader; } return null; }, classes(): (string | undefined)[] { return [ config.class, generateClass.font(this.size), generateClass.size(this.size), ]; }, }, /** @slot $slots.label * Use instead of props.label to fully customize label */ /** @slot $slots.default * Use instead of props.content to fully customize content */ /** @slot $slots.loader * Use instead of props.loader to fully customize loader */ /** @slot $slots.caption * Use instead of props.caption to fully customize caption */ render(): VNode { const Tag = this.tag; return ( {this.renderLabel} {this.type === Type.linear ? this.renderLinear : this.renderCircular} {this.renderContent} {this.renderCaption} ); }, });