@se-studio/core-data-types 0.1.0
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.
- package/README.md +137 -0
- package/dist/index.d.ts +357 -0
- package/dist/index.js +108 -0
- package/dist/index.js.map +1 -0
- package/package.json +48 -0
package/README.md
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# @se-studio/core-data-types
|
|
2
|
+
|
|
3
|
+
Core TypeScript type definitions for SE Studio content models and shared types across the monorepo.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# pnpm
|
|
9
|
+
pnpm add @se-studio/core-data-types
|
|
10
|
+
|
|
11
|
+
# npm
|
|
12
|
+
npm install @se-studio/core-data-types
|
|
13
|
+
|
|
14
|
+
# yarn
|
|
15
|
+
yarn add @se-studio/core-data-types
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
import type { IPage, ISeoMetadata, IAsset, DeepPartial } from '@se-studio/core-data-types';
|
|
22
|
+
|
|
23
|
+
// Use the page interface
|
|
24
|
+
const page: IPage = {
|
|
25
|
+
id: 'page-123',
|
|
26
|
+
slug: 'about-us',
|
|
27
|
+
title: 'About Us',
|
|
28
|
+
seo: {
|
|
29
|
+
title: 'About Us - SE Studio',
|
|
30
|
+
description: 'Learn more about SE Studio',
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
// Use utility types
|
|
35
|
+
type PartialPage = DeepPartial<IPage>;
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## API Overview
|
|
39
|
+
|
|
40
|
+
### Page Types
|
|
41
|
+
|
|
42
|
+
- **`IPage`** - Base interface for page content models
|
|
43
|
+
- `id: string` - Unique identifier
|
|
44
|
+
- `slug: string` - URL-friendly slug
|
|
45
|
+
- `title: string` - Page title
|
|
46
|
+
- `seo?: ISeoMetadata` - Optional SEO metadata
|
|
47
|
+
- `publishedAt?: string` - Publication date
|
|
48
|
+
- `updatedAt?: string` - Last updated date
|
|
49
|
+
- `locale?: string` - Content locale
|
|
50
|
+
- `sections?: unknown[]` - Content sections (to be defined)
|
|
51
|
+
|
|
52
|
+
- **`IPageMetadata`** - Page metadata without content sections
|
|
53
|
+
|
|
54
|
+
### Common Types
|
|
55
|
+
|
|
56
|
+
- **`ISeoMetadata`** - SEO metadata structure
|
|
57
|
+
- `title?: string`
|
|
58
|
+
- `description?: string`
|
|
59
|
+
- `keywords?: string[]`
|
|
60
|
+
- `ogImage?: string`
|
|
61
|
+
- `noIndex?: boolean`
|
|
62
|
+
- `canonicalUrl?: string`
|
|
63
|
+
|
|
64
|
+
- **`IAsset`** - Image/media asset structure
|
|
65
|
+
- `url: string`
|
|
66
|
+
- `title?: string`
|
|
67
|
+
- `description?: string`
|
|
68
|
+
- `width?: number`
|
|
69
|
+
- `height?: number`
|
|
70
|
+
- `contentType?: string`
|
|
71
|
+
|
|
72
|
+
- **`ILink`** - Link/reference structure
|
|
73
|
+
- `text: string`
|
|
74
|
+
- `url: string`
|
|
75
|
+
- `target?: '_blank' | '_self'`
|
|
76
|
+
- `ariaLabel?: string`
|
|
77
|
+
|
|
78
|
+
### Utility Types
|
|
79
|
+
|
|
80
|
+
- **`DeepPartial<T>`** - Makes all nested properties optional
|
|
81
|
+
- **`Prettify<T>`** - Improves type readability in IDE tooltips
|
|
82
|
+
|
|
83
|
+
## Development
|
|
84
|
+
|
|
85
|
+
This package is part of the SE Studio monorepo. To work on this package:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
# Install dependencies
|
|
89
|
+
pnpm install
|
|
90
|
+
|
|
91
|
+
# Build the package
|
|
92
|
+
pnpm build
|
|
93
|
+
|
|
94
|
+
# Run tests
|
|
95
|
+
pnpm test
|
|
96
|
+
|
|
97
|
+
# Type check
|
|
98
|
+
pnpm type-check
|
|
99
|
+
|
|
100
|
+
# Run linting
|
|
101
|
+
pnpm lint
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Extending Types
|
|
105
|
+
|
|
106
|
+
These types serve as a foundation and should be extended based on your actual Contentful content model:
|
|
107
|
+
|
|
108
|
+
```typescript
|
|
109
|
+
import type { IPage } from '@se-studio/core-data-types';
|
|
110
|
+
|
|
111
|
+
// Extend the base page type with your custom fields
|
|
112
|
+
interface ICustomPage extends IPage {
|
|
113
|
+
hero: {
|
|
114
|
+
title: string;
|
|
115
|
+
image: IAsset;
|
|
116
|
+
};
|
|
117
|
+
content: RichTextContent;
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Future Additions
|
|
122
|
+
|
|
123
|
+
This package currently contains placeholder types. As the content model evolves, additional types will be added for:
|
|
124
|
+
|
|
125
|
+
- Component types (Hero, CTA, etc.)
|
|
126
|
+
- Rich text content structures
|
|
127
|
+
- Navigation structures
|
|
128
|
+
- Blog/Article types
|
|
129
|
+
- And more...
|
|
130
|
+
|
|
131
|
+
## License
|
|
132
|
+
|
|
133
|
+
MIT
|
|
134
|
+
|
|
135
|
+
## Repository
|
|
136
|
+
|
|
137
|
+
[https://github.com/Something-Else-Studio/se-core-product](https://github.com/Something-Else-Studio/se-core-product)
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
import { VideoTypeData } from '@extractus/oembed-extractor';
|
|
2
|
+
|
|
3
|
+
interface IPage<TConfig extends BaseCmsConfig> extends IBaseModel<TConfig> {
|
|
4
|
+
type: 'Page';
|
|
5
|
+
isHomePage: boolean;
|
|
6
|
+
structuredData?: ReadonlyArray<unknown>;
|
|
7
|
+
contents?: ReadonlyArray<PageContent<TConfig>>;
|
|
8
|
+
tags?: ReadonlyArray<IInternalLink<TConfig>>;
|
|
9
|
+
}
|
|
10
|
+
type PageLink<TConfig extends BaseCmsConfig> = Omit<IPage<TConfig>, BaseModelLinkOmissions | 'structuredData' | 'contents'>;
|
|
11
|
+
declare function isPage<TConfig extends BaseCmsConfig>(content: IBaseModel<TConfig>): content is IPage<TConfig>;
|
|
12
|
+
|
|
13
|
+
interface ITag<TConfig extends BaseCmsConfig> extends IBaseModel<TConfig> {
|
|
14
|
+
type: 'Tag';
|
|
15
|
+
tagType?: string | null;
|
|
16
|
+
contents?: ReadonlyArray<PageContent<TConfig>>;
|
|
17
|
+
}
|
|
18
|
+
type TagLink<TConfig extends BaseCmsConfig> = Omit<ITag<TConfig>, BaseModelLinkOmissions | 'contents'>;
|
|
19
|
+
declare function isTag<TConfig extends BaseCmsConfig>(content: IBaseModel<TConfig>): content is ITag<TConfig>;
|
|
20
|
+
interface ITags<TConfig extends BaseCmsConfig> extends IBaseModel<TConfig> {
|
|
21
|
+
type: 'Tags';
|
|
22
|
+
}
|
|
23
|
+
declare function isTags<TConfig extends BaseCmsConfig>(content: IBaseModel<TConfig>): content is ITags<TConfig>;
|
|
24
|
+
|
|
25
|
+
type Vertical = 'Top' | 'Middle' | 'Bottom';
|
|
26
|
+
type Horizontal = 'Left' | 'Middle' | 'Right';
|
|
27
|
+
interface IInternalBreakpoint {
|
|
28
|
+
maxWidth: number;
|
|
29
|
+
proportion: number;
|
|
30
|
+
pixels: number;
|
|
31
|
+
size: string;
|
|
32
|
+
}
|
|
33
|
+
type IBreakpoint = Pick<IInternalBreakpoint, 'maxWidth'> & Partial<Omit<IInternalBreakpoint, 'maxWidth'>>;
|
|
34
|
+
interface IVisualSizes {
|
|
35
|
+
defaultSize?: string;
|
|
36
|
+
defaultPixels?: number;
|
|
37
|
+
breakpoints?: IBreakpoint[];
|
|
38
|
+
}
|
|
39
|
+
declare function processSizes({ defaultSize, defaultPixels, breakpoints }: IVisualSizes): {
|
|
40
|
+
defaultSize: string | undefined;
|
|
41
|
+
defaultPixels: number | undefined;
|
|
42
|
+
breakpoints: IInternalBreakpoint[] | undefined;
|
|
43
|
+
};
|
|
44
|
+
interface IVisualCommon {
|
|
45
|
+
type: string;
|
|
46
|
+
id: string;
|
|
47
|
+
name: string;
|
|
48
|
+
description?: string | null;
|
|
49
|
+
nameAsCaption?: boolean | null;
|
|
50
|
+
dontCrop?: boolean | null;
|
|
51
|
+
horizontalCropPosition?: Horizontal | null;
|
|
52
|
+
verticalCropPosition?: Vertical | null;
|
|
53
|
+
horizontalPosition?: Horizontal | null;
|
|
54
|
+
widthPercent?: number | null;
|
|
55
|
+
}
|
|
56
|
+
interface IOptimisedSvg {
|
|
57
|
+
data: string;
|
|
58
|
+
width: number;
|
|
59
|
+
height: number;
|
|
60
|
+
}
|
|
61
|
+
interface IImageCommon extends IVisualCommon {
|
|
62
|
+
mimeType: string;
|
|
63
|
+
}
|
|
64
|
+
interface IPicture extends IImageCommon {
|
|
65
|
+
type: 'Picture';
|
|
66
|
+
src: string;
|
|
67
|
+
width: number;
|
|
68
|
+
height: number;
|
|
69
|
+
size: number;
|
|
70
|
+
}
|
|
71
|
+
interface ISvgImage extends IImageCommon {
|
|
72
|
+
type: 'Svg image';
|
|
73
|
+
size: number;
|
|
74
|
+
svgSrc: string;
|
|
75
|
+
width: number;
|
|
76
|
+
height: number;
|
|
77
|
+
}
|
|
78
|
+
interface ISvgData extends IImageCommon {
|
|
79
|
+
type: 'Svg data';
|
|
80
|
+
data: string;
|
|
81
|
+
width: number;
|
|
82
|
+
height: number;
|
|
83
|
+
}
|
|
84
|
+
type IImage = IPicture | ISvgImage | ISvgData;
|
|
85
|
+
declare function isPicture(obj: IVisualCommon | undefined | null): obj is IPicture;
|
|
86
|
+
declare function isSvgImage(obj: IVisualCommon | undefined | null): obj is ISvgImage;
|
|
87
|
+
declare function isSvgData(obj: IVisualCommon | undefined | null): obj is ISvgData;
|
|
88
|
+
declare function isImage(obj: IVisualCommon | undefined | null): obj is IImage;
|
|
89
|
+
interface IVideoDetails {
|
|
90
|
+
id: string;
|
|
91
|
+
videoUrl: string;
|
|
92
|
+
mimeType: string;
|
|
93
|
+
fileName: string;
|
|
94
|
+
size: number;
|
|
95
|
+
}
|
|
96
|
+
interface IVideoCommon extends IVisualCommon {
|
|
97
|
+
poster?: string;
|
|
98
|
+
loop?: boolean | null;
|
|
99
|
+
autoPlay?: boolean | null;
|
|
100
|
+
width?: number;
|
|
101
|
+
height?: number;
|
|
102
|
+
hideControls?: boolean | null;
|
|
103
|
+
}
|
|
104
|
+
interface ILocalVideo extends IVideoCommon {
|
|
105
|
+
type: 'Local video';
|
|
106
|
+
preview: IVideoDetails;
|
|
107
|
+
}
|
|
108
|
+
interface IFullVideo extends IVideoCommon {
|
|
109
|
+
type: 'Full video';
|
|
110
|
+
preview?: IVideoDetails;
|
|
111
|
+
full: IVideoDetails;
|
|
112
|
+
}
|
|
113
|
+
interface IExternalVideo extends IVideoCommon {
|
|
114
|
+
type: 'External video';
|
|
115
|
+
preview?: IVideoDetails;
|
|
116
|
+
external: string;
|
|
117
|
+
embed?: VideoTypeData;
|
|
118
|
+
}
|
|
119
|
+
type IVideo = ILocalVideo | IFullVideo | IExternalVideo;
|
|
120
|
+
declare function isLocalVideo(obj: IVisualCommon | undefined | null): obj is ILocalVideo;
|
|
121
|
+
declare function isFullVideo(obj: IVisualCommon | undefined | null): obj is IFullVideo;
|
|
122
|
+
declare function isExternalVideo(obj: IVisualCommon | undefined | null): obj is IExternalVideo;
|
|
123
|
+
declare function isVideo(obj: IVisualCommon | undefined | null): obj is IVideo;
|
|
124
|
+
interface IAnimation extends IVisualCommon {
|
|
125
|
+
type: 'Animation';
|
|
126
|
+
optimised?: IOptimisedSvg;
|
|
127
|
+
animationSrc: string;
|
|
128
|
+
loop?: boolean | null;
|
|
129
|
+
loopDelay?: number | null;
|
|
130
|
+
autoPlay?: boolean | null;
|
|
131
|
+
}
|
|
132
|
+
declare function isAnimation(obj: IVisualCommon | undefined | null): boolean;
|
|
133
|
+
interface IVisual {
|
|
134
|
+
type: 'Visual';
|
|
135
|
+
id: string;
|
|
136
|
+
image?: IImage;
|
|
137
|
+
video?: IVideo;
|
|
138
|
+
animation?: IAnimation;
|
|
139
|
+
}
|
|
140
|
+
declare function isVisualVideo(visual: IVisual | undefined | null): boolean;
|
|
141
|
+
declare function isVisualImage(visual: IVisual | undefined | null): boolean;
|
|
142
|
+
declare function isVisualAnimation(visual: IVisual | undefined | null): boolean;
|
|
143
|
+
interface IResponsiveVisual {
|
|
144
|
+
visual: IVisual;
|
|
145
|
+
hideVisual?: boolean;
|
|
146
|
+
mobileVisual?: IVisual;
|
|
147
|
+
hideMobileVisual?: boolean;
|
|
148
|
+
visualCustomSize?: number | null;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
type BaseModelType = 'Page' | 'Article' | 'Tag' | 'Article type' | 'Tags' | 'Person' | 'People' | 'Custom type';
|
|
152
|
+
type BaseContentType = 'Component' | 'Collection' | 'Internal link' | 'Visual' | 'External component';
|
|
153
|
+
type Brand<T, U> = T & {
|
|
154
|
+
__brand: U;
|
|
155
|
+
};
|
|
156
|
+
type ColourName<T extends string = string> = Brand<T, 'ColourName'>;
|
|
157
|
+
type GradientName<T extends string = string> = Brand<T, 'GradientName'>;
|
|
158
|
+
type ModelType<T extends string = string> = Brand<T, 'ModelType'>;
|
|
159
|
+
type ContentType<T extends string = string> = Brand<T, 'ContentType'>;
|
|
160
|
+
type IconName<T extends string = string> = Brand<T, 'IconName'>;
|
|
161
|
+
type ButtonVariant<T extends string = string> = Brand<T, 'ButtonVariant'>;
|
|
162
|
+
type ButtonSize<T extends string = string> = Brand<T, 'ButtonSize'>;
|
|
163
|
+
type ComponentType<T extends string = string> = Brand<T, 'ComponentType'>;
|
|
164
|
+
type CollectionType<T extends string = string> = Brand<T, 'CollectionType'>;
|
|
165
|
+
type ExternalComponentType<T extends string = string> = Brand<T, 'ExternalComponentType'>;
|
|
166
|
+
interface IPageContext<TConfig extends BaseCmsConfig> {
|
|
167
|
+
articleLink?: ArticleLink<TConfig>;
|
|
168
|
+
articleTypeLink?: ArticleTypeLink<TConfig>;
|
|
169
|
+
personLink?: PersonLink<TConfig>;
|
|
170
|
+
pageLink?: PageLink<TConfig>;
|
|
171
|
+
tagLink?: TagLink<TConfig>;
|
|
172
|
+
}
|
|
173
|
+
interface IContentContext<TConfig extends BaseCmsConfig> {
|
|
174
|
+
analyticsContext?: IAnalyticsContext;
|
|
175
|
+
pageContext: IPageContext<TConfig>;
|
|
176
|
+
current: PageContent<TConfig>;
|
|
177
|
+
previousContent?: PageContent<TConfig>;
|
|
178
|
+
nextContent?: PageContent<TConfig>;
|
|
179
|
+
}
|
|
180
|
+
interface IAnalyticsContext {
|
|
181
|
+
slug: string;
|
|
182
|
+
title?: string;
|
|
183
|
+
type?: string;
|
|
184
|
+
}
|
|
185
|
+
interface IRichTextOptions {
|
|
186
|
+
cmsLabel?: string | null;
|
|
187
|
+
analytics?: IAnalyticsContext;
|
|
188
|
+
embedded?: boolean;
|
|
189
|
+
parentId: string;
|
|
190
|
+
parentIndex: number;
|
|
191
|
+
}
|
|
192
|
+
type BaseCmsConfig = {
|
|
193
|
+
RichText: unknown;
|
|
194
|
+
ColourName: ColourName<string>;
|
|
195
|
+
GradientName: GradientName<string>;
|
|
196
|
+
ModelType: ModelType<string>;
|
|
197
|
+
ContentType: ContentType<string>;
|
|
198
|
+
CollectionType: CollectionType<string>;
|
|
199
|
+
ComponentType: ComponentType<string>;
|
|
200
|
+
ExternalComponentType: ExternalComponentType<string>;
|
|
201
|
+
ButtonVariant: ButtonVariant<string>;
|
|
202
|
+
ButtonSize: ButtonSize<string>;
|
|
203
|
+
PageContext: IPageContext<BaseCmsConfig>;
|
|
204
|
+
Component: IBaseComponent<BaseCmsConfig>;
|
|
205
|
+
Collection: IBaseCollection<BaseCmsConfig>;
|
|
206
|
+
ExternalComponent: IBaseExternalComponent<BaseCmsConfig>;
|
|
207
|
+
RichTextOptions: IRichTextOptions;
|
|
208
|
+
PageContent: PageContent<BaseCmsConfig>;
|
|
209
|
+
};
|
|
210
|
+
interface ILinkProps<TConfig extends BaseCmsConfig> {
|
|
211
|
+
parentId?: string;
|
|
212
|
+
parentFieldId?: string;
|
|
213
|
+
id: string;
|
|
214
|
+
useName?: boolean | null;
|
|
215
|
+
name: string;
|
|
216
|
+
text?: string | null;
|
|
217
|
+
icon?: IVisual;
|
|
218
|
+
visual?: IVisual;
|
|
219
|
+
href?: string | null;
|
|
220
|
+
click?: () => void;
|
|
221
|
+
type: 'Blank link' | 'External link' | 'Internal link' | 'Download link';
|
|
222
|
+
backgroundColour?: TConfig['ColourName'] | TConfig['GradientName'] | null;
|
|
223
|
+
textColour?: TConfig['ColourName'] | null;
|
|
224
|
+
variant?: TConfig['ButtonVariant'];
|
|
225
|
+
size?: TConfig['ButtonSize'];
|
|
226
|
+
}
|
|
227
|
+
interface IBLankLink<TConfig extends BaseCmsConfig> extends ILinkProps<TConfig> {
|
|
228
|
+
type: 'Blank link';
|
|
229
|
+
}
|
|
230
|
+
interface IExternalLink<TConfig extends BaseCmsConfig> extends ILinkProps<TConfig> {
|
|
231
|
+
type: 'External link';
|
|
232
|
+
}
|
|
233
|
+
interface IInternalLink<TConfig extends BaseCmsConfig> extends ILinkProps<TConfig> {
|
|
234
|
+
type: 'Internal link';
|
|
235
|
+
slug: string;
|
|
236
|
+
indexed?: boolean | null;
|
|
237
|
+
hidden?: boolean | null;
|
|
238
|
+
tags?: ReadonlyArray<IInternalLink<TConfig>>;
|
|
239
|
+
}
|
|
240
|
+
interface IDownloadLink<TConfig extends BaseCmsConfig> extends ILinkProps<TConfig> {
|
|
241
|
+
type: 'Download link';
|
|
242
|
+
}
|
|
243
|
+
interface INavigation<TConfig extends BaseCmsConfig> {
|
|
244
|
+
id: string;
|
|
245
|
+
name: string;
|
|
246
|
+
entries: ReadonlyArray<INavigationItem<TConfig>>;
|
|
247
|
+
textColour?: TConfig['ColourName'];
|
|
248
|
+
backgroundColour?: TConfig['ColourName'] | TConfig['GradientName'];
|
|
249
|
+
}
|
|
250
|
+
interface INavigationItem<TConfig extends BaseCmsConfig> {
|
|
251
|
+
id: string;
|
|
252
|
+
link?: ILinkProps<TConfig>;
|
|
253
|
+
entries?: ReadonlyArray<INavigationItem<TConfig>>;
|
|
254
|
+
longText: TConfig['RichText'] | string | null;
|
|
255
|
+
}
|
|
256
|
+
interface IBaseModel<TConfig extends BaseCmsConfig> {
|
|
257
|
+
type: BaseModelType | TConfig['ModelType'];
|
|
258
|
+
id: string;
|
|
259
|
+
slug: string;
|
|
260
|
+
title: string;
|
|
261
|
+
description: string;
|
|
262
|
+
featuredImage?: IVisual;
|
|
263
|
+
link?: string;
|
|
264
|
+
indexed?: boolean | null;
|
|
265
|
+
hidden?: boolean | null;
|
|
266
|
+
lastUpdated?: string | Date;
|
|
267
|
+
textColour?: TConfig['ColourName'];
|
|
268
|
+
backgroundColour?: TConfig['ColourName'] | TConfig['GradientName'];
|
|
269
|
+
menu?: INavigation<TConfig>;
|
|
270
|
+
footer?: INavigation<TConfig>;
|
|
271
|
+
}
|
|
272
|
+
type BaseModelLinkOmissions = 'menu' | 'footer';
|
|
273
|
+
interface IBaseContent<TConfig extends BaseCmsConfig> {
|
|
274
|
+
type: BaseContentType | TConfig['ContentType'];
|
|
275
|
+
index: number;
|
|
276
|
+
isFirst: boolean;
|
|
277
|
+
isLast: boolean;
|
|
278
|
+
indexOfType: number;
|
|
279
|
+
id: string;
|
|
280
|
+
name: string;
|
|
281
|
+
anchor?: string | null;
|
|
282
|
+
cmsLabel: string | null;
|
|
283
|
+
backgroundColour?: TConfig['ColourName'] | TConfig['GradientName'];
|
|
284
|
+
textColour?: TConfig['ColourName'];
|
|
285
|
+
hexColor?: string | null;
|
|
286
|
+
backgroundVisual?: IResponsiveVisual;
|
|
287
|
+
backgroundOverlayOpacity?: number | null;
|
|
288
|
+
visual?: IResponsiveVisual;
|
|
289
|
+
parentId?: string;
|
|
290
|
+
parentFieldId?: string;
|
|
291
|
+
}
|
|
292
|
+
interface IBaseComponent<TConfig extends BaseCmsConfig> extends IBaseContent<TConfig> {
|
|
293
|
+
type: 'Component';
|
|
294
|
+
componentType: TConfig['ComponentType'];
|
|
295
|
+
preHeading?: string | null;
|
|
296
|
+
heading?: string | null;
|
|
297
|
+
postHeading?: string | null;
|
|
298
|
+
body?: TConfig['RichText'] | string;
|
|
299
|
+
icon?: IVisual;
|
|
300
|
+
links?: ReadonlyArray<ILinkProps<TConfig>>;
|
|
301
|
+
additionalCopy?: TConfig['RichText'] | string;
|
|
302
|
+
}
|
|
303
|
+
declare function isComponent<TConfig extends BaseCmsConfig>(obj: unknown): obj is TConfig['Component'];
|
|
304
|
+
type CollectionContent<TConfig extends BaseCmsConfig> = IBaseComponent<TConfig> | IBaseCollection<TConfig>;
|
|
305
|
+
interface IBaseCollection<TConfig extends BaseCmsConfig> extends IBaseContent<TConfig> {
|
|
306
|
+
type: 'Collection';
|
|
307
|
+
collectionType: TConfig['CollectionType'];
|
|
308
|
+
anchor?: string | null;
|
|
309
|
+
preHeading?: string | null;
|
|
310
|
+
heading?: string | null;
|
|
311
|
+
postHeading?: string | null;
|
|
312
|
+
body?: TConfig['RichText'] | string;
|
|
313
|
+
icon?: IVisual;
|
|
314
|
+
links?: ReadonlyArray<ILinkProps<TConfig>>;
|
|
315
|
+
additionalCopy?: TConfig['RichText'] | string;
|
|
316
|
+
contents?: ReadonlyArray<CollectionContent<TConfig>>;
|
|
317
|
+
}
|
|
318
|
+
declare function isCollection<TConfig extends BaseCmsConfig>(obj: unknown): obj is TConfig['Collection'];
|
|
319
|
+
interface IBaseExternalComponent<TConfig extends BaseCmsConfig> extends IBaseContent<TConfig> {
|
|
320
|
+
type: 'External component';
|
|
321
|
+
externalType: TConfig['ExternalComponentType'];
|
|
322
|
+
data: unknown | null;
|
|
323
|
+
}
|
|
324
|
+
interface IPerson<TConfig extends BaseCmsConfig> extends IBaseModel<TConfig> {
|
|
325
|
+
type: 'Person';
|
|
326
|
+
jobTitle?: string | null;
|
|
327
|
+
phoneNumber: string | null;
|
|
328
|
+
emailAddress: string | null;
|
|
329
|
+
location: string | null;
|
|
330
|
+
linkedIn: string | null;
|
|
331
|
+
bio: TConfig['RichText'] | null | undefined;
|
|
332
|
+
href: string | undefined;
|
|
333
|
+
structuredData?: ReadonlyArray<unknown>;
|
|
334
|
+
contents?: ReadonlyArray<PageContent<TConfig>>;
|
|
335
|
+
}
|
|
336
|
+
type PersonLink<TConfig extends BaseCmsConfig> = Omit<IPerson<TConfig>, BaseModelLinkOmissions | 'structuredData' | 'contents'>;
|
|
337
|
+
type PageContent<TConfig extends BaseCmsConfig> = IBaseComponent<TConfig> | IBaseCollection<TConfig> | IBaseExternalComponent<TConfig> | IVisual | IInternalLink<TConfig>;
|
|
338
|
+
|
|
339
|
+
interface IArticle<TConfig extends BaseCmsConfig> extends IBaseModel<TConfig> {
|
|
340
|
+
type: 'Article';
|
|
341
|
+
articleType?: IInternalLink<TConfig>;
|
|
342
|
+
structuredData?: ReadonlyArray<unknown>;
|
|
343
|
+
contents?: ReadonlyArray<PageContent<TConfig>>;
|
|
344
|
+
tags?: ReadonlyArray<IInternalLink<TConfig>>;
|
|
345
|
+
}
|
|
346
|
+
type ArticleLink<TConfig extends BaseCmsConfig> = Omit<IArticle<TConfig>, BaseModelLinkOmissions | 'structuredData' | 'contents' | 'tags'> & {
|
|
347
|
+
tags?: ReadonlyArray<TagLink<TConfig>>;
|
|
348
|
+
};
|
|
349
|
+
declare function isArticle<TConfig extends BaseCmsConfig>(content: IBaseModel<TConfig>): content is IArticle<TConfig>;
|
|
350
|
+
interface IArticleType<TConfig extends BaseCmsConfig> extends IBaseModel<TConfig> {
|
|
351
|
+
type: 'Article type';
|
|
352
|
+
indexPageContent?: ReadonlyArray<PageContent<TConfig>>;
|
|
353
|
+
searchPageContent?: ReadonlyArray<PageContent<TConfig>>;
|
|
354
|
+
}
|
|
355
|
+
type ArticleTypeLink<TConfig extends BaseCmsConfig> = Omit<IArticleType<TConfig>, BaseModelLinkOmissions | 'indexPageContent' | 'searchPageContent'>;
|
|
356
|
+
|
|
357
|
+
export { type BaseCmsConfig, type BaseContentType, type BaseModelType, type ButtonSize, type ButtonVariant, type CollectionContent, type CollectionType, type ColourName, type ComponentType, type ContentType, type ExternalComponentType, type GradientName, type Horizontal, type IAnalyticsContext, type IAnimation, type IArticle, type IBLankLink, type IBaseCollection, type IBaseComponent, type IBaseContent, type IBaseExternalComponent, type IBaseModel, type IContentContext, type IDownloadLink, type IExternalLink, type IExternalVideo, type IFullVideo, type IImage, type IInternalLink, type ILinkProps, type ILocalVideo, type INavigation, type INavigationItem, type IPage, type IPageContext, type IPerson, type IPicture, type IResponsiveVisual, type ISvgData, type ISvgImage, type ITag, type ITags, type IVideo, type IVideoDetails, type IVisual, type IVisualCommon, type IVisualSizes, type IconName, type ModelType, type PageContent, type PersonLink, type Vertical, isAnimation, isArticle, isCollection, isComponent, isExternalVideo, isFullVideo, isImage, isLocalVideo, isPage, isPicture, isSvgData, isSvgImage, isTag, isTags, isVideo, isVisualAnimation, isVisualImage, isVisualVideo, processSizes };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
// src/types/article.ts
|
|
2
|
+
function isArticle(content) {
|
|
3
|
+
return content.type === "Article";
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
// src/types/common.ts
|
|
7
|
+
function isComponent(obj) {
|
|
8
|
+
if (typeof obj !== "object" || obj === null) {
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
if (obj.type !== "Component") {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
function isCollection(obj) {
|
|
17
|
+
if (typeof obj !== "object" || obj === null) {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
if (obj.type !== "Collection") {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// src/types/page.ts
|
|
27
|
+
function isPage(content) {
|
|
28
|
+
return content.type === "Page";
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// src/types/tag.ts
|
|
32
|
+
function isTag(content) {
|
|
33
|
+
return content.type === "Tag";
|
|
34
|
+
}
|
|
35
|
+
function isTags(content) {
|
|
36
|
+
return content.type === "Tags";
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// src/types/visual.ts
|
|
40
|
+
function fillInBreakpoints(breakpoints) {
|
|
41
|
+
return breakpoints?.map(({ maxWidth, proportion, pixels, size }) => {
|
|
42
|
+
if (proportion) {
|
|
43
|
+
return {
|
|
44
|
+
maxWidth,
|
|
45
|
+
proportion,
|
|
46
|
+
pixels: Math.round(maxWidth * proportion),
|
|
47
|
+
size: `${Math.round(100 * proportion)}vw`
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
if (pixels) {
|
|
51
|
+
const proportion2 = Math.round(maxWidth / pixels);
|
|
52
|
+
return {
|
|
53
|
+
maxWidth,
|
|
54
|
+
proportion: proportion2,
|
|
55
|
+
pixels,
|
|
56
|
+
size: size ?? `${Math.round(100 * proportion2)}vw`
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
return { maxWidth, proportion: 1, pixels: maxWidth, size: size ?? `100vw` };
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
function processSizes({ defaultSize, defaultPixels, breakpoints }) {
|
|
63
|
+
return {
|
|
64
|
+
defaultSize,
|
|
65
|
+
defaultPixels,
|
|
66
|
+
breakpoints: fillInBreakpoints(breakpoints)
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
function isPicture(obj) {
|
|
70
|
+
return obj?.type === "Picture";
|
|
71
|
+
}
|
|
72
|
+
function isSvgImage(obj) {
|
|
73
|
+
return obj?.type === "Svg image";
|
|
74
|
+
}
|
|
75
|
+
function isSvgData(obj) {
|
|
76
|
+
return obj?.type === "Svg data";
|
|
77
|
+
}
|
|
78
|
+
function isImage(obj) {
|
|
79
|
+
return isPicture(obj) || isSvgImage(obj) || isSvgData(obj);
|
|
80
|
+
}
|
|
81
|
+
function isLocalVideo(obj) {
|
|
82
|
+
return obj?.type === "Local video";
|
|
83
|
+
}
|
|
84
|
+
function isFullVideo(obj) {
|
|
85
|
+
return obj?.type === "Full video";
|
|
86
|
+
}
|
|
87
|
+
function isExternalVideo(obj) {
|
|
88
|
+
return obj?.type === "External video";
|
|
89
|
+
}
|
|
90
|
+
function isVideo(obj) {
|
|
91
|
+
return isLocalVideo(obj) || isFullVideo(obj) || isExternalVideo(obj);
|
|
92
|
+
}
|
|
93
|
+
function isAnimation(obj) {
|
|
94
|
+
return obj?.type === "Animation";
|
|
95
|
+
}
|
|
96
|
+
function isVisualVideo(visual) {
|
|
97
|
+
return visual?.video !== void 0;
|
|
98
|
+
}
|
|
99
|
+
function isVisualImage(visual) {
|
|
100
|
+
return visual?.image !== void 0;
|
|
101
|
+
}
|
|
102
|
+
function isVisualAnimation(visual) {
|
|
103
|
+
return visual?.animation !== void 0;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export { isAnimation, isArticle, isCollection, isComponent, isExternalVideo, isFullVideo, isImage, isLocalVideo, isPage, isPicture, isSvgData, isSvgImage, isTag, isTags, isVideo, isVisualAnimation, isVisualImage, isVisualVideo, processSizes };
|
|
107
|
+
//# sourceMappingURL=index.js.map
|
|
108
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/types/article.ts","../src/types/common.ts","../src/types/page.ts","../src/types/tag.ts","../src/types/visual.ts"],"names":["proportion"],"mappings":"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","file":"index.js","sourcesContent":["import type {\n BaseCmsConfig,\n BaseModelLinkOmissions,\n IBaseModel,\n IInternalLink,\n PageContent,\n} from './common';\nimport type { TagLink } from './tag';\n\nexport interface IArticle<TConfig extends BaseCmsConfig> extends IBaseModel<TConfig> {\n type: 'Article';\n articleType?: IInternalLink<TConfig>;\n structuredData?: ReadonlyArray<unknown>;\n contents?: ReadonlyArray<PageContent<TConfig>>;\n tags?: ReadonlyArray<IInternalLink<TConfig>>;\n}\n\nexport type ArticleLink<TConfig extends BaseCmsConfig> = Omit<\n IArticle<TConfig>,\n BaseModelLinkOmissions | 'structuredData' | 'contents' | 'tags'\n> & {\n tags?: ReadonlyArray<TagLink<TConfig>>;\n};\n\nexport function isArticle<TConfig extends BaseCmsConfig>(\n content: IBaseModel<TConfig>,\n): content is IArticle<TConfig> {\n return content.type === 'Article';\n}\n\nexport interface IArticleType<TConfig extends BaseCmsConfig> extends IBaseModel<TConfig> {\n type: 'Article type';\n indexPageContent?: ReadonlyArray<PageContent<TConfig>>;\n searchPageContent?: ReadonlyArray<PageContent<TConfig>>;\n}\n\nexport type ArticleTypeLink<TConfig extends BaseCmsConfig> = Omit<\n IArticleType<TConfig>,\n BaseModelLinkOmissions | 'indexPageContent' | 'searchPageContent'\n>;\n\nexport function isArticleType<TConfig extends BaseCmsConfig>(\n content: IBaseModel<TConfig>,\n): content is IArticleType<TConfig> {\n return content.type === 'Article type';\n}\n","import type { ArticleLink, ArticleTypeLink } from './article';\nimport type { PageLink } from './page';\nimport type { TagLink } from './tag';\nimport type { IResponsiveVisual, IVisual } from './visual';\n\n/**\n * Utility type to make all nested properties of a type optional\n */\nexport type DeepPartial<T> = {\n [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];\n};\n\n/**\n * Utility type to make TypeScript's complex types more readable in IDE tooltips\n */\nexport type Prettify<T> = {\n [K in keyof T]: T[K];\n} & {};\n\nexport type BaseModelType =\n | 'Page'\n | 'Article'\n | 'Tag'\n | 'Article type'\n | 'Tags'\n | 'Person'\n | 'People'\n | 'Custom type';\n\nexport type BaseContentType =\n | 'Component'\n | 'Collection'\n | 'Internal link'\n | 'Visual'\n | 'External component';\n\nexport type Brand<T, U> = T & { __brand: U }; // Nominal typing helper\n\nexport type ColourName<T extends string = string> = Brand<T, 'ColourName'>;\nexport type GradientName<T extends string = string> = Brand<T, 'GradientName'>;\nexport type ModelType<T extends string = string> = Brand<T, 'ModelType'>;\nexport type ContentType<T extends string = string> = Brand<T, 'ContentType'>;\nexport type IconName<T extends string = string> = Brand<T, 'IconName'>;\nexport type ButtonVariant<T extends string = string> = Brand<T, 'ButtonVariant'>;\nexport type ButtonSize<T extends string = string> = Brand<T, 'ButtonSize'>;\nexport type ComponentType<T extends string = string> = Brand<T, 'ComponentType'>;\nexport type CollectionType<T extends string = string> = Brand<T, 'CollectionType'>;\nexport type ExternalComponentType<T extends string = string> = Brand<T, 'ExternalComponentType'>;\n\nexport interface IPageContext<TConfig extends BaseCmsConfig> {\n articleLink?: ArticleLink<TConfig>;\n articleTypeLink?: ArticleTypeLink<TConfig>;\n personLink?: PersonLink<TConfig>;\n pageLink?: PageLink<TConfig>;\n tagLink?: TagLink<TConfig>;\n}\n\nexport interface IContentContext<TConfig extends BaseCmsConfig> {\n analyticsContext?: IAnalyticsContext;\n pageContext: IPageContext<TConfig>;\n current: PageContent<TConfig>;\n previousContent?: PageContent<TConfig>;\n nextContent?: PageContent<TConfig>;\n}\n\nexport interface IAnalyticsContext {\n slug: string;\n title?: string;\n type?: string;\n}\n\nexport interface IRichTextOptions {\n cmsLabel?: string | null;\n analytics?: IAnalyticsContext;\n embedded?: boolean;\n parentId: string;\n parentIndex: number;\n}\n\nexport type BaseCmsConfig = {\n RichText: unknown; // Or whatever your default rich text type is\n ColourName: ColourName<string>;\n GradientName: GradientName<string>;\n ModelType: ModelType<string>;\n ContentType: ContentType<string>;\n CollectionType: CollectionType<string>;\n ComponentType: ComponentType<string>;\n ExternalComponentType: ExternalComponentType<string>;\n ButtonVariant: ButtonVariant<string>;\n ButtonSize: ButtonSize<string>;\n PageContext: IPageContext<BaseCmsConfig>;\n Component: IBaseComponent<BaseCmsConfig>;\n Collection: IBaseCollection<BaseCmsConfig>;\n ExternalComponent: IBaseExternalComponent<BaseCmsConfig>;\n RichTextOptions: IRichTextOptions;\n PageContent: PageContent<BaseCmsConfig>;\n};\n\nexport interface ILinkProps<TConfig extends BaseCmsConfig> {\n parentId?: string;\n parentFieldId?: string;\n id: string;\n useName?: boolean | null;\n name: string;\n text?: string | null;\n icon?: IVisual;\n visual?: IVisual;\n href?: string | null;\n click?: () => void;\n type: 'Blank link' | 'External link' | 'Internal link' | 'Download link';\n backgroundColour?: TConfig['ColourName'] | TConfig['GradientName'] | null;\n textColour?: TConfig['ColourName'] | null;\n variant?: TConfig['ButtonVariant'];\n size?: TConfig['ButtonSize'];\n}\n\nexport interface IBLankLink<TConfig extends BaseCmsConfig> extends ILinkProps<TConfig> {\n type: 'Blank link';\n}\n\nexport interface IExternalLink<TConfig extends BaseCmsConfig> extends ILinkProps<TConfig> {\n type: 'External link';\n}\n\nexport interface IInternalLink<TConfig extends BaseCmsConfig> extends ILinkProps<TConfig> {\n type: 'Internal link';\n slug: string;\n indexed?: boolean | null;\n hidden?: boolean | null;\n tags?: ReadonlyArray<IInternalLink<TConfig>>;\n}\n\nexport interface IDownloadLink<TConfig extends BaseCmsConfig> extends ILinkProps<TConfig> {\n type: 'Download link';\n}\n\nexport function isBlankLink<TConfig extends BaseCmsConfig>(\n link: ILinkProps<TConfig>,\n): link is IBLankLink<TConfig> {\n return link.type === 'Blank link';\n}\n\nexport function isExternalLink<TConfig extends BaseCmsConfig>(\n link: ILinkProps<TConfig>,\n): link is IExternalLink<TConfig> {\n return link.type === 'External link';\n}\n\nexport function isInternalLink<TConfig extends BaseCmsConfig>(\n link: ILinkProps<TConfig>,\n): link is IInternalLink<TConfig> {\n return link.type === 'Internal link';\n}\n\nexport function isDownloadLink<TConfig extends BaseCmsConfig>(\n link: ILinkProps<TConfig>,\n): link is IDownloadLink<TConfig> {\n return link.type === 'Download link';\n}\n\nexport interface INavigation<TConfig extends BaseCmsConfig> {\n id: string;\n name: string;\n entries: ReadonlyArray<INavigationItem<TConfig>>;\n textColour?: TConfig['ColourName'];\n backgroundColour?: TConfig['ColourName'] | TConfig['GradientName'];\n}\n\nexport interface INavigationItem<TConfig extends BaseCmsConfig> {\n id: string;\n link?: ILinkProps<TConfig>;\n entries?: ReadonlyArray<INavigationItem<TConfig>>;\n longText: TConfig['RichText'] | string | null;\n}\n\nexport interface IBaseModel<TConfig extends BaseCmsConfig> {\n type: BaseModelType | TConfig['ModelType'];\n id: string;\n slug: string;\n title: string;\n description: string;\n featuredImage?: IVisual;\n link?: string;\n indexed?: boolean | null;\n hidden?: boolean | null;\n lastUpdated?: string | Date;\n textColour?: TConfig['ColourName'];\n backgroundColour?: TConfig['ColourName'] | TConfig['GradientName'];\n menu?: INavigation<TConfig>;\n footer?: INavigation<TConfig>;\n}\nexport type BaseModelLinkOmissions = 'menu' | 'footer';\n\nexport interface IBaseContent<TConfig extends BaseCmsConfig> {\n type: BaseContentType | TConfig['ContentType'];\n index: number;\n isFirst: boolean;\n isLast: boolean;\n indexOfType: number;\n id: string;\n name: string;\n anchor?: string | null;\n cmsLabel: string | null; // Original CMS label for tracking purposes\n backgroundColour?: TConfig['ColourName'] | TConfig['GradientName'];\n textColour?: TConfig['ColourName'];\n hexColor?: string | null;\n backgroundVisual?: IResponsiveVisual;\n backgroundOverlayOpacity?: number | null;\n visual?: IResponsiveVisual;\n parentId?: string;\n parentFieldId?: string;\n}\n\nexport interface IBaseComponent<TConfig extends BaseCmsConfig> extends IBaseContent<TConfig> {\n type: 'Component';\n componentType: TConfig['ComponentType'];\n preHeading?: string | null;\n heading?: string | null;\n postHeading?: string | null;\n body?: TConfig['RichText'] | string;\n icon?: IVisual;\n links?: ReadonlyArray<ILinkProps<TConfig>>;\n additionalCopy?: TConfig['RichText'] | string;\n}\n\nexport function isComponent<TConfig extends BaseCmsConfig>(\n obj: unknown,\n): obj is TConfig['Component'] {\n if (typeof obj !== 'object' || obj === null) {\n return false;\n }\n if ((obj as TConfig['Component']).type !== 'Component') {\n return false;\n }\n return true;\n}\n\nexport type CollectionContent<TConfig extends BaseCmsConfig> =\n | IBaseComponent<TConfig>\n | IBaseCollection<TConfig>;\n\nexport interface IBaseCollection<TConfig extends BaseCmsConfig> extends IBaseContent<TConfig> {\n type: 'Collection';\n collectionType: TConfig['CollectionType'];\n anchor?: string | null;\n preHeading?: string | null;\n heading?: string | null;\n postHeading?: string | null;\n body?: TConfig['RichText'] | string;\n icon?: IVisual;\n links?: ReadonlyArray<ILinkProps<TConfig>>;\n additionalCopy?: TConfig['RichText'] | string;\n contents?: ReadonlyArray<CollectionContent<TConfig>>;\n}\n\nexport function isCollection<TConfig extends BaseCmsConfig>(\n obj: unknown,\n): obj is TConfig['Collection'] {\n if (typeof obj !== 'object' || obj === null) {\n return false;\n }\n if ((obj as TConfig['Collection']).type !== 'Collection') {\n return false;\n }\n return true;\n}\n\nexport interface IBaseExternalComponent<TConfig extends BaseCmsConfig>\n extends IBaseContent<TConfig> {\n type: 'External component';\n externalType: TConfig['ExternalComponentType'];\n data: unknown | null;\n}\n\nexport function isExternalComponent<TConfig extends BaseCmsConfig>(\n obj: unknown,\n): obj is TConfig['ExternalComponent'] {\n if (typeof obj !== 'object' || obj === null) {\n return false;\n }\n if ((obj as TConfig['ExternalComponent']).type !== 'External component') {\n return false;\n }\n return true;\n}\n\nexport interface IPerson<TConfig extends BaseCmsConfig> extends IBaseModel<TConfig> {\n type: 'Person';\n jobTitle?: string | null;\n phoneNumber: string | null;\n emailAddress: string | null;\n location: string | null;\n linkedIn: string | null;\n bio: TConfig['RichText'] | null | undefined;\n href: string | undefined;\n structuredData?: ReadonlyArray<unknown>;\n contents?: ReadonlyArray<PageContent<TConfig>>;\n}\n\nexport type PersonLink<TConfig extends BaseCmsConfig> = Omit<\n IPerson<TConfig>,\n BaseModelLinkOmissions | 'structuredData' | 'contents'\n>;\n\nexport function isPerson<TConfig extends BaseCmsConfig>(\n content: IBaseModel<TConfig>,\n): content is IPerson<TConfig> {\n return content.type === 'Person';\n}\n\nexport type PageContent<TConfig extends BaseCmsConfig> =\n | IBaseComponent<TConfig>\n | IBaseCollection<TConfig>\n | IBaseExternalComponent<TConfig>\n | IVisual\n | IInternalLink<TConfig>;\n","import type {\n BaseCmsConfig,\n BaseModelLinkOmissions,\n IBaseModel,\n IInternalLink,\n PageContent,\n} from './common';\n\nexport interface IPage<TConfig extends BaseCmsConfig> extends IBaseModel<TConfig> {\n type: 'Page';\n isHomePage: boolean;\n structuredData?: ReadonlyArray<unknown>;\n contents?: ReadonlyArray<PageContent<TConfig>>;\n tags?: ReadonlyArray<IInternalLink<TConfig>>;\n}\n\nexport type PageLink<TConfig extends BaseCmsConfig> = Omit<\n IPage<TConfig>,\n BaseModelLinkOmissions | 'structuredData' | 'contents'\n>;\n\nexport function isPage<TConfig extends BaseCmsConfig>(\n content: IBaseModel<TConfig>,\n): content is IPage<TConfig> {\n return content.type === 'Page';\n}\n","import type { BaseCmsConfig, BaseModelLinkOmissions, IBaseModel, PageContent } from './common';\n\nexport interface ITag<TConfig extends BaseCmsConfig> extends IBaseModel<TConfig> {\n type: 'Tag';\n tagType?: string | null;\n contents?: ReadonlyArray<PageContent<TConfig>>;\n}\n\nexport type TagLink<TConfig extends BaseCmsConfig> = Omit<\n ITag<TConfig>,\n BaseModelLinkOmissions | 'contents'\n>;\n\nexport function isTag<TConfig extends BaseCmsConfig>(\n content: IBaseModel<TConfig>,\n): content is ITag<TConfig> {\n return content.type === 'Tag';\n}\n\nexport interface ITags<TConfig extends BaseCmsConfig> extends IBaseModel<TConfig> {\n type: 'Tags';\n}\n\nexport function isTags<TConfig extends BaseCmsConfig>(\n content: IBaseModel<TConfig>,\n): content is ITags<TConfig> {\n return content.type === 'Tags';\n}\n","import type { VideoTypeData } from '@extractus/oembed-extractor';\n\nexport type Vertical = 'Top' | 'Middle' | 'Bottom';\nexport type Horizontal = 'Left' | 'Middle' | 'Right';\n\ninterface IInternalBreakpoint {\n maxWidth: number;\n proportion: number;\n pixels: number;\n size: string;\n}\ntype IBreakpoint = Pick<IInternalBreakpoint, 'maxWidth'> &\n Partial<Omit<IInternalBreakpoint, 'maxWidth'>>;\nexport interface IVisualSizes {\n defaultSize?: string;\n defaultPixels?: number;\n breakpoints?: IBreakpoint[];\n}\n\nfunction fillInBreakpoints(breakpoints?: IBreakpoint[]): IInternalBreakpoint[] | undefined {\n return breakpoints?.map(({ maxWidth, proportion, pixels, size }) => {\n if (proportion) {\n return {\n maxWidth,\n proportion,\n pixels: Math.round(maxWidth * proportion),\n size: `${Math.round(100 * proportion)}vw`,\n };\n }\n if (pixels) {\n const proportion = Math.round(maxWidth / pixels);\n return {\n maxWidth,\n proportion,\n pixels,\n size: size ?? `${Math.round(100 * proportion)}vw`,\n };\n }\n\n return { maxWidth, proportion: 1, pixels: maxWidth, size: size ?? `100vw` };\n });\n}\nexport function processSizes({ defaultSize, defaultPixels, breakpoints }: IVisualSizes) {\n return {\n defaultSize,\n defaultPixels,\n breakpoints: fillInBreakpoints(breakpoints),\n };\n}\n\nexport interface IVisualCommon {\n type: string;\n id: string;\n name: string;\n description?: string | null;\n nameAsCaption?: boolean | null;\n dontCrop?: boolean | null;\n horizontalCropPosition?: Horizontal | null;\n verticalCropPosition?: Vertical | null;\n horizontalPosition?: Horizontal | null;\n widthPercent?: number | null;\n}\n\nexport interface IOptimisedSvg {\n data: string;\n width: number;\n height: number;\n}\n\ninterface IImageCommon extends IVisualCommon {\n mimeType: string;\n}\nexport interface IPicture extends IImageCommon {\n type: 'Picture';\n src: string;\n width: number;\n height: number;\n size: number;\n}\n\nexport interface ISvgImage extends IImageCommon {\n type: 'Svg image';\n size: number;\n svgSrc: string;\n width: number;\n height: number;\n}\n\nexport interface ISvgData extends IImageCommon {\n type: 'Svg data';\n data: string;\n width: number;\n height: number;\n}\n\nexport type IImage = IPicture | ISvgImage | ISvgData;\n\nexport function isPicture(obj: IVisualCommon | undefined | null): obj is IPicture {\n return obj?.type === 'Picture';\n}\n\nexport function isSvgImage(obj: IVisualCommon | undefined | null): obj is ISvgImage {\n return obj?.type === 'Svg image';\n}\n\nexport function isSvgData(obj: IVisualCommon | undefined | null): obj is ISvgData {\n return obj?.type === 'Svg data';\n}\n\nexport function isImage(obj: IVisualCommon | undefined | null): obj is IImage {\n return isPicture(obj) || isSvgImage(obj) || isSvgData(obj);\n}\n\nexport interface IVideoDetails {\n id: string;\n videoUrl: string;\n mimeType: string;\n fileName: string;\n size: number;\n}\n\nexport interface IVideoCommon extends IVisualCommon {\n poster?: string;\n loop?: boolean | null;\n autoPlay?: boolean | null;\n width?: number;\n height?: number;\n hideControls?: boolean | null;\n}\n\nexport interface ILocalVideo extends IVideoCommon {\n type: 'Local video';\n preview: IVideoDetails;\n}\n\nexport interface IFullVideo extends IVideoCommon {\n type: 'Full video';\n preview?: IVideoDetails;\n full: IVideoDetails;\n}\n\nexport interface IExternalVideo extends IVideoCommon {\n type: 'External video';\n preview?: IVideoDetails;\n external: string;\n embed?: VideoTypeData;\n}\n\nexport type IVideo = ILocalVideo | IFullVideo | IExternalVideo;\n\nexport function isLocalVideo(obj: IVisualCommon | undefined | null): obj is ILocalVideo {\n return obj?.type === 'Local video';\n}\n\nexport function isFullVideo(obj: IVisualCommon | undefined | null): obj is IFullVideo {\n return obj?.type === 'Full video';\n}\n\nexport function isExternalVideo(obj: IVisualCommon | undefined | null): obj is IExternalVideo {\n return obj?.type === 'External video';\n}\n\nexport function isVideo(obj: IVisualCommon | undefined | null): obj is IVideo {\n return isLocalVideo(obj) || isFullVideo(obj) || isExternalVideo(obj);\n}\n\nexport interface IAnimation extends IVisualCommon {\n type: 'Animation';\n optimised?: IOptimisedSvg;\n animationSrc: string;\n loop?: boolean | null;\n loopDelay?: number | null;\n autoPlay?: boolean | null;\n}\n\nexport function isAnimation(obj: IVisualCommon | undefined | null) {\n return obj?.type === 'Animation';\n}\n\nexport interface IVisual {\n type: 'Visual';\n id: string;\n image?: IImage;\n video?: IVideo;\n animation?: IAnimation;\n}\n\nexport function isVisualVideo(visual: IVisual | undefined | null) {\n return visual?.video !== undefined;\n}\nexport function isVisualImage(visual: IVisual | undefined | null) {\n return visual?.image !== undefined;\n}\nexport function isVisualAnimation(visual: IVisual | undefined | null) {\n return visual?.animation !== undefined;\n}\n\nexport interface IResponsiveVisual {\n visual: IVisual;\n hideVisual?: boolean;\n mobileVisual?: IVisual;\n hideMobileVisual?: boolean;\n visualCustomSize?: number | null;\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@se-studio/core-data-types",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Core TypeScript type definitions for SE Studio content models",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/Something-Else-Studio/se-core-product",
|
|
8
|
+
"directory": "packages/core-data-types"
|
|
9
|
+
},
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"type": "module",
|
|
12
|
+
"main": "./dist/index.js",
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"import": "./dist/index.js"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist"
|
|
22
|
+
],
|
|
23
|
+
"keywords": [
|
|
24
|
+
"typescript",
|
|
25
|
+
"types",
|
|
26
|
+
"contentful",
|
|
27
|
+
"cms",
|
|
28
|
+
"nextjs"
|
|
29
|
+
],
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@biomejs/biome": "^2.3.3",
|
|
32
|
+
"tsup": "^8.5.0",
|
|
33
|
+
"typescript": "^5.9.3",
|
|
34
|
+
"vitest": "^4.0.6"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@extractus/oembed-extractor": "^4.0.9"
|
|
38
|
+
},
|
|
39
|
+
"scripts": {
|
|
40
|
+
"build": "tsup",
|
|
41
|
+
"dev": "tsup --watch --no-clean",
|
|
42
|
+
"test": "vitest run",
|
|
43
|
+
"test:watch": "vitest",
|
|
44
|
+
"type-check": "tsc --noEmit",
|
|
45
|
+
"lint": "biome lint .",
|
|
46
|
+
"clean": "rm -rf dist .turbo"
|
|
47
|
+
}
|
|
48
|
+
}
|