Skip to content

Commit

Permalink
introduce useProgrammaticDialog composable
Browse files Browse the repository at this point in the history
  • Loading branch information
arobsn committed Jan 3, 2025
1 parent 8bcbcef commit 1aac5b1
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 13 deletions.
13 changes: 2 additions & 11 deletions src/common/componentUtils.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { AllowedComponentProps, Component, VNodeProps } from "vue";
import { Component } from "vue";
import { ensureDefaults } from "@fleet-sdk/common";
import { useProgrammatic } from "@oruga-ui/oruga-next";
import TxSignModal from "@/components/TxSignModal.vue";
import { Prettify } from "@/types/internal";
import { ComponentProps } from "@/composables/useProgrammaticDialog";
import { isPopup } from "./browser";

const DEFAULT_PROPS: Partial<ModalParams<Component>> = {
Expand All @@ -27,11 +27,6 @@ export function openModal<T extends Component>(component: T, params: ModalParams
});
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type ComponentProps<C extends Component> = C extends new (...args: any) => any
? Prettify<Omit<InstanceType<C>["$props"], keyof VNodeProps | keyof AllowedComponentProps>>
: never;

export type ModalParams<T extends Component> = {
props?: ComponentProps<T>;
events?: undefined;
Expand All @@ -56,7 +51,3 @@ export type ModalParams<T extends Component> = {
onCancel?: () => void;
onClose?: () => void;
};

export function chunkString(str: string, length: number): string[] {
return str.match(new RegExp(`.{1,${length}}`, "g")) ?? [];
}
80 changes: 80 additions & 0 deletions src/composables/useProgrammaticDialog.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import {
AllowedComponentProps,
Component,
createVNode,
mergeProps,
onUnmounted,
render,
VNode,
VNodeProps
} from "vue";

export type Prettify<T> = { [K in keyof T]: T[K] } & {};

export type ComponentProps<C extends Component> = C extends new (...args: unknown[]) => unknown
? Prettify<Omit<InstanceType<C>["$props"], keyof VNodeProps | keyof AllowedComponentProps>>
: never;

export type DialogLikeComponent = new (...args: unknown[]) => {
open: () => void;
close: () => void;
} & Component;

export function useProgrammaticDialog<T extends DialogLikeComponent>(
component: T,
initialProps?: ComponentProps<T>
) {
let instance: InstanceType<T> | null;
let props = { ...initialProps };
let vnode: VNode | null;
let container: HTMLDivElement | null;

const mount = (mountProps?: ComponentProps<T>) => {
patchProps(mountProps);

container = document.createElement("div");
vnode = createVNode(component, props);

render(vnode, container);
instance = vnode.component?.exposed as InstanceType<T>;

document.body.appendChild(container);
};

const patchProps = (newProps?: ComponentProps<T>) => {
if (!newProps || Object.keys(newProps).length === 0) return;

props = mergeProps(props, newProps);
if (vnode && vnode.component) {
Object.assign(vnode.component.props, props);
}
};

const open = (props?: ComponentProps<T>) => {
if (!instance) {
mount(props);
} else {
patchProps(props);
instance.open();
}
};

const close = () => instance?.close();

const destroy = () => {
if (!container || !instance) return;

render(null, container);
container.remove();
container = null;
instance = null;
vnode = null;
};

onUnmounted(destroy);

return {
open,
close
};
}
2 changes: 0 additions & 2 deletions src/types/internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,5 +115,3 @@ export type SigningState = {
};

export type TransactionBuilderFunction = () => Promise<EIP12UnsignedTransaction>;

export type Prettify<T> = { [K in keyof T]: T[K] } & {};

0 comments on commit 1aac5b1

Please sign in to comment.