From 3769f2bad57710adfadc7bd4b48a394bd2fb7336 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marti=CC=81n?= Date: Wed, 27 Nov 2024 15:36:04 +0100 Subject: [PATCH 1/2] Add Repeatable --- src/helpers/isFilled.ts | 18 +++++++++++++++++- src/types/value/repeatable.ts | 9 +++++++++ src/types/value/types.ts | 7 +++++++ 3 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 src/types/value/repeatable.ts diff --git a/src/helpers/isFilled.ts b/src/helpers/isFilled.ts index e6c454ac..8790c5a2 100644 --- a/src/helpers/isFilled.ts +++ b/src/helpers/isFilled.ts @@ -10,6 +10,7 @@ import type { KeyTextField } from "../types/value/keyText" import type { LinkField } from "../types/value/link" import type { LinkToMediaField } from "../types/value/linkToMedia" import type { NumberField } from "../types/value/number" +import type { Repeatable } from "../types/value/repeatable" import type { RichTextField } from "../types/value/richText" import type { SelectField } from "../types/value/select" import type { SharedSlice } from "../types/value/sharedSlice" @@ -17,7 +18,7 @@ import type { Slice } from "../types/value/slice" import type { SliceZone } from "../types/value/sliceZone" import type { TimestampField } from "../types/value/timestamp" import type { TitleField } from "../types/value/title" -import type { AnyRegularField } from "../types/value/types" +import type { AnyRegularField, AnyRepeatableField } from "../types/value/types" /** * Determines if a value is not nullish (i.e. not `null` or `undefined`). This @@ -266,6 +267,21 @@ export const integrationField = isNonNullish as < // TODO: Remove when we remove support for deprecated `integrationFields` export. export const integrationFields = integrationField +/** + * Determines if a Repeatable has at least one item. + * + * @param repeatable - Repeatable to check. + * + * @returns `true` if `repeatable` contains at least one item, `false` + * otherwise. + */ + +export const repeatable = ( + repeatable: Repeatable | null | undefined, +): repeatable is Repeatable, "filled"> => { + return isNonNullish(repeatable) && isNonEmptyArray(repeatable) +} + /** * Determines if a Group has at least one item. * diff --git a/src/types/value/repeatable.ts b/src/types/value/repeatable.ts new file mode 100644 index 00000000..e1b73e66 --- /dev/null +++ b/src/types/value/repeatable.ts @@ -0,0 +1,9 @@ +import type { AnyRepeatableField, FieldState } from "./types" + +/** + * A list of repeatable fields. + */ +export type Repeatable< + Fields extends Array = Array, + State extends FieldState = FieldState, +> = State extends "empty" ? [] : [Fields, ...Fields[]] diff --git a/src/types/value/types.ts b/src/types/value/types.ts index 73c41d9c..fcb7f2d5 100644 --- a/src/types/value/types.ts +++ b/src/types/value/types.ts @@ -11,6 +11,7 @@ import type { KeyTextField } from "./keyText" import type { LinkField } from "./link" import type { LinkToMediaField } from "./linkToMedia" import type { NumberField } from "./number" +import { Repeatable } from "./repeatable" import type { RichTextField } from "./richText" import type { SelectField } from "./select" import type { TimestampField } from "./timestamp" @@ -26,6 +27,11 @@ export type EmptyObjectField = Record */ export type FieldState = "empty" | "filled" +/** + * Any field that can be repeated. + */ +export type AnyRepeatableField = LinkField + /** * Any regular field that can be nested in a group-like field. */ @@ -46,6 +52,7 @@ export type AnyRegularField = | BooleanField | GeoPointField | IntegrationField + | Repeatable /** * Any field that can be used in a slice's primary section. From 026e0948bf046f88b171594a836c00fc90b2faf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=ADn?= Date: Wed, 27 Nov 2024 15:55:57 +0100 Subject: [PATCH 2/2] Update src/types/value/types.ts --- src/types/value/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types/value/types.ts b/src/types/value/types.ts index fcb7f2d5..546f7aab 100644 --- a/src/types/value/types.ts +++ b/src/types/value/types.ts @@ -11,7 +11,7 @@ import type { KeyTextField } from "./keyText" import type { LinkField } from "./link" import type { LinkToMediaField } from "./linkToMedia" import type { NumberField } from "./number" -import { Repeatable } from "./repeatable" +import type { Repeatable } from "./repeatable" import type { RichTextField } from "./richText" import type { SelectField } from "./select" import type { TimestampField } from "./timestamp"