@pattern-stack/frontend-patterns 0.2.0-alpha.7 → 0.2.0-alpha.9
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.
- package/dist/atoms/components/core/Badge/Badge.d.ts +1 -1
- package/dist/atoms/components/data/DataTable/DataTable.d.ts +2 -2
- package/dist/atoms/components/data/DataTable/DataTable.d.ts.map +1 -1
- package/dist/atoms/components/data/DataTable/DataTable.types.d.ts +40 -2
- package/dist/atoms/components/data/DataTable/DataTable.types.d.ts.map +1 -1
- package/dist/atoms/hooks/index.d.ts +1 -0
- package/dist/atoms/hooks/index.d.ts.map +1 -1
- package/dist/atoms/hooks/useAdaptiveTable.d.ts +49 -0
- package/dist/atoms/hooks/useAdaptiveTable.d.ts.map +1 -0
- package/dist/atoms/hooks/useApi.d.ts +1 -1
- package/dist/atoms/hooks/useApi.d.ts.map +1 -1
- package/dist/atoms/hooks/useResponsiveTable.d.ts +44 -24
- package/dist/atoms/hooks/useResponsiveTable.d.ts.map +1 -1
- package/dist/atoms/shared/config/table-config.d.ts +79 -0
- package/dist/atoms/shared/config/table-config.d.ts.map +1 -0
- package/dist/atoms/shared/index.d.ts +1 -0
- package/dist/atoms/shared/index.d.ts.map +1 -1
- package/dist/atoms/utils/entity-card-mapping.d.ts +1 -1
- package/dist/atoms/utils/entity-card-mapping.d.ts.map +1 -1
- package/dist/index.es.js +559 -180
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +558 -179
- package/dist/index.js.map +1 -1
- package/dist/molecules/layout/navigation-context.d.ts.map +1 -1
- package/dist/templates/factory.d.ts +11 -0
- package/dist/templates/factory.d.ts.map +1 -1
- package/package.json +5 -3
package/dist/index.es.js
CHANGED
|
@@ -7,7 +7,7 @@ import { twMerge } from "tailwind-merge";
|
|
|
7
7
|
import axios from "axios";
|
|
8
8
|
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
9
9
|
import * as React from "react";
|
|
10
|
-
import React__default, { useRef, useState, useEffect, useMemo, forwardRef, useCallback, useContext, createContext, useId, Component } from "react";
|
|
10
|
+
import React__default, { useRef, useState, useEffect, useMemo, forwardRef, useCallback, useContext, createContext, useId, Component, Suspense } from "react";
|
|
11
11
|
import * as SheetPrimitive from "@radix-ui/react-dialog";
|
|
12
12
|
import { Map as Map$1, Calculator, Brain, User, Handshake, Truck, Building, HelpCircle, Info, AlertCircle, Check, ArrowDown, ArrowUp, ArrowLeft, ArrowRight, ChevronUp, ChevronLeft, ChevronDown, ChevronRight, Music, Video, Image, Folder, File, Flag, Tag, Bookmark, Heart, Star, MapPin, Clock, Calendar, Phone, Mail, Unlock, Lock, Share, Upload, Download, Eye, Trash2, Edit, Plus, Search, Bell, Settings, Home, Layout, TrendingUp, Database, BarChart3, Users, Shield, X, Menu, Palette, Circle, Building2, Package, FileText, Loader2, EyeOff, InfoIcon, ChevronsUpDown, AreaChart, LineChart, TrendingDown, Minus, AlertTriangle, Activity, WifiOff, CloudOff, Cloud, CheckCircle, FileX, Sun, Moon, LogOut, Square, Waves, Zap, TreePine, Sparkles, Sunset, DollarSign, ShoppingCart, Target, ExternalLink, MoreHorizontal, Filter, Edit2, Undo2, RefreshCw, History, Save, Copy, Grid3X3, Layers, XCircle, Briefcase } from "lucide-react";
|
|
13
13
|
import * as LabelPrimitive from "@radix-ui/react-label";
|
|
@@ -136,6 +136,141 @@ const RESPONSIVE_CHART_HEIGHTS = {
|
|
|
136
136
|
secondary: DASHBOARD_CHART_HEIGHTS.medium
|
|
137
137
|
}
|
|
138
138
|
};
|
|
139
|
+
const COLUMN_WIDTHS = {
|
|
140
|
+
// Text
|
|
141
|
+
text: 180,
|
|
142
|
+
password: 120,
|
|
143
|
+
// Numbers
|
|
144
|
+
number: 80,
|
|
145
|
+
money: 100,
|
|
146
|
+
percent: 70,
|
|
147
|
+
// Dates
|
|
148
|
+
date: 100,
|
|
149
|
+
datetime: 140,
|
|
150
|
+
// Contact/Links
|
|
151
|
+
email: 180,
|
|
152
|
+
phone: 120,
|
|
153
|
+
url: 160,
|
|
154
|
+
// Visual indicators
|
|
155
|
+
status: 90,
|
|
156
|
+
badge: 90,
|
|
157
|
+
boolean: 60,
|
|
158
|
+
rating: 80,
|
|
159
|
+
color: 60,
|
|
160
|
+
// Entity references
|
|
161
|
+
entity: 140,
|
|
162
|
+
user: 140,
|
|
163
|
+
// Special
|
|
164
|
+
image: 60,
|
|
165
|
+
file: 100,
|
|
166
|
+
json: 200
|
|
167
|
+
};
|
|
168
|
+
const COMPACT_COLUMN_WIDTHS = {
|
|
169
|
+
text: 120,
|
|
170
|
+
// With truncation
|
|
171
|
+
money: 60,
|
|
172
|
+
// $2.5k format
|
|
173
|
+
date: 55,
|
|
174
|
+
// "Dec 5" or "Tu"
|
|
175
|
+
datetime: 65,
|
|
176
|
+
// "5m ago"
|
|
177
|
+
email: 100,
|
|
178
|
+
// Truncated
|
|
179
|
+
phone: 80,
|
|
180
|
+
url: 80,
|
|
181
|
+
entity: 100,
|
|
182
|
+
user: 80,
|
|
183
|
+
json: 80
|
|
184
|
+
};
|
|
185
|
+
const COMPACT_FORMATTERS = {
|
|
186
|
+
money: "compactCurrency",
|
|
187
|
+
// $2,456.99 → $2.5k
|
|
188
|
+
date: "shortDate",
|
|
189
|
+
// 2024-01-15 → Dec 5
|
|
190
|
+
datetime: "relative",
|
|
191
|
+
// 2024-01-15T10:30 → 5m ago
|
|
192
|
+
text: "truncate",
|
|
193
|
+
// Long customer name → Long cust...
|
|
194
|
+
email: "truncate",
|
|
195
|
+
url: "domain",
|
|
196
|
+
// https://example.com/path → example.com
|
|
197
|
+
number: "compact"
|
|
198
|
+
// 1234567 → 1.2M
|
|
199
|
+
};
|
|
200
|
+
const COMPACT_LABELS = {
|
|
201
|
+
// Common field names → short versions
|
|
202
|
+
customer: "Cust",
|
|
203
|
+
description: "Desc",
|
|
204
|
+
quantity: "Qty",
|
|
205
|
+
amount: "Amt",
|
|
206
|
+
total: "Tot",
|
|
207
|
+
priority: "Pri",
|
|
208
|
+
status: "Stat",
|
|
209
|
+
created_at: "Created",
|
|
210
|
+
updated_at: "Updated",
|
|
211
|
+
email: "Email",
|
|
212
|
+
phone: "Ph",
|
|
213
|
+
category: "Cat",
|
|
214
|
+
// Time fields
|
|
215
|
+
time: "Time",
|
|
216
|
+
timeAgo: "Time",
|
|
217
|
+
timestamp: "Time",
|
|
218
|
+
// ID fields
|
|
219
|
+
order_id: "#",
|
|
220
|
+
id: "#",
|
|
221
|
+
transaction_id: "Txn"
|
|
222
|
+
};
|
|
223
|
+
const TABLE_BREAKPOINTS = {
|
|
224
|
+
/** Below this width (px), always use cards */
|
|
225
|
+
minForTable: 400,
|
|
226
|
+
/** Buffer (px) to add when calculating if columns fit */
|
|
227
|
+
widthBuffer: 50,
|
|
228
|
+
/** Minimum columns to show in compact mode */
|
|
229
|
+
minCompactColumns: 3,
|
|
230
|
+
/** Maximum columns in compact mode */
|
|
231
|
+
maxCompactColumns: 6
|
|
232
|
+
};
|
|
233
|
+
const IMPORTANCE_VISIBILITY = {
|
|
234
|
+
full: ["primary", "secondary", "tertiary", "critical", "high", "medium", "low", "minimal"],
|
|
235
|
+
compact: ["primary", "secondary", "critical", "high", "medium"],
|
|
236
|
+
cards: ["primary", "critical", "high"]
|
|
237
|
+
};
|
|
238
|
+
function getColumnWidth(type, mode = "full") {
|
|
239
|
+
if (mode === "compact" && type in COMPACT_COLUMN_WIDTHS) {
|
|
240
|
+
return COMPACT_COLUMN_WIDTHS[type];
|
|
241
|
+
}
|
|
242
|
+
return COLUMN_WIDTHS[type] ?? COLUMN_WIDTHS.text;
|
|
243
|
+
}
|
|
244
|
+
function calculateTableWidth(columns, mode = "full") {
|
|
245
|
+
return columns.reduce((sum, col) => sum + getColumnWidth(col.type, mode), 0);
|
|
246
|
+
}
|
|
247
|
+
function getCompactLabel(fieldName, originalLabel) {
|
|
248
|
+
const normalized = fieldName.toLowerCase();
|
|
249
|
+
return COMPACT_LABELS[normalized] ?? originalLabel;
|
|
250
|
+
}
|
|
251
|
+
function getCompactFormatter(type) {
|
|
252
|
+
return COMPACT_FORMATTERS[type];
|
|
253
|
+
}
|
|
254
|
+
function determineTableMode(containerWidth, columns) {
|
|
255
|
+
const { minForTable, widthBuffer } = TABLE_BREAKPOINTS;
|
|
256
|
+
if (containerWidth < minForTable) {
|
|
257
|
+
return "cards";
|
|
258
|
+
}
|
|
259
|
+
const fullWidth = calculateTableWidth(columns, "full");
|
|
260
|
+
const compactColumns = columns.filter(
|
|
261
|
+
(col) => IMPORTANCE_VISIBILITY.compact.includes(
|
|
262
|
+
col.importance ?? "medium"
|
|
263
|
+
)
|
|
264
|
+
);
|
|
265
|
+
const compactWidth = calculateTableWidth(compactColumns, "compact");
|
|
266
|
+
if (fullWidth + widthBuffer <= containerWidth) {
|
|
267
|
+
return "full";
|
|
268
|
+
}
|
|
269
|
+
if (compactWidth + widthBuffer <= containerWidth) {
|
|
270
|
+
return "compact";
|
|
271
|
+
}
|
|
272
|
+
return "cards";
|
|
273
|
+
}
|
|
139
274
|
const breakpoints = {
|
|
140
275
|
"2xs": 400,
|
|
141
276
|
xs: 500,
|
|
@@ -2009,6 +2144,143 @@ function renderField(value, fieldName, fieldType, breakpoint, item, customRender
|
|
|
2009
2144
|
function cn(...inputs) {
|
|
2010
2145
|
return twMerge(clsx(inputs));
|
|
2011
2146
|
}
|
|
2147
|
+
const IconBadge = ({
|
|
2148
|
+
children,
|
|
2149
|
+
icon,
|
|
2150
|
+
variant = "category",
|
|
2151
|
+
category = 1,
|
|
2152
|
+
status = "neutral",
|
|
2153
|
+
size = "md",
|
|
2154
|
+
interactive = false,
|
|
2155
|
+
onClick,
|
|
2156
|
+
className,
|
|
2157
|
+
tooltip
|
|
2158
|
+
}) => {
|
|
2159
|
+
const currentSize = useResponsiveValue(size);
|
|
2160
|
+
const sizeConfig = responsiveScales.components.iconBadge[currentSize];
|
|
2161
|
+
const sizeClasses2 = {
|
|
2162
|
+
xs: `${(sizeConfig == null ? void 0 : sizeConfig.size) || "w-6 h-6"} ${(sizeConfig == null ? void 0 : sizeConfig.text) || "text-[10px]"} ${(sizeConfig == null ? void 0 : sizeConfig.rounded) || "rounded-md"}`,
|
|
2163
|
+
sm: "w-8 h-8 text-xs rounded-lg",
|
|
2164
|
+
md: "w-10 h-10 text-sm rounded-xl",
|
|
2165
|
+
lg: "w-12 h-12 text-base rounded-xl"
|
|
2166
|
+
};
|
|
2167
|
+
const baseClasses = cn(
|
|
2168
|
+
"inline-flex items-center justify-center font-bold shadow-md",
|
|
2169
|
+
sizeClasses2[currentSize],
|
|
2170
|
+
interactive && [
|
|
2171
|
+
"cursor-pointer",
|
|
2172
|
+
getAnimationClasses({
|
|
2173
|
+
...animationPresets.dataBadge,
|
|
2174
|
+
size: currentSize === "lg" ? "lg" : currentSize === "sm" || currentSize === "xs" ? "sm" : "md"
|
|
2175
|
+
})
|
|
2176
|
+
],
|
|
2177
|
+
className
|
|
2178
|
+
);
|
|
2179
|
+
const gradientClasses = variant === "category" ? `bg-gradient-to-br from-category-${category} to-category-${Math.min(category + 1, 8)}` : variant === "status" ? `bg-gradient-to-br from-status-${status} to-status-${status}` : "bg-gradient-to-br from-category-1 to-category-2";
|
|
2180
|
+
const badge = /* @__PURE__ */ jsxs(
|
|
2181
|
+
"div",
|
|
2182
|
+
{
|
|
2183
|
+
className: cn(baseClasses, gradientClasses, "animate-fade-in"),
|
|
2184
|
+
onClick,
|
|
2185
|
+
role: interactive ? "button" : void 0,
|
|
2186
|
+
tabIndex: interactive ? 0 : void 0,
|
|
2187
|
+
onKeyDown: interactive ? (e) => {
|
|
2188
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
2189
|
+
e.preventDefault();
|
|
2190
|
+
onClick == null ? void 0 : onClick();
|
|
2191
|
+
}
|
|
2192
|
+
} : void 0,
|
|
2193
|
+
"data-component-name": "IconBadge",
|
|
2194
|
+
children: [
|
|
2195
|
+
icon && /* @__PURE__ */ jsx("span", { className: "text-primary-foreground drop-shadow", children: icon }),
|
|
2196
|
+
children && !icon && /* @__PURE__ */ jsx("span", { className: "text-primary-foreground font-bold", children })
|
|
2197
|
+
]
|
|
2198
|
+
}
|
|
2199
|
+
);
|
|
2200
|
+
if (tooltip) {
|
|
2201
|
+
return /* @__PURE__ */ jsx(Tooltip, { content: tooltip, position: "top", size: "sm", children: badge });
|
|
2202
|
+
}
|
|
2203
|
+
return badge;
|
|
2204
|
+
};
|
|
2205
|
+
const valueColorMap = {
|
|
2206
|
+
success: "text-green-600",
|
|
2207
|
+
error: "text-red-600",
|
|
2208
|
+
warning: "text-yellow-600",
|
|
2209
|
+
info: "text-blue-600",
|
|
2210
|
+
neutral: "text-muted-foreground",
|
|
2211
|
+
default: "text-foreground"
|
|
2212
|
+
};
|
|
2213
|
+
function ListCard({
|
|
2214
|
+
icon,
|
|
2215
|
+
title,
|
|
2216
|
+
subtitle,
|
|
2217
|
+
metadata,
|
|
2218
|
+
value,
|
|
2219
|
+
badge,
|
|
2220
|
+
onClick,
|
|
2221
|
+
className,
|
|
2222
|
+
children
|
|
2223
|
+
}) {
|
|
2224
|
+
return /* @__PURE__ */ jsxs(
|
|
2225
|
+
"div",
|
|
2226
|
+
{
|
|
2227
|
+
className: cn(
|
|
2228
|
+
"flex items-start gap-3 p-3 rounded-lg border border-border transition-colors",
|
|
2229
|
+
onClick && "hover:bg-muted/50 cursor-pointer",
|
|
2230
|
+
className
|
|
2231
|
+
),
|
|
2232
|
+
onClick,
|
|
2233
|
+
children: [
|
|
2234
|
+
icon && /* @__PURE__ */ jsx(
|
|
2235
|
+
IconBadge,
|
|
2236
|
+
{
|
|
2237
|
+
variant: icon.variant || "category",
|
|
2238
|
+
category: icon.variant === "category" ? icon.category || 1 : void 0,
|
|
2239
|
+
status: icon.variant === "status" ? icon.status || "neutral" : void 0,
|
|
2240
|
+
size: icon.size || "sm",
|
|
2241
|
+
icon: icon.icon,
|
|
2242
|
+
tooltip: icon.tooltip
|
|
2243
|
+
}
|
|
2244
|
+
),
|
|
2245
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
2246
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-2", children: [
|
|
2247
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1", children: [
|
|
2248
|
+
/* @__PURE__ */ jsx("h4", { className: "text-sm font-medium text-foreground truncate", children: title }),
|
|
2249
|
+
subtitle && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-0.5", children: subtitle }),
|
|
2250
|
+
metadata && metadata.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-3 mt-1", children: metadata.map((item, index) => /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: item }, index)) })
|
|
2251
|
+
] }),
|
|
2252
|
+
(value || badge) && /* @__PURE__ */ jsxs("div", { className: "text-right", children: [
|
|
2253
|
+
value && /* @__PURE__ */ jsx(
|
|
2254
|
+
"p",
|
|
2255
|
+
{
|
|
2256
|
+
className: cn(
|
|
2257
|
+
"text-sm font-semibold",
|
|
2258
|
+
value.variant && valueColorMap[value.variant],
|
|
2259
|
+
value.className
|
|
2260
|
+
),
|
|
2261
|
+
children: value.text
|
|
2262
|
+
}
|
|
2263
|
+
),
|
|
2264
|
+
badge && /* @__PURE__ */ jsx(
|
|
2265
|
+
DataBadge,
|
|
2266
|
+
{
|
|
2267
|
+
variant: badge.variant,
|
|
2268
|
+
status: badge.variant === "status" ? badge.status : void 0,
|
|
2269
|
+
category: badge.variant === "category" ? badge.category : void 0,
|
|
2270
|
+
size: badge.size || "sm",
|
|
2271
|
+
icon: badge.icon,
|
|
2272
|
+
className: "mt-1",
|
|
2273
|
+
children: badge.text
|
|
2274
|
+
}
|
|
2275
|
+
)
|
|
2276
|
+
] })
|
|
2277
|
+
] }),
|
|
2278
|
+
children
|
|
2279
|
+
] })
|
|
2280
|
+
]
|
|
2281
|
+
}
|
|
2282
|
+
);
|
|
2283
|
+
}
|
|
2012
2284
|
const STATUS_COLOR_MAP = {
|
|
2013
2285
|
// Success states
|
|
2014
2286
|
active: "success",
|
|
@@ -2347,7 +2619,6 @@ function getCompactWidth(type) {
|
|
|
2347
2619
|
}
|
|
2348
2620
|
}
|
|
2349
2621
|
function createMobileCardRenderer(columns, mapping, entityType) {
|
|
2350
|
-
const { ListCard: ListCard2 } = require("../components/data/ListCard");
|
|
2351
2622
|
return ({ data, onItemClick }) => /* @__PURE__ */ jsx("div", { className: "space-y-2", children: data.map((item, index) => {
|
|
2352
2623
|
const cardProps = entityToListCardProps(
|
|
2353
2624
|
item,
|
|
@@ -2356,7 +2627,7 @@ function createMobileCardRenderer(columns, mapping, entityType) {
|
|
|
2356
2627
|
entityType
|
|
2357
2628
|
);
|
|
2358
2629
|
return /* @__PURE__ */ jsx(
|
|
2359
|
-
|
|
2630
|
+
ListCard,
|
|
2360
2631
|
{
|
|
2361
2632
|
...cardProps,
|
|
2362
2633
|
onClick: onItemClick ? () => onItemClick(item) : void 0
|
|
@@ -2530,10 +2801,10 @@ function useApiMutation(mutationFn, options) {
|
|
|
2530
2801
|
const queryClient = useQueryClient();
|
|
2531
2802
|
return useMutation({
|
|
2532
2803
|
mutationFn,
|
|
2533
|
-
onSuccess: (
|
|
2804
|
+
onSuccess: (...args) => {
|
|
2534
2805
|
var _a;
|
|
2535
|
-
queryClient.invalidateQueries();
|
|
2536
|
-
(_a = options == null ? void 0 : options.onSuccess) == null ? void 0 : _a.call(options,
|
|
2806
|
+
void queryClient.invalidateQueries({});
|
|
2807
|
+
(_a = options == null ? void 0 : options.onSuccess) == null ? void 0 : _a.call(options, ...args);
|
|
2537
2808
|
},
|
|
2538
2809
|
...options
|
|
2539
2810
|
});
|
|
@@ -2608,43 +2879,87 @@ function useFieldMetadata({
|
|
|
2608
2879
|
}
|
|
2609
2880
|
function useResponsiveTable(options = {}) {
|
|
2610
2881
|
const {
|
|
2882
|
+
columns,
|
|
2611
2883
|
initialView = "full",
|
|
2612
2884
|
autoSwitch = true,
|
|
2613
|
-
minWidthForCompact =
|
|
2885
|
+
minWidthForCompact = TABLE_BREAKPOINTS.minForTable,
|
|
2614
2886
|
debounceMs = 100,
|
|
2615
2887
|
onViewChange
|
|
2616
2888
|
} = options;
|
|
2617
2889
|
const [viewMode, setViewModeState] = useState(initialView);
|
|
2618
2890
|
const [isAutoSwitching, setIsAutoSwitching] = useState(autoSwitch);
|
|
2891
|
+
const [containerWidth, setContainerWidth] = useState(0);
|
|
2619
2892
|
const [overflowState, setOverflowState] = useState({
|
|
2620
2893
|
fullOverflows: false,
|
|
2621
2894
|
compactOverflows: false
|
|
2622
2895
|
});
|
|
2896
|
+
const containerRef = useRef(null);
|
|
2623
2897
|
const fullTableRef = useRef(null);
|
|
2624
2898
|
const compactTableRef = useRef(null);
|
|
2625
2899
|
const debounceTimerRef = useRef(null);
|
|
2626
2900
|
const isTransitioningRef = useRef(false);
|
|
2901
|
+
const compactColumns = useCallback(() => {
|
|
2902
|
+
if (!columns) return null;
|
|
2903
|
+
const validImportance = IMPORTANCE_VISIBILITY.compact;
|
|
2904
|
+
const filtered = columns.filter(
|
|
2905
|
+
(col) => validImportance.includes(col.importance ?? "medium")
|
|
2906
|
+
);
|
|
2907
|
+
const limited = filtered.slice(0, TABLE_BREAKPOINTS.maxCompactColumns);
|
|
2908
|
+
return limited.map((col) => ({
|
|
2909
|
+
...col,
|
|
2910
|
+
label: getCompactLabel(col.field, col.label)
|
|
2911
|
+
}));
|
|
2912
|
+
}, [columns])();
|
|
2913
|
+
const calculatedWidths = useCallback(() => {
|
|
2914
|
+
if (!columns) {
|
|
2915
|
+
return { full: 0, compact: 0, container: containerWidth };
|
|
2916
|
+
}
|
|
2917
|
+
const fullWidth = calculateTableWidth(
|
|
2918
|
+
columns.map((c) => ({ type: c.type })),
|
|
2919
|
+
"full"
|
|
2920
|
+
);
|
|
2921
|
+
const compactCols = compactColumns ?? [];
|
|
2922
|
+
const compactWidth = calculateTableWidth(
|
|
2923
|
+
compactCols.map((c) => ({ type: c.type })),
|
|
2924
|
+
"compact"
|
|
2925
|
+
);
|
|
2926
|
+
return {
|
|
2927
|
+
full: fullWidth,
|
|
2928
|
+
compact: compactWidth,
|
|
2929
|
+
container: containerWidth
|
|
2930
|
+
};
|
|
2931
|
+
}, [columns, compactColumns, containerWidth])();
|
|
2627
2932
|
const hasOverflow = useCallback((element) => {
|
|
2628
2933
|
if (!element) return false;
|
|
2629
2934
|
return element.scrollWidth > element.clientWidth + 2;
|
|
2630
2935
|
}, []);
|
|
2631
2936
|
const determineView = useCallback(() => {
|
|
2632
|
-
var _a, _b, _c, _d;
|
|
2633
|
-
|
|
2634
|
-
|
|
2937
|
+
var _a, _b, _c, _d, _e;
|
|
2938
|
+
if (columns && containerWidth > 0) {
|
|
2939
|
+
const { full, compact } = calculatedWidths;
|
|
2940
|
+
const buffer = TABLE_BREAKPOINTS.widthBuffer;
|
|
2941
|
+
if (containerWidth < minWidthForCompact) {
|
|
2942
|
+
return "cards";
|
|
2943
|
+
}
|
|
2944
|
+
if (full + buffer <= containerWidth) {
|
|
2945
|
+
return "full";
|
|
2946
|
+
}
|
|
2947
|
+
if (compact + buffer <= containerWidth) {
|
|
2948
|
+
return "compact";
|
|
2949
|
+
}
|
|
2950
|
+
return "cards";
|
|
2951
|
+
}
|
|
2952
|
+
const width = ((_a = containerRef.current) == null ? void 0 : _a.clientWidth) || ((_c = (_b = fullTableRef.current) == null ? void 0 : _b.parentElement) == null ? void 0 : _c.clientWidth) || ((_e = (_d = compactTableRef.current) == null ? void 0 : _d.parentElement) == null ? void 0 : _e.clientWidth) || window.innerWidth;
|
|
2953
|
+
if (width < minWidthForCompact) {
|
|
2635
2954
|
return "cards";
|
|
2636
2955
|
}
|
|
2637
2956
|
const fullOverflows = hasOverflow(fullTableRef.current);
|
|
2638
2957
|
const compactOverflows = hasOverflow(compactTableRef.current);
|
|
2639
2958
|
setOverflowState({ fullOverflows, compactOverflows });
|
|
2640
|
-
if (!fullOverflows)
|
|
2641
|
-
|
|
2642
|
-
}
|
|
2643
|
-
if (!compactOverflows) {
|
|
2644
|
-
return "compact";
|
|
2645
|
-
}
|
|
2959
|
+
if (!fullOverflows) return "full";
|
|
2960
|
+
if (!compactOverflows) return "compact";
|
|
2646
2961
|
return "cards";
|
|
2647
|
-
}, [
|
|
2962
|
+
}, [columns, containerWidth, calculatedWidths, minWidthForCompact, hasOverflow]);
|
|
2648
2963
|
const checkAndUpdate = useCallback(() => {
|
|
2649
2964
|
if (!isAutoSwitching || isTransitioningRef.current) return;
|
|
2650
2965
|
if (debounceTimerRef.current) {
|
|
@@ -2676,42 +2991,49 @@ function useResponsiveTable(options = {}) {
|
|
|
2676
2991
|
useEffect(() => {
|
|
2677
2992
|
var _a, _b;
|
|
2678
2993
|
if (!isAutoSwitching) return;
|
|
2679
|
-
const
|
|
2994
|
+
const updateContainerWidth = () => {
|
|
2995
|
+
var _a2;
|
|
2996
|
+
const ref = containerRef.current || ((_a2 = fullTableRef.current) == null ? void 0 : _a2.parentElement);
|
|
2997
|
+
if (ref) {
|
|
2998
|
+
setContainerWidth(ref.clientWidth);
|
|
2999
|
+
}
|
|
3000
|
+
};
|
|
3001
|
+
const initialTimer = setTimeout(updateContainerWidth, 50);
|
|
2680
3002
|
const resizeObserver = new ResizeObserver(() => {
|
|
3003
|
+
updateContainerWidth();
|
|
2681
3004
|
checkAndUpdate();
|
|
2682
3005
|
});
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
if (compactTableRef.current) {
|
|
2687
|
-
resizeObserver.observe(compactTableRef.current);
|
|
3006
|
+
const observeTarget = containerRef.current || ((_a = fullTableRef.current) == null ? void 0 : _a.parentElement) || ((_b = compactTableRef.current) == null ? void 0 : _b.parentElement);
|
|
3007
|
+
if (observeTarget) {
|
|
3008
|
+
resizeObserver.observe(observeTarget);
|
|
2688
3009
|
}
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
resizeObserver.observe(
|
|
3010
|
+
if (!columns) {
|
|
3011
|
+
if (fullTableRef.current) resizeObserver.observe(fullTableRef.current);
|
|
3012
|
+
if (compactTableRef.current) resizeObserver.observe(compactTableRef.current);
|
|
2692
3013
|
}
|
|
2693
3014
|
window.addEventListener("resize", checkAndUpdate);
|
|
2694
3015
|
return () => {
|
|
2695
|
-
clearTimeout(
|
|
2696
|
-
if (debounceTimerRef.current)
|
|
2697
|
-
clearTimeout(debounceTimerRef.current);
|
|
2698
|
-
}
|
|
3016
|
+
clearTimeout(initialTimer);
|
|
3017
|
+
if (debounceTimerRef.current) clearTimeout(debounceTimerRef.current);
|
|
2699
3018
|
resizeObserver.disconnect();
|
|
2700
3019
|
window.removeEventListener("resize", checkAndUpdate);
|
|
2701
3020
|
};
|
|
2702
|
-
}, [isAutoSwitching, checkAndUpdate]);
|
|
3021
|
+
}, [isAutoSwitching, columns, checkAndUpdate]);
|
|
2703
3022
|
useEffect(() => {
|
|
2704
3023
|
if (!isAutoSwitching) return;
|
|
2705
3024
|
const timer = setTimeout(checkAndUpdate, 100);
|
|
2706
3025
|
return () => clearTimeout(timer);
|
|
2707
|
-
}, [viewMode, isAutoSwitching, checkAndUpdate]);
|
|
3026
|
+
}, [viewMode, containerWidth, isAutoSwitching, checkAndUpdate]);
|
|
2708
3027
|
return {
|
|
2709
3028
|
viewMode,
|
|
2710
3029
|
setViewMode,
|
|
2711
3030
|
enableAutoSwitch,
|
|
2712
3031
|
isAutoSwitching,
|
|
3032
|
+
containerRef,
|
|
2713
3033
|
fullTableRef,
|
|
2714
3034
|
compactTableRef,
|
|
3035
|
+
compactColumns,
|
|
3036
|
+
calculatedWidths,
|
|
2715
3037
|
overflowState
|
|
2716
3038
|
};
|
|
2717
3039
|
}
|
|
@@ -2730,6 +3052,154 @@ function useOverflowDetection(ref) {
|
|
|
2730
3052
|
}, [ref]);
|
|
2731
3053
|
return hasOverflow;
|
|
2732
3054
|
}
|
|
3055
|
+
const IMPORTANCE_PRIORITY = {
|
|
3056
|
+
minimal: 0,
|
|
3057
|
+
low: 1,
|
|
3058
|
+
tertiary: 2,
|
|
3059
|
+
medium: 3,
|
|
3060
|
+
secondary: 4,
|
|
3061
|
+
high: 5,
|
|
3062
|
+
critical: 6,
|
|
3063
|
+
primary: 7
|
|
3064
|
+
};
|
|
3065
|
+
function getColumnModeWidth(col, mode) {
|
|
3066
|
+
if (mode === "hidden") return 0;
|
|
3067
|
+
return getColumnWidth(col.type, mode === "compact" ? "compact" : "full");
|
|
3068
|
+
}
|
|
3069
|
+
function calculateAdaptiveWidth(columns, modes) {
|
|
3070
|
+
return columns.reduce((sum, col) => sum + getColumnModeWidth(col, modes[col.field] ?? "full"), 0);
|
|
3071
|
+
}
|
|
3072
|
+
function calculateColumnModes(columns, containerWidth, protectedColumns, minColumnsVisible) {
|
|
3073
|
+
const buffer = TABLE_BREAKPOINTS.widthBuffer;
|
|
3074
|
+
const sortedByImportance = [...columns].sort((a, b) => {
|
|
3075
|
+
const priorityA = IMPORTANCE_PRIORITY[a.importance ?? "tertiary"];
|
|
3076
|
+
const priorityB = IMPORTANCE_PRIORITY[b.importance ?? "tertiary"];
|
|
3077
|
+
return priorityA - priorityB;
|
|
3078
|
+
});
|
|
3079
|
+
const modes = {};
|
|
3080
|
+
columns.forEach((col) => modes[col.field] = "full");
|
|
3081
|
+
let currentWidth = calculateAdaptiveWidth(columns, modes);
|
|
3082
|
+
if (currentWidth + buffer <= containerWidth) {
|
|
3083
|
+
return { modes, degradationLevel: 0 };
|
|
3084
|
+
}
|
|
3085
|
+
let degradationLevel = 1;
|
|
3086
|
+
for (const col of sortedByImportance) {
|
|
3087
|
+
if (protectedColumns.has(col.field)) continue;
|
|
3088
|
+
const priority = IMPORTANCE_PRIORITY[col.importance ?? "tertiary"];
|
|
3089
|
+
if (priority > 2) break;
|
|
3090
|
+
modes[col.field] = "compact";
|
|
3091
|
+
currentWidth = calculateAdaptiveWidth(columns, modes);
|
|
3092
|
+
if (currentWidth + buffer <= containerWidth) return { modes, degradationLevel };
|
|
3093
|
+
}
|
|
3094
|
+
degradationLevel = 2;
|
|
3095
|
+
for (const col of sortedByImportance) {
|
|
3096
|
+
if (protectedColumns.has(col.field)) continue;
|
|
3097
|
+
const priority = IMPORTANCE_PRIORITY[col.importance ?? "tertiary"];
|
|
3098
|
+
if (priority <= 2) continue;
|
|
3099
|
+
if (priority > 4) break;
|
|
3100
|
+
modes[col.field] = "compact";
|
|
3101
|
+
currentWidth = calculateAdaptiveWidth(columns, modes);
|
|
3102
|
+
if (currentWidth + buffer <= containerWidth) return { modes, degradationLevel };
|
|
3103
|
+
}
|
|
3104
|
+
degradationLevel = 3;
|
|
3105
|
+
let visibleCount = columns.length;
|
|
3106
|
+
for (const col of sortedByImportance) {
|
|
3107
|
+
const priority = IMPORTANCE_PRIORITY[col.importance ?? "tertiary"];
|
|
3108
|
+
if (priority > 2) break;
|
|
3109
|
+
if (visibleCount <= minColumnsVisible) break;
|
|
3110
|
+
modes[col.field] = "hidden";
|
|
3111
|
+
visibleCount--;
|
|
3112
|
+
currentWidth = calculateAdaptiveWidth(columns, modes);
|
|
3113
|
+
if (currentWidth + buffer <= containerWidth) return { modes, degradationLevel };
|
|
3114
|
+
}
|
|
3115
|
+
degradationLevel = 4;
|
|
3116
|
+
for (const col of sortedByImportance) {
|
|
3117
|
+
const priority = IMPORTANCE_PRIORITY[col.importance ?? "tertiary"];
|
|
3118
|
+
if (priority <= 2) continue;
|
|
3119
|
+
if (priority > 4) break;
|
|
3120
|
+
if (visibleCount <= minColumnsVisible) break;
|
|
3121
|
+
modes[col.field] = "hidden";
|
|
3122
|
+
visibleCount--;
|
|
3123
|
+
currentWidth = calculateAdaptiveWidth(columns, modes);
|
|
3124
|
+
if (currentWidth + buffer <= containerWidth) return { modes, degradationLevel };
|
|
3125
|
+
}
|
|
3126
|
+
degradationLevel = 5;
|
|
3127
|
+
for (const col of sortedByImportance) {
|
|
3128
|
+
if (modes[col.field] === "hidden") continue;
|
|
3129
|
+
modes[col.field] = "compact";
|
|
3130
|
+
currentWidth = calculateAdaptiveWidth(columns, modes);
|
|
3131
|
+
if (currentWidth + buffer <= containerWidth) return { modes, degradationLevel };
|
|
3132
|
+
}
|
|
3133
|
+
return { modes, degradationLevel: 6 };
|
|
3134
|
+
}
|
|
3135
|
+
function useAdaptiveTable(options) {
|
|
3136
|
+
const {
|
|
3137
|
+
columns,
|
|
3138
|
+
protectedColumns = [],
|
|
3139
|
+
minColumnsVisible = 2,
|
|
3140
|
+
minWidthForTable = TABLE_BREAKPOINTS.minForTable,
|
|
3141
|
+
debounceMs = 100,
|
|
3142
|
+
onModeChange
|
|
3143
|
+
} = options;
|
|
3144
|
+
const containerRef = useRef(null);
|
|
3145
|
+
const [containerWidth, setContainerWidth] = useState(0);
|
|
3146
|
+
const debounceTimerRef = useRef(null);
|
|
3147
|
+
const protectedSet = useMemo(() => new Set(protectedColumns), [protectedColumns]);
|
|
3148
|
+
const { modes: columnModes, degradationLevel } = useMemo(() => {
|
|
3149
|
+
if (containerWidth === 0) {
|
|
3150
|
+
const modes = {};
|
|
3151
|
+
columns.forEach((col) => modes[col.field] = "full");
|
|
3152
|
+
return { modes, degradationLevel: 0 };
|
|
3153
|
+
}
|
|
3154
|
+
return calculateColumnModes(columns, containerWidth, protectedSet, minColumnsVisible);
|
|
3155
|
+
}, [columns, containerWidth, protectedSet, minColumnsVisible]);
|
|
3156
|
+
const visibleColumns = useMemo(() => {
|
|
3157
|
+
return columns.filter((col) => columnModes[col.field] !== "hidden").map(
|
|
3158
|
+
(col) => columnModes[col.field] === "compact" ? { ...col, label: getCompactLabel(col.field, col.label) } : col
|
|
3159
|
+
);
|
|
3160
|
+
}, [columns, columnModes]);
|
|
3161
|
+
const calculatedWidth = useMemo(
|
|
3162
|
+
() => calculateAdaptiveWidth(columns, columnModes),
|
|
3163
|
+
[columns, columnModes]
|
|
3164
|
+
);
|
|
3165
|
+
const viewMode = useMemo(() => {
|
|
3166
|
+
if (containerWidth > 0 && containerWidth < minWidthForTable) return "cards";
|
|
3167
|
+
if (visibleColumns.length < minColumnsVisible) return "cards";
|
|
3168
|
+
return "table";
|
|
3169
|
+
}, [containerWidth, minWidthForTable, visibleColumns.length, minColumnsVisible]);
|
|
3170
|
+
useEffect(() => {
|
|
3171
|
+
const updateWidth = () => {
|
|
3172
|
+
if (containerRef.current) setContainerWidth(containerRef.current.clientWidth);
|
|
3173
|
+
};
|
|
3174
|
+
const initialTimer = setTimeout(updateWidth, 50);
|
|
3175
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
3176
|
+
if (debounceTimerRef.current) clearTimeout(debounceTimerRef.current);
|
|
3177
|
+
debounceTimerRef.current = setTimeout(updateWidth, debounceMs);
|
|
3178
|
+
});
|
|
3179
|
+
if (containerRef.current) resizeObserver.observe(containerRef.current);
|
|
3180
|
+
return () => {
|
|
3181
|
+
clearTimeout(initialTimer);
|
|
3182
|
+
if (debounceTimerRef.current) clearTimeout(debounceTimerRef.current);
|
|
3183
|
+
resizeObserver.disconnect();
|
|
3184
|
+
};
|
|
3185
|
+
}, [debounceMs]);
|
|
3186
|
+
const prevModesRef = useRef(columnModes);
|
|
3187
|
+
useEffect(() => {
|
|
3188
|
+
if (onModeChange && columnModes !== prevModesRef.current) {
|
|
3189
|
+
onModeChange(columnModes);
|
|
3190
|
+
prevModesRef.current = columnModes;
|
|
3191
|
+
}
|
|
3192
|
+
}, [columnModes, onModeChange]);
|
|
3193
|
+
return {
|
|
3194
|
+
containerRef,
|
|
3195
|
+
columnModes,
|
|
3196
|
+
visibleColumns,
|
|
3197
|
+
viewMode,
|
|
3198
|
+
calculatedWidth,
|
|
3199
|
+
containerWidth,
|
|
3200
|
+
degradationLevel
|
|
3201
|
+
};
|
|
3202
|
+
}
|
|
2733
3203
|
function useEntityData(entity, options = {}) {
|
|
2734
3204
|
var _a, _b, _c;
|
|
2735
3205
|
const {
|
|
@@ -4612,8 +5082,9 @@ function normalizeColumn(col) {
|
|
|
4612
5082
|
return col;
|
|
4613
5083
|
}
|
|
4614
5084
|
function DataTable({
|
|
4615
|
-
data,
|
|
4616
|
-
columns,
|
|
5085
|
+
data: dataProp,
|
|
5086
|
+
columns: columnsProp,
|
|
5087
|
+
query,
|
|
4617
5088
|
searchPlaceholder = "Search...",
|
|
4618
5089
|
pageSize = 10,
|
|
4619
5090
|
showPagination = true,
|
|
@@ -4622,12 +5093,12 @@ function DataTable({
|
|
|
4622
5093
|
emptyMessage = "No data available",
|
|
4623
5094
|
className = "",
|
|
4624
5095
|
hover = false,
|
|
4625
|
-
isLoading = false,
|
|
5096
|
+
isLoading: isLoadingProp = false,
|
|
4626
5097
|
loadingItemCount = 5,
|
|
4627
5098
|
responsive = true,
|
|
4628
5099
|
renderMobileCard,
|
|
4629
5100
|
ui,
|
|
4630
|
-
error = null,
|
|
5101
|
+
error: errorProp = null,
|
|
4631
5102
|
errorTitle,
|
|
4632
5103
|
errorRetry,
|
|
4633
5104
|
selectable = false,
|
|
@@ -4642,6 +5113,10 @@ function DataTable({
|
|
|
4642
5113
|
const [currentPage, setCurrentPage] = useState(1);
|
|
4643
5114
|
const currentBreakpoint = useBreakpoint();
|
|
4644
5115
|
const isMobile = currentBreakpoint === "xs" || currentBreakpoint === "2xs" || currentBreakpoint === "sm";
|
|
5116
|
+
const data = dataProp ?? (query == null ? void 0 : query.data) ?? [];
|
|
5117
|
+
const columns = columnsProp ?? (query == null ? void 0 : query.columns) ?? [];
|
|
5118
|
+
const isLoading = isLoadingProp || (query == null ? void 0 : query.isLoading) || (query == null ? void 0 : query.isLoadingMetadata) || false;
|
|
5119
|
+
const error = errorProp ?? (query == null ? void 0 : query.error) ?? (query == null ? void 0 : query.metadataError) ?? null;
|
|
4645
5120
|
const normalizedColumns = useMemo(
|
|
4646
5121
|
() => columns.map((col) => normalizeColumn(col)),
|
|
4647
5122
|
[columns]
|
|
@@ -5028,64 +5503,6 @@ const TableHead = TableHead$1;
|
|
|
5028
5503
|
const TableHeader = TableHeader$1;
|
|
5029
5504
|
const TableRow = TableRow$1;
|
|
5030
5505
|
const TableFooter = TableFooter$1;
|
|
5031
|
-
const IconBadge = ({
|
|
5032
|
-
children,
|
|
5033
|
-
icon,
|
|
5034
|
-
variant = "category",
|
|
5035
|
-
category = 1,
|
|
5036
|
-
status = "neutral",
|
|
5037
|
-
size = "md",
|
|
5038
|
-
interactive = false,
|
|
5039
|
-
onClick,
|
|
5040
|
-
className,
|
|
5041
|
-
tooltip
|
|
5042
|
-
}) => {
|
|
5043
|
-
const currentSize = useResponsiveValue(size);
|
|
5044
|
-
const sizeConfig = responsiveScales.components.iconBadge[currentSize];
|
|
5045
|
-
const sizeClasses2 = {
|
|
5046
|
-
xs: `${(sizeConfig == null ? void 0 : sizeConfig.size) || "w-6 h-6"} ${(sizeConfig == null ? void 0 : sizeConfig.text) || "text-[10px]"} ${(sizeConfig == null ? void 0 : sizeConfig.rounded) || "rounded-md"}`,
|
|
5047
|
-
sm: "w-8 h-8 text-xs rounded-lg",
|
|
5048
|
-
md: "w-10 h-10 text-sm rounded-xl",
|
|
5049
|
-
lg: "w-12 h-12 text-base rounded-xl"
|
|
5050
|
-
};
|
|
5051
|
-
const baseClasses = cn(
|
|
5052
|
-
"inline-flex items-center justify-center font-bold shadow-md",
|
|
5053
|
-
sizeClasses2[currentSize],
|
|
5054
|
-
interactive && [
|
|
5055
|
-
"cursor-pointer",
|
|
5056
|
-
getAnimationClasses({
|
|
5057
|
-
...animationPresets.dataBadge,
|
|
5058
|
-
size: currentSize === "lg" ? "lg" : currentSize === "sm" || currentSize === "xs" ? "sm" : "md"
|
|
5059
|
-
})
|
|
5060
|
-
],
|
|
5061
|
-
className
|
|
5062
|
-
);
|
|
5063
|
-
const gradientClasses = variant === "category" ? `bg-gradient-to-br from-category-${category} to-category-${Math.min(category + 1, 8)}` : variant === "status" ? `bg-gradient-to-br from-status-${status} to-status-${status}` : "bg-gradient-to-br from-category-1 to-category-2";
|
|
5064
|
-
const badge = /* @__PURE__ */ jsxs(
|
|
5065
|
-
"div",
|
|
5066
|
-
{
|
|
5067
|
-
className: cn(baseClasses, gradientClasses, "animate-fade-in"),
|
|
5068
|
-
onClick,
|
|
5069
|
-
role: interactive ? "button" : void 0,
|
|
5070
|
-
tabIndex: interactive ? 0 : void 0,
|
|
5071
|
-
onKeyDown: interactive ? (e) => {
|
|
5072
|
-
if (e.key === "Enter" || e.key === " ") {
|
|
5073
|
-
e.preventDefault();
|
|
5074
|
-
onClick == null ? void 0 : onClick();
|
|
5075
|
-
}
|
|
5076
|
-
} : void 0,
|
|
5077
|
-
"data-component-name": "IconBadge",
|
|
5078
|
-
children: [
|
|
5079
|
-
icon && /* @__PURE__ */ jsx("span", { className: "text-primary-foreground drop-shadow", children: icon }),
|
|
5080
|
-
children && !icon && /* @__PURE__ */ jsx("span", { className: "text-primary-foreground font-bold", children })
|
|
5081
|
-
]
|
|
5082
|
-
}
|
|
5083
|
-
);
|
|
5084
|
-
if (tooltip) {
|
|
5085
|
-
return /* @__PURE__ */ jsx(Tooltip, { content: tooltip, position: "top", size: "sm", children: badge });
|
|
5086
|
-
}
|
|
5087
|
-
return badge;
|
|
5088
|
-
};
|
|
5089
5506
|
const Chart = ({
|
|
5090
5507
|
title,
|
|
5091
5508
|
subtitle,
|
|
@@ -5848,85 +6265,6 @@ const ProgressBar = ({
|
|
|
5848
6265
|
)
|
|
5849
6266
|
] });
|
|
5850
6267
|
};
|
|
5851
|
-
const valueColorMap = {
|
|
5852
|
-
success: "text-green-600",
|
|
5853
|
-
error: "text-red-600",
|
|
5854
|
-
warning: "text-yellow-600",
|
|
5855
|
-
info: "text-blue-600",
|
|
5856
|
-
neutral: "text-muted-foreground",
|
|
5857
|
-
default: "text-foreground"
|
|
5858
|
-
};
|
|
5859
|
-
function ListCard({
|
|
5860
|
-
icon,
|
|
5861
|
-
title,
|
|
5862
|
-
subtitle,
|
|
5863
|
-
metadata,
|
|
5864
|
-
value,
|
|
5865
|
-
badge,
|
|
5866
|
-
onClick,
|
|
5867
|
-
className,
|
|
5868
|
-
children
|
|
5869
|
-
}) {
|
|
5870
|
-
return /* @__PURE__ */ jsxs(
|
|
5871
|
-
"div",
|
|
5872
|
-
{
|
|
5873
|
-
className: cn(
|
|
5874
|
-
"flex items-start gap-3 p-3 rounded-lg border border-border transition-colors",
|
|
5875
|
-
onClick && "hover:bg-muted/50 cursor-pointer",
|
|
5876
|
-
className
|
|
5877
|
-
),
|
|
5878
|
-
onClick,
|
|
5879
|
-
children: [
|
|
5880
|
-
icon && /* @__PURE__ */ jsx(
|
|
5881
|
-
IconBadge,
|
|
5882
|
-
{
|
|
5883
|
-
variant: icon.variant || "category",
|
|
5884
|
-
category: icon.variant === "category" ? icon.category || 1 : void 0,
|
|
5885
|
-
status: icon.variant === "status" ? icon.status || "neutral" : void 0,
|
|
5886
|
-
size: icon.size || "sm",
|
|
5887
|
-
icon: icon.icon,
|
|
5888
|
-
tooltip: icon.tooltip
|
|
5889
|
-
}
|
|
5890
|
-
),
|
|
5891
|
-
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
5892
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-2", children: [
|
|
5893
|
-
/* @__PURE__ */ jsxs("div", { className: "flex-1", children: [
|
|
5894
|
-
/* @__PURE__ */ jsx("h4", { className: "text-sm font-medium text-foreground truncate", children: title }),
|
|
5895
|
-
subtitle && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-0.5", children: subtitle }),
|
|
5896
|
-
metadata && metadata.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-3 mt-1", children: metadata.map((item, index) => /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: item }, index)) })
|
|
5897
|
-
] }),
|
|
5898
|
-
(value || badge) && /* @__PURE__ */ jsxs("div", { className: "text-right", children: [
|
|
5899
|
-
value && /* @__PURE__ */ jsx(
|
|
5900
|
-
"p",
|
|
5901
|
-
{
|
|
5902
|
-
className: cn(
|
|
5903
|
-
"text-sm font-semibold",
|
|
5904
|
-
value.variant && valueColorMap[value.variant],
|
|
5905
|
-
value.className
|
|
5906
|
-
),
|
|
5907
|
-
children: value.text
|
|
5908
|
-
}
|
|
5909
|
-
),
|
|
5910
|
-
badge && /* @__PURE__ */ jsx(
|
|
5911
|
-
DataBadge,
|
|
5912
|
-
{
|
|
5913
|
-
variant: badge.variant,
|
|
5914
|
-
status: badge.variant === "status" ? badge.status : void 0,
|
|
5915
|
-
category: badge.variant === "category" ? badge.category : void 0,
|
|
5916
|
-
size: badge.size || "sm",
|
|
5917
|
-
icon: badge.icon,
|
|
5918
|
-
className: "mt-1",
|
|
5919
|
-
children: badge.text
|
|
5920
|
-
}
|
|
5921
|
-
)
|
|
5922
|
-
] })
|
|
5923
|
-
] }),
|
|
5924
|
-
children
|
|
5925
|
-
] })
|
|
5926
|
-
]
|
|
5927
|
-
}
|
|
5928
|
-
);
|
|
5929
|
-
}
|
|
5930
6268
|
const TruncatedText = ({
|
|
5931
6269
|
text,
|
|
5932
6270
|
className,
|
|
@@ -9247,6 +9585,13 @@ const defaultShowcaseNavigation = [
|
|
|
9247
9585
|
path: "/admin/dashboard",
|
|
9248
9586
|
category: 2
|
|
9249
9587
|
},
|
|
9588
|
+
{
|
|
9589
|
+
value: "admin-dashboard-v2",
|
|
9590
|
+
label: "Admin Dashboard V2",
|
|
9591
|
+
icon: "Shield",
|
|
9592
|
+
path: "/admin/dashboard-v2",
|
|
9593
|
+
category: 2
|
|
9594
|
+
},
|
|
9250
9595
|
{
|
|
9251
9596
|
value: "admin-users",
|
|
9252
9597
|
label: "User Management",
|
|
@@ -9517,7 +9862,6 @@ const Sidebar = ({ className }) => {
|
|
|
9517
9862
|
);
|
|
9518
9863
|
};
|
|
9519
9864
|
const AppHeader = ({ className }) => {
|
|
9520
|
-
const isTrialMode = false;
|
|
9521
9865
|
return /* @__PURE__ */ jsx(
|
|
9522
9866
|
"header",
|
|
9523
9867
|
{
|
|
@@ -9530,7 +9874,7 @@ const AppHeader = ({ className }) => {
|
|
|
9530
9874
|
children: /* @__PURE__ */ jsx("div", { className: "mx-auto max-w-7xl px-4 sm:px-6 lg:px-8", children: /* @__PURE__ */ jsxs("div", { className: "flex h-16 items-center justify-between", children: [
|
|
9531
9875
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
9532
9876
|
/* @__PURE__ */ jsx("h1", { className: "text-xl font-bold text-foreground", children: "Frontend Template" }),
|
|
9533
|
-
|
|
9877
|
+
/* @__PURE__ */ jsx(DataBadge, { variant: "status", status: "info", display: "icon-text", children: "Trial Mode" })
|
|
9534
9878
|
] }),
|
|
9535
9879
|
/* @__PURE__ */ jsx("div", { className: "flex-1 max-w-2xl mx-8", children: /* @__PURE__ */ jsx(
|
|
9536
9880
|
GlobalSearch,
|
|
@@ -14314,18 +14658,41 @@ function createReactApp(config) {
|
|
|
14314
14658
|
enableRouting = true,
|
|
14315
14659
|
auth,
|
|
14316
14660
|
navigation,
|
|
14317
|
-
customProviders = []
|
|
14661
|
+
customProviders = [],
|
|
14662
|
+
persistQueryCache = false,
|
|
14663
|
+
queryCacheKey = "PATTERN_STACK_QUERY_CACHE"
|
|
14318
14664
|
} = appConfig;
|
|
14319
14665
|
const queryClient = new QueryClient({
|
|
14320
14666
|
defaultOptions: {
|
|
14321
14667
|
queries: {
|
|
14322
14668
|
retry: 1,
|
|
14323
14669
|
refetchOnWindowFocus: false,
|
|
14324
|
-
staleTime: 5 * 60 * 1e3
|
|
14670
|
+
staleTime: 5 * 60 * 1e3,
|
|
14325
14671
|
// 5 minutes
|
|
14672
|
+
// Keep data longer when persistence is enabled
|
|
14673
|
+
gcTime: persistQueryCache ? 1e3 * 60 * 60 * 24 : 1e3 * 60 * 5
|
|
14326
14674
|
}
|
|
14327
14675
|
}
|
|
14328
14676
|
});
|
|
14677
|
+
if (persistQueryCache && typeof window !== "undefined") {
|
|
14678
|
+
import("@tanstack/react-query-persist-client").then(({ persistQueryClient }) => {
|
|
14679
|
+
import("@tanstack/query-sync-storage-persister").then(({ createSyncStoragePersister }) => {
|
|
14680
|
+
const persister = createSyncStoragePersister({
|
|
14681
|
+
storage: window.localStorage,
|
|
14682
|
+
key: queryCacheKey
|
|
14683
|
+
});
|
|
14684
|
+
persistQueryClient({
|
|
14685
|
+
queryClient,
|
|
14686
|
+
persister,
|
|
14687
|
+
maxAge: 1e3 * 60 * 60 * 24
|
|
14688
|
+
// 24 hours
|
|
14689
|
+
});
|
|
14690
|
+
console.info("[app] Query cache persistence enabled");
|
|
14691
|
+
});
|
|
14692
|
+
}).catch((err) => {
|
|
14693
|
+
console.warn("[app] Query persistence not available:", err.message);
|
|
14694
|
+
});
|
|
14695
|
+
}
|
|
14329
14696
|
const routes = [];
|
|
14330
14697
|
const DefaultHome = () => /* @__PURE__ */ jsx(DashboardTemplate, { title, description, children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center min-h-[400px] text-center", children: [
|
|
14331
14698
|
/* @__PURE__ */ jsxs("h1", { className: "text-4xl font-bold text-foreground mb-4", children: [
|
|
@@ -14344,7 +14711,7 @@ function createReactApp(config) {
|
|
|
14344
14711
|
] }) });
|
|
14345
14712
|
const createProviderTree = (children) => {
|
|
14346
14713
|
let tree = children;
|
|
14347
|
-
customProviders.reverse().forEach((Provider) => {
|
|
14714
|
+
[...customProviders].reverse().forEach((Provider) => {
|
|
14348
14715
|
tree = /* @__PURE__ */ jsx(Provider, { children: tree }, Provider.name);
|
|
14349
14716
|
});
|
|
14350
14717
|
if (enableRouting) {
|
|
@@ -14387,10 +14754,10 @@ function createReactApp(config) {
|
|
|
14387
14754
|
}
|
|
14388
14755
|
return component;
|
|
14389
14756
|
};
|
|
14390
|
-
const AppContent = () => /* @__PURE__ */ jsx(Routes, { children: /* @__PURE__ */ jsxs(Route, { path: "/", element: /* @__PURE__ */ jsx(AppLayout, {}), children: [
|
|
14757
|
+
const AppContent = () => /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center min-h-screen", children: "Loading..." }), children: /* @__PURE__ */ jsx(Routes, { children: /* @__PURE__ */ jsxs(Route, { path: "/", element: /* @__PURE__ */ jsx(AppLayout, {}), children: [
|
|
14391
14758
|
/* @__PURE__ */ jsx(Route, { index: true, element: wrapWithProtection("/", /* @__PURE__ */ jsx(DefaultHome, {})) }),
|
|
14392
14759
|
routes.map(({ path, component }, index) => /* @__PURE__ */ jsx(Route, { path, element: wrapWithProtection(path, component) }, index))
|
|
14393
|
-
] }) });
|
|
14760
|
+
] }) }) });
|
|
14394
14761
|
return createProviderTree(/* @__PURE__ */ jsx(AppContent, {}));
|
|
14395
14762
|
},
|
|
14396
14763
|
mount(elementId = "root") {
|
|
@@ -17586,6 +17953,10 @@ export {
|
|
|
17586
17953
|
Breadcrumb,
|
|
17587
17954
|
BulkSelectionBar,
|
|
17588
17955
|
Button,
|
|
17956
|
+
COLUMN_WIDTHS,
|
|
17957
|
+
COMPACT_COLUMN_WIDTHS,
|
|
17958
|
+
COMPACT_FORMATTERS,
|
|
17959
|
+
COMPACT_LABELS,
|
|
17589
17960
|
Card,
|
|
17590
17961
|
CardContent,
|
|
17591
17962
|
CardDescription,
|
|
@@ -17644,6 +18015,7 @@ export {
|
|
|
17644
18015
|
FormField,
|
|
17645
18016
|
FormGroup,
|
|
17646
18017
|
GlobalSearch,
|
|
18018
|
+
IMPORTANCE_VISIBILITY,
|
|
17647
18019
|
Icon,
|
|
17648
18020
|
IconBadge,
|
|
17649
18021
|
Input,
|
|
@@ -17699,6 +18071,7 @@ export {
|
|
|
17699
18071
|
StatCard,
|
|
17700
18072
|
StyleGuide,
|
|
17701
18073
|
Switch,
|
|
18074
|
+
TABLE_BREAKPOINTS,
|
|
17702
18075
|
Table,
|
|
17703
18076
|
TableBody,
|
|
17704
18077
|
TableCaption,
|
|
@@ -17721,6 +18094,7 @@ export {
|
|
|
17721
18094
|
animationPresets,
|
|
17722
18095
|
apiClient,
|
|
17723
18096
|
breakpoints,
|
|
18097
|
+
calculateTableWidth,
|
|
17724
18098
|
cn,
|
|
17725
18099
|
createAPIDataTemplate,
|
|
17726
18100
|
createApiClient,
|
|
@@ -17730,6 +18104,7 @@ export {
|
|
|
17730
18104
|
defaultFieldRenderers,
|
|
17731
18105
|
detectBulkOperationType,
|
|
17732
18106
|
detectUIConfig,
|
|
18107
|
+
determineTableMode,
|
|
17733
18108
|
entityToListCardProps,
|
|
17734
18109
|
env,
|
|
17735
18110
|
formatNumberWithTooltip,
|
|
@@ -17737,6 +18112,9 @@ export {
|
|
|
17737
18112
|
generateCompactColumns,
|
|
17738
18113
|
getAnimationClasses,
|
|
17739
18114
|
getChartHeight,
|
|
18115
|
+
getColumnWidth,
|
|
18116
|
+
getCompactFormatter,
|
|
18117
|
+
getCompactLabel,
|
|
17740
18118
|
getContainerHeightClass,
|
|
17741
18119
|
getCurrentBreakpoint,
|
|
17742
18120
|
getFieldType,
|
|
@@ -17755,6 +18133,7 @@ export {
|
|
|
17755
18133
|
responsiveScales,
|
|
17756
18134
|
setGlobalAuthService,
|
|
17757
18135
|
tooltipContent,
|
|
18136
|
+
useAdaptiveTable,
|
|
17758
18137
|
useApiMutation,
|
|
17759
18138
|
useApiQuery,
|
|
17760
18139
|
useAuth,
|