hippofish/packages/client/src/widgets/widget.ts

82 lines
1.7 KiB
TypeScript
Raw Normal View History

2023-01-13 05:40:33 +01:00
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<P extends Record<string, unknown>> = {
id: string;
data: Partial<P>;
};
export type WidgetComponentProps<P extends Record<string, unknown>> = {
widget?: Widget<P>;
};
export type WidgetComponentEmits<P extends Record<string, unknown>> = {
2023-01-13 05:40:33 +01:00
(ev: "updateProps", props: P);
};
export type WidgetComponentExpose = {
name: string;
id: string | null;
configure: () => void;
};
2023-01-13 05:40:33 +01:00
export const useWidgetPropsManager = <
F extends Form & Record<string, { default: any }>,
>(
name: string,
propsDef: F,
props: Readonly<WidgetComponentProps<GetFormResultType<F>>>,
emit: WidgetComponentEmits<GetFormResultType<F>>,
): {
widgetProps: GetFormResultType<F>;
save: () => void;
configure: () => void;
} => {
2023-01-13 05:40:33 +01:00
const widgetProps = reactive(
props.widget ? deepClone(props.widget.data) : {},
);
const mergeProps = () => {
for (const prop of Object.keys(propsDef)) {
2023-01-13 05:40:33 +01:00
if (typeof widgetProps[prop] === "undefined") {
2022-07-04 16:39:04 +02:00
widgetProps[prop] = propsDef[prop].default;
}
}
};
2023-01-13 05:40:33 +01:00
watch(
widgetProps,
() => {
mergeProps();
},
{ deep: true, immediate: true },
);
const save = throttle(3000, () => {
2023-01-13 05:40:33 +01:00
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,
};
};