@apptimate/ui 1.0.0 → 1.1.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 (29) hide show
  1. package/CHANGELOG.md +7 -7
  2. package/package.json +21 -18
  3. package/src/{Button.tsx → base-components/Button.tsx} +21 -13
  4. package/src/{ChipInput.tsx → base-components/ChipInput.tsx} +1 -1
  5. package/src/base-components/DesktopFilterPopover.tsx +53 -0
  6. package/src/base-components/DesktopSearchPopover.tsx +51 -0
  7. package/src/{Dropdown.tsx → base-components/Dropdown.tsx} +11 -5
  8. package/src/{Input.tsx → base-components/Input.tsx} +8 -7
  9. package/src/base-components/Label.tsx +24 -0
  10. package/src/{Modal.tsx → base-components/Modal.tsx} +21 -7
  11. package/src/base-components/RecordCount.tsx +19 -0
  12. package/src/{SearchableSelect.tsx → base-components/SearchableSelect.tsx} +9 -9
  13. package/src/{Select.tsx → base-components/Select.tsx} +7 -6
  14. package/src/base-components/Table.tsx +83 -0
  15. package/src/base-components/TableMobileOptions.tsx +51 -0
  16. package/src/common-components/Charts.tsx +222 -0
  17. package/src/common-components/DashboardLayout.tsx +462 -0
  18. package/src/index.tsx +25 -18
  19. package/src/Table.tsx +0 -78
  20. /package/src/{Accordion.tsx → base-components/Accordion.tsx} +0 -0
  21. /package/src/{Badge.tsx → base-components/Badge.tsx} +0 -0
  22. /package/src/{ButtonGroup.tsx → base-components/ButtonGroup.tsx} +0 -0
  23. /package/src/{Card.tsx → base-components/Card.tsx} +0 -0
  24. /package/src/{Checkbox.tsx → base-components/Checkbox.tsx} +0 -0
  25. /package/src/{Divider.tsx → base-components/Divider.tsx} +0 -0
  26. /package/src/{EmptyState.tsx → base-components/EmptyState.tsx} +0 -0
  27. /package/src/{HintIcon.tsx → base-components/HintIcon.tsx} +0 -0
  28. /package/src/{Pagination.tsx → base-components/Pagination.tsx} +0 -0
  29. /package/src/{PopConfirm.tsx → base-components/PopConfirm.tsx} +0 -0
