Skip to content

Commit b0ebd0a

Browse files
umbobaboleannecornish-ft
authored andcommitted
feat: add timeline and event nodes
1 parent 988df94 commit b0ebd0a

File tree

6 files changed

+585
-19
lines changed

6 files changed

+585
-19
lines changed

README.md

Lines changed: 47 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ type BodyBlock =
107107
| Video
108108
| YoutubeVideo
109109
| Text
110+
| Timeline
110111
```
111112
112113
`BodyBlock` nodes are the only things that are valid as the top level of a `Body`.
@@ -754,24 +755,24 @@ interface Table extends Parent {
754755

755756
```ts
756757
type CustomCodeComponentAttributes = {
757-
[key: string]: string | boolean | undefined
758+
[key: string]: string | boolean | undefined
758759
}
759760

760761
interface CustomCodeComponent extends Node {
761-
/** Component type */
762-
type: "custom-code-component"
763-
/** Id taken from the CAPI url */
764-
id: string
765-
/** How the component should be presented in the article page according to the column layout system */
766-
layoutWidth: LayoutWidth
767-
/** Repository for the code of the component in the format "[github org]/[github repo]/[component name]". */
768-
external path: string
769-
/** Semantic version of the code of the component, e.g. "^0.3.5". */
770-
external versionRange: string
771-
/** Last date-time when the attributes for this block were modified, in ISO-8601 format. */
772-
external attributesLastModified: string
773-
/** Configuration data to be passed to the component. */
774-
external attributes: CustomCodeComponentAttributes
762+
/** Component type */
763+
type: "custom-code-component"
764+
/** Id taken from the CAPI url */
765+
id: string
766+
/** How the component should be presented in the article page according to the column layout system */
767+
layoutWidth: LayoutWidth
768+
/** Repository for the code of the component in the format "[github org]/[github repo]/[component name]". */
769+
external path: string
770+
/** Semantic version of the code of the component, e.g. "^0.3.5". */
771+
external versionRange: string
772+
/** Last date-time when the attributes for this block were modified, in ISO-8601 format. */
773+
external attributesLastModified: string
774+
/** Configuration data to be passed to the component. */
775+
external attributes: CustomCodeComponentAttributes
775776
}
776777
```
777778

@@ -780,6 +781,37 @@ interface CustomCodeComponent extends Node {
780781
- The basic interface in Spark to make reference to this system above (eg. the git repo URL or a public S3 bucket), and provide some data for it if necessary. This will be the Custom Component storyblock.
781782
- The data Spark receives from entering a specific ID will be used to render dynamic fields (the `attributes`).
782783

784+
### Timeline
785+
786+
```ts
787+
/**
788+
* Allowed layout widths for a Timeline.
789+
*/
790+
type TimelineLayoutWidth = Extract<LayoutWidth, "full-width" | "insert-left">
791+
792+
/**
793+
* Timeline nodes display a timeline of events in arbitrary order.
794+
*/
795+
interface Timeline extends Parent {
796+
type: "timeline"
797+
/** The title for the timeline */
798+
title: string
799+
/** The layout width for the timeline */
800+
layoutWidth: TimelineLayoutWidth
801+
children: TimelineEvent[]
802+
}
803+
804+
/**
805+
* TimelineEvent is the representation of a single event in a Timeline.
806+
*/
807+
interface TimelineEvent extends Parent {
808+
type: "timeline-event"
809+
/** The title of the event */
810+
title: string
811+
/** A paragraph and an optional image set, or just an image set */
812+
children:[Paragraph, ImageSet?] | [ImageSet];
813+
}
814+
```
783815

784816
## License
785817

content-tree.d.ts

Lines changed: 104 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
export declare namespace ContentTree {
2-
type BodyBlock = Paragraph | Heading | ImageSet | Flourish | BigNumber | CustomCodeComponent | Layout | List | Blockquote | Pullquote | ScrollyBlock | ThematicBreak | Table | Recommended | RecommendedList | Tweet | Video | YoutubeVideo | Text;
2+
type BodyBlock = Paragraph | Heading | ImageSet | Flourish | BigNumber | CustomCodeComponent | Layout | List | Blockquote | Pullquote | ScrollyBlock | ThematicBreak | Table | Recommended | RecommendedList | Tweet | Video | YoutubeVideo | Text | Timeline;
33
type LayoutWidth = "auto" | "in-line" | "inset-left" | "inset-right" | "full-bleed" | "full-grid" | "mid-grid" | "full-width";
44
type Phrasing = Text | Break | Strong | Emphasis | Strikethrough | Link;
55
interface Node {
@@ -285,8 +285,33 @@ export declare namespace ContentTree {
285285
/** Configuration data to be passed to the component. */
286286
attributes: CustomCodeComponentAttributes;
287287
}
288+
/**
289+
* Allowed layout widths for a Timeline.
290+
*/
291+
type TimelineLayoutWidth = Extract<LayoutWidth, "full-width" | "insert-left">;
292+
/**
293+
* Timeline nodes display a timeline of events in arbitrary order.
294+
*/
295+
interface Timeline extends Parent {
296+
type: "timeline";
297+
/** The title for the timeline */
298+
title: string;
299+
/** The layout width for the timeline */
300+
layoutWidth: TimelineLayoutWidth;
301+
children: TimelineEvent[];
302+
}
303+
/**
304+
* TimelineEvent is the representation of a single event in a Timeline.
305+
*/
306+
interface TimelineEvent extends Parent {
307+
type: "timeline-event";
308+
/** The title of the event */
309+
title: string;
310+
/** A paragraph and an optional image set, or just an image set */
311+
children: [Paragraph, ImageSet?] | [ImageSet];
312+
}
288313
namespace full {
289-
type BodyBlock = Paragraph | Heading | ImageSet | Flourish | BigNumber | CustomCodeComponent | Layout | List | Blockquote | Pullquote | ScrollyBlock | ThematicBreak | Table | Recommended | RecommendedList | Tweet | Video | YoutubeVideo | Text;
314+
type BodyBlock = Paragraph | Heading | ImageSet | Flourish | BigNumber | CustomCodeComponent | Layout | List | Blockquote | Pullquote | ScrollyBlock | ThematicBreak | Table | Recommended | RecommendedList | Tweet | Video | YoutubeVideo | Text | Timeline;
290315
type LayoutWidth = "auto" | "in-line" | "inset-left" | "inset-right" | "full-bleed" | "full-grid" | "mid-grid" | "full-width";
291316
type Phrasing = Text | Break | Strong | Emphasis | Strikethrough | Link;
292317
interface Node {
@@ -572,9 +597,34 @@ export declare namespace ContentTree {
572597
/** Configuration data to be passed to the component. */
573598
attributes: CustomCodeComponentAttributes;
574599
}
600+
/**
601+
* Allowed layout widths for a Timeline.
602+
*/
603+
type TimelineLayoutWidth = Extract<LayoutWidth, "full-width" | "insert-left">;
604+
/**
605+
* Timeline nodes display a timeline of events in arbitrary order.
606+
*/
607+
interface Timeline extends Parent {
608+
type: "timeline";
609+
/** The title for the timeline */
610+
title: string;
611+
/** The layout width for the timeline */
612+
layoutWidth: TimelineLayoutWidth;
613+
children: TimelineEvent[];
614+
}
615+
/**
616+
* TimelineEvent is the representation of a single event in a Timeline.
617+
*/
618+
interface TimelineEvent extends Parent {
619+
type: "timeline-event";
620+
/** The title of the event */
621+
title: string;
622+
/** A paragraph and an optional image set, or just an image set */
623+
children: [Paragraph, ImageSet?] | [ImageSet];
624+
}
575625
}
576626
namespace transit {
577-
type BodyBlock = Paragraph | Heading | ImageSet | Flourish | BigNumber | CustomCodeComponent | Layout | List | Blockquote | Pullquote | ScrollyBlock | ThematicBreak | Table | Recommended | RecommendedList | Tweet | Video | YoutubeVideo | Text;
627+
type BodyBlock = Paragraph | Heading | ImageSet | Flourish | BigNumber | CustomCodeComponent | Layout | List | Blockquote | Pullquote | ScrollyBlock | ThematicBreak | Table | Recommended | RecommendedList | Tweet | Video | YoutubeVideo | Text | Timeline;
578628
type LayoutWidth = "auto" | "in-line" | "inset-left" | "inset-right" | "full-bleed" | "full-grid" | "mid-grid" | "full-width";
579629
type Phrasing = Text | Break | Strong | Emphasis | Strikethrough | Link;
580630
interface Node {
@@ -845,9 +895,34 @@ export declare namespace ContentTree {
845895
/** How the component should be presented in the article page according to the column layout system */
846896
layoutWidth: LayoutWidth;
847897
}
898+
/**
899+
* Allowed layout widths for a Timeline.
900+
*/
901+
type TimelineLayoutWidth = Extract<LayoutWidth, "full-width" | "insert-left">;
902+
/**
903+
* Timeline nodes display a timeline of events in arbitrary order.
904+
*/
905+
interface Timeline extends Parent {
906+
type: "timeline";
907+
/** The title for the timeline */
908+
title: string;
909+
/** The layout width for the timeline */
910+
layoutWidth: TimelineLayoutWidth;
911+
children: TimelineEvent[];
912+
}
913+
/**
914+
* TimelineEvent is the representation of a single event in a Timeline.
915+
*/
916+
interface TimelineEvent extends Parent {
917+
type: "timeline-event";
918+
/** The title of the event */
919+
title: string;
920+
/** A paragraph and an optional image set, or just an image set */
921+
children: [Paragraph, ImageSet?] | [ImageSet];
922+
}
848923
}
849924
namespace loose {
850-
type BodyBlock = Paragraph | Heading | ImageSet | Flourish | BigNumber | CustomCodeComponent | Layout | List | Blockquote | Pullquote | ScrollyBlock | ThematicBreak | Table | Recommended | RecommendedList | Tweet | Video | YoutubeVideo | Text;
925+
type BodyBlock = Paragraph | Heading | ImageSet | Flourish | BigNumber | CustomCodeComponent | Layout | List | Blockquote | Pullquote | ScrollyBlock | ThematicBreak | Table | Recommended | RecommendedList | Tweet | Video | YoutubeVideo | Text | Timeline;
851926
type LayoutWidth = "auto" | "in-line" | "inset-left" | "inset-right" | "full-bleed" | "full-grid" | "mid-grid" | "full-width";
852927
type Phrasing = Text | Break | Strong | Emphasis | Strikethrough | Link;
853928
interface Node {
@@ -1133,5 +1208,30 @@ export declare namespace ContentTree {
11331208
/** Configuration data to be passed to the component. */
11341209
attributes?: CustomCodeComponentAttributes;
11351210
}
1211+
/**
1212+
* Allowed layout widths for a Timeline.
1213+
*/
1214+
type TimelineLayoutWidth = Extract<LayoutWidth, "full-width" | "insert-left">;
1215+
/**
1216+
* Timeline nodes display a timeline of events in arbitrary order.
1217+
*/
1218+
interface Timeline extends Parent {
1219+
type: "timeline";
1220+
/** The title for the timeline */
1221+
title: string;
1222+
/** The layout width for the timeline */
1223+
layoutWidth: TimelineLayoutWidth;
1224+
children: TimelineEvent[];
1225+
}
1226+
/**
1227+
* TimelineEvent is the representation of a single event in a Timeline.
1228+
*/
1229+
interface TimelineEvent extends Parent {
1230+
type: "timeline-event";
1231+
/** The title of the event */
1232+
title: string;
1233+
/** A paragraph and an optional image set, or just an image set */
1234+
children: [Paragraph, ImageSet?] | [ImageSet];
1235+
}
11361236
}
11371237
}

schemas/body-tree.schema.json

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,9 @@
125125
},
126126
{
127127
"$ref": "#/definitions/ContentTree.transit.Text"
128+
},
129+
{
130+
"$ref": "#/definitions/ContentTree.transit.Timeline"
128131
}
129132
]
130133
},
@@ -1120,6 +1123,88 @@
11201123
],
11211124
"type": "object"
11221125
},
1126+
"ContentTree.transit.Timeline": {
1127+
"additionalProperties": false,
1128+
"description": "Timeline nodes display a timeline of events in arbitrary order.",
1129+
"properties": {
1130+
"children": {
1131+
"items": {
1132+
"$ref": "#/definitions/ContentTree.transit.TimelineEvent"
1133+
},
1134+
"type": "array"
1135+
},
1136+
"data": {},
1137+
"layoutWidth": {
1138+
"const": "full-width",
1139+
"description": "The layout width for the timeline",
1140+
"type": "string"
1141+
},
1142+
"title": {
1143+
"description": "The title for the timeline",
1144+
"type": "string"
1145+
},
1146+
"type": {
1147+
"const": "timeline",
1148+
"type": "string"
1149+
}
1150+
},
1151+
"required": [
1152+
"children",
1153+
"layoutWidth",
1154+
"title",
1155+
"type"
1156+
],
1157+
"type": "object"
1158+
},
1159+
"ContentTree.transit.TimelineEvent": {
1160+
"additionalProperties": false,
1161+
"description": "TimelineEvent is the representation of a single event in a Timeline.",
1162+
"properties": {
1163+
"children": {
1164+
"anyOf": [
1165+
{
1166+
"items": [
1167+
{
1168+
"$ref": "#/definitions/ContentTree.transit.Paragraph"
1169+
},
1170+
{
1171+
"$ref": "#/definitions/ContentTree.transit.ImageSet"
1172+
}
1173+
],
1174+
"maxItems": 2,
1175+
"minItems": 1,
1176+
"type": "array"
1177+
},
1178+
{
1179+
"items": [
1180+
{
1181+
"$ref": "#/definitions/ContentTree.transit.ImageSet"
1182+
}
1183+
],
1184+
"maxItems": 1,
1185+
"minItems": 1,
1186+
"type": "array"
1187+
}
1188+
],
1189+
"description": "A paragraph and an optional image set, or just an image set"
1190+
},
1191+
"data": {},
1192+
"title": {
1193+
"description": "The title of the event",
1194+
"type": "string"
1195+
},
1196+
"type": {
1197+
"const": "timeline-event",
1198+
"type": "string"
1199+
}
1200+
},
1201+
"required": [
1202+
"children",
1203+
"title",
1204+
"type"
1205+
],
1206+
"type": "object"
1207+
},
11231208
"ContentTree.transit.Tweet": {
11241209
"additionalProperties": false,
11251210
"properties": {

0 commit comments

Comments
 (0)