@ethlete/contentful 3.2.1 → 3.3.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.
@@ -1,12 +1,31 @@
1
1
  import { NgClass, DOCUMENT } from '@angular/common';
2
2
  import * as i0 from '@angular/core';
3
- import { input, Component, ChangeDetectionStrategy, ViewEncapsulation, InjectionToken, inject, numberAttribute, booleanAttribute, computed, ViewContainerRef, Renderer2, ElementRef, isDevMode } from '@angular/core';
3
+ import { input, computed, Component, ChangeDetectionStrategy, ViewEncapsulation, InjectionToken, inject, numberAttribute, booleanAttribute, ViewContainerRef, Renderer2, ElementRef, isDevMode } from '@angular/core';
4
+ import { gql } from '@ethlete/query';
4
5
  import { normalizePictureSizes, PictureComponent } from '@ethlete/cdk';
5
6
  import { toSignal, toObservable, takeUntilDestroyed } from '@angular/core/rxjs-interop';
6
7
  import { INLINES, BLOCKS } from '@contentful/rich-text-types';
7
8
  import { RuntimeError, isObject, getObjectProperty } from '@ethlete/core';
8
9
  import { startWith, pairwise, tap } from 'rxjs';
9
- import { gql } from '@ethlete/query';
10
+
11
+ const GQL_FRAGMENT_CONTENTFUL_ASSET = gql `
12
+ fragment AssetData on Asset {
13
+ sys {
14
+ id
15
+ }
16
+ url
17
+ title
18
+ width
19
+ height
20
+ description
21
+ contentType
22
+ size
23
+ }
24
+ `;
25
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
26
+ const isContentfulGqlAsset = (asset) => {
27
+ return asset?.sys?.id && asset?.url && typeof asset?.size === 'number';
28
+ };
10
29
 
