@webstudio-is/sdk-components-react 0.144.0 → 0.144.1-710b1d2.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/lib/components.js CHANGED
@@ -65,13 +65,10 @@ var execute = async (container) => {
65
65
  const syncTasks = [];
66
66
  const asyncTasks = [];
67
67
  scripts.forEach((script) => {
68
- const type = script.getAttribute("type");
69
- if (type == null || type === "" || type === "text/javascript") {
70
- const tasks = script.hasAttribute("async") ? asyncTasks : syncTasks;
71
- tasks.push(() => {
72
- return insertScript(script);
73
- });
74
- }
68
+ const tasks = script.hasAttribute("async") ? asyncTasks : syncTasks;
69
+ tasks.push(() => {
70
+ return insertScript(script);
71
+ });
75
72
  });
76
73
  for (const task of asyncTasks) {
77
74
  task();
@@ -437,17 +434,13 @@ import { colord } from "colord";
437
434
  import {
438
435
  forwardRef as forwardRef29,
439
436
  useState as useState2,
440
- useRef as useRef2,
441
437
  useEffect as useEffect2,
442
438
  useContext as useContext3,
443
- createContext,
444
- useMemo,
445
- useCallback
439
+ createContext
446
440
  } from "react";
447
441
  import { ReactSdkContext as ReactSdkContext3 } from "@webstudio-is/react-sdk";
448
- import { shallowEqual } from "shallow-equal";
449
- import { jsx as jsx26 } from "react/jsx-runtime";
450
- var getUrl = (options) => {
442
+ import { Fragment as Fragment2, jsx as jsx26, jsxs } from "react/jsx-runtime";
443
+ var getVideoUrl = (options) => {
451
444
  if (options.url === void 0) {
452
445
  return;
453
446
  }
@@ -461,23 +454,34 @@ var getUrl = (options) => {
461
454
  if (url === void 0) {
462
455
  return;
463
456
  }
457
+ const optionsMap = {
458
+ showPortrait: "portrait",
459
+ showByline: "byline",
460
+ showTitle: "title",
461
+ controlsColor: "color",
462
+ showControls: "controls",
463
+ interactiveParams: "interactive_params",
464
+ backgroundMode: "background",
465
+ doNotTrack: "dnt"
466
+ };
464
467
  let option;
465
468
  for (option in options) {
466
469
  const value = options[option];
467
470
  if (option === "url" || value === void 0) {
468
471
  continue;
469
472
  }
470
- url.searchParams.append(option, value.toString());
473
+ const mappedOption = optionsMap[option] ?? option;
474
+ url.searchParams.append(mappedOption, value.toString());
471
475
  }
472
476
  url.searchParams.set("autoplay", "true");
473
- if (typeof options.color === "string") {
474
- const color = colord(options.color).toHex().replace("#", "");
477
+ if (typeof options.controlsColor === "string") {
478
+ const color = colord(options.controlsColor).toHex().replace("#", "");
475
479
  url.searchParams.set("color", color);
476
480
  }
477
- if (options.portrait) {
481
+ if (options.showPortrait) {
478
482
  url.searchParams.set("title", "true");
479
483
  }
480
- if (options.byline) {
484
+ if (options.showByline) {
481
485
  url.searchParams.set("portrait", "true");
482
486
  url.searchParams.set("title", "true");
483
487
  }
@@ -506,43 +510,10 @@ var warmConnections = () => {
506
510
  preconnect(IMAGE_CDN);
507
511
  warmed = true;
508
512
  };
509
- var createPlayer = (parent, vimeoOptions, extendedOptions, callback) => {
510
- const url = getUrl(vimeoOptions);
511
- if (url === void 0) {
512
- return;
513
- }
514
- const iframe = document.createElement("iframe");
515
- iframe.setAttribute(
516
- "allow",
517
- "accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture;"
518
- );
519
- iframe.setAttribute("frameborder", "0");
520
- iframe.setAttribute("allowfullscreen", "true");
521
- iframe.setAttribute("src", url);
522
- iframe.setAttribute(
523
- "style",
524
- "position: absolute; width: 100%; height: 100%; opacity: 0; transition: opacity 1s;"
525
- );
526
- if (extendedOptions.loading) {
527
- iframe.setAttribute("loading", extendedOptions.loading);
528
- }
529
- iframe.addEventListener(
530
- "load",
531
- () => {
532
- iframe.style.opacity = "1";
533
- callback();
534
- },
535
- { once: true }
536
- );
537
- parent.appendChild(iframe);
538
- return () => {
539
- iframe.parentElement?.removeChild(iframe);
540
- };
541
- };
542
513
  var getVideoId = (url) => {
543
514
  try {
544
515
  const parsedUrl = new URL(url);
545
- const id = parsedUrl.pathname.split("/")[1];
516
+ const id = parsedUrl.pathname.split("/")[2];
546
517
  if (id === "" || id == null) {
547
518
  return;
548
519
  }
@@ -550,7 +521,7 @@ var getVideoId = (url) => {
550
521
  } catch {
551
522
  }
552
523
  };
553
- var loadPreviewImage = async (element, videoUrl) => {
524
+ var loadPreviewImageUrl = async (videoUrl) => {
554
525
  const videoId = getVideoId(videoUrl);
555
526
  const apiUrl = `https://vimeo.com/api/v2/video/${videoId}.json`;
556
527
  const response = (await (await fetch(apiUrl)).json())[0];
@@ -563,69 +534,89 @@ var loadPreviewImage = async (element, videoUrl) => {
563
534
  imageUrl.searchParams.append("q", "70");
564
535
  return imageUrl;
565
536
  };
566
- var useVimeo = ({
567
- options,
537
+ var EmptyState = () => {
538
+ return /* @__PURE__ */ jsx26(
539
+ "div",
540
+ {
541
+ style: {
542
+ display: "flex",
543
+ width: "100%",
544
+ height: "100%",
545
+ alignItems: "center",
546
+ justifyContent: "center",
547
+ fontSize: "1.2em"
548
+ },
549
+ children: 'Open the "Settings" panel and paste a video URL, e.g. https://vimeo.com/831343124.'
550
+ }
551
+ );
552
+ };
553
+ var Player = ({
554
+ status,
555
+ loading,
556
+ videoUrl,
557
+ previewImageUrl,
558
+ autoplay,
568
559
  renderer,
569
560
  showPreview,
570
- loading
561
+ onStatusChange,
562
+ onPreviewImageUrlChange
571
563
  }) => {
572
- const [playerStatus, setPlayerStatus] = useState2("initial");
573
- const elementRef = useRef2(null);
574
- const [previewImageUrl, setPreviewImageUrl] = useState2();
575
- const [isPending, setIsPending] = useState2(false);
576
- const loadPreviewOnceRef = useRef2(false);
577
- useEffect2(() => {
578
- setPlayerStatus(
579
- options.autoplay && renderer !== "canvas" ? "initialized" : "initial"
580
- );
581
- }, [options.autoplay, renderer]);
564
+ const [opacity, setOpacity] = useState2(0);
582
565
  useEffect2(() => {
583
- if (elementRef.current === null || playerStatus === "ready" || options.url === void 0) {
584
- return;
585
- }
586
- if (showPreview) {
587
- if (loadPreviewOnceRef.current) {
588
- return;
589
- }
590
- loadPreviewOnceRef.current = true;
591
- loadPreviewImage(elementRef.current, options.url).then(setPreviewImageUrl).catch(() => {
592
- });
593
- return;
566
+ if (autoplay && renderer !== "canvas" && status === "initial") {
567
+ onStatusChange("loading");
594
568
  }
595
- setPreviewImageUrl(void 0);
596
- }, [renderer, showPreview, options.url, playerStatus]);
597
- const optionsRef = useRef2(options);
598
- const stableOptions = useMemo(() => {
599
- if (shallowEqual(options, optionsRef.current) === false) {
600
- optionsRef.current = options;
601
- }
602
- return optionsRef.current;
603
- }, [options]);
569
+ }, [autoplay, status, renderer, onStatusChange]);
604
570
  useEffect2(() => {
605
- if (isPending) {
606
- setPlayerStatus(
607
- (status2) => status2 === "initial" ? "initialized" : status2
608
- );
571
+ if (renderer !== "canvas") {
572
+ warmConnections();
609
573
  }
610
- }, [isPending]);
611
- const toggleCreatePlayer = playerStatus !== "initial";
574
+ }, [renderer]);
612
575
  useEffect2(() => {
613
- if (elementRef.current === null) {
576
+ if (videoUrl === void 0) {
614
577
  return;
615
578
  }
616
- if (toggleCreatePlayer === false) {
579
+ if (showPreview === false) {
580
+ onPreviewImageUrlChange(void 0);
617
581
  return;
618
582
  }
619
- return createPlayer(elementRef.current, stableOptions, { loading }, () => {
620
- setPlayerStatus("ready");
621
- });
622
- }, [stableOptions, toggleCreatePlayer, loading]);
623
- const start = useCallback(() => {
624
- setIsPending(true);
625
- }, []);
626
- const status = isPending ? "initialized" : playerStatus;
627
- return { previewImageUrl, status, start, elementRef };
583
+ if (previewImageUrl === void 0) {
584
+ loadPreviewImageUrl(videoUrl).then(onPreviewImageUrlChange).catch(() => {
585
+ console.error(`Could not load preview image for ${videoUrl}`);
586
+ });
587
+ }
588
+ }, [onPreviewImageUrlChange, showPreview, videoUrl, previewImageUrl]);
589
+ if (renderer === "canvas" || status === "initial") {
590
+ return;
591
+ }
592
+ return /* @__PURE__ */ jsx26(
593
+ "iframe",
594
+ {
595
+ src: videoUrl,
596
+ loading,
597
+ allow: "accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture;",
598
+ allowFullScreen: true,
599
+ style: {
600
+ position: "absolute",
601
+ width: "100%",
602
+ height: "100%",
603
+ opacity,
604
+ transition: "opacity 1s",
605
+ border: "none"
606
+ },
607
+ onLoad: () => {
608
+ onStatusChange("ready");
609
+ setOpacity(1);
610
+ }
611
+ }
612
+ );
628
613
  };
614
+ var VimeoContext = createContext({
615
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
616
+ onInitPlayer: () => {
617
+ },
618
+ status: "initial"
619
+ });
629
620
  var Vimeo = forwardRef29(
630
621
  ({
631
622
  url,
@@ -655,33 +646,31 @@ var Vimeo = forwardRef29(
655
646
  children,
656
647
  ...rest
657
648
  }, ref) => {
649
+ const [status, setStatus] = useState2("initial");
650
+ const [previewImageUrl, setPreviewImageUrl] = useState2();
658
651
  const { renderer } = useContext3(ReactSdkContext3);
659
- const { previewImageUrl, status, start, elementRef } = useVimeo({
660
- renderer,
661
- showPreview,
662
- loading,
663
- options: {
664
- url,
665
- autoplay,
666
- autopause,
667
- keyboard,
668
- loop,
669
- muted,
670
- pip,
671
- playsinline,
672
- quality,
673
- responsive,
674
- speed,
675
- transparent,
676
- portrait: showPortrait,
677
- byline: showByline,
678
- title: showTitle,
679
- color: controlsColor,
680
- controls: showControls,
681
- interactive_params: interactiveParams,
682
- background: backgroundMode,
683
- dnt: doNotTrack
684
- }
652
+ const videoUrl = getVideoUrl({
653
+ url,
654
+ autoplay,
655
+ autopause,
656
+ backgroundMode,
657
+ showControls,
658
+ controlsColor,
659
+ doNotTrack,
660
+ interactiveParams,
661
+ keyboard,
662
+ loop,
663
+ muted,
664
+ pip,
665
+ playsinline,
666
+ quality,
667
+ responsive,
668
+ speed,
669
+ texttrack,
670
+ showTitle,
671
+ transparent,
672
+ showPortrait,
673
+ autopip
685
674
  });
686
675
  return /* @__PURE__ */ jsx26(
687
676
  VimeoContext.Provider,
@@ -691,7 +680,7 @@ var Vimeo = forwardRef29(
691
680
  previewImageUrl,
692
681
  onInitPlayer() {
693
682
  if (renderer !== "canvas") {
694
- start();
683
+ setStatus("loading");
695
684
  }
696
685
  }
697
686
  },
@@ -700,17 +689,27 @@ var Vimeo = forwardRef29(
700
689
  {
701
690
  ...rest,
702
691
  ref: (value) => {
703
- elementRef.current = value;
704
692
  if (ref !== null) {
705
693
  typeof ref === "function" ? ref(value) : ref.current = value;
706
694
  }
707
695
  },
708
- onPointerOver: () => {
709
- if (renderer !== "canvas") {
710
- warmConnections();
711
- }
712
- },
713
- children: url === void 0 ? /* @__PURE__ */ jsx26(EmptyState, {}) : children
696
+ children: videoUrl === void 0 ? /* @__PURE__ */ jsx26(EmptyState, {}) : /* @__PURE__ */ jsxs(Fragment2, { children: [
697
+ children,
698
+ /* @__PURE__ */ jsx26(
699
+ Player,
700
+ {
701
+ autoplay,
702
+ videoUrl,
703
+ previewImageUrl,
704
+ loading,
705
+ showPreview,
706
+ renderer,
707
+ status,
708
+ onStatusChange: setStatus,
709
+ onPreviewImageUrlChange: setPreviewImageUrl
710
+ }
711
+ )
712
+ ] })
714
713
  }
715
714
  )
716
715
  }
@@ -718,28 +717,6 @@ var Vimeo = forwardRef29(
718
717
  }
719
718
  );
720
719
  Vimeo.displayName = "Vimeo";
721
- var EmptyState = () => {
722
- return /* @__PURE__ */ jsx26(
723
- "div",
724
- {
725
- style: {
726
- display: "flex",
727
- width: "100%",
728
- height: "100%",
729
- alignItems: "center",
730
- justifyContent: "center",
731
- fontSize: "1.2em"
732
- },
733
- children: 'Open the "Settings" panel and paste a video URL, e.g. https://vimeo.com/831343124.'
734
- }
735
- );
736
- };
737
- var VimeoContext = createContext({
738
- // eslint-disable-next-line @typescript-eslint/no-empty-function
739
- onInitPlayer: () => {
740
- },
741
- status: "initial"
742
- });
743
720
 
744
721
  // src/vimeo-preview-image.tsx
745
722
  import {
@@ -771,7 +748,7 @@ var VimeoPlayButton = forwardRef31(
771
748
  (props, ref) => {
772
749
  const vimeoContext = useContext5(VimeoContext);
773
750
  if (vimeoContext.status !== "initial") {
774
- return null;
751
+ return;
775
752
  }
776
753
  return /* @__PURE__ */ jsx28(Button, { ...props, onClick: vimeoContext.onInitPlayer, ref });
777
754
  }
@@ -787,8 +764,8 @@ import { jsx as jsx29 } from "react/jsx-runtime";
787
764
  var VimeoSpinner = forwardRef32(
788
765
  (props, ref) => {
789
766
  const vimeoContext = useContext6(VimeoContext);
790
- if (vimeoContext.status !== "initialized") {
791
- return null;
767
+ if (vimeoContext.status !== "loading") {
768
+ return;
792
769
  }
793
770
  return /* @__PURE__ */ jsx29("div", { ...props, ref });
794
771
  }
package/lib/metas.js CHANGED
@@ -57,8 +57,7 @@ var propsMeta = {
57
57
  code: {
58
58
  required: true,
59
59
  control: "code",
60
- type: "string",
61
- rows: 10
60
+ type: "string"
62
61
  }
63
62
  },
64
63
  initialProps: ["clientOnly", "executeScriptOnCanvas"]
package/lib/props.js CHANGED
@@ -39,8 +39,7 @@ var propsMeta3 = {
39
39
  code: {
40
40
  required: true,
41
41
  control: "code",
42
- type: "string",
43
- rows: 10
42
+ type: "string"
44
43
  }
45
44
  },
46
45
  initialProps: ["clientOnly", "executeScriptOnCanvas"]
@@ -1,5 +1,4 @@
1
1
  import { type ComponentProps } from "react";
2
- declare const defaultTag = "div";
3
2
  type VimeoPlayerOptions = {
4
3
  background?: boolean;
5
4
  color?: string;
@@ -42,7 +41,6 @@ type VimeoPlayerOptions = {
42
41
  /** Whether the responsive player and transparent background are enabled. */
43
42
  transparent?: boolean;
44
43
  };
45
- type PlayerStatus = "initial" | "initialized" | "ready";
46
44
  export type VimeoOptions = Omit<VimeoPlayerOptions, "dnt" | "interactive_params" | "background" | "controls" | "color" | "byline" | "title" | "portrait"> & {
47
45
  /** Not a Vimeo attribute: Whether the preview image should be loaded from Vimeo API. Ideally don't use it, because it will show up with some delay and will make your project feel slower. */
48
46
  showPreview?: boolean;
@@ -65,11 +63,13 @@ export type VimeoOptions = Omit<VimeoPlayerOptions, "dnt" | "interactive_params"
65
63
  /** Whether to display the video owner's portrait. Only works if either title or byline are also enabled */
66
64
  showPortrait?: VimeoPlayerOptions["portrait"];
67
65
  };
68
- type Props = Omit<ComponentProps<typeof defaultTag>, keyof VimeoOptions> & VimeoOptions;
69
- export declare const Vimeo: import("react").ForwardRefExoticComponent<Omit<Props, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
66
+ type PlayerStatus = "initial" | "loading" | "ready";
70
67
  export declare const VimeoContext: import("react").Context<{
71
68
  previewImageUrl?: URL | undefined;
72
69
  onInitPlayer: () => void;
73
70
  status: PlayerStatus;
74
71
  }>;
72
+ declare const defaultTag = "div";
73
+ type Props = Omit<ComponentProps<typeof defaultTag>, keyof VimeoOptions> & VimeoOptions;
74
+ export declare const Vimeo: import("react").ForwardRefExoticComponent<Omit<Props, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
75
75
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webstudio-is/sdk-components-react",
3
- "version": "0.144.0",
3
+ "version": "0.144.1-710b1d2.0",
4
4
  "description": "Webstudio default library for react",
5
5
  "author": "Webstudio <github@webstudio.is>",
6
6
  "homepage": "https://webstudio.is",
@@ -39,13 +39,14 @@
39
39
  "dependencies": {
40
40
  "@react-aria/utils": "^3.21.0",
41
41
  "colord": "^2.9.3",
42
- "shallow-equal": "^3.1.0",
43
- "@webstudio-is/icons": "0.144.0",
44
- "@webstudio-is/image": "0.144.0",
45
- "@webstudio-is/react-sdk": "0.144.0"
42
+ "@webstudio-is/icons": "0.144.1-710b1d2.0",
43
+ "@webstudio-is/image": "0.144.1-710b1d2.0",
44
+ "@webstudio-is/react-sdk": "0.144.1-710b1d2.0"
46
45
  },
47
46
  "devDependencies": {
48
47
  "@jest/globals": "^29.7.0",
48
+ "@storybook/addon-essentials": "^7.4.0",
49
+ "@storybook/addon-links": "^7.4.0",
49
50
  "@storybook/react": "^7.4.0",
50
51
  "@testing-library/jest-dom": "^6.4.2",
51
52
  "@testing-library/react": "^14.2.2",
@@ -55,10 +56,10 @@
55
56
  "react": "^18.2.0",
56
57
  "react-dom": "^18.2.0",
57
58
  "typescript": "5.2.2",
58
- "@webstudio-is/generate-arg-types": "0.144.0",
59
- "@webstudio-is/jest-config": "1.0.7",
60
- "@webstudio-is/tsconfig": "1.0.7",
61
- "@webstudio-is/storybook-config": "0.0.0"
59
+ "@webstudio-is/generate-arg-types": "0.144.1-710b1d2.0",
60
+ "@webstudio-is/jest-config": "1.0.8-710b1d2.0",
61
+ "@webstudio-is/storybook-config": "0.0.1-710b1d2.0",
62
+ "@webstudio-is/tsconfig": "1.0.8-710b1d2.0"
62
63
  },
63
64
  "scripts": {
64
65
  "dev": "rm -rf lib && esbuild 'src/**/*.ts' 'src/**/*.tsx' --outdir=lib --watch",