>,
},
},
emits: [EVENT_NAME.CLOSE, EVENT_NAME.CANCEL, EVENT_NAME.ACCEPT],
setup(props, { emit }) {
const { closeFocusId } = useClosable(props, emit);
return { closeFocusId };
},
computed: {
backdropTransitionBindings(): TransitionBindings {
return {
enterActiveClass: styles.backdropTransitionEnterActive,
leaveActiveClass: styles.backdropTransitionLeaveActive,
};
},
backdropClass(): string | undefined {
return generateClass.transition(this.transition);
},
renderBackdrop(): VNode | null {
if (!this.isModal) {
return null;
}
return (
{this.isShown && (
)}
);
},
renderTitle(): VNode | null {
return this.title ? (
{this.title}
) : null;
},
renderCloseButton(): VNode {
// TODO: slot, tag, ... (like content in other components)
return (
);
},
renderHeader(): VNode | null {
if (this.hideHeader) {
return null;
}
// TODO: header, tag, ... (like content in other components)
return (
);
},
renderContent(): VNode {
return (
{this.$slots.default?.() || this.content}
);
},
renderFooter(): VNode | null {
if (this.hideFooter) {
return null;
}
// TODO: footer, tag, ... (like content in other components)
return (
);
},
transitionBindings(): TransitionBindings {
return {
enterActiveClass: styles.transitionEnterActive,
leaveActiveClass: styles.transitionLeaveActive,
};
},
classes(): (string | undefined)[] {
return [
config.class,
generateClass.colorScheme(this.colorScheme),
...generateClass.padding(this.padding, this.size),
generateClass.rounding(this.rounding),
generateClass.size(this.size),
generateClass.transition(this.transition),
];
},
styles(): CSSProperties {
return {
"--min-width": prepareHtmlSize(this.minWidth), // TODO: config
"--max-width": prepareHtmlSize(this.maxWidth), // TODO: config
"--min-height": prepareHtmlSize(this.minHeight), // TODO: config
"--max-height": prepareHtmlSize(this.maxHeight), // TODO: config
"--z-index": this.zIndex, // TODO: config
};
},
bindings(): DialogHTMLAttributes {
return {
open: this.isShown,
role: this.role,
["aria-label"]: this.title?.toString(), // TODO: what if this.title is VNode ???
["aria-modal"]: this.isModal,
class: this.classes,
style: this.styles,
};
},
renderModal(): VNode {
const Tag = this.tag;
/* TODO
* .showModal() or .show()
* inert others ???
* autofocus
* aria-labelledby="dialog1Title"
* aria-describedby="dialog1Desc"
* */
return (
{this.isShown && (
{this.renderHeader}
{this.renderContent}
{this.renderFooter}
)}
);
},
},
methods: {
closeHandler(): void {
/**
* Emits on the component close
* @event close
*/
this.$emit(EVENT_NAME.CLOSE);
this.whenClose?.();
},
cancelHandler(): void {
/**
* Emits on the component cancel
* @event cancel
*/
this.$emit(EVENT_NAME.CANCEL);
this.whenCancel?.();
},
acceptHandler(): void {
/**
* Emits on the component confirmation
* @event confirm
*/
this.$emit(EVENT_NAME.ACCEPT);
this.whenAccept?.();
},
},
/*TODO: why vue-docgen cant' detect not default slots ???*/
/** @slot $slots.default
* Use instead of props.content to fully customize content
*/
/** @slot $slots.header
* Use instead of default header to fully customize content
*/
/** @slot $slots.footer
* Use instead of default footer to fully customize content
*/
render(): VNode {
return (
{this.renderBackdrop}
{this.renderModal}
);
},
});
// TODO: long enough