/* * SPDX-FileCopyrightText: syuilo and other misskey contributors * SPDX-License-Identifier: AGPL-3.0-only */ 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 = >( 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, }; };