@revenuecat/purchases-ui-js 3.11.0 → 3.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { untrack } from "svelte";
|
|
2
3
|
import { getColorModeContext } from "../../stores/color-mode";
|
|
3
4
|
import { getSelectedStateContext } from "../../stores/selected";
|
|
4
5
|
import type { VideoProps } from "../../types/components/video";
|
|
5
6
|
import type { VideoFiles, ImageFiles } from "../../types/media";
|
|
6
7
|
import {
|
|
7
8
|
css,
|
|
9
|
+
mapBorderRadius,
|
|
8
10
|
mapColor,
|
|
9
11
|
mapColorMode,
|
|
10
12
|
mapFitMode,
|
|
@@ -59,6 +61,7 @@
|
|
|
59
61
|
});
|
|
60
62
|
let videoElement = $state<HTMLVideoElement | null>(null);
|
|
61
63
|
let hasVideoError = $state(false);
|
|
64
|
+
let showControlsFallback = $state(false);
|
|
62
65
|
|
|
63
66
|
// Load video or fallback image metadata to get dimensions
|
|
64
67
|
$effect(() => {
|
|
@@ -157,87 +160,162 @@
|
|
|
157
160
|
|
|
158
161
|
const { x, y, radius, color } = shadow;
|
|
159
162
|
const shadowColor = mapColor(colorMode, color);
|
|
160
|
-
return `filter:
|
|
163
|
+
return `filter:drop-shadow(${x}px ${y}px ${radius}px ${shadowColor})`;
|
|
161
164
|
});
|
|
162
165
|
|
|
166
|
+
const wrapperStyle = $derived.by(() => {
|
|
167
|
+
return svgStyle ? `${style};${svgStyle}` : style;
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
const clipDivStyle = $derived(
|
|
171
|
+
css({
|
|
172
|
+
width: "100%",
|
|
173
|
+
height: "100%",
|
|
174
|
+
overflow: "hidden",
|
|
175
|
+
"border-radius": mapBorderRadius(mask_shape),
|
|
176
|
+
"clip-path":
|
|
177
|
+
mask_shape?.type === "concave" || mask_shape?.type === "convex"
|
|
178
|
+
? `url(#${id}-path)`
|
|
179
|
+
: "none",
|
|
180
|
+
}),
|
|
181
|
+
);
|
|
182
|
+
|
|
163
183
|
const overlay = $derived(
|
|
164
184
|
color_overlay && mapColorMode(colorMode, color_overlay),
|
|
165
185
|
);
|
|
166
186
|
|
|
167
187
|
const shouldShowFallback = $derived(hasVideoError || !video);
|
|
168
|
-
</script>
|
|
169
188
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
<defs>
|
|
179
|
-
<clipPath id={`${id}-path`}>
|
|
180
|
-
<ClipPath shape={mask_shape} width={svgWidth} height={svgHeight} />
|
|
181
|
-
</clipPath>
|
|
182
|
-
|
|
183
|
-
<g id={`${id}-border`}>
|
|
184
|
-
<ClipPath shape={mask_shape} width={svgWidth} height={svgHeight} />
|
|
185
|
-
</g>
|
|
189
|
+
// Programmatic autoplay (single path; HTML autoplay omitted to avoid iOS quirks).
|
|
190
|
+
$effect(() => {
|
|
191
|
+
if (!auto_play) {
|
|
192
|
+
untrack(() => {
|
|
193
|
+
showControlsFallback = false;
|
|
194
|
+
});
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
186
197
|
|
|
187
|
-
|
|
188
|
-
|
|
198
|
+
if (shouldShowFallback || !video) {
|
|
199
|
+
untrack(() => {
|
|
200
|
+
showControlsFallback = false;
|
|
201
|
+
});
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
189
204
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
205
|
+
const el = videoElement;
|
|
206
|
+
if (!el) {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
193
209
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
x="0"
|
|
221
|
-
y="0"
|
|
222
|
-
height="100%"
|
|
223
|
-
width="100%"
|
|
224
|
-
fill={`url(#${id}-overlay)`}
|
|
210
|
+
void video.url;
|
|
211
|
+
void mute_audio;
|
|
212
|
+
|
|
213
|
+
untrack(() => {
|
|
214
|
+
showControlsFallback = false;
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
const playPromise = el.play();
|
|
218
|
+
if (playPromise !== undefined) {
|
|
219
|
+
playPromise.catch(() => {
|
|
220
|
+
untrack(() => {
|
|
221
|
+
showControlsFallback = true;
|
|
222
|
+
});
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
</script>
|
|
227
|
+
|
|
228
|
+
<div class="video-outer" style={wrapperStyle} bind:clientWidth={wrapperWidth}>
|
|
229
|
+
<div class="video-media">
|
|
230
|
+
<div class="video-clip" style={clipDivStyle}>
|
|
231
|
+
{#if shouldShowFallback && fallbackImage}
|
|
232
|
+
<img
|
|
233
|
+
src={fallbackImage.original}
|
|
234
|
+
style="object-fit:{mapFitMode(fit_mode)}"
|
|
235
|
+
alt=""
|
|
225
236
|
/>
|
|
237
|
+
{:else if video}
|
|
238
|
+
<video
|
|
239
|
+
bind:this={videoElement}
|
|
240
|
+
src={video.url}
|
|
241
|
+
style="object-fit:{mapFitMode(fit_mode)}"
|
|
242
|
+
{loop}
|
|
243
|
+
muted={mute_audio}
|
|
244
|
+
controls={show_controls || showControlsFallback}
|
|
245
|
+
playsinline
|
|
246
|
+
>
|
|
247
|
+
<track kind="captions" />
|
|
248
|
+
</video>
|
|
226
249
|
{/if}
|
|
250
|
+
</div>
|
|
251
|
+
|
|
252
|
+
<svg
|
|
253
|
+
class="video-deco"
|
|
254
|
+
bind:contentRect={svgRect}
|
|
255
|
+
width="100%"
|
|
256
|
+
height="100%"
|
|
257
|
+
{viewBox}
|
|
258
|
+
>
|
|
259
|
+
<defs>
|
|
260
|
+
<clipPath id={`${id}-path`}>
|
|
261
|
+
<ClipPath shape={mask_shape} width={svgWidth} height={svgHeight} />
|
|
262
|
+
</clipPath>
|
|
263
|
+
|
|
264
|
+
<g id={`${id}-border`}>
|
|
265
|
+
<ClipPath shape={mask_shape} width={svgWidth} height={svgHeight} />
|
|
266
|
+
</g>
|
|
267
|
+
|
|
268
|
+
<Overlay id={`${id}-overlay`} {overlay} />
|
|
269
|
+
</defs>
|
|
227
270
|
|
|
228
271
|
{#if border && border.width > 0}
|
|
229
|
-
<use
|
|
230
|
-
href={`#${id}-border`}
|
|
231
|
-
fill="none"
|
|
232
|
-
stroke={mapColor(colorMode, border.color)}
|
|
233
|
-
stroke-width={border.width}
|
|
234
|
-
/>
|
|
272
|
+
<use href={`#${id}-border`} fill="transparent" />
|
|
235
273
|
{/if}
|
|
236
|
-
|
|
237
|
-
|
|
274
|
+
|
|
275
|
+
<g clip-path={`url(#${id}-path)`}>
|
|
276
|
+
{#if overlay}
|
|
277
|
+
<rect
|
|
278
|
+
x="0"
|
|
279
|
+
y="0"
|
|
280
|
+
height="100%"
|
|
281
|
+
width="100%"
|
|
282
|
+
fill={`url(#${id}-overlay)`}
|
|
283
|
+
/>
|
|
284
|
+
{/if}
|
|
285
|
+
|
|
286
|
+
{#if border && border.width > 0}
|
|
287
|
+
<use
|
|
288
|
+
href={`#${id}-border`}
|
|
289
|
+
fill="none"
|
|
290
|
+
stroke={mapColor(colorMode, border.color)}
|
|
291
|
+
stroke-width={border.width}
|
|
292
|
+
/>
|
|
293
|
+
{/if}
|
|
294
|
+
</g>
|
|
295
|
+
</svg>
|
|
296
|
+
</div>
|
|
238
297
|
</div>
|
|
239
298
|
|
|
240
299
|
<style>
|
|
300
|
+
.video-outer {
|
|
301
|
+
position: relative;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
.video-media {
|
|
305
|
+
position: relative;
|
|
306
|
+
width: 100%;
|
|
307
|
+
height: 100%;
|
|
308
|
+
min-height: 0;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
.video-deco {
|
|
312
|
+
position: absolute;
|
|
313
|
+
inset: 0;
|
|
314
|
+
width: 100%;
|
|
315
|
+
height: 100%;
|
|
316
|
+
pointer-events: none;
|
|
317
|
+
}
|
|
318
|
+
|
|
241
319
|
video,
|
|
242
320
|
img {
|
|
243
321
|
width: 100%;
|