import type { FormKitFrameworkContext, FormKitTypeDefinition } from '@formkit/core';
import type { FormKitInputs } from '@formkit/inputs';
import { createSection, label, outer } from '@formkit/inputs';
import type { CascadeSelectEmitsOptions, CascadeSelectProps } from 'primevue/cascadeselect';
import PrimevueCascadeselect from 'primevue/cascadeselect';
import { defineComponent, markRaw, ref } from 'vue';
import { floatLabel } from '../sections/floatLabel';
import { messages } from '../sections/messages';
// https://formkit.com/inputs/dropdown
type PrimevueSelectListeners = {
'onUpdate:modelValue': CascadeSelectEmitsOptions['update:modelValue'];
'onBlur': CascadeSelectEmitsOptions['blur'];
};
const SchemaComponent = defineComponent(
(vueProps: { context: FormKitFrameworkContext }) => {
const formkitContext = vueProps.context;
const listeners: PrimevueSelectListeners = {
'onUpdate:modelValue': (value: unknown) => {
formkitContext.node.input(value);
},
'onBlur': async e => {
setTimeout(
() => formkitContext.handlers.blur.call(undefined, e as never),
166, // 因为会触发两次。所以让blur事件延迟一点,可以考虑优化。(Cascadeselect好像没有这个问题)
);
},
};
const p_options = ref();
const loading = ref(true);
const loadOptions = async () => {
try {
let result;
if (formkitContext.options instanceof Promise) {
result = await formkitContext.options;
} else {
console.warn('未支持的 options 类型 :>> ', typeof formkitContext.options);
}
p_options.value = result;
} catch (error) {
console.error('Failed to load options:', error);
p_options.value = [];
} finally {
loading.value = false;
}
};
loadOptions(); // 立即加载options
return () => {
return (
);
};
},
// https://cn.vuejs.org/api/general#definecomponent
// 目前仍然需要手动声明运行时的 props
// 在将来,我们计划提供一个 Babel 插件,自动推断并注入运行时 props (就像在单文件组件中的 defineProps 一样),以便省略运行时 props 的声明。
{
props: ['context'],
},
);
const input = createSection('input', () => ({
$cmp: markRaw(SchemaComponent) as never,
bind: '$attrs',
props: {
context: '$node.context',
},
}));
export const PCascadeSelect: FormKitTypeDefinition = {
type: 'input',
schema: outer(
floatLabel(
input(), //
label('$label'),
),
messages(),
),
props: ['options', 'optionLabel', 'optionValue'],
schemaMemoKey: '72psvunq45', // Math.random().toString(36).substring(2, 15)
};
type OptionsType = CascadeSelectProps['options'];
declare module '@formkit/inputs' {
// https://formkit.com/essentials/custom-inputs#typescript-support
interface FormKitInputProps> {
PCascadeSelect: {
type: 'PCascadeSelect';
options: Promise;
optionLabel: string;
optionValue: string;
};
}
}