@yoamigo.com/core 0.3.0 → 0.3.3
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/dist/{MarkdownText-BUTYfqXS.d.ts → MarkdownText-Nvkeyr1z.d.ts} +46 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +619 -180
- package/dist/lib.js +30 -5
- package/dist/plugin.js +6 -0
- package/dist/prod.d.ts +136 -3
- package/dist/prod.js +591 -4
- package/package.json +1 -1
package/dist/prod.js
CHANGED
|
@@ -298,12 +298,588 @@ function MarkdownText({ content, className }) {
|
|
|
298
298
|
return /* @__PURE__ */ jsx6("span", { className, children: elements });
|
|
299
299
|
}
|
|
300
300
|
|
|
301
|
+
// src/components/StaticContainer.tsx
|
|
302
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
303
|
+
function parseBackgroundConfig(value) {
|
|
304
|
+
if (!value) {
|
|
305
|
+
return { type: "none" };
|
|
306
|
+
}
|
|
307
|
+
try {
|
|
308
|
+
const parsed = JSON.parse(value);
|
|
309
|
+
if (typeof parsed === "object" && parsed.type) {
|
|
310
|
+
return parsed;
|
|
311
|
+
}
|
|
312
|
+
} catch {
|
|
313
|
+
}
|
|
314
|
+
return { type: "none" };
|
|
315
|
+
}
|
|
316
|
+
function serializeBackgroundConfig(config) {
|
|
317
|
+
return JSON.stringify(config);
|
|
318
|
+
}
|
|
319
|
+
function getObjectPosition2(imageConfig) {
|
|
320
|
+
if (imageConfig.focalPoint) {
|
|
321
|
+
return `${imageConfig.focalPoint.x}% ${imageConfig.focalPoint.y}%`;
|
|
322
|
+
}
|
|
323
|
+
return imageConfig.objectPosition || "50% 50%";
|
|
324
|
+
}
|
|
325
|
+
function StaticContainer({
|
|
326
|
+
fieldId,
|
|
327
|
+
className,
|
|
328
|
+
style,
|
|
329
|
+
as: Tag = "section",
|
|
330
|
+
children,
|
|
331
|
+
defaultBackground
|
|
332
|
+
}) {
|
|
333
|
+
const { getValue } = useContentStore();
|
|
334
|
+
const rawValue = getValue(fieldId);
|
|
335
|
+
const backgroundConfig = rawValue ? parseBackgroundConfig(rawValue) : defaultBackground || { type: "none" };
|
|
336
|
+
const hasBackground = backgroundConfig.type !== "none";
|
|
337
|
+
const backgroundStyles = {};
|
|
338
|
+
if (backgroundConfig.type === "color" && backgroundConfig.backgroundColor) {
|
|
339
|
+
backgroundStyles.backgroundColor = backgroundConfig.backgroundColor;
|
|
340
|
+
}
|
|
341
|
+
if (backgroundConfig.type === "image" && backgroundConfig.backgroundImage) {
|
|
342
|
+
const img = backgroundConfig.backgroundImage;
|
|
343
|
+
const resolvedSrc = resolveAssetUrl(img.src);
|
|
344
|
+
backgroundStyles.backgroundImage = `url(${resolvedSrc})`;
|
|
345
|
+
backgroundStyles.backgroundSize = img.objectFit || "cover";
|
|
346
|
+
backgroundStyles.backgroundPosition = getObjectPosition2(img);
|
|
347
|
+
backgroundStyles.backgroundRepeat = "no-repeat";
|
|
348
|
+
}
|
|
349
|
+
const overlayCustomProps = {};
|
|
350
|
+
if (backgroundConfig.overlay) {
|
|
351
|
+
overlayCustomProps["--ya-overlay-color"] = backgroundConfig.overlay.color;
|
|
352
|
+
overlayCustomProps["--ya-overlay-opacity"] = backgroundConfig.overlay.opacity;
|
|
353
|
+
}
|
|
354
|
+
return /* @__PURE__ */ jsx7(
|
|
355
|
+
Tag,
|
|
356
|
+
{
|
|
357
|
+
className: `ya-container ${hasBackground ? "ya-container-has-overlay" : ""} ${className || ""}`,
|
|
358
|
+
style: {
|
|
359
|
+
...backgroundStyles,
|
|
360
|
+
...overlayCustomProps,
|
|
361
|
+
...style
|
|
362
|
+
},
|
|
363
|
+
"data-field-id": fieldId,
|
|
364
|
+
children
|
|
365
|
+
}
|
|
366
|
+
);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// src/components/StaticVideo.tsx
|
|
370
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
371
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
372
|
+
function parseVideoValue(value) {
|
|
373
|
+
if (!value) {
|
|
374
|
+
return { type: "upload", src: "" };
|
|
375
|
+
}
|
|
376
|
+
try {
|
|
377
|
+
const parsed = JSON.parse(value);
|
|
378
|
+
if (typeof parsed === "object" && parsed.src) {
|
|
379
|
+
return {
|
|
380
|
+
type: parsed.type || "upload",
|
|
381
|
+
...parsed
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
} catch {
|
|
385
|
+
}
|
|
386
|
+
return { type: "upload", src: value };
|
|
387
|
+
}
|
|
388
|
+
function serializeVideoValue(value) {
|
|
389
|
+
return JSON.stringify(value);
|
|
390
|
+
}
|
|
391
|
+
function buildYouTubeEmbedUrl(videoId, value) {
|
|
392
|
+
const params = new URLSearchParams({
|
|
393
|
+
rel: "0",
|
|
394
|
+
modestbranding: "1"
|
|
395
|
+
});
|
|
396
|
+
if (value.autoplay) params.set("autoplay", "1");
|
|
397
|
+
if (value.muted) params.set("mute", "1");
|
|
398
|
+
if (value.loop) {
|
|
399
|
+
params.set("loop", "1");
|
|
400
|
+
params.set("playlist", videoId);
|
|
401
|
+
}
|
|
402
|
+
if (value.controls === false) params.set("controls", "0");
|
|
403
|
+
if (value.startTime) params.set("start", String(Math.floor(value.startTime)));
|
|
404
|
+
if (value.endTime) params.set("end", String(Math.floor(value.endTime)));
|
|
405
|
+
return `https://www.youtube.com/embed/${videoId}?${params.toString()}`;
|
|
406
|
+
}
|
|
407
|
+
function buildVimeoEmbedUrl(videoId, value) {
|
|
408
|
+
const params = new URLSearchParams({
|
|
409
|
+
title: "0",
|
|
410
|
+
byline: "0",
|
|
411
|
+
portrait: "0"
|
|
412
|
+
});
|
|
413
|
+
if (value.autoplay) params.set("autoplay", "1");
|
|
414
|
+
if (value.muted) params.set("muted", "1");
|
|
415
|
+
if (value.loop) params.set("loop", "1");
|
|
416
|
+
if (value.controls === false) params.set("controls", "0");
|
|
417
|
+
let url = `https://player.vimeo.com/video/${videoId}?${params.toString()}`;
|
|
418
|
+
if (value.startTime) {
|
|
419
|
+
url += `#t=${Math.floor(value.startTime)}s`;
|
|
420
|
+
}
|
|
421
|
+
return url;
|
|
422
|
+
}
|
|
423
|
+
function StaticVideo({
|
|
424
|
+
fieldId,
|
|
425
|
+
className,
|
|
426
|
+
aspectRatio: propAspectRatio,
|
|
427
|
+
objectFit: propObjectFit,
|
|
428
|
+
loading = "lazy",
|
|
429
|
+
defaultValue,
|
|
430
|
+
fallbackSrc,
|
|
431
|
+
fallbackPoster
|
|
432
|
+
}) {
|
|
433
|
+
const { getValue } = useContentStore();
|
|
434
|
+
const containerRef = useRef(null);
|
|
435
|
+
const videoRef = useRef(null);
|
|
436
|
+
const [isInView, setIsInView] = useState(loading === "eager");
|
|
437
|
+
const rawValue = getValue(fieldId);
|
|
438
|
+
const parsedValue = parseVideoValue(rawValue);
|
|
439
|
+
const videoData = parsedValue.src ? parsedValue : defaultValue || parsedValue;
|
|
440
|
+
const src = videoData.src || fallbackSrc || "";
|
|
441
|
+
const poster = videoData.poster || fallbackPoster || "";
|
|
442
|
+
const objectFit = videoData.objectFit || propObjectFit || "cover";
|
|
443
|
+
const aspectRatio = videoData.aspectRatio || propAspectRatio || "16/9";
|
|
444
|
+
const autoplay = videoData.autoplay ?? false;
|
|
445
|
+
const muted = videoData.muted ?? false;
|
|
446
|
+
const loop = videoData.loop ?? false;
|
|
447
|
+
const controls = videoData.controls ?? true;
|
|
448
|
+
const playsinline = videoData.playsinline ?? true;
|
|
449
|
+
const preload = videoData.preload ?? "metadata";
|
|
450
|
+
const [prefersReducedMotion, setPrefersReducedMotion] = useState(false);
|
|
451
|
+
useEffect(() => {
|
|
452
|
+
const mediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
453
|
+
setPrefersReducedMotion(mediaQuery.matches);
|
|
454
|
+
const handleChange = (e) => {
|
|
455
|
+
setPrefersReducedMotion(e.matches);
|
|
456
|
+
};
|
|
457
|
+
mediaQuery.addEventListener("change", handleChange);
|
|
458
|
+
return () => mediaQuery.removeEventListener("change", handleChange);
|
|
459
|
+
}, []);
|
|
460
|
+
const effectiveAutoplay = autoplay && !prefersReducedMotion;
|
|
461
|
+
useEffect(() => {
|
|
462
|
+
if (loading === "eager" || isInView) return;
|
|
463
|
+
const observer = new IntersectionObserver(
|
|
464
|
+
(entries) => {
|
|
465
|
+
if (entries[0]?.isIntersecting) {
|
|
466
|
+
setIsInView(true);
|
|
467
|
+
observer.disconnect();
|
|
468
|
+
}
|
|
469
|
+
},
|
|
470
|
+
{ rootMargin: "200px" }
|
|
471
|
+
);
|
|
472
|
+
if (containerRef.current) {
|
|
473
|
+
observer.observe(containerRef.current);
|
|
474
|
+
}
|
|
475
|
+
return () => observer.disconnect();
|
|
476
|
+
}, [loading, isInView]);
|
|
477
|
+
const handleKeyDown = useCallback(
|
|
478
|
+
(e) => {
|
|
479
|
+
if ((e.key === " " || e.key === "Enter") && videoData.type === "upload" && controls) {
|
|
480
|
+
e.preventDefault();
|
|
481
|
+
const video = videoRef.current;
|
|
482
|
+
if (video) {
|
|
483
|
+
if (video.paused) {
|
|
484
|
+
video.play();
|
|
485
|
+
} else {
|
|
486
|
+
video.pause();
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
},
|
|
491
|
+
[videoData.type, controls]
|
|
492
|
+
);
|
|
493
|
+
const renderVideo = () => {
|
|
494
|
+
if (!src) return null;
|
|
495
|
+
if (!isInView && loading === "lazy") {
|
|
496
|
+
return /* @__PURE__ */ jsx8("div", { className: "ya-video-placeholder", style: { aspectRatio } });
|
|
497
|
+
}
|
|
498
|
+
if (videoData.type === "youtube" && src) {
|
|
499
|
+
const embedUrl = buildYouTubeEmbedUrl(src, videoData);
|
|
500
|
+
return /* @__PURE__ */ jsx8(
|
|
501
|
+
"iframe",
|
|
502
|
+
{
|
|
503
|
+
src: embedUrl,
|
|
504
|
+
className,
|
|
505
|
+
style: {
|
|
506
|
+
width: "100%",
|
|
507
|
+
height: "100%",
|
|
508
|
+
border: "none",
|
|
509
|
+
aspectRatio,
|
|
510
|
+
objectFit
|
|
511
|
+
},
|
|
512
|
+
allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",
|
|
513
|
+
allowFullScreen: true,
|
|
514
|
+
loading
|
|
515
|
+
}
|
|
516
|
+
);
|
|
517
|
+
}
|
|
518
|
+
if (videoData.type === "vimeo" && src) {
|
|
519
|
+
const embedUrl = buildVimeoEmbedUrl(src, videoData);
|
|
520
|
+
return /* @__PURE__ */ jsx8(
|
|
521
|
+
"iframe",
|
|
522
|
+
{
|
|
523
|
+
src: embedUrl,
|
|
524
|
+
className,
|
|
525
|
+
style: {
|
|
526
|
+
width: "100%",
|
|
527
|
+
height: "100%",
|
|
528
|
+
border: "none",
|
|
529
|
+
aspectRatio,
|
|
530
|
+
objectFit
|
|
531
|
+
},
|
|
532
|
+
allow: "autoplay; fullscreen; picture-in-picture",
|
|
533
|
+
allowFullScreen: true,
|
|
534
|
+
loading
|
|
535
|
+
}
|
|
536
|
+
);
|
|
537
|
+
}
|
|
538
|
+
const resolvedSrc = resolveAssetUrl(src);
|
|
539
|
+
const resolvedPoster = poster ? resolveAssetUrl(poster) : void 0;
|
|
540
|
+
return /* @__PURE__ */ jsx8(
|
|
541
|
+
"video",
|
|
542
|
+
{
|
|
543
|
+
ref: videoRef,
|
|
544
|
+
src: resolvedSrc,
|
|
545
|
+
poster: resolvedPoster,
|
|
546
|
+
className,
|
|
547
|
+
style: {
|
|
548
|
+
objectFit,
|
|
549
|
+
aspectRatio
|
|
550
|
+
},
|
|
551
|
+
autoPlay: effectiveAutoplay,
|
|
552
|
+
muted,
|
|
553
|
+
loop,
|
|
554
|
+
controls,
|
|
555
|
+
playsInline: playsinline,
|
|
556
|
+
preload,
|
|
557
|
+
onLoadedMetadata: (e) => {
|
|
558
|
+
if (videoData.startTime) {
|
|
559
|
+
e.currentTarget.currentTime = videoData.startTime;
|
|
560
|
+
}
|
|
561
|
+
},
|
|
562
|
+
onTimeUpdate: (e) => {
|
|
563
|
+
if (videoData.endTime && e.currentTarget.currentTime >= videoData.endTime) {
|
|
564
|
+
if (loop) {
|
|
565
|
+
e.currentTarget.currentTime = videoData.startTime || 0;
|
|
566
|
+
} else {
|
|
567
|
+
e.currentTarget.pause();
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
);
|
|
573
|
+
};
|
|
574
|
+
return /* @__PURE__ */ jsx8(
|
|
575
|
+
"div",
|
|
576
|
+
{
|
|
577
|
+
ref: containerRef,
|
|
578
|
+
className: `ya-video-wrapper ${className || ""}`,
|
|
579
|
+
style: { aspectRatio },
|
|
580
|
+
"data-field-id": fieldId,
|
|
581
|
+
tabIndex: videoData.type === "upload" && controls ? 0 : void 0,
|
|
582
|
+
role: videoData.type === "upload" && controls ? "application" : void 0,
|
|
583
|
+
"aria-label": videoData.type === "upload" && controls ? "Video player. Press Space or Enter to play/pause." : void 0,
|
|
584
|
+
onKeyDown: handleKeyDown,
|
|
585
|
+
children: renderVideo()
|
|
586
|
+
}
|
|
587
|
+
);
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
// src/components/StaticEmbed.tsx
|
|
591
|
+
import { useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
|
|
592
|
+
import { jsx as jsx9, jsxs } from "react/jsx-runtime";
|
|
593
|
+
function parseEmbedValue(value) {
|
|
594
|
+
if (!value) {
|
|
595
|
+
return { type: "custom", src: "" };
|
|
596
|
+
}
|
|
597
|
+
try {
|
|
598
|
+
const parsed = JSON.parse(value);
|
|
599
|
+
if (typeof parsed === "object" && parsed.src) {
|
|
600
|
+
return {
|
|
601
|
+
type: parsed.type || "custom",
|
|
602
|
+
...parsed
|
|
603
|
+
};
|
|
604
|
+
}
|
|
605
|
+
} catch {
|
|
606
|
+
}
|
|
607
|
+
return { type: "custom", src: value, originalUrl: value };
|
|
608
|
+
}
|
|
609
|
+
function serializeEmbedValue(value) {
|
|
610
|
+
return JSON.stringify(value);
|
|
611
|
+
}
|
|
612
|
+
function buildSpotifyEmbedUrl(src) {
|
|
613
|
+
return `https://open.spotify.com/embed/${src}?utm_source=generator&theme=0`;
|
|
614
|
+
}
|
|
615
|
+
function buildSoundCloudEmbedUrl(src) {
|
|
616
|
+
return `https://w.soundcloud.com/player/?url=${encodeURIComponent(src)}&color=%23ff5500&auto_play=false&hide_related=true&show_comments=false&show_user=true&show_reposts=false&show_teaser=false`;
|
|
617
|
+
}
|
|
618
|
+
function buildInstagramEmbedUrl(shortcode) {
|
|
619
|
+
return `https://www.instagram.com/p/${shortcode}/embed`;
|
|
620
|
+
}
|
|
621
|
+
function StaticEmbed({
|
|
622
|
+
fieldId,
|
|
623
|
+
className,
|
|
624
|
+
aspectRatio: propAspectRatio,
|
|
625
|
+
maxWidth,
|
|
626
|
+
loading = "lazy",
|
|
627
|
+
defaultValue
|
|
628
|
+
}) {
|
|
629
|
+
const { getValue } = useContentStore();
|
|
630
|
+
const containerRef = useRef2(null);
|
|
631
|
+
const [isInView, setIsInView] = useState2(loading === "eager");
|
|
632
|
+
const rawValue = getValue(fieldId);
|
|
633
|
+
const parsedValue = parseEmbedValue(rawValue);
|
|
634
|
+
const embedData = parsedValue.src ? parsedValue : defaultValue || parsedValue;
|
|
635
|
+
const src = embedData.src || "";
|
|
636
|
+
const embedType = embedData.type || "custom";
|
|
637
|
+
const height = embedData.height;
|
|
638
|
+
const aspectRatio = embedData.aspectRatio || propAspectRatio || "16/9";
|
|
639
|
+
useEffect2(() => {
|
|
640
|
+
if (loading === "eager" || isInView) return;
|
|
641
|
+
const observer = new IntersectionObserver(
|
|
642
|
+
(entries) => {
|
|
643
|
+
if (entries[0]?.isIntersecting) {
|
|
644
|
+
setIsInView(true);
|
|
645
|
+
observer.disconnect();
|
|
646
|
+
}
|
|
647
|
+
},
|
|
648
|
+
{ rootMargin: "200px" }
|
|
649
|
+
);
|
|
650
|
+
if (containerRef.current) {
|
|
651
|
+
observer.observe(containerRef.current);
|
|
652
|
+
}
|
|
653
|
+
return () => observer.disconnect();
|
|
654
|
+
}, [loading, isInView]);
|
|
655
|
+
const renderEmbed = () => {
|
|
656
|
+
if (!src) return null;
|
|
657
|
+
if (!isInView && loading === "lazy") {
|
|
658
|
+
return /* @__PURE__ */ jsx9("div", { className: "ya-embed-placeholder", style: { aspectRatio } });
|
|
659
|
+
}
|
|
660
|
+
if (embedType === "spotify" && src) {
|
|
661
|
+
const embedUrl = buildSpotifyEmbedUrl(src);
|
|
662
|
+
return /* @__PURE__ */ jsx9(
|
|
663
|
+
"iframe",
|
|
664
|
+
{
|
|
665
|
+
src: embedUrl,
|
|
666
|
+
style: {
|
|
667
|
+
width: "100%",
|
|
668
|
+
height: height ? `${height}px` : "100%",
|
|
669
|
+
border: "none",
|
|
670
|
+
borderRadius: "12px"
|
|
671
|
+
},
|
|
672
|
+
allow: "autoplay; clipboard-write; encrypted-media; fullscreen; picture-in-picture",
|
|
673
|
+
loading,
|
|
674
|
+
title: "Spotify embed"
|
|
675
|
+
}
|
|
676
|
+
);
|
|
677
|
+
}
|
|
678
|
+
if (embedType === "soundcloud" && src) {
|
|
679
|
+
const embedUrl = buildSoundCloudEmbedUrl(src);
|
|
680
|
+
return /* @__PURE__ */ jsx9(
|
|
681
|
+
"iframe",
|
|
682
|
+
{
|
|
683
|
+
src: embedUrl,
|
|
684
|
+
style: {
|
|
685
|
+
width: "100%",
|
|
686
|
+
height: height ? `${height}px` : "166px",
|
|
687
|
+
border: "none"
|
|
688
|
+
},
|
|
689
|
+
allow: "autoplay",
|
|
690
|
+
loading,
|
|
691
|
+
title: "SoundCloud embed"
|
|
692
|
+
}
|
|
693
|
+
);
|
|
694
|
+
}
|
|
695
|
+
if (embedType === "twitter" && src) {
|
|
696
|
+
return /* @__PURE__ */ jsxs("div", { className: "ya-embed-twitter", children: [
|
|
697
|
+
/* @__PURE__ */ jsx9("blockquote", { className: "twitter-tweet", "data-dnt": "true", children: /* @__PURE__ */ jsx9("a", { href: embedData.originalUrl || `https://twitter.com/i/status/${src}`, children: "Loading tweet..." }) }),
|
|
698
|
+
/* @__PURE__ */ jsx9(TwitterWidgetLoader, {})
|
|
699
|
+
] });
|
|
700
|
+
}
|
|
701
|
+
if (embedType === "instagram" && src) {
|
|
702
|
+
const embedUrl = buildInstagramEmbedUrl(src);
|
|
703
|
+
return /* @__PURE__ */ jsx9(
|
|
704
|
+
"iframe",
|
|
705
|
+
{
|
|
706
|
+
src: embedUrl,
|
|
707
|
+
style: {
|
|
708
|
+
width: "100%",
|
|
709
|
+
height: "100%",
|
|
710
|
+
aspectRatio,
|
|
711
|
+
border: "none",
|
|
712
|
+
minHeight: "400px"
|
|
713
|
+
},
|
|
714
|
+
allow: "encrypted-media",
|
|
715
|
+
loading,
|
|
716
|
+
title: "Instagram embed"
|
|
717
|
+
}
|
|
718
|
+
);
|
|
719
|
+
}
|
|
720
|
+
if (embedType === "custom" && src) {
|
|
721
|
+
return /* @__PURE__ */ jsx9(
|
|
722
|
+
"iframe",
|
|
723
|
+
{
|
|
724
|
+
src,
|
|
725
|
+
style: {
|
|
726
|
+
width: "100%",
|
|
727
|
+
height: "100%",
|
|
728
|
+
border: "none",
|
|
729
|
+
aspectRatio
|
|
730
|
+
},
|
|
731
|
+
sandbox: "allow-scripts allow-same-origin allow-popups allow-forms",
|
|
732
|
+
loading,
|
|
733
|
+
title: "Embedded content"
|
|
734
|
+
}
|
|
735
|
+
);
|
|
736
|
+
}
|
|
737
|
+
return null;
|
|
738
|
+
};
|
|
739
|
+
const wrapperStyle = {
|
|
740
|
+
aspectRatio: height ? void 0 : aspectRatio,
|
|
741
|
+
height: height ? `${height}px` : void 0,
|
|
742
|
+
maxWidth: maxWidth ? `${maxWidth}px` : void 0
|
|
743
|
+
};
|
|
744
|
+
return /* @__PURE__ */ jsx9(
|
|
745
|
+
"div",
|
|
746
|
+
{
|
|
747
|
+
ref: containerRef,
|
|
748
|
+
className: `ya-embed-wrapper ${className || ""}`,
|
|
749
|
+
style: wrapperStyle,
|
|
750
|
+
"data-field-id": fieldId,
|
|
751
|
+
"data-embed-type": embedType,
|
|
752
|
+
children: renderEmbed()
|
|
753
|
+
}
|
|
754
|
+
);
|
|
755
|
+
}
|
|
756
|
+
function TwitterWidgetLoader() {
|
|
757
|
+
useEffect2(() => {
|
|
758
|
+
if (window.twttr?.widgets) {
|
|
759
|
+
;
|
|
760
|
+
window.twttr.widgets.load();
|
|
761
|
+
return;
|
|
762
|
+
}
|
|
763
|
+
if (document.getElementById("twitter-wjs")) {
|
|
764
|
+
return;
|
|
765
|
+
}
|
|
766
|
+
const script = document.createElement("script");
|
|
767
|
+
script.id = "twitter-wjs";
|
|
768
|
+
script.src = "https://platform.twitter.com/widgets.js";
|
|
769
|
+
script.async = true;
|
|
770
|
+
document.body.appendChild(script);
|
|
771
|
+
}, []);
|
|
772
|
+
return null;
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
// src/components/YaEmbed.tsx
|
|
776
|
+
import { useCallback as useCallback2, useEffect as useEffect3, useRef as useRef3, useState as useState3 } from "react";
|
|
777
|
+
|
|
778
|
+
// #style-inject:#style-inject
|
|
779
|
+
function styleInject(css, { insertAt } = {}) {
|
|
780
|
+
if (!css || typeof document === "undefined") return;
|
|
781
|
+
const head = document.head || document.getElementsByTagName("head")[0];
|
|
782
|
+
const style = document.createElement("style");
|
|
783
|
+
style.type = "text/css";
|
|
784
|
+
if (insertAt === "top") {
|
|
785
|
+
if (head.firstChild) {
|
|
786
|
+
head.insertBefore(style, head.firstChild);
|
|
787
|
+
} else {
|
|
788
|
+
head.appendChild(style);
|
|
789
|
+
}
|
|
790
|
+
} else {
|
|
791
|
+
head.appendChild(style);
|
|
792
|
+
}
|
|
793
|
+
if (style.styleSheet) {
|
|
794
|
+
style.styleSheet.cssText = css;
|
|
795
|
+
} else {
|
|
796
|
+
style.appendChild(document.createTextNode(css));
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
// src/components/ya-embed.css
|
|
801
|
+
styleInject('.ya-embed-wrapper {\n position: relative;\n display: block;\n width: 100%;\n}\n.ya-embed-wrapper iframe {\n display: block;\n width: 100%;\n height: 100%;\n}\n.ya-embed-container {\n position: relative;\n display: block;\n width: 100%;\n min-width: 80px;\n min-height: 80px;\n cursor: pointer;\n transition: outline 0.15s ease;\n}\n.ya-embed-container iframe {\n display: block;\n width: 100%;\n height: 100%;\n pointer-events: none;\n}\n.ya-embed-editable {\n cursor: pointer;\n}\n.ya-embed-editable:hover {\n outline: 2px dashed var(--color-primary, #d4a574);\n outline-offset: 4px;\n}\n.ya-embed-selected {\n outline: 3px solid var(--color-primary, #d4a574);\n outline-offset: 4px;\n}\n.ya-embed-overlay {\n position: absolute;\n inset: 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 8px;\n background: rgba(0, 0, 0, 0.5);\n opacity: 0;\n transition: opacity 0.2s ease;\n pointer-events: none;\n border-radius: inherit;\n}\n.ya-embed-editable:hover .ya-embed-overlay {\n opacity: 1;\n}\n.ya-embed-selected .ya-embed-overlay {\n opacity: 0;\n}\n.ya-embed-edit-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 48px;\n height: 48px;\n background: white;\n border-radius: 50%;\n color: #1a1a1a;\n box-shadow: 0 2px 12px rgba(0, 0, 0, 0.2);\n}\n.ya-embed-edit-icon svg {\n width: 24px;\n height: 24px;\n}\n.ya-embed-edit-label {\n color: white;\n font-size: 14px;\n font-weight: 500;\n text-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);\n}\n.ya-embed-placeholder {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 8px;\n width: 100%;\n height: 100%;\n min-height: 120px;\n background: #f3f4f6;\n border: 2px dashed #d1d5db;\n border-radius: 8px;\n color: #6b7280;\n font-size: 14px;\n}\n.ya-embed-placeholder img {\n width: 64px;\n height: auto;\n opacity: 0.5;\n}\n@keyframes ya-embed-success {\n 0% {\n outline-color: var(--color-primary, #d4a574);\n }\n 50% {\n outline-color: #22c55e;\n outline-width: 4px;\n }\n 100% {\n outline-color: var(--color-primary, #d4a574);\n outline-width: 2px;\n }\n}\n.ya-embed-success {\n animation: ya-embed-success 0.4s ease;\n}\n.ya-embed-loading::after {\n content: "";\n position: absolute;\n inset: 0;\n background:\n linear-gradient(\n 90deg,\n rgba(255, 255, 255, 0) 0%,\n rgba(255, 255, 255, 0.3) 50%,\n rgba(255, 255, 255, 0) 100%);\n background-size: 200% 100%;\n animation: ya-embed-shimmer 1.5s infinite;\n}\n@keyframes ya-embed-shimmer {\n 0% {\n background-position: -200% 0;\n }\n 100% {\n background-position: 200% 0;\n }\n}\n.ya-embed-container:focus {\n outline: 3px solid var(--color-primary, #d4a574);\n outline-offset: 4px;\n}\n.ya-embed-container:focus:not(:focus-visible) {\n outline: none;\n}\n.ya-embed-container:focus-visible {\n outline: 3px solid var(--color-primary, #d4a574);\n outline-offset: 4px;\n}\n.ya-embed-small .ya-embed-overlay {\n display: none;\n}\n.ya-embed-twitter {\n min-height: 200px;\n}\n.ya-embed-twitter .twitter-tweet {\n margin: 0 auto !important;\n}\n.ya-embed-wrapper[data-embed-type=spotify],\n.ya-embed-container[data-embed-type=spotify] {\n min-height: 80px;\n}\n.ya-embed-wrapper[data-embed-type=soundcloud],\n.ya-embed-container[data-embed-type=soundcloud] {\n min-height: 166px;\n}\n.ya-embed-wrapper[data-embed-type=instagram] iframe,\n.ya-embed-container[data-embed-type=instagram] iframe {\n min-height: 400px;\n}\n');
|
|
802
|
+
|
|
803
|
+
// src/components/YaEmbed.tsx
|
|
804
|
+
import { jsx as jsx10, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
805
|
+
function parseEmbedUrl(url) {
|
|
806
|
+
if (!url) return null;
|
|
807
|
+
const trimmedUrl = url.trim();
|
|
808
|
+
const spotifyMatch = trimmedUrl.match(
|
|
809
|
+
/open\.spotify\.com\/(track|album|playlist|episode|show)\/([a-zA-Z0-9]+)/
|
|
810
|
+
);
|
|
811
|
+
if (spotifyMatch) {
|
|
812
|
+
const spotifyType = spotifyMatch[1];
|
|
813
|
+
const spotifyId = spotifyMatch[2];
|
|
814
|
+
const height = spotifyType === "track" ? 152 : 352;
|
|
815
|
+
return {
|
|
816
|
+
type: "spotify",
|
|
817
|
+
src: `${spotifyType}/${spotifyId}`,
|
|
818
|
+
originalUrl: trimmedUrl,
|
|
819
|
+
height,
|
|
820
|
+
spotifyType
|
|
821
|
+
};
|
|
822
|
+
}
|
|
823
|
+
const soundcloudMatch = trimmedUrl.match(/soundcloud\.com\/([^/]+)\/([^/?]+)/);
|
|
824
|
+
if (soundcloudMatch) {
|
|
825
|
+
return {
|
|
826
|
+
type: "soundcloud",
|
|
827
|
+
src: trimmedUrl,
|
|
828
|
+
// SoundCloud embeds use full URL
|
|
829
|
+
originalUrl: trimmedUrl,
|
|
830
|
+
height: 166
|
|
831
|
+
};
|
|
832
|
+
}
|
|
833
|
+
const twitterMatch = trimmedUrl.match(/(?:twitter\.com|x\.com)\/\w+\/status\/(\d+)/);
|
|
834
|
+
if (twitterMatch) {
|
|
835
|
+
return {
|
|
836
|
+
type: "twitter",
|
|
837
|
+
src: twitterMatch[1],
|
|
838
|
+
// Tweet ID
|
|
839
|
+
originalUrl: trimmedUrl,
|
|
840
|
+
aspectRatio: "1/1"
|
|
841
|
+
// Twitter embeds are roughly square
|
|
842
|
+
};
|
|
843
|
+
}
|
|
844
|
+
const instagramMatch = trimmedUrl.match(/instagram\.com\/(?:p|reel)\/([a-zA-Z0-9_-]+)/);
|
|
845
|
+
if (instagramMatch) {
|
|
846
|
+
return {
|
|
847
|
+
type: "instagram",
|
|
848
|
+
src: instagramMatch[1],
|
|
849
|
+
// Post shortcode
|
|
850
|
+
originalUrl: trimmedUrl,
|
|
851
|
+
aspectRatio: "1/1"
|
|
852
|
+
};
|
|
853
|
+
}
|
|
854
|
+
if (trimmedUrl.startsWith("https://")) {
|
|
855
|
+
if (trimmedUrl.startsWith("javascript:") || trimmedUrl.startsWith("data:") || trimmedUrl.includes("<script")) {
|
|
856
|
+
return null;
|
|
857
|
+
}
|
|
858
|
+
return {
|
|
859
|
+
type: "custom",
|
|
860
|
+
src: trimmedUrl,
|
|
861
|
+
originalUrl: trimmedUrl,
|
|
862
|
+
aspectRatio: "16/9"
|
|
863
|
+
};
|
|
864
|
+
}
|
|
865
|
+
return null;
|
|
866
|
+
}
|
|
867
|
+
var PLACEHOLDER_SVG = `data:image/svg+xml,${encodeURIComponent(`
|
|
868
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="400" height="225" viewBox="0 0 400 225">
|
|
869
|
+
<rect fill="#e5e7eb" width="400" height="225"/>
|
|
870
|
+
<g fill="#9ca3af" transform="translate(175, 87)">
|
|
871
|
+
<rect x="5" y="5" width="40" height="30" rx="4" stroke="currentColor" stroke-width="2" fill="none"/>
|
|
872
|
+
<path d="M15 15 L25 22 L15 29 Z" fill="currentColor"/>
|
|
873
|
+
</g>
|
|
874
|
+
</svg>
|
|
875
|
+
`)}`;
|
|
876
|
+
|
|
301
877
|
// src/router/Link.tsx
|
|
302
878
|
import { Link as WouterLink } from "wouter";
|
|
303
|
-
import { jsx as
|
|
879
|
+
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
304
880
|
function Link({ to, href, children, className, onClick, replace, ...props }) {
|
|
305
881
|
const target = href ?? to ?? "/";
|
|
306
|
-
return /* @__PURE__ */
|
|
882
|
+
return /* @__PURE__ */ jsx11(WouterLink, { href: target, className, onClick, replace, ...props, children });
|
|
307
883
|
}
|
|
308
884
|
|
|
309
885
|
// src/router/useNavigate.ts
|
|
@@ -322,7 +898,7 @@ function useNavigate() {
|
|
|
322
898
|
|
|
323
899
|
// src/router/Router.tsx
|
|
324
900
|
import { Router as WouterRouter } from "wouter";
|
|
325
|
-
import { jsx as
|
|
901
|
+
import { jsx as jsx12 } from "react/jsx-runtime";
|
|
326
902
|
function detectBasename() {
|
|
327
903
|
if (typeof window === "undefined") return "";
|
|
328
904
|
const sessionMatch = window.location.pathname.match(/^\/session\/[^/]+/);
|
|
@@ -337,7 +913,7 @@ function detectBasename() {
|
|
|
337
913
|
}
|
|
338
914
|
function Router({ children, base }) {
|
|
339
915
|
const basename = base ?? detectBasename();
|
|
340
|
-
return /* @__PURE__ */
|
|
916
|
+
return /* @__PURE__ */ jsx12(WouterRouter, { base: basename, children });
|
|
341
917
|
}
|
|
342
918
|
|
|
343
919
|
// src/router/index.ts
|
|
@@ -349,19 +925,30 @@ export {
|
|
|
349
925
|
Route,
|
|
350
926
|
Router,
|
|
351
927
|
SafeHtml,
|
|
928
|
+
StaticContainer,
|
|
929
|
+
StaticEmbed,
|
|
352
930
|
MpImage as StaticImage,
|
|
353
931
|
StaticLink,
|
|
354
932
|
MpText as StaticText,
|
|
933
|
+
StaticVideo,
|
|
355
934
|
Switch,
|
|
935
|
+
StaticContainer as YaContainer,
|
|
936
|
+
StaticEmbed as YaEmbed,
|
|
356
937
|
MpImage as YaImage,
|
|
357
938
|
StaticLink as YaLink,
|
|
358
939
|
MpText as YaText,
|
|
940
|
+
StaticVideo as YaVideo,
|
|
359
941
|
contentRegistry,
|
|
360
942
|
getAllContent,
|
|
361
943
|
getContent,
|
|
362
944
|
hasContent,
|
|
945
|
+
parseBackgroundConfig,
|
|
946
|
+
parseEmbedUrl,
|
|
363
947
|
registerContent,
|
|
364
948
|
resolveAssetUrl,
|
|
949
|
+
serializeBackgroundConfig,
|
|
950
|
+
serializeEmbedValue,
|
|
951
|
+
serializeVideoValue,
|
|
365
952
|
setAssetResolver,
|
|
366
953
|
useContentStore,
|
|
367
954
|
useNavigate,
|