@ayasofyazilim/ui 0.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 (236) hide show
  1. package/__mocks__/canvas.ts +8 -0
  2. package/components.json +21 -0
  3. package/eslint.config.js +4 -0
  4. package/jest-environment.js +37 -0
  5. package/jest.config.ts +47 -0
  6. package/jest.setup.ts +69 -0
  7. package/package.json +124 -0
  8. package/postcss.config.mjs +6 -0
  9. package/src/aria/index.tsx +1 -0
  10. package/src/aria/number-field.tsx +41 -0
  11. package/src/components/.gitkeep +0 -0
  12. package/src/components/accordion.tsx +66 -0
  13. package/src/components/alert-dialog.tsx +157 -0
  14. package/src/components/alert.tsx +70 -0
  15. package/src/components/aspect-ratio.tsx +11 -0
  16. package/src/components/avatar.tsx +53 -0
  17. package/src/components/badge.tsx +67 -0
  18. package/src/components/breadcrumb.tsx +109 -0
  19. package/src/components/button-group.tsx +83 -0
  20. package/src/components/button.tsx +68 -0
  21. package/src/components/calendar.tsx +219 -0
  22. package/src/components/card.tsx +92 -0
  23. package/src/components/carousel.tsx +241 -0
  24. package/src/components/chart.tsx +363 -0
  25. package/src/components/checkbox.tsx +32 -0
  26. package/src/components/collapsible.tsx +33 -0
  27. package/src/components/command.tsx +184 -0
  28. package/src/components/context-menu.tsx +252 -0
  29. package/src/components/dialog.tsx +144 -0
  30. package/src/components/drawer.tsx +135 -0
  31. package/src/components/dropdown-menu.tsx +258 -0
  32. package/src/components/empty.tsx +100 -0
  33. package/src/components/field.tsx +248 -0
  34. package/src/components/form.tsx +169 -0
  35. package/src/components/hover-card.tsx +44 -0
  36. package/src/components/input-group.tsx +170 -0
  37. package/src/components/input-otp.tsx +77 -0
  38. package/src/components/input.tsx +21 -0
  39. package/src/components/item.tsx +193 -0
  40. package/src/components/kbd.tsx +28 -0
  41. package/src/components/label.tsx +24 -0
  42. package/src/components/menubar.tsx +276 -0
  43. package/src/components/navigation-menu.tsx +168 -0
  44. package/src/components/pagination.tsx +130 -0
  45. package/src/components/popover.tsx +88 -0
  46. package/src/components/progress.tsx +31 -0
  47. package/src/components/radio-group.tsx +45 -0
  48. package/src/components/resizable.tsx +56 -0
  49. package/src/components/scroll-area.tsx +58 -0
  50. package/src/components/select.tsx +189 -0
  51. package/src/components/separator.tsx +28 -0
  52. package/src/components/sheet.tsx +140 -0
  53. package/src/components/sidebar.tsx +862 -0
  54. package/src/components/skeleton.tsx +13 -0
  55. package/src/components/slider.tsx +63 -0
  56. package/src/components/sonner.tsx +40 -0
  57. package/src/components/spinner.tsx +16 -0
  58. package/src/components/stepper.tsx +291 -0
  59. package/src/components/switch.tsx +31 -0
  60. package/src/components/table.tsx +133 -0
  61. package/src/components/tabs.tsx +66 -0
  62. package/src/components/textarea.tsx +18 -0
  63. package/src/components/toggle-group.tsx +83 -0
  64. package/src/components/toggle.tsx +47 -0
  65. package/src/components/tooltip.tsx +66 -0
  66. package/src/custom/action-button.tsx +48 -0
  67. package/src/custom/async-select.tsx +287 -0
  68. package/src/custom/awesome-not-found.tsx +116 -0
  69. package/src/custom/charts/area-chart.tsx +147 -0
  70. package/src/custom/charts/bar-chart.tsx +233 -0
  71. package/src/custom/charts/chart-card.tsx +103 -0
  72. package/src/custom/charts/index.tsx +16 -0
  73. package/src/custom/charts/pie-chart.tsx +168 -0
  74. package/src/custom/charts/radar-chart.tsx +126 -0
  75. package/src/custom/checkbox-tree.tsx +100 -0
  76. package/src/custom/combobox.tsx +296 -0
  77. package/src/custom/confirm-dialog.tsx +102 -0
  78. package/src/custom/country-selector.tsx +204 -0
  79. package/src/custom/date-picker/calendar-rac.tsx +109 -0
  80. package/src/custom/date-picker/datefield-rac.tsx +84 -0
  81. package/src/custom/date-picker/index.tsx +273 -0
  82. package/src/custom/date-picker/types/index.ts +4 -0
  83. package/src/custom/date-picker/utils/index.ts +42 -0
  84. package/src/custom/date-picker-old.tsx +50 -0
  85. package/src/custom/date-tooltip.tsx +98 -0
  86. package/src/custom/document-scanner/consts.ts +5 -0
  87. package/src/custom/document-scanner/corner-adjustment/action-buttons.tsx +33 -0
  88. package/src/custom/document-scanner/corner-adjustment/corner-handle.tsx +43 -0
  89. package/src/custom/document-scanner/corner-adjustment/hooks/use-corner-drag.ts +85 -0
  90. package/src/custom/document-scanner/corner-adjustment/index.tsx +125 -0
  91. package/src/custom/document-scanner/corner-adjustment/types.ts +53 -0
  92. package/src/custom/document-scanner/corner-adjustment/utils/clip-path.ts +22 -0
  93. package/src/custom/document-scanner/corner-adjustment/zoom-magnifier.tsx +115 -0
  94. package/src/custom/document-scanner/hooks/use-document-capture.ts +81 -0
  95. package/src/custom/document-scanner/hooks/use-document-scanner.ts +80 -0
  96. package/src/custom/document-scanner/hooks/use-perspective-crop.ts +38 -0
  97. package/src/custom/document-scanner/index.tsx +255 -0
  98. package/src/custom/document-scanner/lib.ts +407 -0
  99. package/src/custom/document-scanner/types.ts +205 -0
  100. package/src/custom/document-scanner/utils/perspective-correction.ts +139 -0
  101. package/src/custom/document-viewer/controllers.tsx +98 -0
  102. package/src/custom/document-viewer/index.tsx +43 -0
  103. package/src/custom/document-viewer/renderers/image.tsx +37 -0
  104. package/src/custom/document-viewer/renderers/index.tsx +2 -0
  105. package/src/custom/document-viewer/renderers/pdf.tsx +105 -0
  106. package/src/custom/email-input/domains.json +159 -0
  107. package/src/custom/email-input/email.tsx +229 -0
  108. package/src/custom/email-input/index.tsx +4 -0
  109. package/src/custom/email-input/types.ts +104 -0
  110. package/src/custom/file-uploader.tsx +541 -0
  111. package/src/custom/filter-component/fields/async-select.tsx +33 -0
  112. package/src/custom/filter-component/fields/date.tsx +60 -0
  113. package/src/custom/filter-component/fields/multi-select.tsx +30 -0
  114. package/src/custom/filter-component/index.tsx +217 -0
  115. package/src/custom/image-canvas.tsx +260 -0
  116. package/src/custom/json-editor.tsx +22 -0
  117. package/src/custom/master-data-grid/components/dialogs/column-settings-dialog.tsx +100 -0
  118. package/src/custom/master-data-grid/components/dialogs/index.ts +1 -0
  119. package/src/custom/master-data-grid/components/filters/client-filter.tsx +368 -0
  120. package/src/custom/master-data-grid/components/filters/filter-input.tsx +256 -0
  121. package/src/custom/master-data-grid/components/filters/index.ts +3 -0
  122. package/src/custom/master-data-grid/components/filters/inline-column-filter.tsx +233 -0
  123. package/src/custom/master-data-grid/components/filters/multi-filter-dialog.tsx +90 -0
  124. package/src/custom/master-data-grid/components/filters/server-filter.tsx +255 -0
  125. package/src/custom/master-data-grid/components/master-data-grid.tsx +472 -0
  126. package/src/custom/master-data-grid/components/pagination/index.ts +1 -0
  127. package/src/custom/master-data-grid/components/pagination/pagination.tsx +178 -0
  128. package/src/custom/master-data-grid/components/table/cell-renderer.tsx +634 -0
  129. package/src/custom/master-data-grid/components/table/header-cell.tsx +162 -0
  130. package/src/custom/master-data-grid/components/table/index.ts +4 -0
  131. package/src/custom/master-data-grid/components/table/table-body-renderer.tsx +113 -0
  132. package/src/custom/master-data-grid/components/table/virtual-body.tsx +138 -0
  133. package/src/custom/master-data-grid/components/toolbar/index.ts +1 -0
  134. package/src/custom/master-data-grid/components/toolbar/toolbar.tsx +314 -0
  135. package/src/custom/master-data-grid/hooks/index.ts +3 -0
  136. package/src/custom/master-data-grid/hooks/use-columns.tsx +332 -0
  137. package/src/custom/master-data-grid/hooks/use-editing.ts +106 -0
  138. package/src/custom/master-data-grid/hooks/use-table-state-reducer.ts +157 -0
  139. package/src/custom/master-data-grid/hooks/use-table-state.ts +31 -0
  140. package/src/custom/master-data-grid/index.ts +16 -0
  141. package/src/custom/master-data-grid/types.ts +466 -0
  142. package/src/custom/master-data-grid/utils/column-generator.tsx +306 -0
  143. package/src/custom/master-data-grid/utils/export-utils.ts +67 -0
  144. package/src/custom/master-data-grid/utils/filter-fns.ts +290 -0
  145. package/src/custom/master-data-grid/utils/index.ts +8 -0
  146. package/src/custom/master-data-grid/utils/pinning-utils.ts +88 -0
  147. package/src/custom/master-data-grid/utils/translation-utils.ts +42 -0
  148. package/src/custom/multi-select.tsx +432 -0
  149. package/src/custom/password-input.tsx +194 -0
  150. package/src/custom/phone-input.tsx +172 -0
  151. package/src/custom/schema-form/custom/index.tsx +1 -0
  152. package/src/custom/schema-form/custom/label.tsx +53 -0
  153. package/src/custom/schema-form/fields/base-input-field.tsx +82 -0
  154. package/src/custom/schema-form/fields/field.tsx +67 -0
  155. package/src/custom/schema-form/fields/index.tsx +5 -0
  156. package/src/custom/schema-form/fields/object.tsx +12 -0
  157. package/src/custom/schema-form/fields/table-array/array-field-item.tsx +90 -0
  158. package/src/custom/schema-form/fields/table-array/array-field-template.tsx +115 -0
  159. package/src/custom/schema-form/index.tsx +259 -0
  160. package/src/custom/schema-form/templates/description.tsx +20 -0
  161. package/src/custom/schema-form/templates/index.tsx +2 -0
  162. package/src/custom/schema-form/templates/submit.tsx +32 -0
  163. package/src/custom/schema-form/types.ts +64 -0
  164. package/src/custom/schema-form/utils/index.ts +4 -0
  165. package/src/custom/schema-form/utils/schema-dependency.ts +655 -0
  166. package/src/custom/schema-form/utils/schemas.ts +289 -0
  167. package/src/custom/schema-form/utils/validation.ts +23 -0
  168. package/src/custom/schema-form/widgets/boolean.tsx +77 -0
  169. package/src/custom/schema-form/widgets/combobox.tsx +274 -0
  170. package/src/custom/schema-form/widgets/date.tsx +59 -0
  171. package/src/custom/schema-form/widgets/email.tsx +34 -0
  172. package/src/custom/schema-form/widgets/index.tsx +10 -0
  173. package/src/custom/schema-form/widgets/password.tsx +40 -0
  174. package/src/custom/schema-form/widgets/phone.tsx +40 -0
  175. package/src/custom/schema-form/widgets/select.tsx +105 -0
  176. package/src/custom/schema-form/widgets/selectable.tsx +25 -0
  177. package/src/custom/schema-form/widgets/string-array.tsx +296 -0
  178. package/src/custom/schema-form/widgets/url.tsx +56 -0
  179. package/src/custom/section-layout-v2.tsx +212 -0
  180. package/src/custom/select-tabs.tsx +109 -0
  181. package/src/custom/selectable.tsx +316 -0
  182. package/src/custom/stepper.tsx +236 -0
  183. package/src/custom/tab-layout.tsx +213 -0
  184. package/src/custom/tanstack-table/fields/index.tsx +12 -0
  185. package/src/custom/tanstack-table/fields/tanstack-table-action-dialogs.tsx +89 -0
  186. package/src/custom/tanstack-table/fields/tanstack-table-column-header.tsx +66 -0
  187. package/src/custom/tanstack-table/fields/tanstack-table-filter-date.tsx +180 -0
  188. package/src/custom/tanstack-table/fields/tanstack-table-filter-faceted.tsx +158 -0
  189. package/src/custom/tanstack-table/fields/tanstack-table-filter-text.tsx +76 -0
  190. package/src/custom/tanstack-table/fields/tanstack-table-pagination.tsx +136 -0
  191. package/src/custom/tanstack-table/fields/tanstack-table-plain-table.tsx +142 -0
  192. package/src/custom/tanstack-table/fields/tanstack-table-row-actions-confirmation.tsx +77 -0
  193. package/src/custom/tanstack-table/fields/tanstack-table-row-actions-custom-dialog.tsx +87 -0
  194. package/src/custom/tanstack-table/fields/tanstack-table-row-actions.tsx +151 -0
  195. package/src/custom/tanstack-table/fields/tanstack-table-table-actions-custom-dialog.tsx +88 -0
  196. package/src/custom/tanstack-table/fields/tanstack-table-table-actions-schemaform-dialog.tsx +47 -0
  197. package/src/custom/tanstack-table/fields/tanstack-table-toolbar.tsx +143 -0
  198. package/src/custom/tanstack-table/fields/tanstack-table-view-options.tsx +171 -0
  199. package/src/custom/tanstack-table/index.tsx +244 -0
  200. package/src/custom/tanstack-table/types/index.ts +328 -0
  201. package/src/custom/tanstack-table/utils/cell-with-actions.tsx +21 -0
  202. package/src/custom/tanstack-table/utils/column-names.ts +26 -0
  203. package/src/custom/tanstack-table/utils/columns-by-row-data.tsx +312 -0
  204. package/src/custom/tanstack-table/utils/editable-columns-by-row-data.tsx +219 -0
  205. package/src/custom/tanstack-table/utils/faceted-boolean-options.tsx +22 -0
  206. package/src/custom/tanstack-table/utils/index.tsx +10 -0
  207. package/src/custom/tanstack-table/utils/pinning-styles.ts +57 -0
  208. package/src/custom/tanstack-table/utils/table.tsx +83 -0
  209. package/src/custom/tanstack-table/utils/test-conditions.ts +17 -0
  210. package/src/custom/timeline.tsx +208 -0
  211. package/src/custom/tree.tsx +200 -0
  212. package/src/custom/tscanify/browser.ts +66 -0
  213. package/src/custom/tscanify/index.ts +51 -0
  214. package/src/custom/tscanify/tscanify-browser.ts +522 -0
  215. package/src/custom/tscanify/tscanify.ts +262 -0
  216. package/src/custom/tscanify/types.ts +22 -0
  217. package/src/custom/webcam.tsx +737 -0
  218. package/src/hooks/.gitkeep +0 -0
  219. package/src/hooks/use-callback-ref.ts +27 -0
  220. package/src/hooks/use-controllable-state.ts +67 -0
  221. package/src/hooks/use-debounce.ts +19 -0
  222. package/src/hooks/use-is-visible.ts +23 -0
  223. package/src/hooks/use-media-query.ts +21 -0
  224. package/src/hooks/use-mobile.ts +21 -0
  225. package/src/hooks/use-on-window-resize.ts +15 -0
  226. package/src/hooks/use-scroll.tsx +22 -0
  227. package/src/lib/utils.ts +61 -0
  228. package/src/lib/zod.ts +2 -0
  229. package/src/styles/core.css +57 -0
  230. package/src/styles/globals.css +130 -0
  231. package/src/test/email-input.test.tsx +217 -0
  232. package/src/test/password-input.test.tsx +92 -0
  233. package/src/test/select-tabs.test.tsx +302 -0
  234. package/src/test/selectable.test.tsx +1093 -0
  235. package/tsconfig.json +13 -0
  236. package/tsconfig.lint.json +8 -0
