@streamscloud/embeddable 3.4.1 → 4.0.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.
Files changed (98) hide show
  1. package/dist/ads/ad-card/cmp.ad-card.svelte +193 -0
  2. package/dist/{short-videos/short-video-viewer/cmp.ad.svelte.d.ts → ads/ad-card/cmp.ad-card.svelte.d.ts} +3 -2
  3. package/dist/ads/ad-card/index.d.ts +3 -0
  4. package/dist/ads/ad-card/index.js +2 -0
  5. package/dist/ads/ad-card/mapper.d.ts +3 -0
  6. package/dist/ads/ad-card/mapper.js +13 -0
  7. package/dist/ads/ad-card/operations.generated.d.ts +23 -0
  8. package/dist/ads/ad-card/operations.generated.js +47 -0
  9. package/dist/ads/ad-card/operations.graphql +20 -0
  10. package/dist/ads/ad-card/types.d.ts +17 -0
  11. package/dist/ads/ad-card/types.js +1 -0
  12. package/dist/core/locale.d.ts +3 -0
  13. package/dist/products/price-helper.d.ts +18 -3
  14. package/dist/products/price-helper.js +9 -6
  15. package/dist/products/product-card/cmp.product-card.svelte +218 -0
  16. package/dist/products/product-card/cmp.product-card.svelte.d.ts +15 -0
  17. package/dist/products/product-card/index.d.ts +4 -0
  18. package/dist/products/product-card/index.js +2 -0
  19. package/dist/products/product-card/mapper.d.ts +3 -0
  20. package/dist/products/product-card/mapper.js +22 -0
  21. package/dist/products/product-card/operations.generated.d.ts +26 -0
  22. package/dist/products/product-card/operations.generated.js +59 -0
  23. package/dist/products/product-card/operations.graphql +23 -0
  24. package/dist/products/product-card/product-card-localization.d.ts +8 -0
  25. package/dist/{short-videos/short-video-viewer/short-video-product-localization.js → products/product-card/product-card-localization.js} +1 -1
  26. package/dist/products/product-card/types.d.ts +12 -0
  27. package/dist/products/product-card/types.js +1 -0
  28. package/dist/short-videos/short-video-viewer/cmp.attachments.svelte +12 -40
  29. package/dist/short-videos/short-video-viewer/cmp.attachments.svelte.d.ts +1 -1
  30. package/dist/short-videos/short-video-viewer/cmp.short-video-controls.svelte +134 -0
  31. package/dist/short-videos/short-video-viewer/cmp.short-video-controls.svelte.d.ts +19 -0
  32. package/dist/short-videos/short-video-viewer/cmp.short-video-viewer.svelte +45 -20
  33. package/dist/short-videos/short-video-viewer/cmp.short-video-viewer.svelte.d.ts +1 -0
  34. package/dist/short-videos/short-video-viewer/index.d.ts +2 -6
  35. package/dist/short-videos/short-video-viewer/index.js +1 -4
  36. package/dist/short-videos/short-video-viewer/mapper.js +12 -42
  37. package/dist/short-videos/short-video-viewer/operations.generated.d.ts +5 -8
  38. package/dist/short-videos/short-video-viewer/operations.generated.js +98 -94
  39. package/dist/short-videos/short-video-viewer/operations.graphql +2 -42
  40. package/dist/short-videos/short-video-viewer/short-video-attachments-localization.d.ts +3 -7
  41. package/dist/short-videos/short-video-viewer/short-video-attachments-localization.js +0 -14
  42. package/dist/short-videos/short-video-viewer/short-video-viewer-localization.d.ts +3 -3
  43. package/dist/short-videos/short-video-viewer/types.d.ts +9 -28
  44. package/dist/short-videos/short-video-viewer/types.js +1 -1
  45. package/dist/short-videos/short-video-viewer/ui-manager.svelte.d.ts +5 -0
  46. package/dist/short-videos/short-video-viewer/ui-manager.svelte.js +14 -1
  47. package/dist/short-videos/short-videos-player/cmp.short-videos-player.svelte +23 -163
  48. package/dist/short-videos/short-videos-player/cmp.short-videos-player.svelte.d.ts +3 -2
  49. package/dist/short-videos/short-videos-player/controls.svelte +110 -127
  50. package/dist/short-videos/short-videos-player/controls.svelte.d.ts +2 -1
  51. package/dist/short-videos/short-videos-player/index.d.ts +2 -0
  52. package/dist/short-videos/short-videos-player/index.js +6 -3
  53. package/dist/short-videos/short-videos-player/operations.generated.d.ts +5 -8
  54. package/dist/short-videos/short-videos-player/operations.generated.js +77 -73
  55. package/dist/short-videos/short-videos-player/short-videos-player-localization.d.ts +1 -3
  56. package/dist/short-videos/short-videos-player/short-videos-player-localization.js +0 -2
  57. package/dist/short-videos/short-videos-player/short-videos-player-view.svelte +198 -0
  58. package/dist/short-videos/short-videos-player/short-videos-player-view.svelte.d.ts +14 -0
  59. package/dist/short-videos/short-videos-player/types.d.ts +2 -0
  60. package/dist/short-videos/short-videos-player/ui-manager.svelte.d.ts +3 -3
  61. package/dist/short-videos/short-videos-player/ui-manager.svelte.js +8 -8
  62. package/dist/streams/layout/element-views/price-element-view.svelte +5 -4
  63. package/dist/streams/layout/models/mapper.js +8 -17
  64. package/dist/streams/stream-player/cmp.stream-player.svelte +18 -5
  65. package/dist/streams/stream-player/cmp.stream-player.svelte.d.ts +1 -1
  66. package/dist/streams/stream-player/controls.svelte +66 -73
  67. package/dist/streams/stream-player/index.js +2 -2
  68. package/dist/streams/stream-player/stream-overview.svelte +12 -1
  69. package/dist/streams/stream-player/stream-overview.svelte.d.ts +1 -0
  70. package/dist/streams/stream-player/stream-player-localization.d.ts +1 -3
  71. package/dist/streams/stream-player/stream-player-localization.js +0 -2
  72. package/dist/streams/stream-player/ui-manager.svelte.d.ts +3 -2
  73. package/dist/streams/stream-player/ui-manager.svelte.js +9 -5
  74. package/dist/ui/button/resources/button-theme.svelte +1 -0
  75. package/dist/ui/shadow-dom/index.d.ts +2 -1
  76. package/dist/ui/shadow-dom/index.js +2 -1
  77. package/dist/ui/shadow-dom/{shadow-host.d.ts → modal-shadow-host.d.ts} +1 -1
  78. package/dist/ui/shadow-dom/modal-shadow-host.js +21 -0
  79. package/dist/ui/shadow-dom/shadow-root-service.d.ts +1 -0
  80. package/dist/ui/shadow-dom/shadow-root-service.js +23 -0
  81. package/dist/ui/video/cmp.video.svelte +2 -2
  82. package/dist/ui/video/cmp.video.svelte.d.ts +1 -0
  83. package/package.json +1 -1
  84. package/dist/short-videos/short-video-viewer/cmp.ad.svelte +0 -140
  85. package/dist/short-videos/short-video-viewer/cmp.product.svelte +0 -168
  86. package/dist/short-videos/short-video-viewer/cmp.product.svelte.d.ts +0 -14
  87. package/dist/short-videos/short-video-viewer/cmp.short-video-details.svelte +0 -125
  88. package/dist/short-videos/short-video-viewer/cmp.short-video-details.svelte.d.ts +0 -14
  89. package/dist/short-videos/short-video-viewer/cmp.social-interactions.svelte +0 -69
  90. package/dist/short-videos/short-video-viewer/cmp.social-interactions.svelte.d.ts +0 -10
  91. package/dist/short-videos/short-video-viewer/description.svelte +0 -53
  92. package/dist/short-videos/short-video-viewer/description.svelte.d.ts +0 -9
  93. package/dist/short-videos/short-video-viewer/short-video-details-localization.d.ts +0 -14
  94. package/dist/short-videos/short-video-viewer/short-video-details-localization.js +0 -17
  95. package/dist/short-videos/short-video-viewer/short-video-product-localization.d.ts +0 -8
  96. package/dist/short-videos/short-videos-player/action-button.svelte +0 -38
  97. package/dist/short-videos/short-videos-player/action-button.svelte.d.ts +0 -10
  98. package/dist/ui/shadow-dom/shadow-host.js +0 -32
