dst-rg 1.0.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.
Files changed (249) hide show
  1. package/.gitlab-ci.yml +43 -0
  2. package/.storybook/main.ts +15 -0
  3. package/.storybook/preview.ts +15 -0
  4. package/README.md +254 -0
  5. package/components.json +21 -0
  6. package/dist/Avatar.png +0 -0
  7. package/dist/assets/index-CCq7hmG3.js +186 -0
  8. package/dist/assets/index-Mg-hjQGu.css +1 -0
  9. package/dist/index.html +15 -0
  10. package/dist/test.png +0 -0
  11. package/dist/vite.svg +1 -0
  12. package/eslint.config.js +29 -0
  13. package/index.html +14 -0
  14. package/package.json +102 -0
  15. package/postcss.config.mjs +11 -0
  16. package/rollup.config.mjs +55 -0
  17. package/src/assets/react.svg +1 -0
  18. package/src/assets/style/animation.css +27 -0
  19. package/src/assets/style/box-shadow.css +25 -0
  20. package/src/assets/style/colors.css +402 -0
  21. package/src/assets/style/dark-theme.css +288 -0
  22. package/src/assets/style/font-size.css +14 -0
  23. package/src/assets/style/gradient.css +3 -0
  24. package/src/assets/style/index.css +12 -0
  25. package/src/assets/style/light-theme.css +148 -0
  26. package/src/assets/style/line-height.css +13 -0
  27. package/src/assets/style/max-width.css +5 -0
  28. package/src/assets/style/radius.css +13 -0
  29. package/src/assets/style/utility-colors.css +166 -0
  30. package/src/components/Accordion/_.stories.tsx +75 -0
  31. package/src/components/Accordion/_.test.tsx +77 -0
  32. package/src/components/Accordion/index.tsx +47 -0
  33. package/src/components/Accordion/type.ts +24 -0
  34. package/src/components/Avatar/_.stories.tsx +179 -0
  35. package/src/components/Avatar/_.style.ts +40 -0
  36. package/src/components/Avatar/_.test.tsx +150 -0
  37. package/src/components/Avatar/_.types.ts +66 -0
  38. package/src/components/Avatar/index.tsx +63 -0
  39. package/src/components/Badge/_.stories.tsx +75 -0
  40. package/src/components/Badge/_.style.ts +53 -0
  41. package/src/components/Badge/_.test.tsx +27 -0
  42. package/src/components/Badge/_.types.ts +11 -0
  43. package/src/components/Badge/index.tsx +42 -0
  44. package/src/components/Breadcrumbs/_.stories.tsx +95 -0
  45. package/src/components/Breadcrumbs/_.test.tsx +29 -0
  46. package/src/components/Breadcrumbs/_.type.ts +15 -0
  47. package/src/components/Breadcrumbs/index.tsx +103 -0
  48. package/src/components/Button/_.stories.tsx +85 -0
  49. package/src/components/Button/_.style.ts +56 -0
  50. package/src/components/Button/_.test.tsx +103 -0
  51. package/src/components/Button/_.types.ts +14 -0
  52. package/src/components/Button/index.tsx +70 -0
  53. package/src/components/Checkbox/_.stories.tsx +96 -0
  54. package/src/components/Checkbox/_.style.ts +24 -0
  55. package/src/components/Checkbox/_.test.tsx +85 -0
  56. package/src/components/Checkbox/_.types.ts +23 -0
  57. package/src/components/Checkbox/index.tsx +93 -0
  58. package/src/components/CheckboxGroup/PaymentCard/_.stories.tsx +104 -0
  59. package/src/components/CheckboxGroup/PaymentCard/_.style.ts +28 -0
  60. package/src/components/CheckboxGroup/PaymentCard/_.test.tsx +58 -0
  61. package/src/components/CheckboxGroup/PaymentCard/_.types.ts +28 -0
  62. package/src/components/CheckboxGroup/PaymentCard/index.tsx +71 -0
  63. package/src/components/CheckboxGroup/PlanCard/_.stories.tsx +165 -0
  64. package/src/components/CheckboxGroup/PlanCard/_.style.ts +32 -0
  65. package/src/components/CheckboxGroup/PlanCard/_.test.tsx +54 -0
  66. package/src/components/CheckboxGroup/PlanCard/_.types.ts +35 -0
  67. package/src/components/CheckboxGroup/PlanCard/index.tsx +53 -0
  68. package/src/components/CheckboxGroup/UserCard/_.stories.tsx +89 -0
  69. package/src/components/CheckboxGroup/UserCard/_.style.ts +42 -0
  70. package/src/components/CheckboxGroup/UserCard/_.test.tsx +66 -0
  71. package/src/components/CheckboxGroup/UserCard/_.types.ts +26 -0
  72. package/src/components/CheckboxGroup/UserCard/index.tsx +75 -0
  73. package/src/components/Dropdown/_.stories.tsx +180 -0
  74. package/src/components/Dropdown/_.style.ts +108 -0
  75. package/src/components/Dropdown/_.test.tsx +334 -0
  76. package/src/components/Dropdown/_.types.ts +12 -0
  77. package/src/components/Dropdown/index.tsx +130 -0
  78. package/src/components/FileUpload/_.stories.tsx +74 -0
  79. package/src/components/FileUpload/_.style.ts +0 -0
  80. package/src/components/FileUpload/_.test.tsx +222 -0
  81. package/src/components/FileUpload/_.types.ts +53 -0
  82. package/src/components/FileUpload/index.tsx +44 -0
  83. package/src/components/ImageMagnify/_.stories.tsx +226 -0
  84. package/src/components/ImageMagnify/_.style.ts +109 -0
  85. package/src/components/ImageMagnify/_.types.ts +44 -0
  86. package/src/components/ImageMagnify/index.tsx +204 -0
  87. package/src/components/Input/_.stories.tsx +177 -0
  88. package/src/components/Input/_.style.ts +79 -0
  89. package/src/components/Input/_.test.tsx +146 -0
  90. package/src/components/Input/_.types.ts +66 -0
  91. package/src/components/Input/index.tsx +231 -0
  92. package/src/components/InputTags/_.stories.tsx +51 -0
  93. package/src/components/InputTags/_.style.ts +28 -0
  94. package/src/components/InputTags/_.test.tsx +123 -0
  95. package/src/components/InputTags/_.types.ts +26 -0
  96. package/src/components/InputTags/index.tsx +140 -0
  97. package/src/components/Message/_.stories.tsx +79 -0
  98. package/src/components/Message/_.style.ts +87 -0
  99. package/src/components/Message/_.test.tsx +73 -0
  100. package/src/components/Message/_.types.ts +13 -0
  101. package/src/components/Message/index.tsx +57 -0
  102. package/src/components/Metric/_.stories.tsx +142 -0
  103. package/src/components/Metric/_.style.ts +14 -0
  104. package/src/components/Metric/_.test.tsx +166 -0
  105. package/src/components/Metric/_.types.ts +18 -0
  106. package/src/components/Metric/index.tsx +100 -0
  107. package/src/components/Modal/_.stories.tsx +93 -0
  108. package/src/components/Modal/_.style.ts +31 -0
  109. package/src/components/Modal/_.test.tsx +90 -0
  110. package/src/components/Modal/_.types.ts +14 -0
  111. package/src/components/Modal/index.tsx +82 -0
  112. package/src/components/Pagination/_.stories.tsx +118 -0
  113. package/src/components/Pagination/_.test.tsx +51 -0
  114. package/src/components/Pagination/index.tsx +256 -0
  115. package/src/components/Pagination/type.ts +48 -0
  116. package/src/components/PriceSlider/_.stories.tsx +107 -0
  117. package/src/components/PriceSlider/_.test.tsx +63 -0
  118. package/src/components/PriceSlider/_.type.tsx +19 -0
  119. package/src/components/PriceSlider/index.tsx +86 -0
  120. package/src/components/Progress/_.stories.tsx +93 -0
  121. package/src/components/Progress/_.style.ts +15 -0
  122. package/src/components/Progress/_.test.tsx +34 -0
  123. package/src/components/Progress/_.types.ts +17 -0
  124. package/src/components/Progress/index.tsx +173 -0
  125. package/src/components/Radio/_.stories.tsx +391 -0
  126. package/src/components/Radio/_.style.ts +33 -0
  127. package/src/components/Radio/_.test.tsx +77 -0
  128. package/src/components/Radio/_.types.ts +14 -0
  129. package/src/components/Radio/index.tsx +59 -0
  130. package/src/components/Select/_.stories.tsx +308 -0
  131. package/src/components/Select/_.style.ts +5 -0
  132. package/src/components/Select/_.types.ts +24 -0
  133. package/src/components/Select/index.tsx +172 -0
  134. package/src/components/Switch/_.stories.tsx +61 -0
  135. package/src/components/Switch/_.test.tsx +69 -0
  136. package/src/components/Switch/_.type.ts +12 -0
  137. package/src/components/Switch/index.tsx +70 -0
  138. package/src/components/Tabs/_.stories.tsx +508 -0
  139. package/src/components/Tabs/_.style.ts +63 -0
  140. package/src/components/Tabs/_.test.tsx +174 -0
  141. package/src/components/Tabs/_.type.ts +19 -0
  142. package/src/components/Tabs/index.tsx +35 -0
  143. package/src/components/Tag/_.stories.tsx +78 -0
  144. package/src/components/Tag/_.style.ts +71 -0
  145. package/src/components/Tag/_.test.tsx +44 -0
  146. package/src/components/Tag/_.types.ts +27 -0
  147. package/src/components/Tag/index.tsx +46 -0
  148. package/src/components/TextArea/_.stories.tsx +62 -0
  149. package/src/components/TextArea/_.style.ts +11 -0
  150. package/src/components/TextArea/_.test.tsx +43 -0
  151. package/src/components/TextArea/_.types.ts +29 -0
  152. package/src/components/TextArea/index.tsx +83 -0
  153. package/src/components/Toast/_.style.tsx +27 -0
  154. package/src/components/Toast/_.type.ts +30 -0
  155. package/src/components/Toast/_.utils.ts +23 -0
  156. package/src/components/Toast/container.tsx +171 -0
  157. package/src/components/Toast/index.tsx +29 -0
  158. package/src/components/Tooltip/_.stories.tsx +106 -0
  159. package/src/components/Tooltip/_.style.ts +27 -0
  160. package/src/components/Tooltip/_.test.tsx +54 -0
  161. package/src/components/Tooltip/_.types.ts +31 -0
  162. package/src/components/Tooltip/index.tsx +80 -0
  163. package/src/components/developers/AmirHossein.tsx +149 -0
  164. package/src/components/developers/Fardin.tsx +130 -0
  165. package/src/components/developers/Maryam.tsx +260 -0
  166. package/src/components/developers/Milad.tsx +431 -0
  167. package/src/components/developers/Rasoul.tsx +198 -0
  168. package/src/components/index.ts +28 -0
  169. package/src/components/ui/accordion.tsx +162 -0
  170. package/src/components/ui/avatars-component/avatar-description.tsx +30 -0
  171. package/src/components/ui/avatars-component/avatar-groups.tsx +68 -0
  172. package/src/components/ui/avatars-component/avatar-single.tsx +50 -0
  173. package/src/components/ui/card.tsx +92 -0
  174. package/src/components/ui/checkbox-group/plan-card/basic/_.test.tsx +66 -0
  175. package/src/components/ui/checkbox-group/plan-card/basic/index.tsx +70 -0
  176. package/src/components/ui/checkbox-group/plan-card/with-header/_.test.tsx +110 -0
  177. package/src/components/ui/checkbox-group/plan-card/with-header/header.test.tsx +96 -0
  178. package/src/components/ui/checkbox-group/plan-card/with-header/header.tsx +74 -0
  179. package/src/components/ui/checkbox-group/plan-card/with-header/index.tsx +65 -0
  180. package/src/components/ui/file-content/File-content.tsx +43 -0
  181. package/src/components/ui/file-uploader-components/file-uploader-box.tsx +76 -0
  182. package/src/components/ui/file-uploader-components/file-uploader-item.tsx +64 -0
  183. package/src/components/ui/icon-wrapper/_.test.tsx +60 -0
  184. package/src/components/ui/icon-wrapper/index.tsx +19 -0
  185. package/src/components/ui/input-component/input-label.tsx +11 -0
  186. package/src/components/ui/number.tsx +18 -0
  187. package/src/components/ui/pagination/card-minimal-center-align.tsx +96 -0
  188. package/src/components/ui/pagination/card-minimal-right-aligne.tsx +90 -0
  189. package/src/components/ui/pagination/default-pagination.tsx +128 -0
  190. package/src/components/ui/pagination/get-pagination-item.tsx +36 -0
  191. package/src/components/ui/pagination/pagination-card-button-group-aligned.tsx +94 -0
  192. package/src/components/ui/pagination/pagination-card-minimal-left-aligned.tsx +90 -0
  193. package/src/components/ui/pagination/pagination-content.tsx +15 -0
  194. package/src/components/ui/pagination/pagination-item.tsx +11 -0
  195. package/src/components/ui/pagination/pagination-link.tsx +42 -0
  196. package/src/components/ui/tab-components/tabs-content.tsx +15 -0
  197. package/src/components/ui/tab-components/tabs-list.tsx +27 -0
  198. package/src/components/ui/tab-components/tabs-trigger.tsx +25 -0
  199. package/src/components/ui/text-content-wrapper.tsx +36 -0
  200. package/src/hooks/useClickOutside.ts +23 -0
  201. package/src/icons/general/ArrowLeft.tsx +31 -0
  202. package/src/icons/general/ArrowRight.tsx +31 -0
  203. package/src/icons/general/activity-heart.tsx +31 -0
  204. package/src/icons/general/activity.tsx +31 -0
  205. package/src/icons/general/anchor.tsx +31 -0
  206. package/src/icons/general/archive.tsx +31 -0
  207. package/src/icons/general/arrow-left.tsx +25 -0
  208. package/src/icons/general/arrow-right.tsx +25 -0
  209. package/src/icons/general/asterisk-01.tsx +31 -0
  210. package/src/icons/general/asterisk-02.tsx +31 -0
  211. package/src/icons/general/at-sign.tsx +31 -0
  212. package/src/icons/general/attention-mark.tsx +43 -0
  213. package/src/icons/general/bookmark-add.tsx +31 -0
  214. package/src/icons/general/bookmark.tsx +31 -0
  215. package/src/icons/general/chevron-left.tsx +25 -0
  216. package/src/icons/general/chevron-right.tsx +25 -0
  217. package/src/icons/general/circle-minues.tsx +25 -0
  218. package/src/icons/general/circle-plus.tsx +25 -0
  219. package/src/icons/general/circle-question-mark.tsx +32 -0
  220. package/src/icons/general/circle.tsx +32 -0
  221. package/src/icons/general/copy.tsx +43 -0
  222. package/src/icons/general/email.tsx +32 -0
  223. package/src/icons/general/home.tsx +25 -0
  224. package/src/icons/general/layer.tsx +36 -0
  225. package/src/icons/general/leading.tsx +19 -0
  226. package/src/icons/general/master-card.tsx +37 -0
  227. package/src/icons/general/minus.tsx +36 -0
  228. package/src/icons/general/plus.tsx +19 -0
  229. package/src/icons/general/remove.tsx +32 -0
  230. package/src/icons/general/slash-divider.tsx +26 -0
  231. package/src/icons/general/tick-box.tsx +37 -0
  232. package/src/icons/general/trailing.tsx +19 -0
  233. package/src/icons/general/unkown-format.tsx +25 -0
  234. package/src/icons/general/visa-card.tsx +38 -0
  235. package/src/icons/general/x-close.tsx +35 -0
  236. package/src/icons/icons.type.ts +7 -0
  237. package/src/index.css +21 -0
  238. package/src/index.ts +3 -0
  239. package/src/lib/utils.ts +6 -0
  240. package/src/lib/zIndexUtils.ts +2 -0
  241. package/src/main.tsx +50 -0
  242. package/src/vite-env.d.ts +1 -0
  243. package/tests/setup.ts +8 -0
  244. package/tsconfig.app.json +31 -0
  245. package/tsconfig.json +7 -0
  246. package/tsconfig.node.json +24 -0
  247. package/tsconfig.rollup.json +12 -0
  248. package/vite.config.ts +20 -0
  249. package/vitest.config.ts +47 -0
