diff --git a/packages/components/tag/index.tsx b/packages/components/tag/index.tsx
deleted file mode 100644
index 5b3e22cf86..0000000000
--- a/packages/components/tag/index.tsx
+++ /dev/null
@@ -1,210 +0,0 @@
-import React from "react";
-import PropTypes from "prop-types";
-import { ReactSVG } from "react-svg";
-// @ts-expect-error TS(2307): Cannot find module 'PUBLIC_DIR/images/cross.react.... Remove this comment to see the full error message
-import CrossIconReactSvgUrl from "PUBLIC_DIR/images/cross.react.svg?url";
-// @ts-expect-error TS(2307): Cannot find module 'PUBLIC_DIR/images/tag.react.sv... Remove this comment to see the full error message
-import TagIconReactSvgUrl from "PUBLIC_DIR/images/tag.react.svg?url";
-import DropDown from "../drop-down";
-import DropDownItem from "../drop-down-item";
-import IconButton from "../icon-button";
-import Text from "../text";
-
-import {
- StyledTag,
- StyledDropdownIcon,
- StyledDropdownText,
-} from "./styled-tag";
-
-const Tag = ({
- tag,
- label,
- isNewTag,
- isDisabled,
- isDefault,
- isLast,
- onDelete,
- onClick,
- advancedOptions,
- tagMaxWidth,
- id,
- className,
- style,
- icon
-}: any) => {
- const [openDropdown, setOpenDropdown] = React.useState(false);
-
- const tagRef = React.useRef(null);
- const isMountedRef = React.useRef(true);
- const onClickOutside = React.useCallback((e: any) => {
- if (e?.target?.className?.includes("advanced-tag") || !isMountedRef.current)
- return;
-
- setOpenDropdown(false);
- }, []);
-
- React.useEffect(() => {
- if (openDropdown) {
- return document.addEventListener("click", onClickOutside);
- }
-
- document.removeEventListener("click", onClickOutside);
- return () => {
- document.removeEventListener("click", onClickOutside);
- };
- }, [openDropdown, onClickOutside]);
-
- React.useEffect(() => {
- return () => {
- isMountedRef.current = false;
- };
- }, []);
-
- const openDropdownAction = (e: any) => {
- if (e?.target?.className?.includes("backdrop-active")) return;
-
- setOpenDropdown(true);
- };
-
- const onClickAction = React.useCallback(
- (e: any) => {
- if (onClick && !isDisabled) {
- onClick(e.target.dataset.tag);
- }
- },
- [onClick, isDisabled]
- );
-
- const onDeleteAction = React.useCallback(
- (e: any) => {
- if (e.target != tagRef.current && onDelete) {
- onDelete && onDelete(tag);
- }
- },
- [onDelete, tag, tagRef]
- );
-
- return <>
- {!!advancedOptions ? (
- <>
-
- // @ts-expect-error TS(2322): Type '{ children: string; className: string; "font... Remove this comment to see the full error message
-
- ...
-
-
- // @ts-expect-error TS(2769): No overload matches this call.
-
- {advancedOptions.map((tag: any, index: any) => (
-
-
-
- {tag}
-
-
- ))}
-
- >
- ) : (
-
- {icon ? (
-
- ) : (
- <>
- // @ts-expect-error TS(2322): Type '{ children: any; className: string; title: a... Remove this comment to see the full error message
-
- {label}
-
- {isNewTag && (
-
- )}
- >
- )}
-
- )}
- >;
-};
-
-Tag.propTypes = {
- /** Accepts the tag id */
- tag: PropTypes.string,
- /** Accepts the tag label */
- label: PropTypes.string,
- /** Accepts class */
- className: PropTypes.string,
- /** Accepts id */
- id: PropTypes.string,
- /** Accepts css style */
- style: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
- /** Accepts the tag styles as new and adds the delete button */
- isNewTag: PropTypes.bool,
- /** Accepts the tag styles as disabled and disables clicking */
- isDisabled: PropTypes.bool,
- /** Accepts the function that is called when the tag is clicked */
- onClick: PropTypes.func,
- /** Accepts the function that ist called when the tag delete button is clicked */
- onDelete: PropTypes.func,
- /** Accepts the max width of the tag */
- tagMaxWidth: PropTypes.string,
- /** Accepts the dropdown options */
- advancedOptions: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
-};
-
-export default React.memo(Tag);
diff --git a/packages/components/tag/tag.stories.tsx b/packages/components/tag/tag.stories.tsx
deleted file mode 100644
index 11e584968c..0000000000
--- a/packages/components/tag/tag.stories.tsx
+++ /dev/null
@@ -1,72 +0,0 @@
-import React from "react";
-
-import Tag from ".";
-
-export default {
- title: "Components/Tag",
- component: Tag,
- parameters: {
- design: {
- type: "figma",
- url: "https://www.figma.com/file/ZiW5KSwb4t7Tj6Nz5TducC/UI-Kit-DocSpace-1.0.0?type=design&node-id=62-2597&mode=design&t=TBNCKMQKQMxr44IZ-0",
- },
- },
-};
-
-const Template = (args: any) => ;
-
-export const Default = Template.bind({});
-
-// @ts-expect-error TS(2339): Property 'args' does not exist on type '(args: any... Remove this comment to see the full error message
-Default.args = {
- tag: "script",
- label: "Script",
- isNewTag: false,
- isDisabled: false,
- onDelete: (tag: any) => console.log(tag),
- onClick: (tag: any) => console.log(tag),
- advancedOptions: null,
- tagMaxWidth: "160px",
- id: "",
- className: "",
- style: { color: "red" },
-};
-
-export const WithDropDown = Template.bind({});
-
-// @ts-expect-error TS(2339): Property 'args' does not exist on type '(args: any... Remove this comment to see the full error message
-WithDropDown.args = {
- tag: "script",
- label: "Script",
- isNewTag: false,
- isDisabled: false,
- onDelete: (tag: any) => console.log(tag),
- onClick: (tag: any) => console.log(tag),
- advancedOptions: ["Option 1", "Option 2"],
-};
-
-export const NewTag = Template.bind({});
-
-// @ts-expect-error TS(2339): Property 'args' does not exist on type '(args: any... Remove this comment to see the full error message
-NewTag.args = {
- tag: "script",
- label: "Script",
- isNewTag: true,
- isDisabled: false,
- onDelete: (tag: any) => console.log(tag),
- onClick: (tag: any) => console.log(tag),
- advancedOptions: null,
-};
-
-export const DisabledTag = Template.bind({});
-
-// @ts-expect-error TS(2339): Property 'args' does not exist on type '(args: any... Remove this comment to see the full error message
-DisabledTag.args = {
- tag: "script",
- label: "No tag",
- isNewTag: false,
- isDisabled: true,
- onDelete: (tag: any) => console.log(tag),
- onClick: (tag: any) => console.log(tag),
- advancedOptions: null,
-};
diff --git a/packages/components/tag/tag.test.tsx b/packages/components/tag/tag.test.tsx
deleted file mode 100644
index 54eb4927d1..0000000000
--- a/packages/components/tag/tag.test.tsx
+++ /dev/null
@@ -1,42 +0,0 @@
-import React from "react";
-// @ts-expect-error TS(7016): Could not find a declaration file for module 'enzy... Remove this comment to see the full error message
-import { mount } from "enzyme";
-import Tag from ".";
-
-const baseProps = {
- tag: "script",
- label: "Script",
- isNewTag: false,
- isDisabled: false,
- onDelete: (tag: any) => console.log(tag),
- onClick: (tag: any) => console.log(tag),
- advancedOptions: null,
- tagMaxWidth: "160px",
-};
-
-// @ts-expect-error TS(2582): Cannot find name 'describe'. Do you need to instal... Remove this comment to see the full error message
-describe("", () => {
- // @ts-expect-error TS(2582): Cannot find name 'it'. Do you need to install type... Remove this comment to see the full error message
- it("renders without error", () => {
- const wrapper = mount();
-
- // @ts-expect-error TS(2304): Cannot find name 'expect'.
- expect(wrapper).toExist();
- });
-
- // @ts-expect-error TS(2582): Cannot find name 'it'. Do you need to install type... Remove this comment to see the full error message
- it("accepts id", () => {
- const wrapper = mount();
-
- // @ts-expect-error TS(2304): Cannot find name 'expect'.
- expect(wrapper.prop("id")).toEqual("testId");
- });
-
- // @ts-expect-error TS(2582): Cannot find name 'it'. Do you need to install type... Remove this comment to see the full error message
- it("accepts className", () => {
- const wrapper = mount();
-
- // @ts-expect-error TS(2304): Cannot find name 'expect'.
- expect(wrapper.prop("className")).toEqual("test");
- });
-});
diff --git a/packages/shared/components/index.ts b/packages/shared/components/index.ts
index 5572ffd53d..0f8392cbcf 100644
--- a/packages/shared/components/index.ts
+++ b/packages/shared/components/index.ts
@@ -83,6 +83,7 @@ import { SaveCancelButtons } from "./save-cancel-buttons";
import { TimePicker } from "./time-picker";
import { ArticleItem } from "./article-item";
import { ToggleContent } from "./toggle-content";
+import { Tag } from "./tag";
export type {
TFallbackAxisSideDirection,
@@ -95,6 +96,7 @@ export type {
};
export {
+ Tag,
ToggleContent,
ArticleItem,
TimePicker,
diff --git a/packages/components/tag/README.md b/packages/shared/components/tag/README.md
similarity index 100%
rename from packages/components/tag/README.md
rename to packages/shared/components/tag/README.md
diff --git a/packages/components/tag/styled-tag.ts b/packages/shared/components/tag/Tag.styled.ts
similarity index 60%
rename from packages/components/tag/styled-tag.ts
rename to packages/shared/components/tag/Tag.styled.ts
index 131a55cde7..0960f6c937 100644
--- a/packages/components/tag/styled-tag.ts
+++ b/packages/shared/components/tag/Tag.styled.ts
@@ -1,13 +1,20 @@
import styled, { css } from "styled-components";
import { ReactSVG } from "react-svg";
-import Text from "../text";
-import Base from "../themes/base";
+import { Text } from "../text";
-const StyledTag = styled.div`
+import { Base } from "../../themes";
+
+const StyledTag = styled.div<{
+ tagMaxWidth?: string;
+ isLast?: boolean;
+ isDisabled?: boolean;
+ isNewTag?: boolean;
+ isDefault?: boolean;
+ isClickable?: boolean;
+}>`
width: fit-content;
- // @ts-expect-error TS(2339): Property 'tagMaxWidth' does not exist on type 'The... Remove this comment to see the full error message
max-width: ${(props) => (props.tagMaxWidth ? props.tagMaxWidth : "100%")};
display: flex;
@@ -20,28 +27,23 @@ const StyledTag = styled.div`
${(props) =>
props.theme.interfaceDirection === "rtl"
? css`
- // @ts-expect-error TS(2339): Property 'isLast' does not exist on type 'ThemedSt... Remove this comment to see the full error message
margin-left: ${props.isLast ? "0" : "4px"};
`
: css`
- // @ts-expect-error TS(2339): Property 'isLast' does not exist on type 'ThemedSt... Remove this comment to see the full error message
margin-right: ${props.isLast ? "0" : "4px"};
`}
background: ${(props) =>
- // @ts-expect-error TS(2339): Property 'isDisabled' does not exist on type 'Them... Remove this comment to see the full error message
props.isDisabled
? props.theme.tag.disabledBackground
- // @ts-expect-error TS(2339): Property 'isNewTag' does not exist on type 'Themed... Remove this comment to see the full error message
: props.isNewTag
- ? props.theme.tag.newTagBackground
- : props.theme.tag.background};
+ ? props.theme.tag.newTagBackground
+ : props.theme.tag.background};
border-radius: 6px;
.tag-text {
color: ${(props) =>
- // @ts-expect-error TS(2339): Property 'isDefault' does not exist on type 'Theme... Remove this comment to see the full error message
props.isDefault
? props.theme.tag.defaultTagColor
: props.theme.tag.color};
@@ -68,14 +70,12 @@ const StyledTag = styled.div`
}
${(props) =>
- // @ts-expect-error TS(2339): Property 'isClickable' does not exist on type 'The... Remove this comment to see the full error message
props.isClickable &&
- // @ts-expect-error TS(2339): Property 'isDisabled' does not exist on type 'Them... Remove this comment to see the full error message
!props.isDisabled &&
css`
cursor: pointer;
&:hover {
- background: ${(props) => props.theme.tag.hoverBackground};
+ background: ${props.theme.tag.hoverBackground};
}
`}
`;
diff --git a/packages/shared/components/tag/Tag.tsx b/packages/shared/components/tag/Tag.tsx
new file mode 100644
index 0000000000..338f3023e5
--- /dev/null
+++ b/packages/shared/components/tag/Tag.tsx
@@ -0,0 +1,185 @@
+import React from "react";
+import { ReactSVG } from "react-svg";
+
+import CrossIconReactSvgUrl from "PUBLIC_DIR/images/cross.react.svg?url";
+import TagIconReactSvgUrl from "PUBLIC_DIR/images/tag.react.svg?url";
+
+import { DropDown } from "../drop-down";
+import { DropDownItem } from "../drop-down-item";
+import { IconButton } from "../icon-button";
+import { Text } from "../text";
+
+import {
+ StyledTag,
+ StyledDropdownIcon,
+ StyledDropdownText,
+} from "./Tag.styled";
+import { TagProps } from "./Tag.types";
+
+export const TagPure = ({
+ tag,
+ label,
+ isNewTag,
+ isDisabled,
+ isDefault,
+ isLast,
+ onDelete,
+ onClick,
+ advancedOptions,
+ tagMaxWidth,
+ id,
+ className,
+ style,
+ icon,
+}: TagProps) => {
+ const [openDropdown, setOpenDropdown] = React.useState(false);
+
+ const tagRef = React.useRef(null);
+ const isMountedRef = React.useRef(true);
+
+ const onClickOutside = React.useCallback((e: Event) => {
+ const target = e.target as HTMLElement;
+ if (target.className?.includes("advanced-tag") || !isMountedRef.current)
+ return;
+
+ setOpenDropdown(false);
+ }, []);
+
+ React.useEffect(() => {
+ if (openDropdown) {
+ return document.addEventListener("click", onClickOutside);
+ }
+
+ document.removeEventListener("click", onClickOutside);
+ return () => {
+ document.removeEventListener("click", onClickOutside);
+ };
+ }, [openDropdown, onClickOutside]);
+
+ React.useEffect(() => {
+ return () => {
+ isMountedRef.current = false;
+ };
+ }, []);
+
+ const openDropdownAction = (e: React.MouseEvent) => {
+ const target = e.target as HTMLDivElement;
+ if (target?.className?.includes("backdrop-active")) return;
+
+ setOpenDropdown(true);
+ };
+
+ const onClickAction = React.useCallback(
+ (e: React.MouseEvent | React.ChangeEvent) => {
+ if (onClick && !isDisabled) {
+ const target = e.target as HTMLDivElement;
+ onClick(target.dataset.tag);
+ }
+ },
+ [onClick, isDisabled],
+ );
+
+ const onDeleteAction = React.useCallback(
+ (e: React.MouseEvent) => {
+ if (e.target !== tagRef.current) {
+ onDelete?.(tag);
+ }
+ },
+ [onDelete, tag, tagRef],
+ );
+
+ return advancedOptions ? (
+ <>
+
+
+ ...
+
+
+
+ {advancedOptions.map((t, index) => (
+
+
+
+ {tag}
+
+
+ ))}
+
+ >
+ ) : (
+
+ {icon ? (
+
+ ) : (
+ <>
+
+ {label}
+
+ {isNewTag && (
+
+ )}
+ >
+ )}
+
+ );
+};
+
+const Tag = React.memo(TagPure);
+
+export { Tag };
diff --git a/packages/shared/components/tag/Tag.types.tsx b/packages/shared/components/tag/Tag.types.tsx
new file mode 100644
index 0000000000..9a0112b993
--- /dev/null
+++ b/packages/shared/components/tag/Tag.types.tsx
@@ -0,0 +1,27 @@
+export interface TagProps {
+ /** Accepts the tag id */
+ tag: string;
+ /** Accepts the tag label */
+ label?: string;
+ /** Accepts class */
+ className?: string;
+ /** Accepts id */
+ id?: string;
+ /** Accepts css style */
+ style?: React.CSSProperties;
+ /** Accepts the tag styles as new and adds the delete button */
+ isNewTag?: boolean;
+ /** Accepts the tag styles as disabled and disables clicking */
+ isDisabled?: boolean;
+ /** Accepts the function that is called when the tag is clicked */
+ onClick: (tag?: string) => void;
+ /** Accepts the function that ist called when the tag delete button is clicked */
+ onDelete?: (tag?: string) => void;
+ /** Accepts the max width of the tag */
+ tagMaxWidth?: string;
+ /** Accepts the dropdown options */
+ advancedOptions?: React.ReactNode[];
+ icon?: string;
+ isDefault?: boolean;
+ isLast?: boolean;
+}
diff --git a/packages/shared/components/tag/index.tsx b/packages/shared/components/tag/index.tsx
new file mode 100644
index 0000000000..736cac7bef
--- /dev/null
+++ b/packages/shared/components/tag/index.tsx
@@ -0,0 +1 @@
+export { Tag } from "./Tag";
diff --git a/packages/shared/components/tag/tag.stories.tsx b/packages/shared/components/tag/tag.stories.tsx
new file mode 100644
index 0000000000..3fab998820
--- /dev/null
+++ b/packages/shared/components/tag/tag.stories.tsx
@@ -0,0 +1,67 @@
+import { Meta, StoryObj } from "@storybook/react";
+
+import { TagPure } from "./Tag";
+
+const meta = {
+ title: "Components/Tag",
+ component: TagPure,
+ parameters: {
+ design: {
+ type: "figma",
+ url: "https://www.figma.com/file/ZiW5KSwb4t7Tj6Nz5TducC/UI-Kit-DocSpace-1.0.0?type=design&node-id=62-2597&mode=design&t=TBNCKMQKQMxr44IZ-0",
+ },
+ },
+} satisfies Meta;
+type Story = StoryObj;
+
+export default meta;
+
+export const Default: Story = {
+ args: {
+ tag: "script",
+ label: "Script",
+ isNewTag: false,
+ isDisabled: false,
+ onDelete: () => {},
+ onClick: () => {},
+
+ tagMaxWidth: "160px",
+ id: "",
+ className: "",
+ style: { color: "red" },
+ },
+};
+
+export const WithDropDown: Story = {
+ args: {
+ tag: "script",
+ label: "Script",
+ isNewTag: false,
+ isDisabled: false,
+ onDelete: () => {},
+ onClick: () => {},
+ advancedOptions: ["Option 1", "Option 2"],
+ },
+};
+
+export const NewTag: Story = {
+ args: {
+ tag: "script",
+ label: "Script",
+ isNewTag: true,
+ isDisabled: false,
+ onDelete: () => {},
+ onClick: () => {},
+ },
+};
+
+export const DisabledTag: Story = {
+ args: {
+ tag: "script",
+ label: "No tag",
+ isNewTag: false,
+ isDisabled: true,
+ onDelete: () => {},
+ onClick: () => {},
+ },
+};
diff --git a/packages/shared/components/tag/tag.test.tsx b/packages/shared/components/tag/tag.test.tsx
new file mode 100644
index 0000000000..dd4cfe84b1
--- /dev/null
+++ b/packages/shared/components/tag/tag.test.tsx
@@ -0,0 +1,38 @@
+import React from "react";
+import { render, screen } from "@testing-library/react";
+import "@testing-library/jest-dom";
+
+import { Tag } from "./Tag";
+
+const baseProps = {
+ tag: "script",
+ label: "Script",
+ isNewTag: false,
+ isDisabled: false,
+ onDelete: () => {},
+ onClick: () => {},
+
+ tagMaxWidth: "160px",
+};
+
+describe("", () => {
+ it("renders without error", () => {
+ render();
+
+ expect(screen.getByTestId("tag")).toBeInTheDocument();
+ });
+
+ // it("accepts id", () => {
+ // const wrapper = mount();
+
+ // // @ts-expect-error TS(2304): Cannot find name 'expect'.
+ // expect(wrapper.prop("id")).toEqual("testId");
+ // });
+
+ // it("accepts className", () => {
+ // const wrapper = mount();
+
+ // // @ts-expect-error TS(2304): Cannot find name 'expect'.
+ // expect(wrapper.prop("className")).toEqual("test");
+ // });
+});