@@ -0,0 +1,147 @@
1
+ "use client";
2
+
3
+ import {
4
+ Area,
5
+ CartesianGrid,
6
+ AreaChart as RechartsAreaChart,
7
+ XAxis,
8
+ YAxis,
9
+ } from "recharts";
10
+
11
+ import {
12
+ ChartContainer,
13
+ ChartLegend,
14
+ ChartLegendContent,
15
+ ChartTooltip,
16
+ ChartTooltipContent,
17
+ } from "@repo/ayasofyazilim-ui/components/chart";
18
+ import { cn } from "@repo/ayasofyazilim-ui/lib/utils";
19
+ import { ReactNode } from "react";
20
+ import { CurveType } from "recharts/types/shape/Curve";
21
+ import { BaseAxisProps } from "recharts/types/util/types";
22
+ import { CardClassNames, ChartCard } from "./chart-card";
23
+ import { EmptyConfig } from ".";
24
+
25
+ export const description = "An area chart with a legend";
26
+
27
+ type ChartData = Array<{
28
+ [key: string]: number | string;
29
+ }>;
30
+
31
+ type ChartConfig = {
32
+ [key: string]: {
33
+ label: string;
34
+ type?: CurveType;
35
+ color: string;
36
+ };
37
+ };
38
+
39
+ export type AreaChartProps = {
40
+ data: ChartData;
41
+ config: ChartConfig;
42
+ title?: ReactNode;
43
+ description?: ReactNode;
44
+ period?: ReactNode;
45
+ footer?: ReactNode;
46
+ trendText?: ReactNode;
47
+ trendIcon?: ReactNode;
48
+ showLegend?: boolean;
49
+ xAxisTickFormatter?: BaseAxisProps["tickFormatter"];
50
+ classNames?: {
51
+ chart?: {
52
+ container?: string;
53
+ area?: string;
54
+ legend?: string;
55
+ };
56
+ card?: CardClassNames;
57
+ };
58
+ valuePrefix?: string;
59
+ valueSuffix?: string;
60
+ } & EmptyConfig;
61
+
62
+ export function AreaChart({
63
+ data,
64
+ title,
65
+ config,
66
+ description,
67
+ period,
68
+ footer,
69
+ trendText,
70
+ trendIcon,
71
+ showLegend,
72
+ xAxisTickFormatter = (value) => value,
73
+ classNames,
74
+ valuePrefix,
75
+ valueSuffix,
76
+ emptyState,
77
+ }: AreaChartProps) {
78
+ return (
79
+ <ChartCard
80
+ title={title}
81
+ description={description}
82
+ period={period}
83
+ trendText={trendText}
84
+ trendIcon={trendIcon}
85
+ footer={footer}
86
+ classNames={classNames?.card}
87
+ emptyState={data.length === 0 ? emptyState : undefined}
88
+ >
89
+ <ChartContainer
90
+ config={config}
91
+ className={cn("mx-auto max-h-full", classNames?.chart?.container)}
92
+ >
93
+ <RechartsAreaChart
94
+ accessibilityLayer
95
+ data={data}
96
+ className={cn("flex flex-col pb-2", classNames?.chart?.area)}
97
+ margin={{ top: 0, bottom: 0, left: 0, right: 0 }}
98
+ >
99
+ <CartesianGrid vertical={false} />
100
+ <XAxis
101
+ dataKey="label"
102
+ tickMargin={2}
103
+ minTickGap={2}
104
+ tickFormatter={xAxisTickFormatter}
105
+ />
106
+ <YAxis />
107
+ <ChartTooltip
108
+ cursor={false}
109
+ content={
110
+ <ChartTooltipContent
111
+ indicator="line"
112
+ valuePrefix={valuePrefix}
113
+ valueSuffix={valueSuffix}
114
+ />
115
+ }
116
+ />
117
+ {Object.keys(config).map((key) => (
118
+ <Area
119
+ key={key}
120
+ dataKey={key}
121
+ type={config[key]?.type || "monotoneX"}
122
+ fill={config[key]?.color || `var(--color-${key})`}
123
+ fillOpacity={0.4}
124
+ stroke={config[key]?.color || `var(--color-${key})`}
125
+ stackId="a"
126
+ />
127
+ ))}
128
+ {showLegend && (
129
+ <ChartLegend
130
+ wrapperStyle={{
131
+ position: "relative",
132
+ top: "unset",
133
+ left: "unset",
134
+ bottom: "unset",
135
+ right: "unset",
136
+ width: "100%",
137
+ textAlign: "center",
138
+ }}
139
+ className={cn("p-0", classNames?.chart?.legend)}
140
+ content={<ChartLegendContent />}
141
+ />
142
+ )}
143
+ </RechartsAreaChart>
144
+ </ChartContainer>
145
+ </ChartCard>
146
+ );
147
+ }
@@ -0,0 +1,233 @@
1
+ "use client";
2
+
3
+ import {
4
+ ChartConfig,
5
+ ChartContainer,
6
+ ChartLegend,
7
+ ChartLegendContent,
8
+ ChartTooltip,
9
+ ChartTooltipContent,
10
+ } from "@repo/ayasofyazilim-ui/components/chart";
11
+ import { cn } from "@repo/ayasofyazilim-ui/lib/utils";
12
+ import * as React from "react";
13
+ import {
14
+ Bar,
15
+ CartesianGrid,
16
+ BarChart as RechartsBarChart,
17
+ XAxis,
18
+ YAxis,
19
+ } from "recharts";
20
+ import { BaseAxisProps } from "recharts/types/util/types";
21
+ import { ChartData, EmptyConfig } from ".";
22
+ import { CardClassNames, ChartCard } from "./chart-card";
23
+
24
+ export type BarChartProps = {
25
+ data: ChartData;
26
+ config: ChartConfig;
27
+ xAxisKey: string;
28
+ layout?: "vertical" | "horizontal";
29
+ title?: React.ReactNode;
30
+ description?: React.ReactNode;
31
+ period?: React.ReactNode;
32
+ footer?: React.ReactNode;
33
+ trendText?: React.ReactNode;
34
+ showLegend?: boolean;
35
+ trendIcon?: React.ReactNode;
36
+ xAxisTickFormatter?: BaseAxisProps["tickFormatter"];
37
+ yAxisTickFormatter?: BaseAxisProps["tickFormatter"];
38
+ valuePrefix?: string;
39
+ valueSuffix?: string;
40
+ classNames?: {
41
+ chart?: {
42
+ container?: string;
43
+ bar?: string;
44
+ legend?: string;
45
+ };
46
+ card?: CardClassNames;
47
+ };
48
+ } & EmptyConfig;
49
+
50
+ export function BarChart({ layout = "vertical", ...props }: BarChartProps) {
51
+ if (layout === "horizontal") {
52
+ return <HorizontalBarChart {...props} />;
53
+ }
54
+ return <VerticalBarChart {...props} />;
55
+ }
56
+
57
+ function HorizontalBarChart({
58
+ data,
59
+ config,
60
+ xAxisKey,
61
+ title,
62
+ description,
63
+ period,
64
+ footer,
65
+ trendText,
66
+ trendIcon,
67
+ xAxisTickFormatter = (value) => value,
68
+ yAxisTickFormatter = (value) => value,
69
+ classNames,
70
+ showLegend,
71
+ valuePrefix,
72
+ valueSuffix,
73
+ emptyState,
74
+ }: BarChartProps) {
75
+ return (
76
+ <ChartCard
77
+ title={title}
78
+ description={description}
79
+ period={period}
80
+ footer={footer}
81
+ trendText={trendText}
82
+ trendIcon={trendIcon}
83
+ classNames={classNames?.card}
84
+ emptyState={data.length === 0 ? emptyState : undefined}
85
+ >
86
+ <ChartContainer
87
+ config={config}
88
+ className={cn("mx-auto max-h-full", classNames?.chart?.container)}
89
+ >
90
+ <RechartsBarChart
91
+ accessibilityLayer
92
+ data={data}
93
+ layout="vertical"
94
+ className={cn("flex flex-col pb-2", classNames?.chart?.bar)}
95
+ margin={{ top: 0, bottom: 0, left: 0, right: 0 }}
96
+ >
97
+ <CartesianGrid vertical={false} />
98
+ {Object.keys(config).map((key) => (
99
+ <XAxis type="number" dataKey={key} key={key} />
100
+ ))}
101
+ <YAxis
102
+ dataKey={xAxisKey}
103
+ type="category"
104
+ tickLine={false}
105
+ tickMargin={10}
106
+ axisLine={false}
107
+ tickFormatter={yAxisTickFormatter}
108
+ />
109
+ <ChartTooltip
110
+ cursor={false}
111
+ content={
112
+ <ChartTooltipContent
113
+ hideLabel
114
+ valuePrefix={valuePrefix}
115
+ valueSuffix={valueSuffix}
116
+ />
117
+ }
118
+ />
119
+ {Object.keys(config).map((key) => (
120
+ <Bar
121
+ key={key}
122
+ dataKey={key}
123
+ fill={config[key]?.color || "var(--chart-1)"}
124
+ radius={5}
125
+ />
126
+ ))}
127
+ {showLegend && (
128
+ <ChartLegend
129
+ wrapperStyle={{
130
+ position: "relative",
131
+ top: "unset",
132
+ left: "unset",
133
+ bottom: "unset",
134
+ right: "unset",
135
+ width: "100%",
136
+ textAlign: "center",
137
+ }}
138
+ className={cn("p-0", classNames?.chart?.legend)}
139
+ content={<ChartLegendContent />}
140
+ />
141
+ )}
142
+ </RechartsBarChart>
143
+ </ChartContainer>
144
+ </ChartCard>
145
+ );
146
+ }
147
+
148
+ function VerticalBarChart({
149
+ data,
150
+ config,
151
+ xAxisKey,
152
+ title,
153
+ description,
154
+ period,
155
+ footer,
156
+ trendText,
157
+ trendIcon,
158
+ xAxisTickFormatter = (value) => value,
159
+ classNames,
160
+ showLegend,
161
+ valuePrefix,
162
+ valueSuffix,
163
+ emptyState,
164
+ }: BarChartProps) {
165
+ return (
166
+ <ChartCard
167
+ title={title}
168
+ description={description}
169
+ period={period}
170
+ footer={footer}
171
+ trendText={trendText}
172
+ trendIcon={trendIcon}
173
+ classNames={classNames?.card}
174
+ emptyState={data.length === 0 ? emptyState : undefined}
175
+ >
176
+ <ChartContainer
177
+ config={config}
178
+ className={cn("mx-auto max-h-full", classNames?.chart?.container)}
179
+ >
180
+ <RechartsBarChart
181
+ accessibilityLayer
182
+ data={data}
183
+ layout="horizontal"
184
+ className={cn("flex flex-col pb-2", classNames?.chart?.bar)}
185
+ margin={{ top: 0, bottom: 0, left: 0, right: 0 }}
186
+ >
187
+ <CartesianGrid vertical={false} />
188
+ <XAxis
189
+ dataKey={xAxisKey}
190
+ tickLine={false}
191
+ axisLine={false}
192
+ tickMargin={8}
193
+ minTickGap={32}
194
+ tickFormatter={xAxisTickFormatter}
195
+ />
196
+ <YAxis />
197
+ <ChartTooltip
198
+ cursor={false}
199
+ content={
200
+ <ChartTooltipContent
201
+ valuePrefix={valuePrefix}
202
+ valueSuffix={valueSuffix}
203
+ />
204
+ }
205
+ />
206
+ {Object.keys(config).map((key) => (
207
+ <Bar
208
+ key={key}
209
+ dataKey={key}
210
+ fill={config[key]?.color || "var(--chart-1)"}
211
+ radius={0}
212
+ />
213
+ ))}
214
+ {showLegend && (
215
+ <ChartLegend
216
+ wrapperStyle={{
217
+ position: "relative",
218
+ top: "unset",
219
+ left: "unset",
220
+ bottom: "unset",
221
+ right: "unset",
222
+ width: "100%",
223
+ textAlign: "center",
224
+ }}
225
+ className={cn("p-0", classNames?.chart?.legend)}
226
+ content={<ChartLegendContent />}
227
+ />
228
+ )}
229
+ </RechartsBarChart>
230
+ </ChartContainer>
231
+ </ChartCard>
232
+ );
233
+ }
@@ -0,0 +1,103 @@
1
+ import {
2
+ Card,
3
+ CardContent,
4
+ CardDescription,
5
+ CardFooter,
6
+ CardHeader,
7
+ CardTitle,
8
+ } from "@repo/ayasofyazilim-ui/components/card";
9
+ import {
10
+ Empty,
11
+ EmptyDescription,
12
+ EmptyHeader,
13
+ EmptyMedia,
14
+ EmptyTitle,
15
+ } from "@repo/ayasofyazilim-ui/components/empty";
16
+ import { cn } from "@repo/ayasofyazilim-ui/lib/utils";
17
+ import { ReactNode } from "react";
18
+ import { EmptyConfig } from ".";
19
+
20
+ export type CardClassNames = {
21
+ container?: string;
22
+ header?: string;
23
+ content?: string;
24
+ title?: string;
25
+ description?: string;
26
+ footer?: string;
27
+ isEmpty?: string;
28
+ };
29
+
30
+ export function ChartCard({
31
+ title,
32
+ description,
33
+ period,
34
+ header,
35
+ footer,
36
+ trendText,
37
+ trendIcon,
38
+ children,
39
+ classNames,
40
+ emptyState,
41
+ }: {
42
+ title?: ReactNode;
43
+ description?: ReactNode;
44
+ period?: ReactNode;
45
+ header?: ReactNode;
46
+ footer?: ReactNode;
47
+ trendText?: ReactNode;
48
+ trendIcon?: ReactNode;
49
+ children: ReactNode;
50
+ classNames?: CardClassNames;
51
+ } & Partial<EmptyConfig>) {
52
+ return (
53
+ <Card className={cn(classNames?.container)}>
54
+ <CardHeader
55
+ className={cn("items-center pb-4! grid-rows-1", classNames?.header)}
56
+ >
57
+ {title && (
58
+ <CardTitle className={cn("my-auto", classNames?.title)}>
59
+ {title}
60
+ </CardTitle>
61
+ )}
62
+ {period && (
63
+ <CardDescription className={cn(classNames?.description)}>
64
+ {period}
65
+ </CardDescription>
66
+ )}
67
+ {description && (
68
+ <CardDescription className={cn(classNames?.description)}>
69
+ {description}
70
+ </CardDescription>
71
+ )}
72
+ {header}
73
+ </CardHeader>
74
+ <CardContent className={cn("pb-0 relative", classNames?.content)}>
75
+ {emptyState && (
76
+ <div className="absolute inset-0 bg-white/50 z-2">
77
+ <Empty>
78
+ <EmptyHeader>
79
+ <EmptyMedia variant="icon">{emptyState.icon}</EmptyMedia>
80
+ <EmptyTitle>{emptyState.title}</EmptyTitle>
81
+ <EmptyDescription>{emptyState.description}</EmptyDescription>
82
+ </EmptyHeader>
83
+ </Empty>
84
+ </div>
85
+ )}
86
+ {children}
87
+ </CardContent>
88
+ {(trendText || trendIcon) && (
89
+ <CardFooter
90
+ className={cn(
91
+ "flex items-center gap-2 leading-none font-medium",
92
+ classNames?.footer
93
+ )}
94
+ >
95
+ {trendText} {trendIcon}
96
+ </CardFooter>
97
+ )}
98
+ {footer && (
99
+ <CardFooter className={cn(classNames?.footer)}>{footer}</CardFooter>
100
+ )}
101
+ </Card>
102
+ );
103
+ }
@@ -0,0 +1,16 @@
1
+ export * from "./pie-chart";
2
+ export * from "./area-chart";
3
+ export * from "./radar-chart";
4
+ export * from "./bar-chart";
5
+
6
+ export type ChartData = Array<{
7
+ [key: string]: number | string;
8
+ }>;
9
+
10
+ export type EmptyConfig = {
11
+ emptyState: {
12
+ icon: React.ReactNode;
13
+ title: string;
14
+ description: string;
15
+ };
16
+ };
@@ -0,0 +1,168 @@
1
+ import * as React from "react";
2
+ import { useMemo } from "react";
3
+ import { Label, LabelProps, Pie, PieChart as RechartsPieChart } from "recharts";
4
+ import {
5
+ ChartConfig,
6
+ ChartContainer,
7
+ ChartLegend,
8
+ ChartLegendContent,
9
+ ChartTooltip,
10
+ ChartTooltipContent,
11
+ } from "@repo/ayasofyazilim-ui/components/chart";
12
+ import { CardClassNames, ChartCard } from "./chart-card";
13
+ import { cn } from "@repo/ayasofyazilim-ui/lib/utils";
14
+ import { ChartData, EmptyConfig } from ".";
15
+
16
+ export type PieChartProps = {
17
+ data: ChartData;
18
+ config: ChartConfig;
19
+ valueKey: string;
20
+ nameKey: string;
21
+ title?: React.ReactNode;
22
+ description?: React.ReactNode;
23
+ period?: React.ReactNode;
24
+ trendText?: React.ReactNode;
25
+ trendIcon?: React.ReactNode;
26
+ footer?: React.ReactNode;
27
+ totalLabel?: string;
28
+ chartStyle: "donut" | "pie";
29
+ innerRadius?: number;
30
+ strokeWidth?: number;
31
+ valuePrefix?: string;
32
+ valueSuffix?: string;
33
+ showLegend?: boolean;
34
+ classNames?: {
35
+ chart?: {
36
+ container?: string;
37
+ tooltip?: string;
38
+ legend?: string;
39
+ pie?: string;
40
+ };
41
+ card?: CardClassNames;
42
+ };
43
+ } & EmptyConfig;
44
+
45
+ export function PieChart({
46
+ data,
47
+ config,
48
+ valueKey,
49
+ nameKey,
50
+ title,
51
+ description,
52
+ period,
53
+ trendText,
54
+ trendIcon,
55
+ footer,
56
+ totalLabel,
57
+ chartStyle,
58
+ classNames,
59
+ innerRadius,
60
+ strokeWidth,
61
+ valuePrefix,
62
+ valueSuffix,
63
+ showLegend = true,
64
+ emptyState,
65
+ }: PieChartProps) {
66
+ const totalCount = useMemo(
67
+ () => data.reduce((acc, curr) => acc + (Number(curr[valueKey]) || 0), 0),
68
+ [data, valueKey]
69
+ );
70
+
71
+ // Transform data to ChartConfig shape for ChartContainer
72
+ const renderLabelContent = ({
73
+ viewBox,
74
+ }: {
75
+ viewBox?: LabelProps["viewBox"] | null;
76
+ }) => {
77
+ if (viewBox && "cx" in viewBox && "cy" in viewBox) {
78
+ return (
79
+ <text
80
+ x={viewBox.cx}
81
+ y={viewBox.cy}
82
+ textAnchor="middle"
83
+ dominantBaseline="middle"
84
+ >
85
+ <tspan
86
+ x={viewBox.cx}
87
+ y={viewBox.cy}
88
+ className="fill-foreground text-3xl font-bold"
89
+ >
90
+ {valuePrefix} {totalCount.toLocaleString()} {valueSuffix}
91
+ </tspan>
92
+ <tspan
93
+ x={viewBox.cx}
94
+ y={(viewBox.cy || 0) + 24}
95
+ className="fill-muted-foreground"
96
+ >
97
+ {totalLabel}
98
+ </tspan>
99
+ </text>
100
+ );
101
+ }
102
+ return null;
103
+ };
104
+
105
+ return (
106
+ <ChartCard
107
+ title={title}
108
+ description={description}
109
+ period={period}
110
+ footer={footer}
111
+ trendText={trendText}
112
+ trendIcon={trendIcon}
113
+ classNames={classNames?.card}
114
+ emptyState={data.length === 0 ? emptyState : undefined}
115
+ >
116
+ <ChartContainer
117
+ config={config}
118
+ className={cn("max-h-[300px]", classNames?.chart?.container)}
119
+ >
120
+ <RechartsPieChart className={cn("relative", classNames?.chart?.pie)}>
121
+ <ChartTooltip
122
+ cursor={false}
123
+ content={
124
+ <ChartTooltipContent
125
+ valuePrefix={valuePrefix}
126
+ valueSuffix={valueSuffix}
127
+ />
128
+ }
129
+ />
130
+ <Pie
131
+ data={data.map((item, index) => ({
132
+ ...item,
133
+ fill:
134
+ config[String(item[nameKey])]?.color ||
135
+ `var(--chart-${index + 1})`,
136
+ }))}
137
+ className="fixed"
138
+ dataKey={valueKey}
139
+ nameKey={nameKey}
140
+ innerRadius={innerRadius || (chartStyle === "donut" ? 60 : 0)}
141
+ strokeWidth={
142
+ strokeWidth || (chartStyle === "donut" ? 0 : undefined)
143
+ }
144
+ >
145
+ <Label content={renderLabelContent} />
146
+ </Pie>
147
+ {showLegend && (
148
+ <ChartLegend
149
+ wrapperStyle={{
150
+ width: "100%",
151
+ height: 0,
152
+ bottom: 0,
153
+ }}
154
+ content={
155
+ <ChartLegendContent
156
+ className={cn(
157
+ "flex-col absolute size-full inset-0 items-start justify-end w-full text-nowrap gap-1 p-0",
158
+ classNames?.chart?.legend
159
+ )}
160
+ />
161
+ }
162
+ />
163
+ )}
164
+ </RechartsPieChart>
165
+ </ChartContainer>
166
+ </ChartCard>
167
+ );
168
+ }