import { reactive, watch } from "vue"; import { throttle } from "throttle-debounce"; import { Form, GetFormResultType } from "@/scripts/form"; import * as os from "@/os"; import { deepClone } from "@/scripts/clone"; export type Widget

> = { id: string; data: Partial

; }; export type WidgetComponentProps

> = { widget?: Widget

; }; export type WidgetComponentEmits

> = { (ev: "updateProps", props: P); }; export type WidgetComponentExpose = { name: string; id: string | null; configure: () => void; }; export const useWidgetPropsManager = < F extends Form & Record, >( name: string, propsDef: F, props: Readonly>>, emit: WidgetComponentEmits>, ): { widgetProps: GetFormResultType; save: () => void; configure: () => void; } => { const widgetProps = reactive( props.widget ? deepClone(props.widget.data) : {}, ); const mergeProps = () => { for (const prop of Object.keys(propsDef)) { if (typeof widgetProps[prop] === "undefined") { widgetProps[prop] = propsDef[prop].default; } } }; watch( widgetProps, () => { mergeProps(); }, { deep: true, immediate: true }, ); const save = throttle(3000, () => { emit("updateProps", widgetProps); }); const configure = async () => { const form = deepClone(propsDef); for (const item of Object.keys(form)) { form[item].default = widgetProps[item]; } const { canceled, result } = await os.form(name, form); if (canceled) return; for (const key of Object.keys(result)) { widgetProps[key] = result[key]; } save(); }; return { widgetProps, save, configure, }; };