diff --git a/gradle/changelog/chip_input_component.yaml b/gradle/changelog/chip_input_component.yaml
new file mode 100644
index 0000000000..36625a8de6
--- /dev/null
+++ b/gradle/changelog/chip_input_component.yaml
@@ -0,0 +1,2 @@
+- type: added
+ description: New chip input component
diff --git a/scm-ui/ui-forms/package.json b/scm-ui/ui-forms/package.json
index 6628fc2e11..300ab148bb 100644
--- a/scm-ui/ui-forms/package.json
+++ b/scm-ui/ui-forms/package.json
@@ -43,7 +43,9 @@
"dependencies": {
"@scm-manager/ui-buttons": "2.43.2-SNAPSHOT",
"@scm-manager/ui-overlays": "2.43.2-SNAPSHOT",
- "@scm-manager/ui-api": "2.43.2-SNAPSHOT"
+ "@scm-manager/ui-api": "2.43.2-SNAPSHOT",
+ "@radix-ui/react-slot": "^1.0.1",
+ "@radix-ui/react-visually-hidden": "^1.0.3"
},
"prettier": "@scm-manager/prettier-config",
"eslintConfig": {
@@ -52,4 +54,4 @@
"publishConfig": {
"access": "public"
}
-}
\ No newline at end of file
+}
diff --git a/scm-ui/ui-forms/src/Form.stories.tsx b/scm-ui/ui-forms/src/Form.stories.tsx
index ac98fe2d19..8efeda280c 100644
--- a/scm-ui/ui-forms/src/Form.stories.tsx
+++ b/scm-ui/ui-forms/src/Form.stories.tsx
@@ -36,6 +36,7 @@ import ControlledTable from "./table/ControlledTable";
import AddListEntryForm from "./AddListEntryForm";
import { ScmFormListContextProvider } from "./ScmFormListContext";
import { HalRepresentation } from "@scm-manager/ui-types";
+import ControlledChipInputField from "./chip-input/ControlledChipInputField";
export type SimpleWebHookConfiguration = {
urlPattern: string;
@@ -239,6 +240,7 @@ storiesOf("Forms", module)
disableA: false,
disableB: false,
disableC: true,
+ labels: ["test"],
}}
>
@@ -247,6 +249,7 @@ storiesOf("Forms", module)
+
))
.add("ReadOnly", () => (
@@ -257,6 +260,7 @@ storiesOf("Forms", module)
name: "trillian",
password: "secret",
active: true,
+ labels: ["test", "hero"],
}}
readOnly
>
@@ -269,6 +273,9 @@ storiesOf("Forms", module)
+
+
+
))
.add("Nested", () => (
diff --git a/scm-ui/ui-forms/src/base/help/Help.tsx b/scm-ui/ui-forms/src/base/help/Help.tsx
index cd25fbde36..80b602cfdf 100644
--- a/scm-ui/ui-forms/src/base/help/Help.tsx
+++ b/scm-ui/ui-forms/src/base/help/Help.tsx
@@ -28,7 +28,7 @@ import { Tooltip } from "@scm-manager/ui-overlays";
type Props = { text?: string; className?: string };
const Help = ({ text, className }: Props) => (
-
+
);
export default Help;
diff --git a/scm-ui/ui-forms/src/chip-input/ChipInputField.stories.tsx b/scm-ui/ui-forms/src/chip-input/ChipInputField.stories.tsx
new file mode 100644
index 0000000000..08f92e1054
--- /dev/null
+++ b/scm-ui/ui-forms/src/chip-input/ChipInputField.stories.tsx
@@ -0,0 +1,40 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2020-present Cloudogu GmbH and Contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+import { storiesOf } from "@storybook/react";
+import React, { useState } from "react";
+import ChipInputField from "./ChipInputField";
+
+storiesOf("Chip Input Field", module).add("Default", () => {
+ const [value, setValue] = useState(["test"]);
+ return (
+
+ );
+});
diff --git a/scm-ui/ui-forms/src/chip-input/ChipInputField.tsx b/scm-ui/ui-forms/src/chip-input/ChipInputField.tsx
new file mode 100644
index 0000000000..c161016741
--- /dev/null
+++ b/scm-ui/ui-forms/src/chip-input/ChipInputField.tsx
@@ -0,0 +1,141 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2020-present Cloudogu GmbH and Contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+import React, { ComponentProps, useCallback } from "react";
+import { createAttributesForTesting, useGeneratedId } from "@scm-manager/ui-components";
+import Field from "../base/Field";
+import Label from "../base/label/Label";
+import Help from "../base/help/Help";
+import FieldMessage from "../base/field-message/FieldMessage";
+import styled from "styled-components";
+import classNames from "classnames";
+import { createVariantClass } from "../variants";
+import ChipInput, { NewChipInput } from "../headless-chip-input/ChipInput";
+import { VisuallyHidden } from "@radix-ui/react-visually-hidden";
+import { useTranslation } from "react-i18next";
+
+const StyledChipInput = styled(ChipInput)`
+ min-height: 40px;
+ height: min-content;
+ gap: 0.5rem;
+ &:focus-within {
+ border: 1px solid var(--scm-info-color);
+ box-shadow: rgba(51, 178, 232, 0.25) 0px 0px 0px 0.125em;
+ }
+`;
+
+const StyledInput = styled(NewChipInput)`
+ color: var(--scm-secondary-more-color);
+ font-size: 1rem;
+ &:focus {
+ outline: none;
+ }
+`;
+
+type InputFieldProps = {
+ label: string;
+ createDeleteText?: (value: string) => string;
+ helpText?: string;
+ error?: string;
+ testId?: string;
+ id?: string;
+} & Pick, "placeholder"> &
+ Pick, "onChange" | "value" | "readOnly" | "disabled"> &
+ Pick, "className">;
+
+/**
+ * @beta
+ * @since 2.44.0
+ */
+const ChipInputField = React.forwardRef(
+ (
+ {
+ label,
+ helpText,
+ readOnly,
+ disabled,
+ error,
+ createDeleteText,
+ onChange,
+ placeholder,
+ value,
+ className,
+ testId,
+ id,
+ ...props
+ },
+ ref
+ ) => {
+ const [t] = useTranslation("commons", { keyPrefix: "form.chipList" });
+ const deleteTextCallback = useCallback(
+ (item) => (createDeleteText ? createDeleteText(item) : t("delete", { item })),
+ [createDeleteText, t]
+ );
+ const inputId = useGeneratedId(id ?? testId);
+ const labelId = useGeneratedId();
+ const inputDescriptionId = useGeneratedId();
+ const variant = error ? "danger" : undefined;
+ return (
+
+
+
+ {value?.map((val, index) => (
+
+ {val}
+
+
+ ))}
+
+
+
+ {t("input.description")}
+
+ {error ? {error} : null}
+
+ );
+ }
+);
+export default ChipInputField;
diff --git a/scm-ui/ui-forms/src/chip-input/ControlledChipInputField.tsx b/scm-ui/ui-forms/src/chip-input/ControlledChipInputField.tsx
new file mode 100644
index 0000000000..bde24cc4b5
--- /dev/null
+++ b/scm-ui/ui-forms/src/chip-input/ControlledChipInputField.tsx
@@ -0,0 +1,98 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2020-present Cloudogu GmbH and Contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+import React, { ComponentProps } from "react";
+import { Controller, ControllerRenderProps, Path } from "react-hook-form";
+import { useScmFormContext } from "../ScmFormContext";
+import { useScmFormPathContext } from "../FormPathContext";
+import { prefixWithoutIndices } from "../helpers";
+import classNames from "classnames";
+import ChipInputField from "./ChipInputField";
+
+type Props> = Omit<
+ ComponentProps,
+ "error" | "createDeleteText" | "label" | "defaultChecked" | "required" | keyof ControllerRenderProps
+> & {
+ rules?: ComponentProps["rules"];
+ name: Path;
+ label?: string;
+ defaultValue?: string[];
+ createDeleteText?: (value: string) => string;
+};
+
+/**
+ * @beta
+ * @since 2.44.0
+ */
+function ControlledChipInputField>({
+ name,
+ label,
+ helpText,
+ rules,
+ testId,
+ defaultValue,
+ readOnly,
+ placeholder,
+ className,
+ createDeleteText,
+ ...props
+}: Props) {
+ const { control, t, readOnly: formReadonly } = useScmFormContext();
+ const formPathPrefix = useScmFormPathContext();
+
+ const nameWithPrefix = formPathPrefix ? `${formPathPrefix}.${name}` : name;
+ const prefixedNameWithoutIndices = prefixWithoutIndices(nameWithPrefix);
+ const labelTranslation = label || t(`${prefixedNameWithoutIndices}.label`) || "";
+ const placeholderTranslation = placeholder || t(`${prefixedNameWithoutIndices}.placeholder`) || "";
+ const ariaLabelTranslation = t(`${prefixedNameWithoutIndices}.ariaLabel`);
+ const helpTextTranslation = helpText || t(`${prefixedNameWithoutIndices}.helpText`);
+ return (
+ (
+
+ )}
+ />
+ );
+}
+
+export default ControlledChipInputField;
diff --git a/scm-ui/ui-forms/src/headless-chip-input/ChipInput.tsx b/scm-ui/ui-forms/src/headless-chip-input/ChipInput.tsx
new file mode 100644
index 0000000000..acf72dfd63
--- /dev/null
+++ b/scm-ui/ui-forms/src/headless-chip-input/ChipInput.tsx
@@ -0,0 +1,154 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2020-present Cloudogu GmbH and Contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+import React, {
+ ButtonHTMLAttributes,
+ createContext,
+ HTMLAttributes,
+ InputHTMLAttributes,
+ KeyboardEventHandler,
+ LiHTMLAttributes,
+ useCallback,
+ useContext,
+ useMemo,
+} from "react";
+import { Slot } from "@radix-ui/react-slot";
+
+type ChipInputContextType = {
+ add(newValue: string): void;
+ remove(index: number): void;
+ disabled?: boolean;
+ readOnly?: boolean;
+ value: string[];
+};
+const ChipInputContext = createContext(null as unknown as ChipInputContextType);
+
+type ChipDeleteProps = {
+ asChild?: boolean;
+ index: number;
+} & Omit, "type" | "onClick">;
+
+/**
+ * @beta
+ * @since 2.44.0
+ */
+export const ChipDelete = React.forwardRef(({ asChild, index, ...props }, ref) => {
+ const { remove, disabled } = useContext(ChipInputContext);
+ const Comp = asChild ? Slot : "button";
+
+ if (disabled) {
+ return null;
+ }
+
+ return remove(index)} />;
+});
+
+type NewChipInputProps = {
+ asChild?: boolean;
+} & Omit, "onKeyDown" | "disabled" | "readOnly">;
+
+/**
+ * @beta
+ * @since 2.44.0
+ */
+export const NewChipInput = React.forwardRef(({ asChild, ...props }, ref) => {
+ const { add, value, disabled, readOnly } = useContext(ChipInputContext);
+ const handleKeyDown = useCallback>(
+ (e) => {
+ if (e.key === "Enter") {
+ e.preventDefault();
+ const newValue = e.currentTarget.value.trim();
+ if (newValue && !value?.includes(newValue)) {
+ add(newValue);
+ e.currentTarget.value = "";
+ }
+ return false;
+ }
+ },
+ [add, value]
+ );
+ const Comp = asChild ? Slot : "input";
+ return ;
+});
+
+type ChipProps = { asChild?: boolean } & LiHTMLAttributes;
+
+/**
+ * @beta
+ * @since 2.44.0
+ */
+export const Chip = React.forwardRef(({ asChild, ...props }, ref) => {
+ const Comp = asChild ? Slot : "li";
+
+ return ;
+});
+
+type Props = {
+ value?: string[];
+ onChange?: (newValue: string[]) => void;
+ readOnly?: boolean;
+ disabled?: boolean;
+} & Omit, "onChange">;
+
+/**
+ * @beta
+ * @since 2.44.0
+ */
+const ChipInput = React.forwardRef(
+ ({ children, value = [], disabled, readOnly, onChange, ...props }, ref) => {
+ const isInactive = useMemo(() => disabled || readOnly, [disabled, readOnly]);
+ const add = useCallback(
+ (newValue: string) => !isInactive && onChange && onChange([...value, newValue]),
+ [isInactive, onChange, value]
+ );
+ const remove = useCallback(
+ (index: number) => !isInactive && onChange && onChange(value?.filter((_, itdx) => itdx !== index)),
+ [isInactive, onChange, value]
+ );
+ return (
+ ({
+ value,
+ disabled,
+ readOnly,
+ add,
+ remove,
+ }),
+ [add, disabled, readOnly, remove, value]
+ )}
+ >
+
+
+ );
+ }
+);
+
+export default Object.assign(ChipInput, {
+ Chip: Object.assign(Chip, {
+ Delete: ChipDelete,
+ }),
+});
diff --git a/scm-ui/ui-forms/src/index.ts b/scm-ui/ui-forms/src/index.ts
index b0eaa166e3..47b2f53d23 100644
--- a/scm-ui/ui-forms/src/index.ts
+++ b/scm-ui/ui-forms/src/index.ts
@@ -28,6 +28,7 @@ import ControlledInputField from "./input/ControlledInputField";
import ControlledCheckboxField from "./checkbox/ControlledCheckboxField";
import ControlledSecretConfirmationField from "./input/ControlledSecretConfirmationField";
import ControlledSelectField from "./select/ControlledSelectField";
+import ControlledChipInputField from "./chip-input/ControlledChipInputField";
import { ScmFormListContextProvider } from "./ScmFormListContext";
import ControlledList from "./list/ControlledList";
import ControlledTable from "./table/ControlledTable";
@@ -37,6 +38,7 @@ import { ScmNestedFormPathContextProvider } from "./FormPathContext";
export { default as ConfigurationForm } from "./ConfigurationForm";
export { default as SelectField } from "./select/SelectField";
+export { default as ChipInputField } from "./chip-input/ChipInputField";
export { default as Select } from "./select/Select";
export * from "./resourceHooks";
@@ -53,4 +55,5 @@ export const Form = Object.assign(FormCmp, {
Table: Object.assign(ControlledTable, {
Column: ControlledColumn,
}),
+ ChipInput: ControlledChipInputField,
});
diff --git a/scm-ui/ui-webapp/public/locales/de/commons.json b/scm-ui/ui-webapp/public/locales/de/commons.json
index 1e6bb3e825..2b97696bd2 100644
--- a/scm-ui/ui-webapp/public/locales/de/commons.json
+++ b/scm-ui/ui-webapp/public/locales/de/commons.json
@@ -7,6 +7,12 @@
"reset": "Leeren",
"discardChanges": "Änderungen verwerfen",
"submit-success-notification": "Einstellungen wurden erfolgreich geändert!",
+ "chipList": {
+ "delete": "'{{item}}' löschen",
+ "input": {
+ "description": "Drücke 'Eingabetaste' um den Wert der Liste hinzuzufügen."
+ }
+ },
"table": {
"headers": {
"action": {
diff --git a/scm-ui/ui-webapp/public/locales/en/commons.json b/scm-ui/ui-webapp/public/locales/en/commons.json
index 1b0cbeb8c5..1e514639e2 100644
--- a/scm-ui/ui-webapp/public/locales/en/commons.json
+++ b/scm-ui/ui-webapp/public/locales/en/commons.json
@@ -7,6 +7,12 @@
"reset": "Clear",
"discardChanges": "Discard changes",
"submit-success-notification": "Configuration changed successfully!",
+ "chipList": {
+ "delete": "Delete '{{item}}'",
+ "input": {
+ "description": "Press enter to add value to list."
+ }
+ },
"table": {
"headers": {
"action": {
diff --git a/yarn.lock b/yarn.lock
index c588b80a4c..10fb4b4b5a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2411,6 +2411,13 @@
dependencies:
"@babel/runtime" "^7.13.10"
+"@radix-ui/react-compose-refs@1.0.1":
+ 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/react-context@1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.0.0.tgz#f38e30c5859a9fb5e9aa9a9da452ee3ed9e0aee0"
@@ -2587,6 +2594,14 @@
"@babel/runtime" "^7.13.10"
"@radix-ui/react-slot" "1.0.1"
+"@radix-ui/react-primitive@1.0.3":
+ 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/react-roving-focus@1.0.3":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@radix-ui/react-roving-focus/-/react-roving-focus-1.0.3.tgz#0b4f4f9bd509f4510079e9e0734a734fd17cdce3"
@@ -2611,6 +2626,14 @@
"@babel/runtime" "^7.13.10"
"@radix-ui/react-compose-refs" "1.0.0"
+"@radix-ui/react-slot@1.0.2", "@radix-ui/react-slot@^1.0.1":
+ 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/react-tooltip@1.0.2":
version "1.0.2"
resolved "https://registry.yarnpkg.com/@radix-ui/react-tooltip/-/react-tooltip-1.0.2.tgz#8e10b075767f785bf013146fdc954ac6885efda3"
@@ -2684,6 +2707,14 @@
"@babel/runtime" "^7.13.10"
"@radix-ui/react-primitive" "1.0.1"
+"@radix-ui/react-visually-hidden@^1.0.3":
+ 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/rect@1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@radix-ui/rect/-/rect-1.0.0.tgz#0dc8e6a829ea2828d53cbc94b81793ba6383bf3c"