11
30
  class ContentfulAudioComponent {
12
31
  constructor() {
@@ -14,13 +33,29 @@ class ContentfulAudioComponent {
14
33
  this.audioClass = input(null);
15
34
  this.figureClass = input(null);
16
35
  this.figcaptionClass = input(null);
36
+ this.data = computed(() => {
37
+ const asset = this.asset();
38
+ if (!asset) {
39
+ return null;
40
+ }
41
+ if (isContentfulGqlAsset(asset)) {
42
+ return {
43
+ url: asset.url,
44
+ title: asset.title,
45
+ };
46
+ }
47
+ return {
48
+ url: asset.fields.file.url,
49
+ title: asset.fields.title,
50
+ };
51
+ });
17
52
  }
18
53
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.3", ngImport: i0, type: ContentfulAudioComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
19
54
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.3", type: ContentfulAudioComponent, isStandalone: true, selector: "et-contentful-audio", inputs: { asset: { classPropertyName: "asset", publicName: "asset", isSignal: true, isRequired: true, transformFunction: null }, audioClass: { classPropertyName: "audioClass", publicName: "audioClass", isSignal: true, isRequired: false, transformFunction: null }, figureClass: { classPropertyName: "figureClass", publicName: "figureClass", isSignal: true, isRequired: false, transformFunction: null }, figcaptionClass: { classPropertyName: "figcaptionClass", publicName: "figcaptionClass", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
20
- @if (asset(); as data) {
55
+ @if (data(); as data) {
21
56
  <figure [ngClass]="figureClass()">
22
- <figcaption [ngClass]="figcaptionClass()">{{ data.fields.title }}</figcaption>
23
- <audio [ngClass]="audioClass()" controls src="{{ data.fields.file.url }}"></audio>
57
+ <figcaption [ngClass]="figcaptionClass()">{{ data.title }}</figcaption>
58
+ <audio [ngClass]="audioClass()" controls src="{{ data.url }}"></audio>
24
59
  </figure>
25
60
  }
26
61
  `, isInline: true, dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
@@ -30,10 +65,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.3", ngImpor
30
65
  args: [{
31
66
  selector: 'et-contentful-audio',
32
67
  template: `
33
- @if (asset(); as data) {
68
+ @if (data(); as data) {
34
69
  <figure [ngClass]="figureClass()">
35
- <figcaption [ngClass]="figcaptionClass()">{{ data.fields.title }}</figcaption>
36
- <audio [ngClass]="audioClass()" controls src="{{ data.fields.file.url }}"></audio>
70
+ <figcaption [ngClass]="figcaptionClass()">{{ data.title }}</figcaption>
71
+ <audio [ngClass]="audioClass()" controls src="{{ data.url }}"></audio>
37
72
  </figure>
38
73
  }
39
74
  `,
@@ -48,12 +83,32 @@ class ContentfulFileComponent {
48
83
  constructor() {
49
84
  this.asset = input.required();
50
85
  this.fileClass = input(null);
86
+ this.data = computed(() => {
87
+ const asset = this.asset();
88
+ if (!asset) {
89
+ return null;
90
+ }
91
+ if (isContentfulGqlAsset(asset)) {
92
+ return {
93
+ url: asset.url,
94
+ contentType: asset.contentType,
95
+ size: asset.size,
96
+ title: asset.title,
97
+ };
98
+ }
99
+ return {
100
+ url: asset.fields.file.url,
101
+ contentType: asset.fields.file.contentType,
102
+ size: asset.fields.file.details.size,
103
+ title: asset.fields.title,
104
+ };
105
+ });
51
106
  }
52
107
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.3", ngImport: i0, type: ContentfulFileComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
53
108
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.3", type: ContentfulFileComponent, isStandalone: true, selector: "et-contentful-file", inputs: { asset: { classPropertyName: "asset", publicName: "asset", isSignal: true, isRequired: true, transformFunction: null }, fileClass: { classPropertyName: "fileClass", publicName: "fileClass", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
54
- @if (asset(); as data) {
55
- <a [href]="data.fields.file.url" [ngClass]="fileClass()" class="underline" target="_blank">
56
- {{ data.fields.title }} ({{ data.fields.file.details.size }} Bytes)
109
+ @if (data(); as data) {
110
+ <a [href]="data.url" [ngClass]="fileClass()" class="underline" target="_blank">
111
+ {{ data.title }} ({{ data.size }} Bytes)
57
112
  </a>
58
113
  }
59
114
  `, isInline: true, dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
@@ -63,9 +118,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.3", ngImpor
63
118
  args: [{
64
119
  selector: 'et-contentful-file',
65
120
  template: `
66
- @if (asset(); as data) {
67
- <a [href]="data.fields.file.url" [ngClass]="fileClass()" class="underline" target="_blank">
68
- {{ data.fields.title }} ({{ data.fields.file.details.size }} Bytes)
121
+ @if (data(); as data) {
122
+ <a [href]="data.url" [ngClass]="fileClass()" class="underline" target="_blank">
123
+ {{ data.title }} ({{ data.size }} Bytes)
69
124
  </a>
70
125
  }
71
126
  `,
@@ -79,10 +134,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.3", ngImpor
79
134
  const CONTENTFUL_CONFIG = new InjectionToken('ContentfulConfig');
80
135
 
81
136
  const generateDefaultContentfulImageSource = (data) => {
82
- const file = data.fields.file;
137
+ if (isContentfulGqlAsset(data)) {
138
+ return {
139
+ type: data.contentType,
140
+ srcset: data.url,
141
+ };
142
+ }
83
143
  return {
84
- type: file.contentType,
85
- srcset: file.url,
144
+ type: data.fields.file.contentType,
145
+ srcset: data.fields.file.url,
86
146
  };
87
147
  };
88
148
  /**
@@ -120,7 +180,7 @@ const generateContentfulImageSources = (data, srcsetSizes, backgroundColor, qual
120
180
  const sources = [];
121
181
  const SOURCE_TYPES = ['image/avif', 'image/webp', 'image/png', 'image/jpg'];
122
182
  for (const type of SOURCE_TYPES) {
123
- const baseUrl = assetData.fields.file.url;
183
+ const baseUrl = isContentfulGqlAsset(assetData) ? assetData.url : assetData.fields.file.url;
124
184
  const sourceSets = [];
125
185
  const queryParams = [];
126
186
  // Set the format (e.g. 'fm=webp')
@@ -177,6 +237,25 @@ class ContentfulImageComponent {
177
237
  this.sizes = input(normalizePictureSizes(this._contentfulConfig.imageOptions.sizes), {
178
238
  transform: (v) => normalizePictureSizes(v),
179
239
  });
240
+ this.normalizedAsset = computed(() => {
241
+ const asset = this.asset();
242
+ if (isContentfulGqlAsset(asset)) {
243
+ return {
244
+ alt: asset.title || null,
245
+ figcaption: asset.description || null,
246
+ width: asset.width,
247
+ height: asset.height,
248
+ };
249
+ }
250
+ else {
251
+ return {
252
+ alt: asset?.fields?.title || null,
253
+ figcaption: asset?.fields?.description || null,
254
+ width: asset?.fields?.file?.details?.image?.width ?? null,
255
+ height: asset?.fields?.file?.details?.image?.height ?? null,
256
+ };
257
+ }
258
+ });
180
259
  this._sources = computed(() => {
181
260
  const asset = this.asset();
182
261
  const backgroundColor = this.backgroundColor();
@@ -203,10 +282,10 @@ class ContentfulImageComponent {
203
282
  [pictureClass]="pictureClass()"
204
283
  [figcaptionClass]="figcaptionClass()"
205
284
  [defaultSrc]="_defaultSrc()"
206
- [alt]="asset()?.fields?.title ?? null"
207
- [figcaption]="asset()?.fields?.description ?? null"
208
- [width]="asset()?.fields?.file?.details?.image?.width ?? null"
209
- [height]="asset()?.fields?.file?.details?.image?.height ?? null"
285
+ [alt]="normalizedAsset().alt ?? null"
286
+ [figcaption]="normalizedAsset().figcaption ?? null"
287
+ [width]="normalizedAsset().width ?? null"
288
+ [height]="normalizedAsset().height ?? null"
210
289
  [sizes]="sizes()"
211
290
  [sources]="_sources()"
212
291
  />
@@ -224,10 +303,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.3", ngImpor
224
303
  [pictureClass]="pictureClass()"
225
304
  [figcaptionClass]="figcaptionClass()"
226
305
  [defaultSrc]="_defaultSrc()"
227
- [alt]="asset()?.fields?.title ?? null"
228
- [figcaption]="asset()?.fields?.description ?? null"
229
- [width]="asset()?.fields?.file?.details?.image?.width ?? null"
230
- [height]="asset()?.fields?.file?.details?.image?.height ?? null"
306
+ [alt]="normalizedAsset().alt ?? null"
307
+ [figcaption]="normalizedAsset().figcaption ?? null"
308
+ [width]="normalizedAsset().width ?? null"
309
+ [height]="normalizedAsset().height ?? null"
231
310
  [sizes]="sizes()"
232
311
  [sources]="_sources()"
233
312
  />
@@ -246,12 +325,28 @@ class ContentfulVideoComponent {
246
325
  constructor() {
247
326
  this.asset = input.required();
248
327
  this.videoClass = input(null);
328
+ this.data = computed(() => {
329
+ const asset = this.asset();
330
+ if (!asset) {
331
+ return null;
332
+ }
333
+ if (isContentfulGqlAsset(asset)) {
334
+ return {
335
+ url: asset.url,
336
+ contentType: asset.contentType,
337
+ };
338
+ }
339
+ return {
340
+ url: asset.fields.file.url,
341
+ contentType: asset.fields.file.contentType,
342
+ };
343
+ });
249
344
  }
250
345
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.3", ngImport: i0, type: ContentfulVideoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
251
346
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.3", type: ContentfulVideoComponent, isStandalone: true, selector: "et-contentful-video", inputs: { asset: { classPropertyName: "asset", publicName: "asset", isSignal: true, isRequired: true, transformFunction: null }, videoClass: { classPropertyName: "videoClass", publicName: "videoClass", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
252
- @if (asset(); as data) {
347
+ @if (data(); as data) {
253
348
  <video [ngClass]="videoClass()" controls>
254
- <source src="{{ data.fields.file.url }}" type="{{ data.fields.file.contentType }}" />
349
+ <source src="{{ data.url }}" type="{{ data.contentType }}" />
255
350
  </video>
256
351
  }
257
352
  `, isInline: true, dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
@@ -261,9 +356,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.3", ngImpor
261
356
  args: [{
262
357
  selector: 'et-contentful-video',
263
358
  template: `
264
- @if (asset(); as data) {
359
+ @if (data(); as data) {
265
360
  <video [ngClass]="videoClass()" controls>
266
- <source src="{{ data.fields.file.url }}" type="{{ data.fields.file.contentType }}" />
361
+ <source src="{{ data.url }}" type="{{ data.contentType }}" />
267
362
  </video>
268
363
  }
269
364
  `,
@@ -1123,21 +1218,6 @@ const ContentfulImports = [
1123
1218
  ContentfulRichTextRendererComponent,
1124
1219
  ];
1125
1220
 
1126
- const GQL_FRAGMENT_CONTENTFUL_ASSET = gql `
1127
- fragment AssetData on Asset {
1128
- sys {
1129
- id
1130
- }
1131
- url
1132
- title
1133
- width
1134
- height
1135
- description
1136
- contentType
1137
- size
1138
- }
1139
- `;
1140
-
1141
1221
  const provideContentfulConfig = (contentfulConfig = {}) => {
1142
1222
  return { provide: CONTENTFUL_CONFIG, useValue: createContentfulConfig(contentfulConfig) };
1143
1223
  };
@@ -1148,5 +1228,5 @@ const provideContentfulConfig = (contentfulConfig = {}) => {
1148
1228
  * Generated bundle index. Do not edit.
1149
1229
  */
1150
1230
 
1151
- export { COMPONENT_RENDER_COMMAND_POSITION, CONTENTFUL_CONFIG, ContentfulAudioComponent, ContentfulFileComponent, ContentfulImageComponent, ContentfulImports, ContentfulRichTextRendererComponent, ContentfulVideoComponent, ET_CONTENTFUL_ANY_ENTRY_CONTENT_TYPE_SYS_ID, GQL_FRAGMENT_CONTENTFUL_ASSET, HTML_CLOSE_RENDER_COMMAND_POSITION, HTML_OPEN_RENDER_COMMAND_POSITION, RENDER_COMMAND_POSITION, RENDER_COMMAND_TYPE, RENDER_INSTRUCTION_POSITION, RENDER_INSTRUCTION_TYPE, TEXT_RENDER_COMMAND_POSITION, createContentfulConfig, generateContentfulImageSources, generateDefaultContentfulImageSource, getRenderCommandId, isComponentRenderCommand, isExecutedComponentCommandCacheItem, isExecutedHtmlOrTextCommandCacheItem, isExecutedTextCommandCacheItem, isHtmlCloseRenderCommand, isHtmlOpenRenderCommand, isRichTextRootNode, isTextRenderCommand, marksToClass, parseContentfulImageSize, provideContentfulConfig, translateContentfulNodeTypeToHtmlTag };
1231
+ export { COMPONENT_RENDER_COMMAND_POSITION, CONTENTFUL_CONFIG, ContentfulAudioComponent, ContentfulFileComponent, ContentfulImageComponent, ContentfulImports, ContentfulRichTextRendererComponent, ContentfulVideoComponent, ET_CONTENTFUL_ANY_ENTRY_CONTENT_TYPE_SYS_ID, GQL_FRAGMENT_CONTENTFUL_ASSET, HTML_CLOSE_RENDER_COMMAND_POSITION, HTML_OPEN_RENDER_COMMAND_POSITION, RENDER_COMMAND_POSITION, RENDER_COMMAND_TYPE, RENDER_INSTRUCTION_POSITION, RENDER_INSTRUCTION_TYPE, TEXT_RENDER_COMMAND_POSITION, createContentfulConfig, generateContentfulImageSources, generateDefaultContentfulImageSource, getRenderCommandId, isComponentRenderCommand, isContentfulGqlAsset, isExecutedComponentCommandCacheItem, isExecutedHtmlOrTextCommandCacheItem, isExecutedTextCommandCacheItem, isHtmlCloseRenderCommand, isHtmlOpenRenderCommand, isRichTextRootNode, isTextRenderCommand, marksToClass, parseContentfulImageSize, provideContentfulConfig, translateContentfulNodeTypeToHtmlTag };
1152
1232
  //# sourceMappingURL=ethlete-contentful.mjs.map