@@ -0,0 +1,193 @@
1
+ <script lang="ts">import { toPriceRepresentation } from '../../products/price-helper';
2
+ import { Button, ButtonSize } from '../../ui/button';
3
+ import { Image } from '../../ui/image';
4
+ import { LineClamp } from '../../ui/line-clamp';
5
+ let { ad, inert } = $props();
6
+ </script>
7
+
8
+ <div class="ad-card" inert={inert}>
9
+ <div class="ad-card__image">
10
+ <Image src={ad.image} alt={ad.title} />
11
+ </div>
12
+ <div class="ad-card__info">
13
+ <div class="ad-card__content">
14
+ {#if ad.title}
15
+ <div class="ad-card__title">
16
+ <LineClamp value={ad.title} maxLines={2} />
17
+ </div>
18
+ {/if}
19
+ {#if ad.description}
20
+ <div class="ad-card__description">
21
+ <LineClamp value={ad.description} maxLines={2} />
22
+ </div>
23
+ {/if}
24
+ </div>
25
+ <div class="ad-card__price-container">
26
+ {#if ad.price && ad.currency}
27
+ <div class="ad-card__price">{toPriceRepresentation({ amount: ad.price, currency: ad.currency })}</div>
28
+ {/if}
29
+ </div>
30
+ <div class="ad-card__button-container">
31
+ {#if ad.ctaButton}
32
+ <Button
33
+ size={ButtonSize.Standard}
34
+ on={{ click: () => ad.ctaButton && window.open(ad.ctaButton.url, '_blank') }}
35
+ --button--font--size="1em"
36
+ --button--font--color={ad.ctaButton.textColor}
37
+ --button--background={ad.ctaButton.background}
38
+ --button--min-width="100%">
39
+ <span class="ad-card__button-text">{ad.ctaButton.text}</span>
40
+ </Button>
41
+ {/if}
42
+ </div>
43
+ </div>
44
+ </div>
45
+
46
+ <style>@keyframes fadeIn {
47
+ 0% {
48
+ opacity: 1;
49
+ }
50
+ 50% {
51
+ opacity: 0.4;
52
+ }
53
+ 100% {
54
+ opacity: 1;
55
+ }
56
+ }
57
+ .ad-card {
58
+ width: 100%;
59
+ height: max-content;
60
+ display: flex;
61
+ flex-direction: column;
62
+ position: relative;
63
+ container-type: inline-size;
64
+ aspect-ratio: 10/16;
65
+ background-color: #ffffff;
66
+ border: 0.038125rem solid #f2f2f3;
67
+ border-radius: 0.5rem;
68
+ padding: 0.75rem 0.75rem 1.125rem;
69
+ justify-content: flex-start;
70
+ gap: 0.5rem;
71
+ /* Set 'container-type: inline-size;' to reference container*/
72
+ }
73
+ @container (width < 230px) {
74
+ .ad-card {
75
+ padding: 0.5rem 0.5rem 0.75rem;
76
+ }
77
+ }
78
+ .ad-card__image {
79
+ border-radius: 0.25rem;
80
+ overflow: hidden;
81
+ aspect-ratio: 1/1;
82
+ width: 100%;
83
+ --image--width: 100%;
84
+ --image--height: 100%;
85
+ --image--object-fit: cover;
86
+ }
87
+ .ad-card__info {
88
+ display: grid;
89
+ grid-template-rows: 0.7fr auto auto;
90
+ grid-template-areas: "content" "price" "button";
91
+ row-gap: 0rem;
92
+ flex: 1 1 auto;
93
+ min-height: 0;
94
+ /* Set 'container-type: inline-size;' to reference container*/
95
+ }
96
+ @container (width < 230px) {
97
+ .ad-card__info {
98
+ row-gap: 0rem;
99
+ }
100
+ }
101
+ .ad-card__content {
102
+ grid-area: content;
103
+ display: flex;
104
+ flex-direction: column;
105
+ gap: 0.1875rem;
106
+ align-self: start;
107
+ /* Set 'container-type: inline-size;' to reference container*/
108
+ }
109
+ @container (width < 230px) {
110
+ .ad-card__content {
111
+ gap: 0.09375rem;
112
+ }
113
+ }
114
+ .ad-card__price-container {
115
+ grid-area: price;
116
+ display: flex;
117
+ justify-content: flex-end;
118
+ align-items: center;
119
+ min-height: 3rem;
120
+ /* Set 'container-type: inline-size;' to reference container*/
121
+ }
122
+ @container (width < 230px) {
123
+ .ad-card__price-container {
124
+ min-height: 2rem;
125
+ }
126
+ }
127
+ .ad-card__button-container {
128
+ grid-area: button;
129
+ display: flex;
130
+ justify-content: center;
131
+ align-items: end;
132
+ min-height: 2.5rem;
133
+ margin-top: 0.125rem;
134
+ /* Set 'container-type: inline-size;' to reference container*/
135
+ }
136
+ @container (width < 230px) {
137
+ .ad-card__button-container {
138
+ min-height: 2rem;
139
+ margin-top: 0.09375rem;
140
+ }
141
+ }
142
+ .ad-card__button-text {
143
+ display: block;
144
+ text-overflow: ellipsis;
145
+ width: 100%;
146
+ white-space: nowrap;
147
+ overflow: hidden;
148
+ }
149
+ .ad-card__title {
150
+ font-weight: 700;
151
+ font-size: 1.125rem;
152
+ line-height: 1.375rem;
153
+ min-height: 1.375rem;
154
+ /* Set 'container-type: inline-size;' to reference container*/
155
+ }
156
+ @container (width < 230px) {
157
+ .ad-card__title {
158
+ font-size: 0.75rem;
159
+ line-height: 0.875rem;
160
+ min-height: 0.875rem;
161
+ }
162
+ }
163
+ .ad-card__description {
164
+ font-weight: 400;
165
+ color: #6b7280;
166
+ font-size: 0.9375rem;
167
+ line-height: 1.375rem;
168
+ min-height: 1.375rem;
169
+ /* Set 'container-type: inline-size;' to reference container*/
170
+ }
171
+ @container (width < 230px) {
172
+ .ad-card__description {
173
+ font-size: 0.625rem;
174
+ line-height: 0.875rem;
175
+ min-height: 0.875rem;
176
+ }
177
+ }
178
+ .ad-card__price {
179
+ font-size: 1.875rem;
180
+ font-weight: 700;
181
+ text-align: right;
182
+ /* Set 'container-type: inline-size;' to reference container*/
183
+ }
184
+ @container (width < 230px) {
185
+ .ad-card__price {
186
+ font-size: 1.25rem;
187
+ }
188
+ }
189
+ :global([data-theme="dark"]) .ad-card {
190
+ background-color: #121212;
191
+ color: #ffffff;
192
+ border-color: #1e1e1e;
193
+ }</style>
@@ -1,6 +1,7 @@
1
- import type { ShortVideoViewerAdModel } from './types';
1
+ import type { AdCardModel } from './types';
2
2
  type Props = {
3
- ad: ShortVideoViewerAdModel;
3
+ ad: AdCardModel;
4
+ inert: boolean;
4
5
  };
5
6
  declare const Cmp: import("svelte").Component<Props, {}, "">;
6
7
  type Cmp = ReturnType<typeof Cmp>;
@@ -0,0 +1,3 @@
1
+ export { default as AdCard } from './cmp.ad-card.svelte';
2
+ export type { AdCardModel } from './types';
3
+ export { mapToAdCardModel } from './mapper';
@@ -0,0 +1,2 @@
1
+ export { default as AdCard } from './cmp.ad-card.svelte';
2
+ export { mapToAdCardModel } from './mapper';
@@ -0,0 +1,3 @@
1
+ import type { AdCardPayloadFragment } from './operations.generated';
2
+ import type { AdCardModel } from './types';
3
+ export declare const mapToAdCardModel: (payload: AdCardPayloadFragment) => AdCardModel;
@@ -0,0 +1,13 @@
1
+ import { getMediaItemImageUrl } from '../../core/media';
2
+ export const mapToAdCardModel = (payload) => {
3
+ return {
4
+ id: payload.id,
5
+ type: payload.type,
6
+ image: getMediaItemImageUrl(payload.media[0]),
7
+ title: payload.title,
8
+ description: payload.description,
9
+ price: payload.price,
10
+ currency: payload.currency,
11
+ ctaButton: payload.ctaButton
12
+ };
13
+ };
@@ -0,0 +1,23 @@
1
+ import type * as SchemaTypes from '../../../gql/types';
2
+ import type { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';
3
+ export type AdCardPayloadFragment = {
4
+ id: string;
5
+ title: string;
6
+ description: string | null;
7
+ price: number | null;
8
+ currency: SchemaTypes.Currency | null;
9
+ type: SchemaTypes.AdType;
10
+ ctaButton: {
11
+ background: string;
12
+ textColor: string;
13
+ text: string;
14
+ url: string;
15
+ border: string;
16
+ } | null;
17
+ media: Array<{
18
+ url: string;
19
+ thumbnailUrl: string | null;
20
+ type: SchemaTypes.MediaType;
21
+ }>;
22
+ };
23
+ export declare const AdCardPayloadFragmentDoc: DocumentNode<AdCardPayloadFragment, unknown>;
@@ -0,0 +1,47 @@
1
+ export const AdCardPayloadFragmentDoc = {
2
+ kind: 'Document',
3
+ definitions: [
4
+ {
5
+ kind: 'FragmentDefinition',
6
+ name: { kind: 'Name', value: 'AdCardPayloadFragment' },
7
+ typeCondition: { kind: 'NamedType', name: { kind: 'Name', value: 'Ad' } },
8
+ selectionSet: {
9
+ kind: 'SelectionSet',
10
+ selections: [
11
+ { kind: 'Field', name: { kind: 'Name', value: 'id' } },
12
+ { kind: 'Field', name: { kind: 'Name', value: 'title' } },
13
+ { kind: 'Field', name: { kind: 'Name', value: 'description' } },
14
+ { kind: 'Field', name: { kind: 'Name', value: 'price' } },
15
+ { kind: 'Field', name: { kind: 'Name', value: 'currency' } },
16
+ {
17
+ kind: 'Field',
18
+ name: { kind: 'Name', value: 'ctaButton' },
19
+ selectionSet: {
20
+ kind: 'SelectionSet',
21
+ selections: [
22
+ { kind: 'Field', name: { kind: 'Name', value: 'background' } },
23
+ { kind: 'Field', name: { kind: 'Name', value: 'textColor' } },
24
+ { kind: 'Field', name: { kind: 'Name', value: 'text' } },
25
+ { kind: 'Field', name: { kind: 'Name', value: 'url' } },
26
+ { kind: 'Field', name: { kind: 'Name', value: 'border' } }
27
+ ]
28
+ }
29
+ },
30
+ { kind: 'Field', name: { kind: 'Name', value: 'type' } },
31
+ {
32
+ kind: 'Field',
33
+ name: { kind: 'Name', value: 'media' },
34
+ selectionSet: {
35
+ kind: 'SelectionSet',
36
+ selections: [
37
+ { kind: 'Field', name: { kind: 'Name', value: 'url' } },
38
+ { kind: 'Field', name: { kind: 'Name', value: 'thumbnailUrl' } },
39
+ { kind: 'Field', name: { kind: 'Name', value: 'type' } }
40
+ ]
41
+ }
42
+ }
43
+ ]
44
+ }
45
+ }
46
+ ]
47
+ };
@@ -0,0 +1,20 @@
1
+ fragment AdCardPayloadFragment on Ad {
2
+ id
3
+ title
4
+ description
5
+ price
6
+ currency
7
+ ctaButton {
8
+ background
9
+ textColor
10
+ text
11
+ url
12
+ border
13
+ }
14
+ type
15
+ media {
16
+ url
17
+ thumbnailUrl
18
+ type
19
+ }
20
+ }
@@ -0,0 +1,17 @@
1
+ import { AdType, type Currency } from '../../core/enums';
2
+ export type AdCardModel = {
3
+ id: string;
4
+ type: AdType;
5
+ image: string | null;
6
+ title: string;
7
+ description: string | null;
8
+ price: number | null;
9
+ currency: Currency | null;
10
+ ctaButton: {
11
+ background: string;
12
+ textColor: string;
13
+ text: string;
14
+ url: string;
15
+ border: string;
16
+ } | null;
17
+ };
@@ -0,0 +1 @@
1
+ import { AdType } from '../../core/enums';
@@ -1,4 +1,7 @@
1
1
  export type Locale = 'en' | 'no';
2
+ export type LocalizationSchema = {
3
+ [key: string]: Record<Locale, unknown>;
4
+ };
2
5
  export declare const getLocale: <T>(input?: Locale | T) => Locale | T;
3
6
  export declare const isEn: <T>(input: Locale | T) => input is "en";
4
7
  export declare const isNo: <T>(input: Locale | T) => input is "no";
@@ -1,4 +1,19 @@
1
1
  import { Currency } from '../core/enums';
2
- export declare const toPriceRepresentation: (amount: number, currency: Currency, includeCurrency?: boolean) => string;
3
- export declare const shouldUseSalePrice: (price: number, salePrice: number | null, effectiveDateFrom: string | null, effectiveDateTo: string | null) => boolean;
4
- export declare const isSalePriceEffective: (salePrice: number | null, effectiveDateFrom: string | null, effectiveDateTo: string | null) => boolean;
2
+ export declare const toPriceRepresentation: (data: {
3
+ amount: number;
4
+ currency: Currency;
5
+ includeCurrency?: boolean;
6
+ }) => string;
7
+ export declare const shouldUseSalePrice: (data: {
8
+ price: number;
9
+ salePrice: number | null;
10
+ effectiveDateFrom: number | null;
11
+ effectiveDateTo: number | null;
12
+ referenceDate?: string | Date | null;
13
+ }) => boolean;
14
+ export declare const isSalePriceEffective: (data: {
15
+ salePrice: number | null;
16
+ effectiveDateFrom: number | null;
17
+ effectiveDateTo: number | null;
18
+ referenceDate?: string | Date | null;
19
+ }) => boolean;
@@ -1,6 +1,7 @@
1
1
  import { Currency } from '../core/enums';
2
2
  import { Utils } from '../core/utils';
3
- export const toPriceRepresentation = (amount, currency, includeCurrency = true) => {
3
+ export const toPriceRepresentation = (data) => {
4
+ const { amount, currency, includeCurrency = true } = data;
4
5
  const formatNumber = (value) => {
5
6
  const noDecimals = Number.isInteger(value);
6
7
  const options = {
@@ -27,21 +28,23 @@ export const toPriceRepresentation = (amount, currency, includeCurrency = true)
27
28
  }
28
29
  }
29
30
  };
30
- export const shouldUseSalePrice = (price, salePrice, effectiveDateFrom, effectiveDateTo) => {
31
- if (!isSalePriceEffective(salePrice, effectiveDateFrom, effectiveDateTo)) {
31
+ export const shouldUseSalePrice = (data) => {
32
+ const { price, salePrice, effectiveDateFrom, effectiveDateTo, referenceDate } = data;
33
+ if (!isSalePriceEffective({ salePrice, effectiveDateFrom, effectiveDateTo, referenceDate })) {
32
34
  return false;
33
35
  }
34
36
  return price !== salePrice;
35
37
  };
36
- export const isSalePriceEffective = (salePrice, effectiveDateFrom, effectiveDateTo) => {
38
+ export const isSalePriceEffective = (data) => {
39
+ const { salePrice, effectiveDateFrom, effectiveDateTo, referenceDate } = data;
37
40
  if (!salePrice) {
38
41
  return false;
39
42
  }
40
43
  if (!effectiveDateFrom && !effectiveDateTo) {
41
44
  return true;
42
45
  }
43
- const now = Date.now();
46
+ const reference = referenceDate ? (typeof referenceDate === 'string' ? new Date(referenceDate).getTime() : referenceDate.getTime()) : Date.now();
44
47
  const fromDate = effectiveDateFrom && new Date(effectiveDateFrom);
45
48
  const toDate = effectiveDateTo && new Date(effectiveDateTo);
46
- return (!fromDate || now >= fromDate.getTime()) && (!toDate || now < toDate.getTime());
49
+ return (!fromDate || reference >= fromDate.getTime()) && (!toDate || reference < toDate.getTime());
47
50
  };
@@ -0,0 +1,218 @@
1
+ <script lang="ts">import { toPriceRepresentation } from '../price-helper';
2
+ import { Image } from '../../ui/image';
3
+ import { LineClamp } from '../../ui/line-clamp';
4
+ import { ProportionalContainer } from '../../ui/proportional-container';
5
+ import { ProductCardLocalization } from './product-card-localization';
6
+ let { product, includeBeforeNowPrefix, inert = false, localization: localizationInit = 'en', on } = $props();
7
+ const localization = $derived(new ProductCardLocalization(localizationInit));
8
+ const showDescriptionPresented = $derived(product.shortDescription && product.shortDescription.length > 0);
9
+ const onProductClicked = (event) => {
10
+ if (!product.link) {
11
+ return;
12
+ }
13
+ event.preventDefault();
14
+ event.stopPropagation();
15
+ if (on === null || on === void 0 ? void 0 : on.productClick) {
16
+ on.productClick(product.id);
17
+ }
18
+ window.open(product.link, '_blank', 'noopener noreferrer');
19
+ };
20
+ </script>
21
+
22
+ <div class="product-card" inert={inert}>
23
+ <ProportionalContainer ratio={1}>
24
+ <Image src={product.image} />
25
+ </ProportionalContainer>
26
+
27
+ <div class="product-card__info">
28
+ <LineClamp maxLines={1}>
29
+ <div class="product-card__brand">{product.brandName}</div>
30
+ </LineClamp>
31
+ <LineClamp value={product.shortDescription} maxLines={showDescriptionPresented ? 1 : 2}>
32
+ <div class="product-card__title" class:two-lines={!showDescriptionPresented}>{product.title}</div>
33
+ </LineClamp>
34
+ <LineClamp value={product.shortDescription} maxLines={2}>
35
+ <div class="product-card__description" class:two-lines={showDescriptionPresented}>{product.shortDescription}</div>
36
+ </LineClamp>
37
+ <div class="product-price">
38
+ <div class="product-price__before-price">
39
+ {#if product.salePrice}
40
+ {#if includeBeforeNowPrefix}
41
+ {localization.beforeNowPrefix}
42
+ {/if}
43
+ {toPriceRepresentation({ amount: product.price, currency: product.currency })}
44
+ {/if}
45
+ </div>
46
+ <div class="product-price__price product-price__price--sale">
47
+ {toPriceRepresentation({ amount: product.salePrice ?? product.price, currency: product.currency })}
48
+ </div>
49
+ </div>
50
+ </div>
51
+
52
+ {#if product.link}
53
+ <a href={product.link} onclick={onProductClicked} target="_blank" rel="noopener noreferrer" class="product-card__link" aria-label="none">&nbsp;</a>
54
+ {/if}
55
+ </div>
56
+
57
+ <style>@keyframes fadeIn {
58
+ 0% {
59
+ opacity: 1;
60
+ }
61
+ 50% {
62
+ opacity: 0.4;
63
+ }
64
+ 100% {
65
+ opacity: 1;
66
+ }
67
+ }
68
+ .product-card {
69
+ --image--border-radius: 0.25rem;
70
+ --image--object-fit: fit;
71
+ --image--width: auto;
72
+ --image--height: auto;
73
+ width: 100%;
74
+ height: max-content;
75
+ display: flex;
76
+ flex-direction: column;
77
+ position: relative;
78
+ container-type: inline-size;
79
+ aspect-ratio: 10/16;
80
+ background-color: #ffffff;
81
+ border: 0.038125rem solid #f2f2f3;
82
+ border-radius: 0.5rem;
83
+ padding: 0.75rem 0.75rem 1.125rem;
84
+ justify-content: space-between;
85
+ /* Set 'container-type: inline-size;' to reference container*/
86
+ }
87
+ :global([data-theme="dark"]) .product-card {
88
+ background-color: #121212;
89
+ color: #ffffff;
90
+ border-color: #1e1e1e;
91
+ }
92
+ @container (width < 230px) {
93
+ .product-card {
94
+ padding: 0.5rem 0.5rem 0.75rem;
95
+ }
96
+ }
97
+ .product-card__info {
98
+ display: flex;
99
+ flex-direction: column;
100
+ gap: 0.375rem;
101
+ margin-top: 0.1875rem;
102
+ /* Set 'container-type: inline-size;' to reference container*/
103
+ }
104
+ @container (width < 230px) {
105
+ .product-card__info {
106
+ gap: 0.25rem;
107
+ margin-top: 0.125rem;
108
+ }
109
+ }
110
+ .product-card__brand {
111
+ font-weight: 700;
112
+ font-size: 0.75rem;
113
+ line-height: 1.375rem;
114
+ min-height: 1.375rem;
115
+ /* Set 'container-type: inline-size;' to reference container*/
116
+ }
117
+ @container (width < 230px) {
118
+ .product-card__brand {
119
+ font-size: 0.5rem;
120
+ line-height: 0.875rem;
121
+ min-height: 0.875rem;
122
+ }
123
+ }
124
+ .product-card__title {
125
+ font-weight: 700;
126
+ font-size: 1.125rem;
127
+ line-height: 1.375rem;
128
+ min-height: 1.375rem;
129
+ /* Set 'container-type: inline-size;' to reference container*/
130
+ }
131
+ @container (width < 230px) {
132
+ .product-card__title {
133
+ font-size: 0.75rem;
134
+ line-height: 0.875rem;
135
+ min-height: 0.875rem;
136
+ }
137
+ }
138
+ .product-card__description {
139
+ font-weight: 400;
140
+ color: #6b7280;
141
+ font-size: 0.9375rem;
142
+ line-height: 1.375rem;
143
+ min-height: 1.375rem;
144
+ /* Set 'container-type: inline-size;' to reference container*/
145
+ }
146
+ @container (width < 230px) {
147
+ .product-card__description {
148
+ font-size: 0.625rem;
149
+ line-height: 0.875rem;
150
+ min-height: 0.875rem;
151
+ }
152
+ }
153
+ .product-card .two-lines {
154
+ height: 2.75rem;
155
+ /* Set 'container-type: inline-size;' to reference container*/
156
+ }
157
+ @container (width < 230px) {
158
+ .product-card .two-lines {
159
+ height: 1.75rem;
160
+ }
161
+ }
162
+ .product-card__link {
163
+ position: absolute;
164
+ top: 0;
165
+ left: 0;
166
+ width: 100%;
167
+ height: 100%;
168
+ }
169
+
170
+ .product-price {
171
+ --_product-price--align: right;
172
+ --_product-price--before--color: #6b7280;
173
+ --_product-price--before--font-size: 0.75em;
174
+ --_product-price--color: inherit;
175
+ --_product-price--font-size: 1.875em;
176
+ --_product-price--gap: 0.375em;
177
+ --_product-price--min-height: 2.40625rem;
178
+ width: 100%;
179
+ display: flex;
180
+ flex-direction: column;
181
+ justify-items: end;
182
+ gap: var(--_product-price--gap);
183
+ min-height: var(--_product-price--min-height);
184
+ /* Set 'container-type: inline-size;' to reference container*/
185
+ }
186
+ @container (width < 230px) {
187
+ .product-price {
188
+ --_product-price--before--font-size: 0.5rem;
189
+ --_product-price--font-size: 1.25rem;
190
+ --_product-price--gap: 0.25rem;
191
+ }
192
+ }
193
+ .product-price__before-price {
194
+ width: 100%;
195
+ color: var(--_product-price--before--color);
196
+ text-decoration: line-through;
197
+ font-size: var(--_product-price--before--font-size);
198
+ font-weight: 500;
199
+ text-align: var(--_product-price--align);
200
+ min-height: var(--_product-price--before--font-size);
201
+ text-overflow: ellipsis;
202
+ width: 100%;
203
+ white-space: nowrap;
204
+ overflow: hidden;
205
+ }
206
+ .product-price__price {
207
+ width: 100%;
208
+ color: var(--_product-price--color);
209
+ font-size: var(--_product-price--font-size);
210
+ font-weight: 800;
211
+ margin-top: auto;
212
+ text-align: var(--_product-price--align);
213
+ min-height: var(--_product-price--font-size);
214
+ text-overflow: ellipsis;
215
+ width: 100%;
216
+ white-space: nowrap;
217
+ overflow: hidden;
218
+ }</style>
@@ -0,0 +1,15 @@
1
+ import type { Locale } from '../../core/locale';
2
+ import { type IProductCardLocalization } from './product-card-localization';
3
+ import type { ProductCardModel } from './types';
4
+ type Props = {
5
+ product: ProductCardModel;
6
+ localization?: IProductCardLocalization | Locale;
7
+ includeBeforeNowPrefix?: boolean;
8
+ inert?: boolean;
9
+ on?: {
10
+ productClick?: (id: string) => void;
11
+ };
12
+ };
13
+ declare const Cmp: import("svelte").Component<Props, {}, "">;
14
+ type Cmp = ReturnType<typeof Cmp>;
15
+ export default Cmp;
@@ -0,0 +1,4 @@
1
+ export { default as ProductCard } from './cmp.product-card.svelte';
2
+ export { mapToProductCard } from './mapper';
3
+ export type { ProductCardModel } from './types';
4
+ export type { ProductCardPayloadFragment } from './operations.generated';
@@ -0,0 +1,2 @@
1
+ export { default as ProductCard } from './cmp.product-card.svelte';
2
+ export { mapToProductCard } from './mapper';
@@ -0,0 +1,3 @@
1
+ import type { ProductCardPayloadFragment } from './operations.generated';
2
+ import type { ProductCardModel } from './types';
3
+ export declare const mapToProductCard: (payload: ProductCardPayloadFragment, referenceDate?: string | null) => ProductCardModel;