mirror of
https://github.com/directus/directus.git
synced 2026-04-25 03:00:53 -04:00
112 lines
2.9 KiB
TypeScript
112 lines
2.9 KiB
TypeScript
import { computed, reactive, toRefs, defineComponent, Ref, PropType, Component, ComputedRef } from 'vue';
|
|
import { Filter, LayoutConfig, ShowSelect } from '../types';
|
|
import { useExtensions } from './use-system';
|
|
|
|
const NAME_SUFFIX = 'wrapper';
|
|
const WRITABLE_PROPS = ['selection', 'layoutOptions', 'layoutQuery'] as const;
|
|
|
|
type WritableProp = typeof WRITABLE_PROPS[number];
|
|
|
|
function isWritableProp(prop: string): prop is WritableProp {
|
|
return (WRITABLE_PROPS as readonly string[]).includes(prop);
|
|
}
|
|
|
|
function createLayoutWrapper<Options, Query>(layout: LayoutConfig): Component {
|
|
return defineComponent({
|
|
name: `${layout.id}-${NAME_SUFFIX}`,
|
|
props: {
|
|
collection: {
|
|
type: String,
|
|
required: true,
|
|
},
|
|
selection: {
|
|
type: Array as PropType<(number | string)[]>,
|
|
default: () => [],
|
|
},
|
|
layoutOptions: {
|
|
type: Object as PropType<Options>,
|
|
default: () => ({}),
|
|
},
|
|
layoutQuery: {
|
|
type: Object as PropType<Query>,
|
|
default: () => ({}),
|
|
},
|
|
filter: {
|
|
type: Object as PropType<Filter>,
|
|
default: null,
|
|
},
|
|
filterUser: {
|
|
type: Object as PropType<Filter>,
|
|
default: null,
|
|
},
|
|
filterSystem: {
|
|
type: Object as PropType<Filter>,
|
|
default: null,
|
|
},
|
|
search: {
|
|
type: String as PropType<string | null>,
|
|
default: null,
|
|
},
|
|
showSelect: {
|
|
type: String as PropType<ShowSelect>,
|
|
default: 'multiple',
|
|
},
|
|
selectMode: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
readonly: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
resetPreset: {
|
|
type: Function as PropType<() => Promise<void>>,
|
|
default: null,
|
|
},
|
|
clearFilters: {
|
|
type: Function as PropType<() => void>,
|
|
default: null,
|
|
},
|
|
},
|
|
emits: WRITABLE_PROPS.map((prop) => `update:${prop}` as const),
|
|
setup(props, { emit }) {
|
|
const state: Record<string, unknown> = reactive({ ...layout.setup(props, { emit }), ...toRefs(props) });
|
|
|
|
for (const key in state) {
|
|
state[`onUpdate:${key}`] = (value: unknown) => {
|
|
if (isWritableProp(key)) {
|
|
emit(`update:${key}`, value);
|
|
} else if (!Object.keys(props).includes(key)) {
|
|
state[key] = value;
|
|
}
|
|
};
|
|
}
|
|
|
|
return { state };
|
|
},
|
|
render(ctx: any) {
|
|
return ctx.$slots.default !== undefined ? ctx.$slots.default({ layoutState: ctx.state }) : null;
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useLayout<Options = any, Query = any>(
|
|
layoutId: Ref<string | null>
|
|
): { layoutWrapper: ComputedRef<Component> } {
|
|
const { layouts } = useExtensions();
|
|
|
|
const layoutWrappers = computed(() => layouts.value.map((layout) => createLayoutWrapper<Options, Query>(layout)));
|
|
|
|
const layoutWrapper = computed(() => {
|
|
const layout = layoutWrappers.value.find((layout) => layout.name === `${layoutId.value}-${NAME_SUFFIX}`);
|
|
|
|
if (layout === undefined) {
|
|
return layoutWrappers.value.find((layout) => layout.name === `tabular-${NAME_SUFFIX}`)!;
|
|
}
|
|
|
|
return layout;
|
|
});
|
|
|
|
return { layoutWrapper };
|
|
}
|