@prismicio/types-internal
Version:
Prismic types for Custom Types and Prismic Data
80 lines (68 loc) • 2.17 kB
text/typescript
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"
import type { DynamicSlice, StaticSlice } from "./Slice"
export const CompositeSliceType = "Slice"
export const CompositeSliceConfig = t.exact(
t.partial({
label: StringOrNull,
}),
)
export type CompositeSliceConfig = t.TypeOf<typeof CompositeSliceConfig>
export const CompositeSlice = t.exact(
t.intersection([
t.type({
type: t.literal(CompositeSliceType),
}),
t.partial({
fieldset: StringOrNull,
description: t.string,
icon: t.string,
display: t.string,
"non-repeat": t.record(WidgetKey, NestableWidget),
repeat: t.record(WidgetKey, NestableWidget),
config: CompositeSliceConfig,
}),
]),
)
export type CompositeSlice = t.TypeOf<typeof CompositeSlice>
export function isCompositeSlice(
slice: DynamicSlice | StaticSlice,
): slice is CompositeSlice {
return slice.type === "Slice"
}
export function traverseCompositeSlice(args: {
path: ReadonlyArray<string>
slice: CompositeSlice
onField: OnFieldFn<NestableWidget>
}): CompositeSlice {
const { path: prevPath, slice, onField } = args
let nonRepeat: Record<string, NestableWidget> | undefined
for (const [key, field] of Object.entries(slice["non-repeat"] ?? {})) {
const path = [...prevPath, "non-repeat", key]
const newField = onField({ path, key, field })
if (field !== newField) {
if (!nonRepeat) nonRepeat = { ...slice["non-repeat"] }
nonRepeat[key] = newField
}
}
let repeat: Record<string, NestableWidget> | undefined
for (const [key, field] of Object.entries(slice.repeat ?? {})) {
const path = [...prevPath, "repeat", key]
const newField = onField({ path, key, field })
if (field !== newField) {
if (!repeat) repeat = { ...slice.repeat }
repeat[key] = newField
}
}
// returns the traversed model instead of a new one if it didn't change
return repeat || nonRepeat
? {
...slice,
...(nonRepeat && { "non-repeat": nonRepeat }),
...(repeat && { repeat }),
}
: slice
}