瀏覽代碼

feat: select the export bcg image and bcg color from appState

Arnošt Pleskot 2 年之前
父節點
當前提交
f57cd7e2d5

+ 1 - 0
package.json

@@ -22,6 +22,7 @@
     "@braintree/sanitize-url": "6.0.2",
     "@excalidraw/random-username": "1.0.0",
     "@radix-ui/react-popover": "1.0.3",
+    "@radix-ui/react-select": "1.2.2",
     "@radix-ui/react-tabs": "1.0.2",
     "@sentry/browser": "6.2.5",
     "@sentry/integrations": "6.2.5",

+ 0 - 0
public/backgrounds/04.svg → public/backgrounds/bricks.svg


+ 0 - 0
public/backgrounds/01.svg → public/backgrounds/bubbles.svg


+ 0 - 0
public/backgrounds/02.svg → public/backgrounds/bubbles2.svg


+ 0 - 0
public/backgrounds/03.svg → public/backgrounds/lines.svg


+ 0 - 0
public/backgrounds/05.svg → public/backgrounds/lines2.svg


+ 30 - 1
src/actions/actionExport.tsx

@@ -11,7 +11,13 @@ import { KEYS } from "../keys";
 import { register } from "./register";
 import { CheckboxItem } from "../components/CheckboxItem";
 import { getExportSize } from "../scene/export";
-import { DEFAULT_EXPORT_PADDING, EXPORT_SCALES, THEME } from "../constants";
+import {
+  DEFAULT_EXPORT_BACKGROUND_IMAGE,
+  DEFAULT_EXPORT_PADDING,
+  EXPORT_BACKGROUND_IMAGES,
+  EXPORT_SCALES,
+  THEME,
+} from "../constants";
 import { getSelectedElements, isSomeElementSelected } from "../scene";
 import { getNonDeletedElements } from "../element";
 import { isImageFileHandle } from "../data/blob";
@@ -19,6 +25,7 @@ import { nativeFileSystemSupported } from "../data/filesystem";
 import { Theme } from "../element/types";
 
 import "../components/ToolIcon.scss";
