UNPKG

@prismicio/types-internal

Version:
121 lines (101 loc) 3.25 kB
import * as t from "io-ts" import type { OnFieldFn } from "../../_internal/utils" import { WidgetKey } from "../../common" import { StringOrNull } from "../../validators" import { NestableWidget } from "./nestable/NestableWidget" export const GroupFieldType = "Group" // We're obliged to use `t.Mixed` here, otherwise the factory would be // referencing itself and TypeScript would infer its type as `any` const createGroupConfig = <TWidgets extends t.Mixed>(widgets: TWidgets) => t.exact( t.partial({ label: StringOrNull, repeat: t.boolean, fields: t.record(WidgetKey, widgets), }), ) // We're obliged to use `t.Mixed` here, otherwise the factory would be // referencing itself and TypeScript would infer its type as `any` const createGroup = <TWidgets extends t.Mixed>(widgets: TWidgets) => t.exact( t.intersection([ t.type({ type: t.literal(GroupFieldType), }), t.partial({ fieldset: StringOrNull, icon: t.string, description: t.string, config: createGroupConfig(widgets), }), ]), ) export const NestedGroupConfig = createGroupConfig(NestableWidget) export type NestedGroupConfig = t.TypeOf<typeof NestedGroupConfig> export const NestedGroup = createGroup(NestableWidget) export type NestedGroup = t.TypeOf<typeof NestedGroup> export const GroupConfig = createGroupConfig( t.union([NestableWidget, NestedGroup]), ) export type GroupConfig = t.TypeOf<typeof GroupConfig> export const Group = createGroup(t.union([NestableWidget, NestedGroup])) export type Group = t.TypeOf<typeof Group> export function traverseNestedGroup(args: { path: ReadonlyArray<string> group: NestedGroup onField: OnFieldFn<NestableWidget> }): NestedGroup { const { path: prevPath, group, onField } = args if (!group.config?.fields) return group let fields: Record<string, NestableWidget> | undefined for (const [key, field] of Object.entries(group.config.fields)) { const path = [...prevPath, key] const newField = onField({ path, key, field, }) if (field !== newField) { if (!fields) fields = { ...group.config.fields } fields[key] = newField } } // returns the traversed model instead of a new one if it didn't change return fields ? { ...group, config: { ...group.config, fields } } : group } export function traverseGroup(args: { path: ReadonlyArray<string> group: Group onField: OnFieldFn<NestableWidget | NestedGroup> }): Group { const { path: prevPath, group, onField } = args if (!group.config?.fields) return group let fields: Record<string, NestableWidget | NestedGroup> | undefined for (const [key, prevField] of Object.entries(group.config.fields)) { const path = [...prevPath, key] let field switch (prevField.type) { case "Group": field = traverseNestedGroup({ path, group: prevField, onField: onField as OnFieldFn<NestableWidget>, }) break default: field = prevField break } const newField = onField({ path, key, field, }) if (field !== newField) { if (!fields) fields = { ...group.config.fields } fields[key] = newField } } // returns the traversed model instead of a new one if it didn't change return fields ? { ...group, config: { ...group.config, fields } } : group }