@@ -0,0 +1,51 @@
1
+ import React from 'react';
2
+ import { Search, Settings2 } from 'lucide-react';
3
+ import { Dropdown, DropdownItem } from './Dropdown';
4
+ import { Input } from './Input';
5
+
6
+ export interface TableMobileOptionsProps {
7
+ searchValue: string;
8
+ onSearchChange: (value: string) => void;
9
+ searchPlaceholder?: string;
10
+ searchLabel?: string;
11
+ actionsLabel?: string;
12
+ children?: React.ReactNode;
13
+ }
14
+
15
+ export const TableMobileOptions = ({
16
+ searchValue,
17
+ onSearchChange,
18
+ searchPlaceholder = "Search...",
19
+ searchLabel = "Search",
20
+ actionsLabel = "Actions",
21
+ children
22
+ }: TableMobileOptionsProps) => {
23
+ return (
24
+ <Dropdown
25
+ align="right"
26
+ contentClassName="w-[280px] p-2"
27
+ trigger={
28
+ <button className="flex items-center justify-center gap-2 px-3 py-2 rounded-[10px] bg-white border border-gray-200 text-gray-700 hover:bg-gray-50 transition-colors shadow-sm font-bold text-[13px]">
29
+ <Settings2 size={16} /> Options
30
+ </button>
31
+ }
32
+ >
33
+ <div className="px-2 pb-2 pt-1 mb-1 border-b border-gray-100">
34
+ <p className="text-[11px] font-bold text-gray-400 uppercase tracking-wider mb-2">{searchLabel}</p>
35
+ <Input
36
+ placeholder={searchPlaceholder}
37
+ icon={<Search size={16} className="text-gray-400" />}
38
+ className="[&_input]:rounded-[8px] [&_input]:border [&_input]:border-gray-200 [&_input]:bg-white [&_input]:hover:border-gray-300 [&_input]:focus:border-gray-300 w-full"
39
+ value={searchValue}
40
+ onChange={(e) => onSearchChange(e.target.value)}
41
+ />
42
+ </div>
43
+ {children && (
44
+ <div className="px-2 pt-1 pb-1">
45
+ <p className="text-[11px] font-bold text-gray-400 uppercase tracking-wider mb-1">{actionsLabel}</p>
46
+ {children}
47
+ </div>
48
+ )}
49
+ </Dropdown>
50
+ );
51
+ };
@@ -0,0 +1,222 @@
1
+ "use client";
2
+
3
+ import React, { useMemo } from "react";
4
+ import dynamic from "next/dynamic";
5
+
6
+ const ApexChart = dynamic(() => import("react-apexcharts"), { ssr: false });
7
+
8
+ // ── Shared defaults ──────────────────────────────────────────────────
9
+ const defaultFont = "inherit";
10
+ const defaultAxisStyle = { fontSize: "11px", fontWeight: 600, colors: "#94a3b8" } as const;
11
+ const defaultGrid: ApexCharts.ApexOptions["grid"] = {
12
+ borderColor: "#f1f5f9", strokeDashArray: 0,
13
+ xaxis: { lines: { show: false } }, yaxis: { lines: { show: true } },
14
+ padding: { left: 8, right: 8 },
15
+ };
16
+ const defaultAnimations: ApexCharts.ApexOptions["chart"] = {
17
+ animations: { enabled: true, speed: 1000, animateGradually: { enabled: true, delay: 150 }, dynamicAnimation: { enabled: true, speed: 400 } },
18
+ };
19
+
20
+ // ── Types ────────────────────────────────────────────────────────────
21
+ export interface ChartSeries { name: string; data: number[]; color?: string; }
22
+
23
+ export interface AreaChartProps {
24
+ series: ChartSeries[];
25
+ categories: string[];
26
+ height?: number;
27
+ colors?: string[];
28
+ yFormatter?: (val: number) => string;
29
+ xFormatter?: (val: string) => string;
30
+ tooltipYFormatter?: (val: number) => string;
31
+ tooltipXFormatter?: (val: any, opts?: any) => string;
32
+ showToolbar?: boolean;
33
+ showLegend?: boolean;
34
+ legendPosition?: "top" | "bottom";
35
+ enableZoom?: boolean;
36
+ strokeWidth?: number;
37
+ className?: string;
38
+ }
39
+
40
+ export interface LineChartProps extends AreaChartProps {
41
+ strokeDashArray?: number[];
42
+ }
43
+
44
+ export interface BarChartProps {
45
+ series: ChartSeries[];
46
+ categories: string[];
47
+ height?: number;
48
+ colors?: string[];
49
+ horizontal?: boolean;
50
+ stacked?: boolean;
51
+ yFormatter?: (val: number) => string;
52
+ tooltipYFormatter?: (val: number) => string;
53
+ showToolbar?: boolean;
54
+ showLegend?: boolean;
55
+ borderRadius?: number;
56
+ columnWidth?: string;
57
+ className?: string;
58
+ }
59
+
60
+ export interface DonutChartProps {
61
+ series: number[];
62
+ labels: string[];
63
+ height?: number;
64
+ colors?: string[];
65
+ showLegend?: boolean;
66
+ legendPosition?: "top" | "bottom" | "right" | "left";
67
+ className?: string;
68
+ }
69
+
70
+ // ── Area Chart ───────────────────────────────────────────────────────
71
+ export function AreaChart({
72
+ series, categories, height = 350, colors,
73
+ yFormatter = (v) => String(v),
74
+ xFormatter = (v) => v,
75
+ tooltipYFormatter,
76
+ tooltipXFormatter,
77
+ showToolbar = true, showLegend = true, legendPosition = "top",
78
+ enableZoom = true, strokeWidth = 2.5, className = "",
79
+ }: AreaChartProps) {
80
+ const chartColors = colors || series.map(s => s.color).filter(Boolean) as string[];
81
+
82
+ const options = useMemo<ApexCharts.ApexOptions>(() => ({
83
+ chart: {
84
+ type: "area", height, fontFamily: defaultFont, ...defaultAnimations,
85
+ toolbar: { show: showToolbar },
86
+ zoom: { enabled: enableZoom, type: "x", autoScaleYaxis: true },
87
+ },
88
+ colors: chartColors.length ? chartColors : undefined,
89
+ stroke: { curve: "smooth", width: strokeWidth },
90
+ fill: { type: "gradient", gradient: { shadeIntensity: 1, opacityFrom: 0.25, opacityTo: 0.02, stops: [0, 95, 100] } },
91
+ dataLabels: { enabled: false },
92
+ xaxis: {
93
+ categories, type: "category",
94
+ labels: { style: defaultAxisStyle, rotate: -45, rotateAlways: false, formatter: xFormatter },
95
+ axisBorder: { show: false }, axisTicks: { show: false },
96
+ tickAmount: Math.min(categories.length, 12),
97
+ },
98
+ yaxis: { labels: { style: defaultAxisStyle, formatter: yFormatter } },
99
+ grid: defaultGrid,
100
+ tooltip: {
101
+ theme: "dark", shared: true, intersect: false,
102
+ x: tooltipXFormatter ? { formatter: tooltipXFormatter } : undefined,
103
+ y: { formatter: tooltipYFormatter || yFormatter },
104
+ style: { fontSize: "12px" },
105
+ },
106
+ legend: { show: showLegend, position: legendPosition, horizontalAlign: "center", fontSize: "12px", fontWeight: 700, markers: { size: 5, shape: "circle" as const }, itemMargin: { horizontal: 12, vertical: 4 } },
107
+ markers: { size: 0, hover: { size: 6, sizeOffset: 3 } },
108
+ }), [categories, chartColors, height, showToolbar, enableZoom, strokeWidth, showLegend, legendPosition]);
109
+
110
+ return (
111
+ <div className={`w-full ${className}`}>
112
+ <ApexChart options={options} series={series} type="area" height={height} width="100%" />
113
+ </div>
114
+ );
115
+ }
116
+
117
+ // ── Line Chart ───────────────────────────────────────────────────────
118
+ export function LineChart({
119
+ series, categories, height = 350, colors,
120
+ yFormatter = (v) => String(v),
121
+ xFormatter = (v) => v,
122
+ tooltipYFormatter,
123
+ showToolbar = true, showLegend = true, legendPosition = "top",
124
+ enableZoom = true, strokeWidth = 2.5, strokeDashArray, className = "",
125
+ }: LineChartProps) {
126
+ const chartColors = colors || series.map(s => s.color).filter(Boolean) as string[];
127
+
128
+ const options = useMemo<ApexCharts.ApexOptions>(() => ({
129
+ chart: {
130
+ type: "line", height, fontFamily: defaultFont, ...defaultAnimations,
131
+ toolbar: { show: showToolbar },
132
+ zoom: { enabled: enableZoom, type: "x", autoScaleYaxis: true },
133
+ },
134
+ colors: chartColors.length ? chartColors : undefined,
135
+ stroke: { curve: "smooth", width: strokeWidth, dashArray: strokeDashArray },
136
+ dataLabels: { enabled: false },
137
+ xaxis: {
138
+ categories, type: "category",
139
+ labels: { style: defaultAxisStyle, rotate: -45, rotateAlways: false, formatter: xFormatter },
140
+ axisBorder: { show: false }, axisTicks: { show: false },
141
+ tickAmount: Math.min(categories.length, 12),
142
+ },
143
+ yaxis: { labels: { style: defaultAxisStyle, formatter: yFormatter } },
144
+ grid: defaultGrid,
145
+ tooltip: {
146
+ theme: "dark", shared: true, intersect: false,
147
+ y: { formatter: tooltipYFormatter || yFormatter },
148
+ style: { fontSize: "12px" },
149
+ },
150
+ legend: { show: showLegend, position: legendPosition, horizontalAlign: "center", fontSize: "12px", fontWeight: 700, markers: { size: 5, shape: "circle" as const }, itemMargin: { horizontal: 12, vertical: 4 } },
151
+ markers: { size: 4, hover: { size: 6, sizeOffset: 3 } },
152
+ }), [categories, chartColors, height, showToolbar, enableZoom, strokeWidth, strokeDashArray, showLegend, legendPosition]);
153
+
154
+ return (
155
+ <div className={`w-full ${className}`}>
156
+ <ApexChart options={options} series={series} type="line" height={height} width="100%" />
157
+ </div>
158
+ );
159
+ }
160
+
161
+ // ── Bar Chart ────────────────────────────────────────────────────────
162
+ export function BarChart({
163
+ series, categories, height = 350, colors,
164
+ horizontal = false, stacked = false,
165
+ yFormatter = (v) => String(v),
166
+ tooltipYFormatter,
167
+ showToolbar = false, showLegend = true,
168
+ borderRadius = 6, columnWidth = "50%", className = "",
169
+ }: BarChartProps) {
170
+ const chartColors = colors || series.map(s => s.color).filter(Boolean) as string[];
171
+
172
+ const options = useMemo<ApexCharts.ApexOptions>(() => ({
173
+ chart: {
174
+ type: "bar", height, fontFamily: defaultFont, stacked, ...defaultAnimations,
175
+ toolbar: { show: showToolbar },
176
+ },
177
+ colors: chartColors.length ? chartColors : undefined,
178
+ plotOptions: { bar: { horizontal, borderRadius, columnWidth, borderRadiusApplication: "end" as const } },
179
+ dataLabels: { enabled: false },
180
+ xaxis: {
181
+ categories,
182
+ labels: { style: defaultAxisStyle },
183
+ axisBorder: { show: false }, axisTicks: { show: false },
184
+ },
185
+ yaxis: { labels: { style: defaultAxisStyle, formatter: yFormatter } },
186
+ grid: defaultGrid,
187
+ tooltip: {
188
+ theme: "dark", shared: true, intersect: false,
189
+ y: { formatter: tooltipYFormatter || yFormatter },
190
+ style: { fontSize: "12px" },
191
+ },
192
+ legend: { show: showLegend, position: "top", horizontalAlign: "center", fontSize: "12px", fontWeight: 700, markers: { size: 5, shape: "circle" as const }, itemMargin: { horizontal: 12, vertical: 4 } },
193
+ }), [categories, chartColors, height, horizontal, stacked, showToolbar, showLegend, borderRadius, columnWidth]);
194
+
195
+ return (
196
+ <div className={`w-full ${className}`}>
197
+ <ApexChart options={options} series={series} type="bar" height={height} width="100%" />
198
+ </div>
199
+ );
200
+ }
201
+
202
+ // ── Donut Chart ──────────────────────────────────────────────────────
203
+ export function DonutChart({
204
+ series, labels, height = 300, colors,
205
+ showLegend = true, legendPosition = "bottom", className = "",
206
+ }: DonutChartProps) {
207
+ const options = useMemo<ApexCharts.ApexOptions>(() => ({
208
+ chart: { type: "donut", height, fontFamily: defaultFont, ...defaultAnimations },
209
+ colors,
210
+ labels,
211
+ dataLabels: { enabled: true, style: { fontSize: "12px", fontWeight: 700 } },
212
+ plotOptions: { pie: { donut: { size: "65%", labels: { show: true, name: { fontSize: "14px", fontWeight: 700 }, value: { fontSize: "20px", fontWeight: 800 }, total: { show: true, fontSize: "13px", fontWeight: 600, label: "Total" } } } } },
213
+ legend: { show: showLegend, position: legendPosition, fontSize: "12px", fontWeight: 600, markers: { size: 5, shape: "circle" as const }, itemMargin: { horizontal: 8, vertical: 4 } },
214
+ stroke: { width: 2, colors: ["#fff"] },
215
+ }), [labels, colors, height, showLegend, legendPosition]);
216
+
217
+ return (
218
+ <div className={`w-full ${className}`}>
219
+ <ApexChart options={options} series={series} type="donut" height={height} width="100%" />
220
+ </div>
221
+ );
222
+ }