+import Select from "../components/Select";
 
 export const actionChangeProjectName = register({
   name: "changeProjectName",
@@ -107,6 +114,28 @@ export const actionChangeExportBackground = register({
   ),
 });
 
+export const actionChangeExportBackgroundImage = register({
+  name: "changeExportBackgroundImage",
+  trackEvent: { category: "export", action: "toggleBackgroundImage" },
+  perform: (_elements, appState, value) => {
+    return {
+      appState: { ...appState, exportBackgroundImage: value },
+      commitToHistory: false,
+    };
+  },
+  PanelComponent: ({ updateData }) => (
+    <Select
+      items={EXPORT_BACKGROUND_IMAGES}
+      ariaLabel={t("imageExportDialog.label.backgroundImage")}
+      placeholder={t("imageExportDialog.label.backgroundImage")}
+      value={DEFAULT_EXPORT_BACKGROUND_IMAGE}
+      onChange={(value) => {
+        updateData(value);
+      }}
+    />
+  ),
+});
+
 export const actionChangeExportEmbedScene = register({
   name: "changeExportEmbedScene",
   trackEvent: { category: "export", action: "embedScene" },

+ 2 - 1
src/actions/types.ts

@@ -123,7 +123,8 @@ export type ActionName =
   | "setFrameAsActiveTool"
   | "setEmbeddableAsActiveTool"
   | "createContainerFromText"
-  | "wrapTextInContainer";
+  | "wrapTextInContainer"
+  | "changeExportBackgroundImage";
 
 export type PanelComponentProps = {
   elements: readonly ExcalidrawElement[];

+ 3 - 0
src/appState.ts

@@ -1,6 +1,7 @@
 import { COLOR_PALETTE } from "./colors";
 import {
   DEFAULT_ELEMENT_PROPS,
+  DEFAULT_EXPORT_BACKGROUND_IMAGE,
   DEFAULT_FONT_FAMILY,
   DEFAULT_FONT_SIZE,
   DEFAULT_TEXT_ALIGN,
@@ -99,6 +100,7 @@ export const getDefaultAppState = (): Omit<
     pendingImageElementId: null,
     showHyperlinkPopup: false,
     selectedLinearElement: null,
+    exportBackgroundImage: DEFAULT_EXPORT_BACKGROUND_IMAGE,
   };
 };
 
@@ -206,6 +208,7 @@ const APP_STATE_STORAGE_CONF = (<
   pendingImageElementId: { browser: false, export: false, server: false },
   showHyperlinkPopup: { browser: false, export: false, server: false },
   selectedLinearElement: { browser: true, export: false, server: false },
+  exportBackgroundImage: { browser: true, export: false, server: false },
 });
 
 const _clearAppStateForStorage = <

+ 22 - 0
src/components/ImageExportDialog.tsx

@@ -9,6 +9,7 @@ import {
   actionChangeExportEmbedScene,
   actionChangeExportScale,
   actionChangeProjectName,
+  actionChangeExportBackgroundImage,
 } from "../actions/actionExport";
 import { probablySupportsClipboardBlob } from "../clipboard";
 import {
@@ -16,6 +17,8 @@ import {
   EXPORT_IMAGE_TYPES,
   isFirefox,
   EXPORT_SCALES,
+  EXPORT_BACKGROUND_IMAGES,
+  DEFAULT_EXPORT_BACKGROUND_IMAGE,
 } from "../constants";
 
 import { canvasToBlob } from "../data/blob";
@@ -34,6 +37,7 @@ import { Tooltip } from "./Tooltip";
 import "./ImageExportDialog.scss";
 import { useAppProps } from "./App";
 import { FilledButton } from "./FilledButton";
+import Select from "./Select";
 
 const supportsContextFilters =
   "filter" in document.createElement("canvas").getContext("2d")!;
@@ -74,6 +78,10 @@ const ImageExportModal = ({
   const [exportWithBackground, setExportWithBackground] = useState(
     appState.exportBackground,
   );
+  const [exportBackgroundImage, setExportBackgroundImage] = useState<string>(
+    DEFAULT_EXPORT_BACKGROUND_IMAGE,
+  );
+
   const [exportDarkMode, setExportDarkMode] = useState(
     appState.exportWithDarkMode,
   );
@@ -169,6 +177,20 @@ const ImageExportModal = ({
           label={t("imageExportDialog.label.withBackground")}
           name="exportBackgroundSwitch"
         >
+          <Select
+            items={EXPORT_BACKGROUND_IMAGES}
+            ariaLabel={t("imageExportDialog.label.backgroundImage")}
+            placeholder={t("imageExportDialog.label.backgroundImage")}
+            value={exportBackgroundImage}
+            onChange={(value) => {
+              setExportBackgroundImage(value);
+              actionManager.executeAction(
+                actionChangeExportBackgroundImage,
+                "ui",
+                value,
+              );
+            }}
+          />
           <Switch
             name="exportBackgroundSwitch"
             checked={exportWithBackground}

+ 69 - 0
src/components/Select.scss

@@ -0,0 +1,69 @@
+.Select {
+  &__trigger {
+    display: inline-flex;
+    align-items: center;
+    justify-content: center;
+    padding: 0 15px;
+    line-height: 1;
+    gap: 5px;
+    background: transparent;
+    border: none;
+    font-weight: 600;
+    font-size: 0.8rem;
+    color: var(--text-primary-color);
+  }
+
+  &__trigger-icon {
+    width: 15px;
+    height: 15px;
+  }
+
+  &__content {
+    overflow: hidden;
+    box-shadow: var(--shadow-island);
+    border-radius: var(--border-radius-md);
+    padding: calc(var(--padding) * var(--space-factor));
+    background-color: var(--input-bg-color);
+    z-index: 1;
+  }
+
+  &__viewport {
+    padding: 0.5rem;
+  }
+
+  &__item {
+    font-size: 0.8rem;
+    line-height: 1;
+    border-radius: var(--border-radius-md);
+    display: flex;
+    align-items: center;
+    padding: 0.5rem 1rem;
+    position: relative;
+    user-select: none;
+    font-weight: 600;
+    color: var(--text-primary-color);
+
+    &[data-highlighted] {
+      outline: none;
+      background-color: var(--button-hover-bg);
+    }
+
+    &[data-state="checked"] {
+      background-color: var(--color-primary);
+      color: var(--input-bg-color);
+    }
+
+    &[data-highlighted][data-state="checked"] {
+      background-color: var(--color-primary-darker);
+    }
+  }
+
+  &__scroll-button {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    height: 25px;
+    background-color: white;
+    cursor: default;
+  }
+}

+ 77 - 0
src/components/Select.tsx

@@ -0,0 +1,77 @@
+import React, { forwardRef } from "react";
+import clxs from "clsx";
+import * as RadixSelect from "@radix-ui/react-select";
+import "./Select.scss";
+import { tablerChevronDownIcon, tablerChevronUpIcon } from "./icons";
+
+type SelectItems = Record<string, string>;
+
+export type SelectProps = {
+  items: SelectItems;
+  value: keyof SelectItems;
+  onChange: (value: keyof SelectItems) => void;
+  placeholder?: string;
+  ariaLabel?: string;
+};
+
+const Select = ({
+  items,
+  value,
+  onChange,
+  placeholder,
+  ariaLabel,
+}: SelectProps) => (
+  <RadixSelect.Root value={value} onValueChange={onChange}>
+    <RadixSelect.Trigger
+      className="Select__trigger"
+      aria-label={ariaLabel ?? placeholder}
+    >
+      {placeholder && <RadixSelect.Value placeholder={placeholder} />}
+      <RadixSelect.Icon className="Select__trigger-icon">
+        {tablerChevronDownIcon}
+      </RadixSelect.Icon>
+    </RadixSelect.Trigger>
+    <RadixSelect.Content
+      className="Select__content"
+      position="popper"
+      align="center"
+    >
+      <RadixSelect.ScrollUpButton className="Select__scroll-button">
+        {tablerChevronUpIcon}
+      </RadixSelect.ScrollUpButton>
+
+      <RadixSelect.Viewport className="Select__viewport">
+        {Object.entries(items).map(([itemValue, itemLabel]) => (
+          <SelectItem value={itemValue} key={itemValue}>
+            {itemLabel}
+          </SelectItem>
+        ))}
+      </RadixSelect.Viewport>
+
+      <RadixSelect.ScrollDownButton className="Select__scroll-button">
+        {tablerChevronDownIcon}
+      </RadixSelect.ScrollDownButton>
+    </RadixSelect.Content>
+  </RadixSelect.Root>
+);
+
+type SelectItemProps = React.ComponentProps<typeof RadixSelect.Item>;
+
+const SelectItem = forwardRef(
+  (
+    { children, className, ...props }: SelectItemProps,
+    forwardedRef: React.ForwardedRef<HTMLDivElement>,
+  ) => {
+    return (
+      <RadixSelect.Item
+        className={clxs("Select__item", className)}
+        {...props}
+        ref={forwardedRef}
+      >
+        <RadixSelect.ItemText>{children}</RadixSelect.ItemText>
+      </RadixSelect.Item>
+    );
+  },
+);
+
+export default Select;

+ 16 - 0
src/components/icons.tsx

@@ -1655,3 +1655,19 @@ export const frameToolIcon = createIcon(
   </g>,
   tablerIconProps,
 );
+
+export const tablerChevronDownIcon = createIcon(
+  <>
+    <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
+    <path d="M6 9l6 6l6 -6"></path>
+  </>,
+  tablerIconProps,
+);
+
+export const tablerChevronUpIcon = createIcon(
+  <>
+    <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
+    <path d="M6 15l6 -6l6 6"></path>
+  </>,
+  tablerIconProps,
+);

+ 12 - 0
src/constants.ts

@@ -316,3 +316,15 @@ export const DEFAULT_SIDEBAR = {
 } as const;
 
 export const LIBRARY_DISABLED_TYPES = new Set(["embeddable", "image"] as const);
+
+export const EXPORT_BACKGROUND_IMAGES = {
+  "/backgrounds/bubbles.svg": "bubbles",
+  "/backgrounds/bubbles2.svg": "bubbles 2",
+  "/backgrounds/bricks.svg": "bricks",
+  "/backgrounds/lines.svg": "lines",
+  "/backgrounds/lines2.svg": "lines 2",
+} as const;
+
+export const DEFAULT_EXPORT_BACKGROUND_IMAGE = Object.keys(
+  EXPORT_BACKGROUND_IMAGES,
+)[0];

+ 1 - 0
src/locales/en.json

@@ -375,6 +375,7 @@
     "header": "Export image",
     "label": {
       "withBackground": "Background",
+      "backgroundImage": "Background image",
       "onlySelected": "Only selected",
       "darkMode": "Dark mode",
       "embedScene": "Embed scene",

+ 0 - 95
src/renderer/renderScene.ts

@@ -394,100 +394,6 @@ const getNormalizedCanvasDimensions = (
   return [canvas.width / scale, canvas.height / scale];
 };
 
-const addExportBackground = (
-  canvas: HTMLCanvasElement,
-  normalizedCanvasWidth: number,
-  normalizedCanvasHeight: number,
-  svgUrl: string,
-  rectangleColor: string,
-): void => {
-  const ctx = canvas.getContext("2d") as CanvasRenderingContext2D;
-
-  // Create a new image object
-  const img = new Image();
-
-  // When the image has loaded
-  img.onload = (): void => {
-    // Draw the image onto the canvas
-    ctx.drawImage(img, 0, 0, normalizedCanvasWidth, canvas.height);
-
-    // Create shadow similar to the CSS box-shadow
-    const shadows = [
-      {
-        offsetX: 0,
-        offsetY: 0.7698959708213806,
-        blur: 1.4945039749145508,
-        alpha: 0.02,
-      },
-      {
-        offsetX: 0,
-        offsetY: 1.1299999952316284,
-        blur: 4.1321120262146,
-        alpha: 0.04,
-      },
-      {
-        offsetX: 0,
-        offsetY: 4.130000114440918,
-        blur: 9.94853401184082,
-        alpha: 0.05,
-      },
-      { offsetX: 0, offsetY: 13, blur: 33, alpha: 0.07 },
-    ];
-
-    shadows.forEach((shadow, index): void => {
-      const MARGIN = 24;
-      const BORDER_RADIUS = 12;
-
-      ctx.shadowColor = `rgba(0, 0, 0, ${shadow.alpha})`;
-      ctx.shadowBlur = shadow.blur;
-      ctx.shadowOffsetX = shadow.offsetX;
-      ctx.shadowOffsetY = shadow.offsetY;
-
-      // Define path for rectangle
-      ctx.beginPath();
-      ctx.moveTo(MARGIN, MARGIN);
-      ctx.lineTo(normalizedCanvasWidth - MARGIN, MARGIN);
-      ctx.quadraticCurveTo(
-        normalizedCanvasWidth,
-        MARGIN,
-        normalizedCanvasWidth,
-        MARGIN + BORDER_RADIUS,
-      );
-      ctx.lineTo(normalizedCanvasWidth, normalizedCanvasHeight - MARGIN);
-      ctx.quadraticCurveTo(
-        normalizedCanvasWidth,
-        normalizedCanvasHeight,
-        normalizedCanvasWidth - MARGIN,
-        normalizedCanvasHeight,
-      );
-      ctx.lineTo(MARGIN, normalizedCanvasHeight);
-      ctx.quadraticCurveTo(
-        0,
-        normalizedCanvasHeight,
-        0,
-        normalizedCanvasHeight - MARGIN,
-      );
-      ctx.lineTo(0, MARGIN + BORDER_RADIUS);
-      ctx.quadraticCurveTo(0, MARGIN, MARGIN, MARGIN);
-      ctx.closePath();
-
-      if (index === shadows.length - 1) {
-        ctx.fillStyle = rectangleColor;
-        ctx.fill();
-      }
-    });
-
-    // Reset shadow properties for future drawings
-    ctx.shadowColor = "transparent";
-    ctx.shadowBlur = 0;
-    ctx.shadowOffsetX = 0;
-    ctx.shadowOffsetY = 0;
-  };
-
-  // Start loading the image
-  img.src = svgUrl;
-};
-
 const bootstrapCanvas = ({
   canvas,
   scale,
@@ -535,7 +441,6 @@ const bootstrapCanvas = ({
   return context;
 };
 
-<<<<<<< HEAD
 const _renderInteractiveScene = ({
   canvas,
   elements,

+ 1 - 0
src/scene/export.ts

@@ -73,6 +73,7 @@ export const exportToCanvas = async (
       imageCache,
       renderGrid: false,
       isExporting: true,
+      exportBackgroundImage: appState.exportBackgroundImage,
     },
   });
 

+ 1 - 0
src/scene/types.ts

@@ -28,6 +28,7 @@ export type InteractiveCanvasRenderConfig = {
   remotePointerUserStates: { [id: string]: string };
   remotePointerUsernames: { [id: string]: string };
   remotePointerButton?: { [id: string]: string | undefined };
+  exportBackgroundImage?: string;
   selectionColor?: string;
   // extra options passed to the renderer
   // ---------------------------------------------------------------------------

+ 1 - 0
src/types.ts

@@ -287,6 +287,7 @@ export type AppState = {
   pendingImageElementId: ExcalidrawImageElement["id"] | null;
   showHyperlinkPopup: false | "info" | "editor";
   selectedLinearElement: LinearElementEditor | null;
+  exportBackgroundImage: string;
 };
 
 export type UIAppState = Omit<

+ 255 - 0
yarn.lock

@@ -1761,6 +1761,13 @@
   resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-0.7.3.tgz#d274116678ffae87f6b60e90f88cc4083eefab86"
   integrity sha512-buc8BXHmG9l82+OQXOFU3Kr2XQx9ys01U/Q9HMIrZ300iLc8HLMgh7dcCqgYzAzf4BkoQvDcXf5Y+CuEZ5JBYg==
 
+"@floating-ui/core@^1.4.0":
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.4.0.tgz#bc918b49145115c49cc15882c8f29af03435ff50"
+  integrity sha512-x5Ly1Eiyqt9aR38XzhraoWxgtQtvy3mVChWMZIr49XFyvIhNuqUxZKXBRoI5WiMRaaAZezCauJaEISu3z5y8sg==
+  dependencies:
+    "@floating-ui/utils" "^0.1.0"
+
 "@floating-ui/dom@^0.5.3":
   version "0.5.4"
   resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-0.5.4.tgz#4eae73f78bcd4bd553ae2ade30e6f1f9c73fe3f1"
@@ -1768,6 +1775,14 @@
   dependencies:
     "@floating-ui/core" "^0.7.3"
 
+"@floating-ui/dom@^1.3.0":
+  version "1.5.0"
+  resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.5.0.tgz#a9d7784c1567be8eb3097c61b09b9af8043b24c9"
+  integrity sha512-9jPin5dTlcEN+nXzBRhdreCzlJBIYWeMXpJJ5VnO1l9dLcP7uQNPbmwmIoHpHpH6GPYMYtQA7GfkvsSj/CQPwg==
+  dependencies:
+    "@floating-ui/core" "^1.4.0"
+    "@floating-ui/utils" "^0.1.0"
+
 "@floating-ui/[email protected]":
   version "0.7.2"
   resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-0.7.2.tgz#0bf4ceccb777a140fc535c87eb5d6241c8e89864"
@@ -1776,6 +1791,18 @@
     "@floating-ui/dom" "^0.5.3"
     use-isomorphic-layout-effect "^1.1.1"
 
+"@floating-ui/react-dom@^2.0.0":
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-2.0.1.tgz#7972a4fc488a8c746cded3cfe603b6057c308a91"
+  integrity sha512-rZtAmSht4Lry6gdhAJDrCp/6rKN7++JnL1/Anbr/DdeyYXQPxvg/ivrbYvJulbRf4vL8b212suwMM2lxbv+RQA==
+  dependencies:
+    "@floating-ui/dom" "^1.3.0"
+
+"@floating-ui/utils@^0.1.0":
+  version "0.1.0"
+  resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.1.0.tgz#3acc29138c694d017dc09f1f312c5ffc36e492da"
+  integrity sha512-ZSlli/beGZdvoqT3/Y9oOW79XSEpBfxt8UY6vjyWJW0B8d/M+MKlkQ3kBzLKDXaSsB84IVj6QntQfHLzesB4mA==
+
 "@grpc/grpc-js@^1.0.0":
   version "1.8.13"
   resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.8.13.tgz#e775685962909b76f8d4b813833c3d123867165b"
@@ -1979,6 +2006,13 @@
   resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570"
   integrity sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==
 
+"@radix-ui/[email protected]":
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/@radix-ui/number/-/number-1.0.1.tgz#644161a3557f46ed38a042acf4a770e826021674"
+  integrity sha512-T5gIdVO2mmPW3NNhjNgEP3cqMXjXL9UbO0BzWcXfvdBs+BohbQxvd/K5hSVKmn9/lbTdsQVKbUcP5WLCwvUbBg==
+  dependencies:
+    "@babel/runtime" "^7.13.10"
+
 "@radix-ui/[email protected]":
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.0.0.tgz#e1d8ef30b10ea10e69c76e896f608d9276352253"
@@ -1986,6 +2020,13 @@
   dependencies:
     "@babel/runtime" "^7.13.10"
 
+"@radix-ui/[email protected]":
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.0.1.tgz#e46f9958b35d10e9f6dc71c497305c22e3e55dbd"
+  integrity sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw==
+  dependencies:
+    "@babel/runtime" "^7.13.10"
+
 "@radix-ui/[email protected]":
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-1.0.1.tgz#5246adf79e97f89e819af68da51ddcf349ecf1c4"
@@ -1994,6 +2035,14 @@
     "@babel/runtime" "^7.13.10"
     "@radix-ui/react-primitive" "1.0.1"
 
+"@radix-ui/[email protected]":
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-1.0.3.tgz#c24f7968996ed934d57fe6cde5d6ec7266e1d25d"
+  integrity sha512-wSP+pHsB/jQRaL6voubsQ/ZlrGBHHrOjmBnr19hxYgtS0WvAFwZhK2WP/YY5yF9uKECCEEDGxuLxq1NBK51wFA==
+  dependencies:
+    "@babel/runtime" "^7.13.10"
+    "@radix-ui/react-primitive" "1.0.3"
+
 "@radix-ui/[email protected]":
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/@radix-ui/react-collection/-/react-collection-1.0.1.tgz#259506f97c6703b36291826768d3c1337edd1de5"
@@ -2005,6 +2054,17 @@
     "@radix-ui/react-primitive" "1.0.1"
     "@radix-ui/react-slot" "1.0.1"
 
+"@radix-ui/[email protected]":
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-collection/-/react-collection-1.0.3.tgz#9595a66e09026187524a36c6e7e9c7d286469159"
+  integrity sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA==
+  dependencies:
+    "@babel/runtime" "^7.13.10"
+    "@radix-ui/react-compose-refs" "1.0.1"
+    "@radix-ui/react-context" "1.0.1"
+    "@radix-ui/react-primitive" "1.0.3"
+    "@radix-ui/react-slot" "1.0.2"
+
 "@radix-ui/[email protected]":
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.0.tgz#37595b1f16ec7f228d698590e78eeed18ff218ae"
@@ -2012,6 +2072,13 @@
   dependencies:
     "@babel/runtime" "^7.13.10"
 
+"@radix-ui/[email protected]":
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz#7ed868b66946aa6030e580b1ffca386dd4d21989"
+  integrity sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==
+  dependencies:
+    "@babel/runtime" "^7.13.10"
+
 "@radix-ui/[email protected]":
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.0.0.tgz#f38e30c5859a9fb5e9aa9a9da452ee3ed9e0aee0"
@@ -2019,6 +2086,13 @@
   dependencies:
     "@babel/runtime" "^7.13.10"
 
+"@radix-ui/[email protected]":
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.0.1.tgz#fe46e67c96b240de59187dcb7a1a50ce3e2ec00c"
+  integrity sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg==
+  dependencies:
+    "@babel/runtime" "^7.13.10"
+
 "@radix-ui/[email protected]":
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/@radix-ui/react-direction/-/react-direction-1.0.0.tgz#a2e0b552352459ecf96342c79949dd833c1e6e45"
@@ -2026,6 +2100,13 @@
   dependencies:
     "@babel/runtime" "^7.13.10"
 
+"@radix-ui/[email protected]":
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-direction/-/react-direction-1.0.1.tgz#9cb61bf2ccf568f3421422d182637b7f47596c9b"
+  integrity sha512-RXcvnXgyvYvBEOhCBuddKecVkoMiI10Jcm5cTI7abJRAHYfFxeu+FBQs/DvdxSYucxR5mna0dNsL6QFlds5TMA==
+  dependencies:
+    "@babel/runtime" "^7.13.10"
+
 "@radix-ui/[email protected]":
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.2.tgz#f04d1061bddf00b1ca304148516b9ddc62e45fb2"
@@ -2038,6 +2119,18 @@
     "@radix-ui/react-use-callback-ref" "1.0.0"
     "@radix-ui/react-use-escape-keydown" "1.0.2"
 
+"@radix-ui/[email protected]":
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.4.tgz#883a48f5f938fa679427aa17fcba70c5494c6978"
+  integrity sha512-7UpBa/RKMoHJYjie1gkF1DlK8l1fdU/VKDpoS3rCCo8YBJR294GwcEHyxHw72yvphJ7ld0AXEcSLAzY2F/WyCg==
+  dependencies:
+    "@babel/runtime" "^7.13.10"
+    "@radix-ui/primitive" "1.0.1"
+    "@radix-ui/react-compose-refs" "1.0.1"
+    "@radix-ui/react-primitive" "1.0.3"
+    "@radix-ui/react-use-callback-ref" "1.0.1"
+    "@radix-ui/react-use-escape-keydown" "1.0.3"
+
 "@radix-ui/[email protected]":
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-1.0.0.tgz#339c1c69c41628c1a5e655f15f7020bf11aa01fa"
@@ -2045,6 +2138,13 @@
   dependencies:
     "@babel/runtime" "^7.13.10"
 
+"@radix-ui/[email protected]":
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-1.0.1.tgz#1ea7e32092216b946397866199d892f71f7f98ad"
+  integrity sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA==
+  dependencies:
+    "@babel/runtime" "^7.13.10"
+
 "@radix-ui/[email protected]":
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.1.tgz#faea8c25f537c5a5c38c50914b63722db0e7f951"
@@ -2055,6 +2155,16 @@
     "@radix-ui/react-primitive" "1.0.1"
     "@radix-ui/react-use-callback-ref" "1.0.0"
 
+"@radix-ui/[email protected]":
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.3.tgz#9c2e8d4ed1189a1d419ee61edd5c1828726472f9"
+  integrity sha512-upXdPfqI4islj2CslyfUBNlaJCPybbqRHAi1KER7Isel9Q2AtSJ0zRBZv8mWQiFXD2nyAJ4BhC3yXgZ6kMBSrQ==
+  dependencies:
+    "@babel/runtime" "^7.13.10"
+    "@radix-ui/react-compose-refs" "1.0.1"
+    "@radix-ui/react-primitive" "1.0.3"
+    "@radix-ui/react-use-callback-ref" "1.0.1"
+
 "@radix-ui/[email protected]":
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/@radix-ui/react-id/-/react-id-1.0.0.tgz#8d43224910741870a45a8c9d092f25887bb6d11e"
@@ -2063,6 +2173,14 @@
     "@babel/runtime" "^7.13.10"
     "@radix-ui/react-use-layout-effect" "1.0.0"
 
+"@radix-ui/[email protected]":
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-id/-/react-id-1.0.1.tgz#73cdc181f650e4df24f0b6a5b7aa426b912c88c0"
+  integrity sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ==
+  dependencies:
+    "@babel/runtime" "^7.13.10"
+    "@radix-ui/react-use-layout-effect" "1.0.1"
+
 "@radix-ui/[email protected]":
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/@radix-ui/react-popover/-/react-popover-1.0.3.tgz#65ae2ee1fca2d7fd750308549eb8e0857c6160fe"
@@ -2102,6 +2220,23 @@
     "@radix-ui/react-use-size" "1.0.0"
     "@radix-ui/rect" "1.0.0"
 
+"@radix-ui/[email protected]":
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-1.1.2.tgz#4c0b96fcd188dc1f334e02dba2d538973ad842e9"
+  integrity sha512-1CnGGfFi/bbqtJZZ0P/NQY20xdG3E0LALJaLUEoKwPLwl6PPPfbeiCqMVQnhoFRAxjJj4RpBRJzDmUgsex2tSg==
+  dependencies:
+    "@babel/runtime" "^7.13.10"
+    "@floating-ui/react-dom" "^2.0.0"
+    "@radix-ui/react-arrow" "1.0.3"
+    "@radix-ui/react-compose-refs" "1.0.1"
+    "@radix-ui/react-context" "1.0.1"
+    "@radix-ui/react-primitive" "1.0.3"
+    "@radix-ui/react-use-callback-ref" "1.0.1"
+    "@radix-ui/react-use-layout-effect" "1.0.1"
+    "@radix-ui/react-use-rect" "1.0.1"
+    "@radix-ui/react-use-size" "1.0.1"
+    "@radix-ui/rect" "1.0.1"
+
 "@radix-ui/[email protected]":
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.0.1.tgz#169c5a50719c2bb0079cf4c91a27aa6d37e5dd33"
@@ -2110,6 +2245,14 @@
     "@babel/runtime" "^7.13.10"
     "@radix-ui/react-primitive" "1.0.1"
 
+"@radix-ui/[email protected]":
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.0.3.tgz#ffb961244c8ed1b46f039e6c215a6c4d9989bda1"
+  integrity sha512-xLYZeHrWoPmA5mEKEfZZevoVRK/Q43GfzRXkWV6qawIWWK8t6ifIiLQdd7rmQ4Vk1bmI21XhqF9BN3jWf+phpA==
+  dependencies:
+    "@babel/runtime" "^7.13.10"
+    "@radix-ui/react-primitive" "1.0.3"
+
 "@radix-ui/[email protected]":
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.0.0.tgz#814fe46df11f9a468808a6010e3f3ca7e0b2e84a"
@@ -2127,6 +2270,14 @@
     "@babel/runtime" "^7.13.10"
     "@radix-ui/react-slot" "1.0.1"
 
+"@radix-ui/[email protected]":
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-1.0.3.tgz#d49ea0f3f0b2fe3ab1cb5667eb03e8b843b914d0"
+  integrity sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==
+  dependencies:
+    "@babel/runtime" "^7.13.10"
+    "@radix-ui/react-slot" "1.0.2"
+
 "@radix-ui/[email protected]":
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/@radix-ui/react-roving-focus/-/react-roving-focus-1.0.2.tgz#d8ac2e3b8006697bdfc2b0eb06bef7e15b6245de"
@@ -2143,6 +2294,34 @@
     "@radix-ui/react-use-callback-ref" "1.0.0"
     "@radix-ui/react-use-controllable-state" "1.0.0"
 
+"@radix-ui/[email protected]":
+  version "1.2.2"
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-select/-/react-select-1.2.2.tgz#caa981fa0d672cf3c1b2a5240135524e69b32181"
+  integrity sha512-zI7McXr8fNaSrUY9mZe4x/HC0jTLY9fWNhO1oLWYMQGDXuV4UCivIGTxwioSzO0ZCYX9iSLyWmAh/1TOmX3Cnw==
+  dependencies:
+    "@babel/runtime" "^7.13.10"
+    "@radix-ui/number" "1.0.1"
+    "@radix-ui/primitive" "1.0.1"
+    "@radix-ui/react-collection" "1.0.3"
+    "@radix-ui/react-compose-refs" "1.0.1"
+    "@radix-ui/react-context" "1.0.1"
+    "@radix-ui/react-direction" "1.0.1"
+    "@radix-ui/react-dismissable-layer" "1.0.4"
+    "@radix-ui/react-focus-guards" "1.0.1"
+    "@radix-ui/react-focus-scope" "1.0.3"
+    "@radix-ui/react-id" "1.0.1"
+    "@radix-ui/react-popper" "1.1.2"
+    "@radix-ui/react-portal" "1.0.3"
+    "@radix-ui/react-primitive" "1.0.3"
+    "@radix-ui/react-slot" "1.0.2"
+    "@radix-ui/react-use-callback-ref" "1.0.1"
+    "@radix-ui/react-use-controllable-state" "1.0.1"
+    "@radix-ui/react-use-layout-effect" "1.0.1"
+    "@radix-ui/react-use-previous" "1.0.1"
+    "@radix-ui/react-visually-hidden" "1.0.3"
+    aria-hidden "^1.1.1"
+    react-remove-scroll "2.5.5"
+
 "@radix-ui/[email protected]":
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.0.1.tgz#e7868c669c974d649070e9ecbec0b367ee0b4d81"
@@ -2151,6 +2330,14 @@
     "@babel/runtime" "^7.13.10"
     "@radix-ui/react-compose-refs" "1.0.0"
 
+"@radix-ui/[email protected]":
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.0.2.tgz#a9ff4423eade67f501ffb32ec22064bc9d3099ab"
+  integrity sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==
+  dependencies:
+    "@babel/runtime" "^7.13.10"
+    "@radix-ui/react-compose-refs" "1.0.1"
+
 "@radix-ui/[email protected]":
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/@radix-ui/react-tabs/-/react-tabs-1.0.2.tgz#8f5ec73ca41b151a413bdd6e00553408ff34ce07"
@@ -2173,6 +2360,13 @@
   dependencies:
     "@babel/runtime" "^7.13.10"
 
+"@radix-ui/[email protected]":
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.1.tgz#f4bb1f27f2023c984e6534317ebc411fc181107a"
+  integrity sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==
+  dependencies:
+    "@babel/runtime" "^7.13.10"
+
 "@radix-ui/[email protected]":
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.0.0.tgz#a64deaafbbc52d5d407afaa22d493d687c538b7f"
@@ -2181,6 +2375,14 @@
     "@babel/runtime" "^7.13.10"
     "@radix-ui/react-use-callback-ref" "1.0.0"
 
+"@radix-ui/[email protected]":
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.0.1.tgz#ecd2ced34e6330caf89a82854aa2f77e07440286"
+  integrity sha512-Svl5GY5FQeN758fWKrjM6Qb7asvXeiZltlT4U2gVfl8Gx5UAv2sMR0LWo8yhsIZh2oQ0eFdZ59aoOOMV7b47VA==
+  dependencies:
+    "@babel/runtime" "^7.13.10"
+    "@radix-ui/react-use-callback-ref" "1.0.1"
+
 "@radix-ui/[email protected]":
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.0.2.tgz#09ab6455ab240b4f0a61faf06d4e5132c4d639f6"
@@ -2189,6 +2391,14 @@
     "@babel/runtime" "^7.13.10"
     "@radix-ui/react-use-callback-ref" "1.0.0"
 
+"@radix-ui/[email protected]":
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.0.3.tgz#217b840c250541609c66f67ed7bab2b733620755"
+  integrity sha512-vyL82j40hcFicA+M4Ex7hVkB9vHgSse1ZWomAqV2Je3RleKGO5iM8KMOEtfoSB0PnIelMd2lATjTGMYqN5ylTg==
+  dependencies:
+    "@babel/runtime" "^7.13.10"
+    "@radix-ui/react-use-callback-ref" "1.0.1"
+
 "@radix-ui/[email protected]":
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.0.0.tgz#2fc19e97223a81de64cd3ba1dc42ceffd82374dc"
@@ -2196,6 +2406,20 @@
   dependencies:
     "@babel/runtime" "^7.13.10"
 
+"@radix-ui/[email protected]":
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.0.1.tgz#be8c7bc809b0c8934acf6657b577daf948a75399"
+  integrity sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ==
+  dependencies:
+    "@babel/runtime" "^7.13.10"
+
+"@radix-ui/[email protected]":
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-use-previous/-/react-use-previous-1.0.1.tgz#b595c087b07317a4f143696c6a01de43b0d0ec66"
+  integrity sha512-cV5La9DPwiQ7S0gf/0qiD6YgNqM5Fk97Kdrlc5yBcrF3jyEZQwm7vYFqMo4IfeHgJXsRaMvLABFtd0OVEmZhDw==
+  dependencies:
+    "@babel/runtime" "^7.13.10"
+
 "@radix-ui/[email protected]":
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/@radix-ui/react-use-rect/-/react-use-rect-1.0.0.tgz#b040cc88a4906b78696cd3a32b075ed5b1423b3e"
@@ -2204,6 +2428,14 @@
     "@babel/runtime" "^7.13.10"
     "@radix-ui/rect" "1.0.0"
 
+"@radix-ui/[email protected]":
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-use-rect/-/react-use-rect-1.0.1.tgz#fde50b3bb9fd08f4a1cd204572e5943c244fcec2"
+  integrity sha512-Cq5DLuSiuYVKNU8orzJMbl15TXilTnJKUCltMVQg53BQOF1/C5toAaGrowkgksdBQ9H+SRL23g0HDmg9tvmxXw==
+  dependencies:
+    "@babel/runtime" "^7.13.10"
+    "@radix-ui/rect" "1.0.1"
+
 "@radix-ui/[email protected]":
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/@radix-ui/react-use-size/-/react-use-size-1.0.0.tgz#a0b455ac826749419f6354dc733e2ca465054771"
@@ -2212,6 +2444,22 @@
     "@babel/runtime" "^7.13.10"
     "@radix-ui/react-use-layout-effect" "1.0.0"
 
+"@radix-ui/[email protected]":
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-use-size/-/react-use-size-1.0.1.tgz#1c5f5fea940a7d7ade77694bb98116fb49f870b2"
+  integrity sha512-ibay+VqrgcaI6veAojjofPATwledXiSmX+C0KrBk/xgpX9rBzPV3OsfwlhQdUOFbh+LKQorLYT+xTXW9V8yd0g==
+  dependencies:
+    "@babel/runtime" "^7.13.10"
+    "@radix-ui/react-use-layout-effect" "1.0.1"
+
+"@radix-ui/[email protected]":
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.0.3.tgz#51aed9dd0fe5abcad7dee2a234ad36106a6984ac"
+  integrity sha512-D4w41yN5YRKtu464TLnByKzMDG/JlMPHtfZgQAu9v6mNakUqGUI9vUrfQKz8NK41VMm/xbZbh76NUTVtIYqOMA==
+  dependencies:
+    "@babel/runtime" "^7.13.10"
+    "@radix-ui/react-primitive" "1.0.3"
+
 "@radix-ui/[email protected]":
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/@radix-ui/rect/-/rect-1.0.0.tgz#0dc8e6a829ea2828d53cbc94b81793ba6383bf3c"
@@ -2219,6 +2467,13 @@
   dependencies:
     "@babel/runtime" "^7.13.10"
 
+"@radix-ui/[email protected]":
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/@radix-ui/rect/-/rect-1.0.1.tgz#bf8e7d947671996da2e30f4904ece343bc4a883f"
+  integrity sha512-fyrgCaedtvMg9NK3en0pnOYJdtfwxUcNolezkNPUsoX57X8oQk+NkqcvzHXD2uKNij6GXmWU9NDru2IWjrO4BQ==
+  dependencies:
+    "@babel/runtime" "^7.13.10"
+
 "@rollup/plugin-babel@^5.2.0":
   version "5.3.1"
   resolved "https://registry.yarnpkg.com/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz#04bc0608f4aa4b2e4b1aebf284344d0f68fda283"