@@ -0,0 +1,174 @@
1
+ import { render, screen } from "@testing-library/react";
2
+ import { describe, it, expect } from "vitest";
3
+ import { Tabs } from ".";
4
+
5
+ describe("Tabs Component", () => {
6
+ it("renders with default horizontal direction and dir rtl", () => {
7
+ const { container } = render(
8
+ <Tabs className="custom-tabs" defaultValue="tab1">
9
+ <Tabs.Content value="tab1">Content</Tabs.Content>
10
+ </Tabs>
11
+ );
12
+ const tabsRoot = container.querySelector('[data-slot="tabs"]');
13
+ expect(tabsRoot).toBeDefined();
14
+ expect(tabsRoot).toHaveClass("flex-col");
15
+ expect(tabsRoot).toHaveClass("custom-tabs");
16
+ expect(tabsRoot).toHaveAttribute("dir", "rtl");
17
+ });
18
+
19
+ it("renders with vertical direction when direction is 'vertical'", () => {
20
+ const { container } = render(
21
+ <Tabs direction="vertical" defaultValue="tab1">
22
+ <Tabs.Content value="tab1">Content</Tabs.Content>
23
+ </Tabs>
24
+ );
25
+ const tabsRoot = container.querySelector('[data-slot="tabs"]');
26
+ expect(tabsRoot).toBeDefined();
27
+ expect(tabsRoot).toHaveClass("flex-row");
28
+ });
29
+ });
30
+
31
+ describe("Tabs.List Component", () => {
32
+ it("renders and applies variant styles with fullWidth true", () => {
33
+ render(
34
+ <Tabs defaultValue="tab1">
35
+ <Tabs.List fullWidth listVariant="brand" direction="horizontal">
36
+ <div>List Child</div>
37
+ </Tabs.List>
38
+ </Tabs>
39
+ );
40
+ const listChild = screen.getByText("List Child");
41
+ const tabsList = listChild.closest('[data-slot="tabs-list"]');
42
+ expect(tabsList).toBeDefined();
43
+ expect(tabsList).toHaveClass("w-full");
44
+ });
45
+
46
+ it("renders and does not include fullWidth class when fullWidth is false", () => {
47
+ render(
48
+ <Tabs defaultValue="tab1">
49
+ <Tabs.List fullWidth={false} listVariant="outlined" direction="vertical">
50
+ <div>List Child</div>
51
+ </Tabs.List>
52
+ </Tabs>
53
+ );
54
+ const listChild = screen.getByText("List Child");
55
+ const tabsList = listChild.closest('[data-slot="tabs-list"]');
56
+ expect(tabsList).toBeDefined();
57
+ expect(tabsList).not.toHaveClass("w-full");
58
+ });
59
+
60
+ it("merges extra class names provided via className prop", () => {
61
+ render(
62
+ <Tabs defaultValue="tab1">
63
+ <Tabs.List
64
+ className="extra-class"
65
+ fullWidth={true}
66
+ listVariant="outlined"
67
+ direction="horizontal"
68
+ >
69
+ <div>List Child</div>
70
+ </Tabs.List>
71
+ </Tabs>
72
+ );
73
+ const listChild = screen.getByText("List Child");
74
+ const tabsList = listChild.closest('[data-slot="tabs-list"]');
75
+ expect(tabsList).toHaveClass("extra-class");
76
+ });
77
+ });
78
+
79
+ describe("Tabs.Trigger Component", () => {
80
+ it("renders and applies variant styles with fullWidth true", () => {
81
+ render(
82
+ <Tabs defaultValue="tab1">
83
+ <Tabs.List>
84
+ <Tabs.Trigger value="tab1" fullWidth triggerVariant="brand">
85
+ Tab Trigger
86
+ </Tabs.Trigger>
87
+ </Tabs.List>
88
+ </Tabs>
89
+ );
90
+ const trigger = screen.getByText("Tab Trigger");
91
+ expect(trigger).toBeDefined();
92
+ expect(trigger).toHaveClass("w-full");
93
+ });
94
+
95
+ it("renders without fullWidth and merges extra class names", () => {
96
+ render(
97
+ <Tabs defaultValue="tab1">
98
+ <Tabs.List>
99
+ <Tabs.Trigger
100
+ value="tab1"
101
+ fullWidth={false}
102
+ triggerVariant="minimal"
103
+ className="trigger-extra"
104
+ >
105
+ Tab Trigger
106
+ </Tabs.Trigger>
107
+ </Tabs.List>
108
+ </Tabs>
109
+ );
110
+ const trigger = screen.getByText("Tab Trigger");
111
+ expect(trigger).toBeDefined();
112
+ expect(trigger).not.toHaveClass("w-full");
113
+ expect(trigger).toHaveClass("trigger-extra");
114
+ });
115
+ it("applies active data-state to selected tab and includes active variant classes", () => {
116
+ render(
117
+ <Tabs defaultValue="tab1">
118
+ <Tabs.List>
119
+ <Tabs.Trigger value="tab1" triggerVariant="brand">
120
+ Tab One
121
+ </Tabs.Trigger>
122
+ <Tabs.Trigger value="tab2" triggerVariant="brand">
123
+ Tab Two
124
+ </Tabs.Trigger>
125
+ </Tabs.List>
126
+ <Tabs.Content value="tab1">Content One</Tabs.Content>
127
+ <Tabs.Content value="tab2">Content Two</Tabs.Content>
128
+ </Tabs>
129
+ );
130
+
131
+ const tabOne = screen.getByText("Tab One");
132
+ const tabTwo = screen.getByText("Tab Two");
133
+
134
+ expect(tabOne).toHaveAttribute("data-state", "active");
135
+ expect(tabTwo).toHaveAttribute("data-state", "inactive");
136
+
137
+ expect(tabOne.className).toContain(
138
+ "data-[state=active]:bg-rbg-brand-primary-alt"
139
+ );
140
+ expect(tabTwo.className).toContain(
141
+ "data-[state=active]:bg-rbg-brand-primary-alt"
142
+ );
143
+ });
144
+ });
145
+
146
+ describe("Tabs.Content Component", () => {
147
+ it("renders and has default classes", () => {
148
+ render(
149
+ <Tabs defaultValue="tab1">
150
+ <Tabs.Content value="tab1">
151
+ <div>Content Body</div>
152
+ </Tabs.Content>
153
+ </Tabs>
154
+ );
155
+ const contentChild = screen.getByText("Content Body");
156
+ const tabsContent = contentChild.closest('[data-slot="tabs-content"]');
157
+ expect(tabsContent).toBeDefined();
158
+ expect(tabsContent).toHaveClass("flex-1");
159
+ expect(tabsContent).toHaveClass("outline-none");
160
+ });
161
+
162
+ it("merges extra class names provided via className prop", () => {
163
+ render(
164
+ <Tabs defaultValue="tab1">
165
+ <Tabs.Content value="tab1" className="content-extra">
166
+ <div>Content Body</div>
167
+ </Tabs.Content>
168
+ </Tabs>
169
+ );
170
+ const contentChild = screen.getByText("Content Body");
171
+ const tabsContent = contentChild.closest('[data-slot="tabs-content"]');
172
+ expect(tabsContent).toHaveClass("content-extra");
173
+ });
174
+ });
@@ -0,0 +1,19 @@
1
+ import * as TabsPrimitive from "@radix-ui/react-tabs";
2
+
3
+ export interface TabsProps
4
+ extends React.ComponentProps<typeof TabsPrimitive.Root> {
5
+ direction?: "vertical" | "horizontal";
6
+ dir?: "rtl" | "ltr";
7
+ }
8
+ export interface TabsListProps
9
+ extends React.ComponentProps<typeof TabsPrimitive.List> {
10
+ fullWidth?: boolean;
11
+ listVariant?: "gray" | "brand" | "outlined" | "bordered" | "minimal";
12
+ direction?: "vertical" | "horizontal";
13
+ }
14
+
15
+ export interface TabsTriggerProps
16
+ extends React.ComponentProps<typeof TabsPrimitive.Trigger> {
17
+ triggerVariant?: "gray" | "brand" | "outlined" | "bordered" | "minimal";
18
+ fullWidth?: boolean;
19
+ }
@@ -0,0 +1,35 @@
1
+ import * as TabsPrimitive from "@radix-ui/react-tabs";
2
+
3
+ import { cn } from "@/lib/utils";
4
+ import { TabsContentComp } from "../ui/tab-components/tabs-content";
5
+ import { TabsListComp } from "../ui/tab-components/tabs-list";
6
+ import { TabsTriggerComp } from "../ui/tab-components/tabs-trigger";
7
+ import { TabsProps } from "./_.type";
8
+
9
+ const TabsRoot = ({
10
+ className,
11
+ direction = "horizontal",
12
+ dir = "rtl",
13
+ ...props
14
+ }: Readonly<TabsProps>) => {
15
+ return (
16
+ <TabsPrimitive.Root
17
+ data-slot="tabs"
18
+ dir={dir}
19
+ className={cn(
20
+ "flex gap-2",
21
+ direction == "horizontal" ? "flex-col" : "flex-row",
22
+ className
23
+ )}
24
+ {...props}
25
+ />
26
+ );
27
+ };
28
+
29
+ const Tabs = Object.assign(TabsRoot, {
30
+ List: TabsListComp,
31
+ Trigger: TabsTriggerComp,
32
+ Content: TabsContentComp,
33
+ });
34
+
35
+ export { Tabs };
@@ -0,0 +1,78 @@
1
+ import type { Meta, StoryObj } from "@storybook/react-vite";
2
+ import { Tag } from "./index"; // or wherever your component is exported
3
+ import type { TagProps } from "./_.types";
4
+
5
+ const meta: Meta<TagProps> = {
6
+ title: "Components/Tag",
7
+ component: Tag,
8
+ tags: ["autodocs"],
9
+ argTypes: {
10
+ size: {
11
+ control: { type: "radio" },
12
+ options: ["sm", "md", "lg"],
13
+ },
14
+ dir: {
15
+ control: { type: "radio" },
16
+ options: ["rtl", "ltr"],
17
+ },
18
+ icon: {
19
+ control: { type: "radio" },
20
+ options: [undefined, "x-close"],
21
+ },
22
+ pin: { control: "boolean" },
23
+ checkbox: { control: "text" },
24
+ number: { control: "number" },
25
+ avatar: { control: "text" },
26
+ },
27
+ args: {
28
+ size: "sm",
29
+ dir: "rtl",
30
+ children: "Tag Label",
31
+ },
32
+ };
33
+
34
+ export default meta;
35
+
36
+ type Story = StoryObj<TagProps>;
37
+
38
+ export const Default: Story = {};
39
+
40
+ export const WithIcon: Story = {
41
+ args: {
42
+ icon: "x-close",
43
+ },
44
+ };
45
+
46
+ export const WithAvatar: Story = {
47
+ args: {
48
+ avatar: "https://i.pravatar.cc/40?img=3",
49
+ },
50
+ };
51
+
52
+ export const WithNumber: Story = {
53
+ args: {
54
+ number: 7,
55
+ },
56
+ };
57
+
58
+ export const WithCheckbox: Story = {
59
+ args: {
60
+ checkbox: "checkbox-id",
61
+ },
62
+ };
63
+
64
+ export const WithPin: Story = {
65
+ args: {
66
+ pin: true,
67
+ },
68
+ };
69
+
70
+ export const AllFeatures: Story = {
71
+ args: {
72
+ pin: true,
73
+ avatar: "https://i.pravatar.cc/40?img=3",
74
+ icon: "x-close",
75
+ number: 99,
76
+ checkbox: "check-all",
77
+ },
78
+ };
@@ -0,0 +1,71 @@
1
+ import { cva } from "class-variance-authority";
2
+
3
+ const baseStyles =
4
+ "inline-flex items-center h-fit min-w-fit bg-white w-fit rounded-md text-rtext-secondary-700 font-medium border border-rborder-primary";
5
+
6
+ const sizeStyle = {
7
+ sm: "px-2 py-[3px] text-xs gap-1",
8
+ md: "px-[9px] py-0.5 text-sm gap-[5px]",
9
+ lg: "px-2.5 py-1 text-sm gap-1.5",
10
+ };
11
+
12
+ export const tagVariants = cva(baseStyles, {
13
+ variants: {
14
+ size: sizeStyle,
15
+ dir: {
16
+ ltr: "flex-row-reverse",
17
+ rtl: "flex-row",
18
+ },
19
+ icon: {
20
+ "x-close": "x-close",
21
+ },
22
+ // pin: {
23
+ // true: "[&>span]:relative [&>span]:before:content-[''] [&>span]:ms-3 [&>span]:before:absolute [&>span]:before:-start-3 [&>span]:before:top-1/2 [&>span]:before:-translate-y-1/2 [&>span]:before:w-1.5 [&>span]:before:h-1.5 [&>span]:before:rounded-full [&>span]:before:bg-success-500 [&>span]:before:me-1 [&>span]:before:ltr:ms-1",
24
+ // },
25
+ },
26
+ defaultVariants: {
27
+ size: "sm",
28
+ dir: "rtl",
29
+ },
30
+ });
31
+ // checkbox variants
32
+ export const checkboxVariants = cva("", {
33
+ variants: {
34
+ size: {
35
+ sm: "w-3.5 h-3.5",
36
+ md: "w-4 h-4",
37
+ lg: "w-4.5 h-4.5",
38
+ },
39
+ },
40
+ defaultVariants: {
41
+ size: "sm",
42
+ },
43
+ });
44
+ // number variant
45
+ export const numberVariants = cva("", {
46
+ variants: {
47
+ size: {
48
+ sm: "px-1 leading-[var(--line-height-text-xs)]",
49
+ md: "px-[5px] leading-[var(--line-height-text-xs)]",
50
+ lg: "px-1.5 leading-[var(--line-height-text-sm)]",
51
+ },
52
+ },
53
+ defaultVariants: {
54
+ size: "sm",
55
+ },
56
+ });
57
+ // remove icon variants
58
+ export const removeIconVariants = cva("", {
59
+ variants: {
60
+ size: {
61
+ sm: "10",
62
+ md: "12",
63
+ lg: "14",
64
+ },
65
+ },
66
+ defaultVariants: {
67
+ size: "sm",
68
+ },
69
+ });
70
+
71
+ export { baseStyles, sizeStyle };
@@ -0,0 +1,44 @@
1
+ import { render, screen } from "@testing-library/react";
2
+ import "@testing-library/jest-dom";
3
+ import { describe, expect, it } from "vitest";
4
+ import { Tag } from ".";
5
+
6
+ describe("Tag component", () => {
7
+ it("renders children content", () => {
8
+ render(<Tag>Test Tag</Tag>);
9
+ expect(screen.getByText("Test Tag")).toBeInTheDocument();
10
+ });
11
+
12
+ it("renders checkbox if checkbox prop is passed", () => {
13
+ render(<Tag checkbox="check-1">With Checkbox</Tag>);
14
+ expect(screen.getByRole("checkbox")).toBeInTheDocument();
15
+ });
16
+
17
+ it("renders avatar if avatar prop is passed", () => {
18
+ const testAvatar = "/Avatar.png";
19
+ render(<Tag avatar={testAvatar}>With Avatar</Tag>);
20
+
21
+ const img = screen.getByAltText("avatar") as HTMLImageElement;
22
+ expect(img).toBeInTheDocument();
23
+ expect(img.src).toContain(testAvatar);
24
+ });
25
+
26
+ it("renders number if number prop is passed", () => {
27
+ render(<Tag number={42}>With Number</Tag>);
28
+ expect(screen.getByText("42")).toBeInTheDocument();
29
+ });
30
+
31
+ it("renders icon if icon is 'x-close'", () => {
32
+ render(<Tag icon="x-close">With Icon</Tag>);
33
+ const icon =
34
+ screen.getByRole("x-icon", { hidden: true }) ||
35
+ screen.getByTestId("icon-x-close");
36
+ expect(icon).toBeInTheDocument();
37
+ });
38
+
39
+ it("applies custom className", () => {
40
+ render(<Tag className="custom-class">With Class</Tag>);
41
+ const tagElement = screen.getByText("With Class").parentElement;
42
+ expect(tagElement?.className).toContain("custom-class");
43
+ });
44
+ });
@@ -0,0 +1,27 @@
1
+ export type TagProps = {
2
+ pin?: boolean;
3
+ number?: number;
4
+ checkbox?: string;
5
+ checkboxIndex?: number;
6
+ avatar?: string;
7
+ className?: string;
8
+ size?: "sm" | "md" | "lg";
9
+ dir?: "ltr" | "rtl";
10
+ children?: React.ReactNode;
11
+ icon?: "x-close";
12
+ };
13
+
14
+ export type CheckboxProps = {
15
+ value?: string;
16
+ disabled?: boolean;
17
+ checkboxIndex?: number;
18
+ checked?: boolean;
19
+ defaultChecked?: boolean;
20
+ label?: string;
21
+ id: string;
22
+ name?: string;
23
+ onClick?: () => void;
24
+ onChange?: () => void;
25
+ size?: "sm" | "md" | "lg";
26
+ children?: React.ReactNode;
27
+ };
@@ -0,0 +1,46 @@
1
+ import XClose from "@/icons/general/x-close";
2
+ import { cn } from "@/lib/utils";
3
+ import { Checkbox } from "../Checkbox";
4
+ import Number from "../ui/number";
5
+ import { removeIconVariants, tagVariants } from "./_.style";
6
+ import { TagProps } from "./_.types";
7
+
8
+ const Tag = ({
9
+ className,
10
+ size = "sm",
11
+ number,
12
+ pin = false,
13
+ avatar,
14
+ children,
15
+ checkbox,
16
+ dir = "rtl",
17
+ icon,
18
+ checkboxIndex,
19
+ ...props
20
+ }: Readonly<TagProps>) => {
21
+ const iconElement = icon === "x-close" && (
22
+ <XClose
23
+ width={cn(removeIconVariants({ size }))}
24
+ height={cn(removeIconVariants({ size }))}
25
+ stroke="#98A2B3"
26
+ />
27
+ );
28
+
29
+ return (
30
+ <div className={cn(tagVariants({ size, dir, icon }), className)} {...props}>
31
+ {iconElement}
32
+ {number && <Number number={number} size={size} />}
33
+ <span>{children}</span>
34
+ {avatar && (
35
+ <img src={avatar} alt="avatar" className="w-4 h-4 rounded-full" />
36
+ )}
37
+ {pin && <span className="w-1.5 h-1.5 rounded-full bg-current"></span>}
38
+ {checkbox && (
39
+ <Checkbox checkboxIndex={checkboxIndex} size={size} id={checkbox} name={checkbox || ""} />
40
+ )}
41
+ </div>
42
+ );
43
+ }
44
+
45
+ export { Tag };
46
+
@@ -0,0 +1,62 @@
1
+ import { textAreaProps } from "@/components/TextArea/_.types";
2
+ import type { StoryObj } from "@storybook/react-vite";
3
+ import { Meta } from "@storybook/react-vite";
4
+ import { TextArea } from "./";
5
+
6
+ export default {
7
+ title: "Components/TextArea",
8
+ component: TextArea,
9
+ tags: ["autodocs"],
10
+ argTypes: {
11
+ disabled: {
12
+ control: { type: "radio" },
13
+ options: [true, false]
14
+ },
15
+ destructive: {
16
+ control: { type: "radio" },
17
+ options: [true, false]
18
+ },
19
+ helpIcon: {
20
+ control: { type: "radio" },
21
+ options: [true, false]
22
+ },
23
+ },
24
+ args: {
25
+ row: 5,
26
+ disabled: false,
27
+ label: "Description",
28
+ required: true,
29
+ hintText: "This is a hint text to help user.",
30
+ placeholder: "Enter a description...",
31
+ destructive: false,
32
+ destructiveText: "This is an error message.",
33
+ helpIcon: true,
34
+ tooltipProps: {
35
+ text: "This is a tooltip",
36
+ description: "Tooltips are used to describe or identify an element. In most scenarios",
37
+ position: "top",
38
+ dir: "ltr",
39
+ descriptionClassName: "max-w-[260px] w-full",
40
+ },
41
+ },
42
+ } as Meta<typeof TextArea>;
43
+
44
+ type Story = StoryObj<textAreaProps>;
45
+
46
+ export const Default: Story = {};
47
+
48
+ export const CustomLabel: Story = {
49
+ args: {
50
+ label: "Email",
51
+ labelClass: "text-blue-600",
52
+ labelStarClass: "text-red-500",
53
+ },
54
+ };
55
+
56
+ export const InputAutoFocus: Story = {
57
+ args: {
58
+ label: "توضیحات",
59
+ placeholder: "توضیحات را وارد کنید",
60
+ autoFocus: true
61
+ },
62
+ };
@@ -0,0 +1,11 @@
1
+ import {cva} from "class-variance-authority";
2
+
3
+ const baseStyles =
4
+ "rounded-md p-2 shadow-xs w-fit bg-white border border-rborder-primary" +
5
+ " focus:outline-2 focus:outline-rborder-brand disabled:bg-rbg-disabled-subtle disabled:border-rborder-disabled w-full";
6
+
7
+ const destructiveStyles = "!border-2 !border-rborder-error focus:!outline-0"
8
+
9
+ const textAreaVariants = cva(baseStyles)
10
+
11
+ export {baseStyles,destructiveStyles,textAreaVariants};
@@ -0,0 +1,43 @@
1
+ import { fireEvent, render, screen } from "@testing-library/react";
2
+ import { describe, expect, it, vi } from "vitest";
3
+ import { TextArea } from "./index";
4
+
5
+ describe("TextArea component", () => {
6
+ const defaultProps = {
7
+ destructive: false,
8
+ disabled: false,
9
+ destructiveText: "This is an error message.",
10
+ label: "Description",
11
+ helpIcon: true,
12
+ required: true,
13
+ hintText: "This is a hint text to help user.",
14
+ placeholder: "Enter a description...",
15
+ className: "w-fit",
16
+ name:"description"
17
+ };
18
+
19
+ it("calls onChange handler", () => {
20
+ const handleChange = vi.fn();
21
+ render(<TextArea {...defaultProps} onChange={handleChange} />);
22
+ const textarea = screen.getByRole("textbox");
23
+ fireEvent.change(textarea, { target: { value: "Hello world" } });
24
+ expect(handleChange).toHaveBeenCalledTimes(1);
25
+ });
26
+
27
+ it("renders disabled textarea", () => {
28
+ render(<TextArea {...defaultProps} disabled={true} />);
29
+ const textarea = screen.getByRole("textbox");
30
+ expect(textarea).toBeDisabled();
31
+ });
32
+
33
+ it("applies destructive styles when destructive is true", () => {
34
+ render(
35
+ <TextArea
36
+ {...defaultProps}
37
+ destructive={true}
38
+ />
39
+ );
40
+ const textarea = screen.getByRole("textbox");
41
+ expect(textarea.className).toMatch(/!border-2/);
42
+ });
43
+ });
@@ -0,0 +1,29 @@
1
+ import React from "react";
2
+ import { Position } from "../Tooltip/_.types";
3
+
4
+ export type textAreaProps = {
5
+ className?: string;
6
+ row?: number;
7
+ disabled?: boolean;
8
+ id?: string;
9
+ value?: string;
10
+ placeholder?: string;
11
+ destructive?: boolean;
12
+ destructiveText?: string;
13
+ label?: string;
14
+ required?: boolean;
15
+ hintText?: string;
16
+ helpIcon?: boolean;
17
+ name: string;
18
+ onChange?: ((e: React.ChangeEvent<HTMLTextAreaElement>) => void) | (() => void);
19
+ tooltipProps?: {
20
+ text: string,
21
+ description?: string,
22
+ position?: Position,
23
+ dir?: "rtl" | "ltr",
24
+ descriptionClassName?: string,
25
+ };
26
+ labelClass?: string;
27
+ labelStarClass?: string;
28
+ autoFocus?: boolean
29
+ }