@prismicio/types-internal 2.8.0 → 2.9.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/lib/_internal/utils.d.ts +3 -2
  2. package/lib/content/Document.d.ts +1369 -61
  3. package/lib/content/Document.js +11 -0
  4. package/lib/content/LegacyContentCtx.d.ts +2 -2
  5. package/lib/content/LegacyContentCtx.js +4 -1
  6. package/lib/content/fields/GroupContent.js +13 -0
  7. package/lib/content/fields/RepeatableContent.d.ts +162 -0
  8. package/lib/content/fields/RepeatableContent.js +93 -0
  9. package/lib/content/fields/WidgetContent.d.ts +1369 -61
  10. package/lib/content/fields/index.d.ts +1 -0
  11. package/lib/content/fields/index.js +1 -0
  12. package/lib/content/fields/nestable/LinkContent.d.ts +23 -0
  13. package/lib/content/fields/nestable/LinkContent.js +23 -0
  14. package/lib/content/fields/nestable/NestableContent.d.ts +218 -0
  15. package/lib/content/fields/nestable/NestableContent.js +8 -1
  16. package/lib/content/fields/nestable/RichTextContent/Blocks.d.ts +66 -66
  17. package/lib/content/fields/nestable/RichTextContent/TextBlock.d.ts +727 -0
  18. package/lib/content/fields/nestable/RichTextContent/TextBlock.js +80 -0
  19. package/lib/content/fields/slices/Slice/CompositeSliceContent.d.ts +438 -2
  20. package/lib/content/fields/slices/Slice/RepeatableContent.d.ts +74 -0
  21. package/lib/content/fields/slices/Slice/SharedSliceContent.d.ts +440 -4
  22. package/lib/content/fields/slices/Slice/SharedSliceContent.js +20 -4
  23. package/lib/content/fields/slices/Slice/SimpleSliceContent.d.ts +219 -1
  24. package/lib/content/fields/slices/Slice/SlicePrimaryContent.d.ts +219 -1
  25. package/lib/content/fields/slices/Slice/index.d.ts +735 -5
  26. package/lib/content/fields/slices/SliceItem.d.ts +734 -4
  27. package/lib/content/fields/slices/SlicesContent.d.ts +1098 -8
  28. package/lib/customtypes/CustomType.d.ts +18 -0
  29. package/lib/customtypes/Section.d.ts +18 -0
  30. package/lib/customtypes/diff/SharedSlice.d.ts +8 -0
  31. package/lib/customtypes/diff/Variation.d.ts +8 -0
  32. package/lib/customtypes/widgets/Group.d.ts +6 -0
  33. package/lib/customtypes/widgets/Widget.d.ts +21 -0
  34. package/lib/customtypes/widgets/nestable/Link.d.ts +2 -0
  35. package/lib/customtypes/widgets/nestable/Link.js +5 -1
  36. package/lib/customtypes/widgets/nestable/NestableWidget.d.ts +1 -0
  37. package/lib/customtypes/widgets/slices/CompositeSlice.d.ts +2 -0
  38. package/lib/customtypes/widgets/slices/LegacySlice.d.ts +2 -0
  39. package/lib/customtypes/widgets/slices/SharedSlice.d.ts +8 -0
  40. package/lib/customtypes/widgets/slices/SlicePrimaryWidget.d.ts +6 -0
  41. package/lib/customtypes/widgets/slices/SliceWidget.d.ts +327 -0
  42. package/lib/customtypes/widgets/slices/SliceWidget.js +8 -0
  43. package/lib/customtypes/widgets/slices/Slices.d.ts +28 -0
  44. package/package.json +1 -1
  45. package/src/_internal/utils.ts +3 -1
  46. package/src/content/Document.ts +12 -0
  47. package/src/content/LegacyContentCtx.ts +4 -1
  48. package/src/content/fields/GroupContent.ts +13 -0
  49. package/src/content/fields/RepeatableContent.ts +147 -0
  50. package/src/content/fields/index.ts +1 -0
  51. package/src/content/fields/nestable/LinkContent.ts +24 -0
  52. package/src/content/fields/nestable/NestableContent.ts +12 -1
  53. package/src/content/fields/slices/Slice/SharedSliceContent.ts +18 -0
  54. package/src/customtypes/widgets/nestable/Link.ts +5 -1
@@ -145,6 +145,7 @@ export declare function slicesConfigReader<T extends SharedSlice | SharedSliceRe
145
145
  tags: t.Type<readonly string[], object, unknown>;
146
146
  allowTargetBlank: t.BooleanC;
147
147
  allowText: t.BooleanC;
148
+ repeat: t.BooleanC;
148
149
  }>>;
149
150
  }>]>>, t.ExactC<t.IntersectionC<[t.TypeC<{
150
151
  type: t.LiteralC<"Image">;
@@ -311,6 +312,7 @@ export declare function slicesConfigReader<T extends SharedSlice | SharedSliceRe
311
312
  tags: t.Type<readonly string[], object, unknown>;
312
313
  allowTargetBlank: t.BooleanC;
313
314
  allowText: t.BooleanC;
315
+ repeat: t.BooleanC;
314
316
  }>>;
315
317
  }>]>>, t.ExactC<t.IntersectionC<[t.TypeC<{
316
318
  type: t.LiteralC<"Image">;
@@ -477,6 +479,7 @@ export declare function slicesConfigReader<T extends SharedSlice | SharedSliceRe
477
479
  tags: t.Type<readonly string[], object, unknown>;
478
480
  allowTargetBlank: t.BooleanC;
479
481
  allowText: t.BooleanC;
482
+ repeat: t.BooleanC;
480
483
  }>>;
481
484
  }>]>>, t.ExactC<t.IntersectionC<[t.TypeC<{
482
485
  type: t.LiteralC<"Image">;
@@ -635,6 +638,7 @@ export declare function slicesConfigReader<T extends SharedSlice | SharedSliceRe
635
638
  tags: t.Type<readonly string[], object, unknown>;
636
639
  allowTargetBlank: t.BooleanC;
637
640
  allowText: t.BooleanC;
641
+ repeat: t.BooleanC;
638
642
  }>>;
639
643
  }>]>>, t.ExactC<t.IntersectionC<[t.TypeC<{
640
644
  type: t.LiteralC<"Image">;
@@ -805,6 +809,7 @@ export declare const StaticSlicesConfig: t.ExactC<t.PartialC<{
805
809
  tags: t.Type<readonly string[], object, unknown>;
806
810
  allowTargetBlank: t.BooleanC;
807
811
  allowText: t.BooleanC;
812
+ repeat: t.BooleanC;
808
813
  }>>;
809
814
  }>]>>, t.ExactC<t.IntersectionC<[t.TypeC<{
810
815
  type: t.LiteralC<"Image">;
@@ -971,6 +976,7 @@ export declare const StaticSlicesConfig: t.ExactC<t.PartialC<{
971
976
  tags: t.Type<readonly string[], object, unknown>;
972
977
  allowTargetBlank: t.BooleanC;
973
978
  allowText: t.BooleanC;
979
+ repeat: t.BooleanC;
974
980
  }>>;
975
981
  }>]>>, t.ExactC<t.IntersectionC<[t.TypeC<{
976
982
  type: t.LiteralC<"Image">;
@@ -1137,6 +1143,7 @@ export declare const StaticSlicesConfig: t.ExactC<t.PartialC<{
1137
1143
  tags: t.Type<readonly string[], object, unknown>;
1138
1144
  allowTargetBlank: t.BooleanC;
1139
1145
  allowText: t.BooleanC;
1146
+ repeat: t.BooleanC;
1140
1147
  }>>;
1141
1148
  }>]>>, t.ExactC<t.IntersectionC<[t.TypeC<{
1142
1149
  type: t.LiteralC<"Image">;
@@ -1295,6 +1302,7 @@ export declare const StaticSlicesConfig: t.ExactC<t.PartialC<{
1295
1302
  tags: t.Type<readonly string[], object, unknown>;
1296
1303
  allowTargetBlank: t.BooleanC;
1297
1304
  allowText: t.BooleanC;
1305
+ repeat: t.BooleanC;
1298
1306
  }>>;
1299
1307
  }>]>>, t.ExactC<t.IntersectionC<[t.TypeC<{
1300
1308
  type: t.LiteralC<"Image">;
@@ -1424,6 +1432,7 @@ export declare const StaticSlicesConfig: t.ExactC<t.PartialC<{
1424
1432
  tags?: readonly string[];
1425
1433
  allowTargetBlank?: boolean;
1426
1434
  allowText?: boolean;
1435
+ repeat?: boolean;
1427
1436
  };
1428
1437
  }) | ({
1429
1438
  type: "Number";
@@ -1591,6 +1600,7 @@ export declare const StaticSlicesConfig: t.ExactC<t.PartialC<{
1591
1600
  tags?: readonly string[];
1592
1601
  allowTargetBlank?: boolean;
1593
1602
  allowText?: boolean;
1603
+ repeat?: boolean;
1594
1604
  };
1595
1605
  }) | ({
1596
1606
  type: "Number";
@@ -1758,6 +1768,7 @@ export declare const StaticSlicesConfig: t.ExactC<t.PartialC<{
1758
1768
  tags?: readonly string[];
1759
1769
  allowTargetBlank?: boolean;
1760
1770
  allowText?: boolean;
1771
+ repeat?: boolean;
1761
1772
  };
1762
1773
  }) | ({
1763
1774
  type: "Number";
@@ -1924,6 +1935,7 @@ export declare const StaticSlicesConfig: t.ExactC<t.PartialC<{
1924
1935
  tags?: readonly string[];
1925
1936
  allowTargetBlank?: boolean;
1926
1937
  allowText?: boolean;
1938
+ repeat?: boolean;
1927
1939
  };
1928
1940
  }) | ({
1929
1941
  type: "Number";
@@ -2145,6 +2157,7 @@ export declare const DynamicSlicesConfig: t.ExactC<t.PartialC<{
2145
2157
  tags: t.Type<readonly string[], object, unknown>;
2146
2158
  allowTargetBlank: t.BooleanC;
2147
2159
  allowText: t.BooleanC;
2160
+ repeat: t.BooleanC;
2148
2161
  }>>;
2149
2162
  }>]>>, t.ExactC<t.IntersectionC<[t.TypeC<{
2150
2163
  type: t.LiteralC<"Image">;
@@ -2311,6 +2324,7 @@ export declare const DynamicSlicesConfig: t.ExactC<t.PartialC<{
2311
2324
  tags: t.Type<readonly string[], object, unknown>;
2312
2325
  allowTargetBlank: t.BooleanC;
2313
2326
  allowText: t.BooleanC;
2327
+ repeat: t.BooleanC;
2314
2328
  }>>;
2315
2329
  }>]>>, t.ExactC<t.IntersectionC<[t.TypeC<{
2316
2330
  type: t.LiteralC<"Image">;
@@ -2477,6 +2491,7 @@ export declare const DynamicSlicesConfig: t.ExactC<t.PartialC<{
2477
2491
  tags: t.Type<readonly string[], object, unknown>;
2478
2492
  allowTargetBlank: t.BooleanC;
2479
2493
  allowText: t.BooleanC;
2494
+ repeat: t.BooleanC;
2480
2495
  }>>;
2481
2496
  }>]>>, t.ExactC<t.IntersectionC<[t.TypeC<{
2482
2497
  type: t.LiteralC<"Image">;
@@ -2635,6 +2650,7 @@ export declare const DynamicSlicesConfig: t.ExactC<t.PartialC<{
2635
2650
  tags: t.Type<readonly string[], object, unknown>;
2636
2651
  allowTargetBlank: t.BooleanC;
2637
2652
  allowText: t.BooleanC;
2653
+ repeat: t.BooleanC;
2638
2654
  }>>;
2639
2655
  }>]>>, t.ExactC<t.IntersectionC<[t.TypeC<{
2640
2656
  type: t.LiteralC<"Image">;
@@ -2781,6 +2797,7 @@ export declare const StaticSlices: t.ExactC<t.IntersectionC<[t.TypeC<{
2781
2797
  tags?: readonly string[];
2782
2798
  allowTargetBlank?: boolean;
2783
2799
  allowText?: boolean;
2800
+ repeat?: boolean;
2784
2801
  };
2785
2802
  }) | ({
2786
2803
  type: "Number";
@@ -2948,6 +2965,7 @@ export declare const StaticSlices: t.ExactC<t.IntersectionC<[t.TypeC<{
2948
2965
  tags?: readonly string[];
2949
2966
  allowTargetBlank?: boolean;
2950
2967
  allowText?: boolean;
2968
+ repeat?: boolean;
2951
2969
  };
2952
2970
  }) | ({
2953
2971
  type: "Number";
@@ -3116,6 +3134,7 @@ export declare const StaticSlices: t.ExactC<t.IntersectionC<[t.TypeC<{
3116
3134
  tags?: readonly string[];
3117
3135
  allowTargetBlank?: boolean;
3118
3136
  allowText?: boolean;
3137
+ repeat?: boolean;
3119
3138
  };
3120
3139
  }) | ({
3121
3140
  type: "Number";
@@ -3276,6 +3295,7 @@ export declare const StaticSlices: t.ExactC<t.IntersectionC<[t.TypeC<{
3276
3295
  tags?: readonly string[];
3277
3296
  allowTargetBlank?: boolean;
3278
3297
  allowText?: boolean;
3298
+ repeat?: boolean;
3279
3299
  };
3280
3300
  }) | ({
3281
3301
  type: "Number";
@@ -3452,6 +3472,7 @@ export declare const StaticSlices: t.ExactC<t.IntersectionC<[t.TypeC<{
3452
3472
  tags?: readonly string[];
3453
3473
  allowTargetBlank?: boolean;
3454
3474
  allowText?: boolean;
3475
+ repeat?: boolean;
3455
3476
  };
3456
3477
  }) | ({
3457
3478
  type: "Number";
@@ -3619,6 +3640,7 @@ export declare const StaticSlices: t.ExactC<t.IntersectionC<[t.TypeC<{
3619
3640
  tags?: readonly string[];
3620
3641
  allowTargetBlank?: boolean;
3621
3642
  allowText?: boolean;
3643
+ repeat?: boolean;
3622
3644
  };
3623
3645
  }) | ({
3624
3646
  type: "Number";
@@ -3786,6 +3808,7 @@ export declare const StaticSlices: t.ExactC<t.IntersectionC<[t.TypeC<{
3786
3808
  tags?: readonly string[];
3787
3809
  allowTargetBlank?: boolean;
3788
3810
  allowText?: boolean;
3811
+ repeat?: boolean;
3789
3812
  };
3790
3813
  }) | ({
3791
3814
  type: "Number";
@@ -3952,6 +3975,7 @@ export declare const StaticSlices: t.ExactC<t.IntersectionC<[t.TypeC<{
3952
3975
  tags?: readonly string[];
3953
3976
  allowTargetBlank?: boolean;
3954
3977
  allowText?: boolean;
3978
+ repeat?: boolean;
3955
3979
  };
3956
3980
  }) | ({
3957
3981
  type: "Number";
@@ -4139,6 +4163,7 @@ export declare const DynamicSlices: t.ExactC<t.IntersectionC<[t.TypeC<{
4139
4163
  tags?: readonly string[];
4140
4164
  allowTargetBlank?: boolean;
4141
4165
  allowText?: boolean;
4166
+ repeat?: boolean;
4142
4167
  };
4143
4168
  }) | ({
4144
4169
  type: "Number";
@@ -4306,6 +4331,7 @@ export declare const DynamicSlices: t.ExactC<t.IntersectionC<[t.TypeC<{
4306
4331
  tags?: readonly string[];
4307
4332
  allowTargetBlank?: boolean;
4308
4333
  allowText?: boolean;
4334
+ repeat?: boolean;
4309
4335
  };
4310
4336
  }) | ({
4311
4337
  type: "Number";
@@ -4474,6 +4500,7 @@ export declare const DynamicSlices: t.ExactC<t.IntersectionC<[t.TypeC<{
4474
4500
  tags?: readonly string[];
4475
4501
  allowTargetBlank?: boolean;
4476
4502
  allowText?: boolean;
4503
+ repeat?: boolean;
4477
4504
  };
4478
4505
  }) | ({
4479
4506
  type: "Number";
@@ -4634,6 +4661,7 @@ export declare const DynamicSlices: t.ExactC<t.IntersectionC<[t.TypeC<{
4634
4661
  tags?: readonly string[];
4635
4662
  allowTargetBlank?: boolean;
4636
4663
  allowText?: boolean;
4664
+ repeat?: boolean;
4637
4665
  };
4638
4666
  }) | ({
4639
4667
  type: "Number";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prismicio/types-internal",
3
- "version": "2.8.0",
3
+ "version": "2.9.0-alpha.1",
4
4
  "description": "Prismic types for Custom Types and Prismic Data",
5
5
  "keywords": [
6
6
  "typescript",
@@ -3,6 +3,7 @@ import type {
3
3
  SliceItemContent,
4
4
  WidgetContent,
5
5
  } from "../content"
6
+ import type { RepeatableContent } from "../content/fields/RepeatableContent"
6
7
  import type {
7
8
  CompositeSlice,
8
9
  Group,
@@ -30,7 +31,7 @@ export type TraverseSliceContentFn = <
30
31
  }) => S | SharedSliceItemContent | undefined
31
32
 
32
33
  export type TraverseWidgetContentFn = <
33
- C extends WidgetContent,
34
+ C extends WidgetContent | RepeatableContent,
34
35
  D extends NestableWidget | StaticSlices | Group | UID,
35
36
  >({
36
37
  path,
@@ -56,6 +57,7 @@ export type ContentPathEntry = {
56
57
  | "GroupItem"
57
58
  | "primary"
58
59
  | "items"
60
+ | "RepeatableItem"
59
61
  key: string
60
62
  }
61
63
 
@@ -24,6 +24,7 @@ import {
24
24
  NestableContentDefaultValue,
25
25
  slicesContentWithDefaultValues,
26
26
  traverseGroupContent,
27
+ traverseRepeatableContent,
27
28
  traverseSlices,
28
29
  WidgetContent,
29
30
  WidgetLegacy,
@@ -293,6 +294,17 @@ export function traverseDocument({
293
294
  model: fieldModel?.type === "Group" ? fieldModel : undefined,
294
295
  content,
295
296
  })(transformWidget)
297
+ case "RepeatableContent":
298
+ return traverseRepeatableContent({
299
+ path,
300
+ key,
301
+ apiId: key,
302
+ model:
303
+ fieldModel?.type === "Link" && fieldModel.config?.repeat
304
+ ? fieldModel
305
+ : undefined,
306
+ content,
307
+ })(transformWidget)
296
308
  default:
297
309
  return transformWidget({
298
310
  path,
@@ -2,7 +2,10 @@ import * as t from "io-ts"
2
2
 
3
3
  import { FieldType, SlicesTypes } from "../customtypes/widgets"
4
4
 
5
- export const FieldOrSliceType = t.union([FieldType, SlicesTypes])
5
+ export const FieldOrSliceType = t.union([
6
+ t.union([FieldType, SlicesTypes]),
7
+ t.literal("Repeatable.Link"),
8
+ ])
6
9
  export type FieldOrSliceType = t.TypeOf<typeof FieldOrSliceType>
7
10
  export class LegacyContentCtx {
8
11
  fieldKey: string
@@ -20,6 +20,7 @@ import {
20
20
  } from "../LegacyContentCtx"
21
21
  import { hasContentType } from "../utils"
22
22
  import { isNestableContent, NestableContent, NestableLegacy } from "./nestable"
23
+ import { traverseRepeatableContent } from "./RepeatableContent"
23
24
  import { repeatableContentWithDefaultNestableContentValues } from "./withDefaultValues"
24
25
 
25
26
  export const GroupItemContentType = "GroupItemContent" as const
@@ -235,6 +236,18 @@ export function traverseGroupItemsContent({
235
236
  model: fieldDef,
236
237
  content: fieldContent,
237
238
  })(transform)
239
+ } else if (
240
+ (!fieldDef ||
241
+ (fieldDef?.type === "Link" && fieldDef.config?.repeat)) &&
242
+ fieldContent.__TYPE__ === "RepeatableContent"
243
+ ) {
244
+ transformedField = traverseRepeatableContent({
245
+ path: groupItemPath.concat([{ key: fieldKey, type: "Widget" }]),
246
+ key: fieldKey,
247
+ apiId: fieldKey,
248
+ model: fieldDef,
249
+ content: fieldContent,
250
+ })(transform)
238
251
  } else {
239
252
  transformedField = transform({
240
253
  path: groupItemPath.concat([{ key: fieldKey, type: "Widget" }]),
@@ -0,0 +1,147 @@
1
+ import { either } from "fp-ts"
2
+ import { isLeft } from "fp-ts/lib/Either"
3
+ import { pipe } from "fp-ts/lib/function"
4
+ import * as t from "io-ts"
5
+
6
+ import type {
7
+ ContentPath,
8
+ TraverseWidgetContentFn,
9
+ } from "../../_internal/utils"
10
+ import type { Link, NestableWidget } from "../../customtypes"
11
+ import type { LegacyContentCtx, WithTypes } from "../LegacyContentCtx"
12
+ import {
13
+ isLinkContent,
14
+ LinkContent,
15
+ LinkContentLegacy,
16
+ LinkContentType,
17
+ } from "./nestable"
18
+
19
+ export const RepeatableContent = t.strict({
20
+ __TYPE__: t.literal("RepeatableContent"),
21
+ type: t.literal("Link"),
22
+ value: t.array(LinkContent),
23
+ })
24
+
25
+ export type RepeatableContent = t.TypeOf<typeof RepeatableContent>
26
+
27
+ export const isRepeatableContent = RepeatableContent.is
28
+
29
+ export const RepeatableLegacy = (
30
+ ctx: LegacyContentCtx,
31
+ fieldType: "Link",
32
+ ): t.Type<RepeatableContent, WithTypes<Array<unknown>>, unknown> => {
33
+ return new t.Type<RepeatableContent, WithTypes<Array<unknown>>, unknown>(
34
+ "RepeatableLegacy",
35
+ isRepeatableContent,
36
+ (items) => {
37
+ const parsed = pipe(
38
+ t.array(t.unknown).decode(items),
39
+ either.map((items) => {
40
+ const parsedItems = items.reduce<Array<LinkContent>>((acc, item) => {
41
+ let result
42
+
43
+ switch (fieldType) {
44
+ case "Link":
45
+ result = LinkContentLegacy(ctx).decode(item)
46
+ break
47
+ }
48
+
49
+ if (!result) return acc
50
+ if (isLeft(result)) return acc
51
+
52
+ return [...acc, result.right]
53
+ }, [])
54
+
55
+ return {
56
+ value: parsedItems,
57
+ type: fieldType,
58
+ __TYPE__: "RepeatableContent" as const,
59
+ }
60
+ }),
61
+ )
62
+
63
+ return parsed
64
+ },
65
+ (r: RepeatableContent) => {
66
+ const res = t.array(LinkContent).encode(r.value)
67
+ const encodedItems = res.reduce<Array<WithTypes<unknown>>>(
68
+ (acc, item) => {
69
+ let encoded
70
+
71
+ switch (item.__TYPE__) {
72
+ case LinkContentType:
73
+ encoded = LinkContentLegacy(ctx).encode(item)
74
+ break
75
+ }
76
+
77
+ if (!encoded) return acc
78
+
79
+ return [...acc, encoded]
80
+ },
81
+ [],
82
+ )
83
+
84
+ return {
85
+ content: encodedItems.map((encodedItem) => encodedItem.content),
86
+ types: { [ctx.keyOfType]: `Repeatable.${fieldType}` },
87
+ }
88
+ },
89
+ )
90
+ }
91
+
92
+ export type RepeatableCustomType = Link
93
+
94
+ export function traverseRepeatableContent({
95
+ path,
96
+ key,
97
+ apiId,
98
+ model,
99
+ content,
100
+ }: {
101
+ path: ContentPath
102
+ key: string
103
+ apiId: string
104
+ content: RepeatableContent
105
+ model?: NestableWidget | undefined
106
+ }) {
107
+ return (
108
+ transform: TraverseWidgetContentFn,
109
+ ): RepeatableContent | undefined => {
110
+ const items = content.value.reduce<Array<LinkContent>>(
111
+ (acc, fieldContent, index) => {
112
+ const itemPath = path.concat([
113
+ { key: index.toString(), type: "Widget" },
114
+ ])
115
+
116
+ const transformedField = transform({
117
+ path: itemPath,
118
+ key: key,
119
+ apiId: apiId,
120
+ model: model,
121
+ content: fieldContent,
122
+ })
123
+
124
+ // Can happen if the transform function returns undefined to filter out a field
125
+ if (!transformedField) return acc
126
+
127
+ // If the transformed field is not a link content, we don't include it
128
+ if (!isLinkContent(transformedField)) return acc
129
+
130
+ return acc.concat(transformedField)
131
+ },
132
+ [],
133
+ )
134
+
135
+ return transform({
136
+ path,
137
+ key,
138
+ apiId,
139
+ model,
140
+ content: {
141
+ __TYPE__: content.__TYPE__,
142
+ type: content.type,
143
+ value: items,
144
+ },
145
+ })
146
+ }
147
+ }
@@ -1,6 +1,7 @@
1
1
  export * from "./EmptyContent"
2
2
  export * from "./GroupContent"
3
3
  export * from "./nestable"
4
+ export * from "./RepeatableContent"
4
5
  export * from "./slices"
5
6
  export * from "./UIDContent"
6
7
  export * from "./WidgetContent"
@@ -1,3 +1,27 @@
1
+ /**
2
+ * LinkContent is a union of different link content types.
3
+ *
4
+ * Most link content types are built from a union of a filled and an unfilled version.
5
+ *
6
+ * Filled versions make sure that the important fields that make the link work
7
+ * are present. They are also exported for when there's a need to ensure that
8
+ * the link is filled when used in a specific context, e.g. links in rich text fields.
9
+ *
10
+ * Unfilled versions are used when the link is not filled yet but contains other
11
+ * information like the text.
12
+ *
13
+ * There are some exceptions that don't have a filled version (e.g. MediaLink)
14
+ * for when the exact subtype is not yet known.
15
+ *
16
+ * Unfilled versions all have a special `kind` property that is used to
17
+ * determine the type of the link. For legacy reasons, filled versions don't
18
+ * necessarily require this property or its type is loose (e.g. `string`). In
19
+ * this cases, the type is determined based on a specific combination of the
20
+ * rest of the link data. This is why the order of the subtypes in the union is
21
+ * important and should be from the most specific to the least specific. A
22
+ * battery of tests ensures that the correct type is inferred.
23
+ */
24
+
1
25
  import { either } from "fp-ts"
2
26
  import { pipe } from "fp-ts/lib/function"
3
27
  import * as t from "io-ts"
@@ -4,6 +4,11 @@ import * as t from "io-ts"
4
4
  import type { NestableWidget } from "../../../customtypes"
5
5
  import type { LegacyContentCtx } from "../../LegacyContentCtx"
6
6
  import { EmptyContent, EmptyLegacy, isEmptyContent } from "../EmptyContent"
7
+ import {
8
+ isRepeatableContent,
9
+ RepeatableContent,
10
+ RepeatableLegacy,
11
+ } from "../RepeatableContent"
7
12
  import {
8
13
  BooleanContent,
9
14
  BooleanContentDefaultValue,
@@ -96,6 +101,7 @@ export const NestableContent = t.union([
96
101
  LinkContent,
97
102
  RichTextContent,
98
103
  SeparatorContent,
104
+ RepeatableContent,
99
105
  ])
100
106
  export type NestableContent = t.TypeOf<typeof NestableContent>
101
107
  export type NestableContentType = NestableContent["__TYPE__"]
@@ -129,7 +135,8 @@ export const isNestableContent = (u: unknown): u is NestableContent =>
129
135
  isIntegrationFieldContent(u) ||
130
136
  isLinkContent(u) ||
131
137
  isSeparatorContent(u) ||
132
- isEmptyContent(u)
138
+ isEmptyContent(u) ||
139
+ isRepeatableContent(u)
133
140
 
134
141
  export const NestableLegacy = (ctx: LegacyContentCtx) => {
135
142
  return {
@@ -171,6 +178,8 @@ export const NestableLegacy = (ctx: LegacyContentCtx) => {
171
178
  return LinkContentLegacy(ctx)
172
179
  case "Separator":
173
180
  return SeparatorLegacy(ctx)
181
+ case "Repeatable.Link":
182
+ return RepeatableLegacy(ctx, "Link")
174
183
  default:
175
184
  return
176
185
  }
@@ -209,6 +218,8 @@ export const NestableLegacy = (ctx: LegacyContentCtx) => {
209
218
  return LinkContentLegacy(ctx).encode(value)
210
219
  case SeparatorContentType:
211
220
  return SeparatorLegacy(ctx).encode(value)
221
+ case "RepeatableContent":
222
+ return RepeatableLegacy(ctx, value.type).encode(value)
212
223
 
213
224
  default:
214
225
  return
@@ -26,6 +26,10 @@ import {
26
26
  traverseGroupItemsContent,
27
27
  } from "../../GroupContent"
28
28
  import { isNestableContent } from "../../nestable"
29
+ import {
30
+ isRepeatableContent,
31
+ traverseRepeatableContent,
32
+ } from "../../RepeatableContent"
29
33
  import {
30
34
  repeatableContentWithDefaultNestableContentValues,
31
35
  withDefaultSlicePrimaryContentValues,
@@ -215,6 +219,20 @@ export function traverseSharedSliceContent({
215
219
  content: fieldContent,
216
220
  model: fieldDef?.type === GroupFieldType ? fieldDef : undefined,
217
221
  })(transformWidget)
222
+ } else if (isRepeatableContent(fieldContent)) {
223
+ return traverseRepeatableContent({
224
+ path: path.concat([
225
+ { key: "primary", type: "primary" },
226
+ { key: fieldKey, type: "Widget" },
227
+ ]),
228
+ key: fieldKey,
229
+ apiId: fieldKey,
230
+ content: fieldContent,
231
+ model:
232
+ fieldDef?.type === "Link" && fieldDef.config?.repeat
233
+ ? fieldDef
234
+ : undefined,
235
+ })(transformWidget)
218
236
  } else if (isNestableContent(fieldContent)) {
219
237
  return transformWidget({
220
238
  path: path.concat([
@@ -79,6 +79,7 @@ export const LinkConfig = t.exact(
79
79
  tags: MasksArrayString,
80
80
  allowTargetBlank: t.boolean,
81
81
  allowText: t.boolean,
82
+ repeat: withFallback(t.boolean, false),
82
83
  }),
83
84
  )
84
85
  export type LinkConfig = t.TypeOf<typeof LinkConfig>
@@ -90,7 +91,10 @@ export const Link = t.exact(
90
91
  }),
91
92
  t.partial({
92
93
  fieldset: StringOrNull,
93
- config: LinkConfig,
94
+ config: withFallback(LinkConfig, {
95
+ select: null,
96
+ repeat: false,
97
+ }),
94
98
  }),
95
99
  ]),
96
100
  )