@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.js
CHANGED
|
@@ -179,6 +179,141 @@ const RESPONSIVE_CHART_HEIGHTS = {
|
|
|
179
179
|
secondary: DASHBOARD_CHART_HEIGHTS.medium
|
|
180
180
|
}
|
|
181
181
|
};
|
|
182
|
+
const COLUMN_WIDTHS = {
|
|
183
|
+
// Text
|
|
184
|
+
text: 180,
|
|
185
|
+
password: 120,
|
|
186
|
+
// Numbers
|
|
187
|
+
number: 80,
|
|
188
|
+
money: 100,
|
|
189
|
+
percent: 70,
|
|
190
|
+
// Dates
|
|
191
|
+
date: 100,
|
|
192
|
+
datetime: 140,
|
|
193
|
+
// Contact/Links
|
|
194
|
+
email: 180,
|
|
195
|
+
phone: 120,
|
|
196
|
+
url: 160,
|
|
197
|
+
// Visual indicators
|
|
198
|
+
status: 90,
|
|
199
|
+
badge: 90,
|
|
200
|
+
boolean: 60,
|
|
201
|
+
rating: 80,
|
|
202
|
+
color: 60,
|
|
203
|
+
// Entity references
|
|
204
|
+
entity: 140,
|
|
205
|
+
user: 140,
|
|
206
|
+
// Special
|
|
207
|
+
image: 60,
|
|
208
|
+
file: 100,
|
|
209
|
+
json: 200
|
|
210
|
+
};
|
|
211
|
+
const COMPACT_COLUMN_WIDTHS = {
|
|
212
|
+
text: 120,
|
|
213
|
+
// With truncation
|
|
214
|
+
money: 60,
|
|
215
|
+
// $2.5k format
|
|
216
|
+
date: 55,
|
|
217
|
+
// "Dec 5" or "Tu"
|
|
218
|
+
datetime: 65,
|
|
219
|
+
// "5m ago"
|
|
220
|
+
email: 100,
|
|
221
|
+
// Truncated
|
|
222
|
+
phone: 80,
|
|
223
|
+
url: 80,
|
|
224
|
+
entity: 100,
|
|
225
|
+
user: 80,
|
|
226
|
+
json: 80
|
|
227
|
+
};
|
|
228
|
+
const COMPACT_FORMATTERS = {
|
|
229
|
+
money: "compactCurrency",
|
|
230
|
+
// $2,456.99 → $2.5k
|
|
231
|
+
date: "shortDate",
|
|
232
|
+
// 2024-01-15 → Dec 5
|
|
233
|
+
datetime: "relative",
|
|
234
|
+
// 2024-01-15T10:30 → 5m ago
|
|
235
|
+
text: "truncate",
|
|
236
|
+
// Long customer name → Long cust...
|
|
237
|
+
email: "truncate",
|
|
238
|
+
url: "domain",
|
|
239
|
+
// https://example.com/path → example.com
|
|
240
|
+
number: "compact"
|
|
241
|
+
// 1234567 → 1.2M
|
|
242
|
+
};
|
|
243
|
+
const COMPACT_LABELS = {
|
|
244
|
+
// Common field names → short versions
|
|
245
|
+
customer: "Cust",
|
|
246
|
+
description: "Desc",
|
|
247
|
+
quantity: "Qty",
|
|
248
|
+
amount: "Amt",
|
|
249
|
+
total: "Tot",
|
|
250
|
+
priority: "Pri",
|
|
251
|
+
status: "Stat",
|
|
252
|
+
created_at: "Created",
|
|
253
|
+
updated_at: "Updated",
|
|
254
|
+
email: "Email",
|
|
255
|
+
phone: "Ph",
|
|
256
|
+
category: "Cat",
|
|
257
|
+
// Time fields
|
|
258
|
+
time: "Time",
|
|
259
|
+
timeAgo: "Time",
|
|
260
|
+
timestamp: "Time",
|
|
261
|
+
// ID fields
|
|
262
|
+
order_id: "#",
|
|
263
|
+
id: "#",
|
|
264
|
+
transaction_id: "Txn"
|
|
265
|
+
};
|
|
266
|
+
const TABLE_BREAKPOINTS = {
|
|
267
|
+
/** Below this width (px), always use cards */
|
|
268
|
+
minForTable: 400,
|
|
269
|
+
/** Buffer (px) to add when calculating if columns fit */
|
|
270
|
+
widthBuffer: 50,
|
|
271
|
+
/** Minimum columns to show in compact mode */
|
|
272
|
+
minCompactColumns: 3,
|
|
273
|
+
/** Maximum columns in compact mode */
|
|
274
|
+
maxCompactColumns: 6
|
|
275
|
+
};
|
|
276
|
+
const IMPORTANCE_VISIBILITY = {
|
|
277
|
+
full: ["primary", "secondary", "tertiary", "critical", "high", "medium", "low", "minimal"],
|
|
278
|
+
compact: ["primary", "secondary", "critical", "high", "medium"],
|
|
279
|
+
cards: ["primary", "critical", "high"]
|
|
280
|
+
};
|
|
281
|
+
function getColumnWidth(type, mode = "full") {
|
|
282
|
+
if (mode === "compact" && type in COMPACT_COLUMN_WIDTHS) {
|
|
283
|
+
return COMPACT_COLUMN_WIDTHS[type];
|
|
284
|
+
}
|
|
285
|
+
return COLUMN_WIDTHS[type] ?? COLUMN_WIDTHS.text;
|
|
286
|
+
}
|
|
287
|
+
function calculateTableWidth(columns, mode = "full") {
|
|
288
|
+
return columns.reduce((sum, col) => sum + getColumnWidth(col.type, mode), 0);
|
|
289
|
+
}
|
|
290
|
+
function getCompactLabel(fieldName, originalLabel) {
|
|
291
|
+
const normalized = fieldName.toLowerCase();
|
|
292
|
+
return COMPACT_LABELS[normalized] ?? originalLabel;
|
|
293
|
+
}
|
|
294
|
+
function getCompactFormatter(type) {
|
|
295
|
+
return COMPACT_FORMATTERS[type];
|
|
296
|
+
}
|
|
297
|
+
function determineTableMode(containerWidth, columns) {
|
|
298
|
+
const { minForTable, widthBuffer } = TABLE_BREAKPOINTS;
|
|
299
|
+
if (containerWidth < minForTable) {
|
|
300
|
+
return "cards";
|
|
301
|
+
}
|
|
302
|
+
const fullWidth = calculateTableWidth(columns, "full");
|
|
303
|
+
const compactColumns = columns.filter(
|
|
304
|
+
(col) => IMPORTANCE_VISIBILITY.compact.includes(
|
|
305
|
+
col.importance ?? "medium"
|
|
306
|
+
)
|
|
307
|
+
);
|
|
308
|
+
const compactWidth = calculateTableWidth(compactColumns, "compact");
|
|
309
|
+
if (fullWidth + widthBuffer <= containerWidth) {
|
|
310
|
+
return "full";
|
|
311
|
+
}
|
|
312
|
+
if (compactWidth + widthBuffer <= containerWidth) {
|
|
313
|
+
return "compact";
|
|
314
|
+
}
|
|
315
|
+
return "cards";
|
|
316
|
+
}
|
|
182
317
|
const breakpoints = {
|
|
183
318
|
"2xs": 400,
|
|
184
319
|
xs: 500,
|
|
@@ -2052,6 +2187,143 @@ function renderField(value, fieldName, fieldType, breakpoint, item, customRender
|
|
|
2052
2187
|
function cn(...inputs) {
|
|
2053
2188
|
return tailwindMerge.twMerge(clsx.clsx(inputs));
|
|
2054
2189
|
}
|
|
2190
|
+
const IconBadge = ({
|
|
2191
|
+
children,
|
|
2192
|
+
icon,
|
|
2193
|
+
variant = "category",
|
|
2194
|
+
category = 1,
|
|
2195
|
+
status = "neutral",
|
|
2196
|
+
size = "md",
|
|
2197
|
+
interactive = false,
|
|
2198
|
+
onClick,
|
|
2199
|
+
className,
|
|
2200
|
+
tooltip
|
|
2201
|
+
}) => {
|
|
2202
|
+
const currentSize = useResponsiveValue(size);
|
|
2203
|
+
const sizeConfig = responsiveScales.components.iconBadge[currentSize];
|
|
2204
|
+
const sizeClasses2 = {
|
|
2205
|
+
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"}`,
|
|
2206
|
+
sm: "w-8 h-8 text-xs rounded-lg",
|
|
2207
|
+
md: "w-10 h-10 text-sm rounded-xl",
|
|
2208
|
+
lg: "w-12 h-12 text-base rounded-xl"
|
|
2209
|
+
};
|
|
2210
|
+
const baseClasses = cn(
|
|
2211
|
+
"inline-flex items-center justify-center font-bold shadow-md",
|
|
2212
|
+
sizeClasses2[currentSize],
|
|
2213
|
+
interactive && [
|
|
2214
|
+
"cursor-pointer",
|
|
2215
|
+
getAnimationClasses({
|
|
2216
|
+
...animationPresets.dataBadge,
|
|
2217
|
+
size: currentSize === "lg" ? "lg" : currentSize === "sm" || currentSize === "xs" ? "sm" : "md"
|
|
2218
|
+
})
|
|
2219
|
+
],
|
|
2220
|
+
className
|
|
2221
|
+
);
|
|
2222
|
+
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";
|
|
2223
|
+
const badge = /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2224
|
+
"div",
|
|
2225
|
+
{
|
|
2226
|
+
className: cn(baseClasses, gradientClasses, "animate-fade-in"),
|
|
2227
|
+
onClick,
|
|
2228
|
+
role: interactive ? "button" : void 0,
|
|
2229
|
+
tabIndex: interactive ? 0 : void 0,
|
|
2230
|
+
onKeyDown: interactive ? (e) => {
|
|
2231
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
2232
|
+
e.preventDefault();
|
|
2233
|
+
onClick == null ? void 0 : onClick();
|
|
2234
|
+
}
|
|
2235
|
+
} : void 0,
|
|
2236
|
+
"data-component-name": "IconBadge",
|
|
2237
|
+
children: [
|
|
2238
|
+
icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-primary-foreground drop-shadow", children: icon }),
|
|
2239
|
+
children && !icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-primary-foreground font-bold", children })
|
|
2240
|
+
]
|
|
2241
|
+
}
|
|
2242
|
+
);
|
|
2243
|
+
if (tooltip) {
|
|
2244
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Tooltip, { content: tooltip, position: "top", size: "sm", children: badge });
|
|
2245
|
+
}
|
|
2246
|
+
return badge;
|
|
2247
|
+
};
|
|
2248
|
+
const valueColorMap = {
|
|
2249
|
+
success: "text-green-600",
|
|
2250
|
+
error: "text-red-600",
|
|
2251
|
+
warning: "text-yellow-600",
|
|
2252
|
+
info: "text-blue-600",
|
|
2253
|
+
neutral: "text-muted-foreground",
|
|
2254
|
+
default: "text-foreground"
|
|
2255
|
+
};
|
|
2256
|
+
function ListCard({
|
|
2257
|
+
icon,
|
|
2258
|
+
title,
|
|
2259
|
+
subtitle,
|
|
2260
|
+
metadata,
|
|
2261
|
+
value,
|
|
2262
|
+
badge,
|
|
2263
|
+
onClick,
|
|
2264
|
+
className,
|
|
2265
|
+
children
|
|
2266
|
+
}) {
|
|
2267
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2268
|
+
"div",
|
|
2269
|
+
{
|
|
2270
|
+
className: cn(
|
|
2271
|
+
"flex items-start gap-3 p-3 rounded-lg border border-border transition-colors",
|
|
2272
|
+
onClick && "hover:bg-muted/50 cursor-pointer",
|
|
2273
|
+
className
|
|
2274
|
+
),
|
|
2275
|
+
onClick,
|
|
2276
|
+
children: [
|
|
2277
|
+
icon && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2278
|
+
IconBadge,
|
|
2279
|
+
{
|
|
2280
|
+
variant: icon.variant || "category",
|
|
2281
|
+
category: icon.variant === "category" ? icon.category || 1 : void 0,
|
|
2282
|
+
status: icon.variant === "status" ? icon.status || "neutral" : void 0,
|
|
2283
|
+
size: icon.size || "sm",
|
|
2284
|
+
icon: icon.icon,
|
|
2285
|
+
tooltip: icon.tooltip
|
|
2286
|
+
}
|
|
2287
|
+
),
|
|
2288
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
2289
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-2", children: [
|
|
2290
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1", children: [
|
|
2291
|
+
/* @__PURE__ */ jsxRuntime.jsx("h4", { className: "text-sm font-medium text-foreground truncate", children: title }),
|
|
2292
|
+
subtitle && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground mt-0.5", children: subtitle }),
|
|
2293
|
+
metadata && metadata.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-3 mt-1", children: metadata.map((item, index) => /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground", children: item }, index)) })
|
|
2294
|
+
] }),
|
|
2295
|
+
(value || badge) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-right", children: [
|
|
2296
|
+
value && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2297
|
+
"p",
|
|
2298
|
+
{
|
|
2299
|
+
className: cn(
|
|
2300
|
+
"text-sm font-semibold",
|
|
2301
|
+
value.variant && valueColorMap[value.variant],
|
|
2302
|
+
value.className
|
|
2303
|
+
),
|
|
2304
|
+
children: value.text
|
|
2305
|
+
}
|
|
2306
|
+
),
|
|
2307
|
+
badge && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2308
|
+
DataBadge,
|
|
2309
|
+
{
|
|
2310
|
+
variant: badge.variant,
|
|
2311
|
+
status: badge.variant === "status" ? badge.status : void 0,
|
|
2312
|
+
category: badge.variant === "category" ? badge.category : void 0,
|
|
2313
|
+
size: badge.size || "sm",
|
|
2314
|
+
icon: badge.icon,
|
|
2315
|
+
className: "mt-1",
|
|
2316
|
+
children: badge.text
|
|
2317
|
+
}
|
|
2318
|
+
)
|
|
2319
|
+
] })
|
|
2320
|
+
] }),
|
|
2321
|
+
children
|
|
2322
|
+
] })
|
|
2323
|
+
]
|
|
2324
|
+
}
|
|
2325
|
+
);
|
|
2326
|
+
}
|
|
2055
2327
|
const STATUS_COLOR_MAP = {
|
|
2056
2328
|
// Success states
|
|
2057
2329
|
active: "success",
|
|
@@ -2390,7 +2662,6 @@ function getCompactWidth(type) {
|
|
|
2390
2662
|
}
|
|
2391
2663
|
}
|
|
2392
2664
|
function createMobileCardRenderer(columns, mapping, entityType) {
|
|
2393
|
-
const { ListCard: ListCard2 } = require("../components/data/ListCard");
|
|
2394
2665
|
return ({ data, onItemClick }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: data.map((item, index) => {
|
|
2395
2666
|
const cardProps = entityToListCardProps(
|
|
2396
2667
|
item,
|
|
@@ -2399,7 +2670,7 @@ function createMobileCardRenderer(columns, mapping, entityType) {
|
|
|
2399
2670
|
entityType
|
|
2400
2671
|
);
|
|
2401
2672
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2402
|
-
|
|
2673
|
+
ListCard,
|
|
2403
2674
|
{
|
|
2404
2675
|
...cardProps,
|
|
2405
2676
|
onClick: onItemClick ? () => onItemClick(item) : void 0
|
|
@@ -2573,10 +2844,10 @@ function useApiMutation(mutationFn, options) {
|
|
|
2573
2844
|
const queryClient = reactQuery.useQueryClient();
|
|
2574
2845
|
return reactQuery.useMutation({
|
|
2575
2846
|
mutationFn,
|
|
2576
|
-
onSuccess: (
|
|
2847
|
+
onSuccess: (...args) => {
|
|
2577
2848
|
var _a;
|
|
2578
|
-
queryClient.invalidateQueries();
|
|
2579
|
-
(_a = options == null ? void 0 : options.onSuccess) == null ? void 0 : _a.call(options,
|
|
2849
|
+
void queryClient.invalidateQueries({});
|
|
2850
|
+
(_a = options == null ? void 0 : options.onSuccess) == null ? void 0 : _a.call(options, ...args);
|
|
2580
2851
|
},
|
|
2581
2852
|
...options
|
|
2582
2853
|
});
|
|
@@ -2651,43 +2922,87 @@ function useFieldMetadata({
|
|
|
2651
2922
|
}
|
|
2652
2923
|
function useResponsiveTable(options = {}) {
|
|
2653
2924
|
const {
|
|
2925
|
+
columns,
|
|
2654
2926
|
initialView = "full",
|
|
2655
2927
|
autoSwitch = true,
|
|
2656
|
-
minWidthForCompact =
|
|
2928
|
+
minWidthForCompact = TABLE_BREAKPOINTS.minForTable,
|
|
2657
2929
|
debounceMs = 100,
|
|
2658
2930
|
onViewChange
|
|
2659
2931
|
} = options;
|
|
2660
2932
|
const [viewMode, setViewModeState] = React.useState(initialView);
|
|
2661
2933
|
const [isAutoSwitching, setIsAutoSwitching] = React.useState(autoSwitch);
|
|
2934
|
+
const [containerWidth, setContainerWidth] = React.useState(0);
|
|
2662
2935
|
const [overflowState, setOverflowState] = React.useState({
|
|
2663
2936
|
fullOverflows: false,
|
|
2664
2937
|
compactOverflows: false
|
|
2665
2938
|
});
|
|
2939
|
+
const containerRef = React.useRef(null);
|
|
2666
2940
|
const fullTableRef = React.useRef(null);
|
|
2667
2941
|
const compactTableRef = React.useRef(null);
|
|
2668
2942
|
const debounceTimerRef = React.useRef(null);
|
|
2669
2943
|
const isTransitioningRef = React.useRef(false);
|
|
2944
|
+
const compactColumns = React.useCallback(() => {
|
|
2945
|
+
if (!columns) return null;
|
|
2946
|
+
const validImportance = IMPORTANCE_VISIBILITY.compact;
|
|
2947
|
+
const filtered = columns.filter(
|
|
2948
|
+
(col) => validImportance.includes(col.importance ?? "medium")
|
|
2949
|
+
);
|
|
2950
|
+
const limited = filtered.slice(0, TABLE_BREAKPOINTS.maxCompactColumns);
|
|
2951
|
+
return limited.map((col) => ({
|
|
2952
|
+
...col,
|
|
2953
|
+
label: getCompactLabel(col.field, col.label)
|
|
2954
|
+
}));
|
|
2955
|
+
}, [columns])();
|
|
2956
|
+
const calculatedWidths = React.useCallback(() => {
|
|
2957
|
+
if (!columns) {
|
|
2958
|
+
return { full: 0, compact: 0, container: containerWidth };
|
|
2959
|
+
}
|
|
2960
|
+
const fullWidth = calculateTableWidth(
|
|
2961
|
+
columns.map((c) => ({ type: c.type })),
|
|
2962
|
+
"full"
|
|
2963
|
+
);
|
|
2964
|
+
const compactCols = compactColumns ?? [];
|
|
2965
|
+
const compactWidth = calculateTableWidth(
|
|
2966
|
+
compactCols.map((c) => ({ type: c.type })),
|
|
2967
|
+
"compact"
|
|
2968
|
+
);
|
|
2969
|
+
return {
|
|
2970
|
+
full: fullWidth,
|
|
2971
|
+
compact: compactWidth,
|
|
2972
|
+
container: containerWidth
|
|
2973
|
+
};
|
|
2974
|
+
}, [columns, compactColumns, containerWidth])();
|
|
2670
2975
|
const hasOverflow = React.useCallback((element) => {
|
|
2671
2976
|
if (!element) return false;
|
|
2672
2977
|
return element.scrollWidth > element.clientWidth + 2;
|
|
2673
2978
|
}, []);
|
|
2674
2979
|
const determineView = React.useCallback(() => {
|
|
2675
|
-
var _a, _b, _c, _d;
|
|
2676
|
-
|
|
2677
|
-
|
|
2980
|
+
var _a, _b, _c, _d, _e;
|
|
2981
|
+
if (columns && containerWidth > 0) {
|
|
2982
|
+
const { full, compact } = calculatedWidths;
|
|
2983
|
+
const buffer = TABLE_BREAKPOINTS.widthBuffer;
|
|
2984
|
+
if (containerWidth < minWidthForCompact) {
|
|
2985
|
+
return "cards";
|
|
2986
|
+
}
|
|
2987
|
+
if (full + buffer <= containerWidth) {
|
|
2988
|
+
return "full";
|
|
2989
|
+
}
|
|
2990
|
+
if (compact + buffer <= containerWidth) {
|
|
2991
|
+
return "compact";
|
|
2992
|
+
}
|
|
2993
|
+
return "cards";
|
|
2994
|
+
}
|
|
2995
|
+
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;
|
|
2996
|
+
if (width < minWidthForCompact) {
|
|
2678
2997
|
return "cards";
|
|
2679
2998
|
}
|
|
2680
2999
|
const fullOverflows = hasOverflow(fullTableRef.current);
|
|
2681
3000
|
const compactOverflows = hasOverflow(compactTableRef.current);
|
|
2682
3001
|
setOverflowState({ fullOverflows, compactOverflows });
|
|
2683
|
-
if (!fullOverflows)
|
|
2684
|
-
|
|
2685
|
-
}
|
|
2686
|
-
if (!compactOverflows) {
|
|
2687
|
-
return "compact";
|
|
2688
|
-
}
|
|
3002
|
+
if (!fullOverflows) return "full";
|
|
3003
|
+
if (!compactOverflows) return "compact";
|
|
2689
3004
|
return "cards";
|
|
2690
|
-
}, [
|
|
3005
|
+
}, [columns, containerWidth, calculatedWidths, minWidthForCompact, hasOverflow]);
|
|
2691
3006
|
const checkAndUpdate = React.useCallback(() => {
|
|
2692
3007
|
if (!isAutoSwitching || isTransitioningRef.current) return;
|
|
2693
3008
|
if (debounceTimerRef.current) {
|
|
@@ -2719,42 +3034,49 @@ function useResponsiveTable(options = {}) {
|
|
|
2719
3034
|
React.useEffect(() => {
|
|
2720
3035
|
var _a, _b;
|
|
2721
3036
|
if (!isAutoSwitching) return;
|
|
2722
|
-
const
|
|
3037
|
+
const updateContainerWidth = () => {
|
|
3038
|
+
var _a2;
|
|
3039
|
+
const ref = containerRef.current || ((_a2 = fullTableRef.current) == null ? void 0 : _a2.parentElement);
|
|
3040
|
+
if (ref) {
|
|
3041
|
+
setContainerWidth(ref.clientWidth);
|
|
3042
|
+
}
|
|
3043
|
+
};
|
|
3044
|
+
const initialTimer = setTimeout(updateContainerWidth, 50);
|
|
2723
3045
|
const resizeObserver = new ResizeObserver(() => {
|
|
3046
|
+
updateContainerWidth();
|
|
2724
3047
|
checkAndUpdate();
|
|
2725
3048
|
});
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
if (compactTableRef.current) {
|
|
2730
|
-
resizeObserver.observe(compactTableRef.current);
|
|
3049
|
+
const observeTarget = containerRef.current || ((_a = fullTableRef.current) == null ? void 0 : _a.parentElement) || ((_b = compactTableRef.current) == null ? void 0 : _b.parentElement);
|
|
3050
|
+
if (observeTarget) {
|
|
3051
|
+
resizeObserver.observe(observeTarget);
|
|
2731
3052
|
}
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
resizeObserver.observe(
|
|
3053
|
+
if (!columns) {
|
|
3054
|
+
if (fullTableRef.current) resizeObserver.observe(fullTableRef.current);
|
|
3055
|
+
if (compactTableRef.current) resizeObserver.observe(compactTableRef.current);
|
|
2735
3056
|
}
|
|
2736
3057
|
window.addEventListener("resize", checkAndUpdate);
|
|
2737
3058
|
return () => {
|
|
2738
|
-
clearTimeout(
|
|
2739
|
-
if (debounceTimerRef.current)
|
|
2740
|
-
clearTimeout(debounceTimerRef.current);
|
|
2741
|
-
}
|
|
3059
|
+
clearTimeout(initialTimer);
|
|
3060
|
+
if (debounceTimerRef.current) clearTimeout(debounceTimerRef.current);
|
|
2742
3061
|
resizeObserver.disconnect();
|
|
2743
3062
|
window.removeEventListener("resize", checkAndUpdate);
|
|
2744
3063
|
};
|
|
2745
|
-
}, [isAutoSwitching, checkAndUpdate]);
|
|
3064
|
+
}, [isAutoSwitching, columns, checkAndUpdate]);
|
|
2746
3065
|
React.useEffect(() => {
|
|
2747
3066
|
if (!isAutoSwitching) return;
|
|
2748
3067
|
const timer = setTimeout(checkAndUpdate, 100);
|
|
2749
3068
|
return () => clearTimeout(timer);
|
|
2750
|
-
}, [viewMode, isAutoSwitching, checkAndUpdate]);
|
|
3069
|
+
}, [viewMode, containerWidth, isAutoSwitching, checkAndUpdate]);
|
|
2751
3070
|
return {
|
|
2752
3071
|
viewMode,
|
|
2753
3072
|
setViewMode,
|
|
2754
3073
|
enableAutoSwitch,
|
|
2755
3074
|
isAutoSwitching,
|
|
3075
|
+
containerRef,
|
|
2756
3076
|
fullTableRef,
|
|
2757
3077
|
compactTableRef,
|
|
3078
|
+
compactColumns,
|
|
3079
|
+
calculatedWidths,
|
|
2758
3080
|
overflowState
|
|
2759
3081
|
};
|
|
2760
3082
|
}
|
|
@@ -2773,6 +3095,154 @@ function useOverflowDetection(ref) {
|
|
|
2773
3095
|
}, [ref]);
|
|
2774
3096
|
return hasOverflow;
|
|
2775
3097
|
}
|
|
3098
|
+
const IMPORTANCE_PRIORITY = {
|
|
3099
|
+
minimal: 0,
|
|
3100
|
+
low: 1,
|
|
3101
|
+
tertiary: 2,
|
|
3102
|
+
medium: 3,
|
|
3103
|
+
secondary: 4,
|
|
3104
|
+
high: 5,
|
|
3105
|
+
critical: 6,
|
|
3106
|
+
primary: 7
|
|
3107
|
+
};
|
|
3108
|
+
function getColumnModeWidth(col, mode) {
|
|
3109
|
+
if (mode === "hidden") return 0;
|
|
3110
|
+
return getColumnWidth(col.type, mode === "compact" ? "compact" : "full");
|
|
3111
|
+
}
|
|
3112
|
+
function calculateAdaptiveWidth(columns, modes) {
|
|
3113
|
+
return columns.reduce((sum, col) => sum + getColumnModeWidth(col, modes[col.field] ?? "full"), 0);
|
|
3114
|
+
}
|
|
3115
|
+
function calculateColumnModes(columns, containerWidth, protectedColumns, minColumnsVisible) {
|
|
3116
|
+
const buffer = TABLE_BREAKPOINTS.widthBuffer;
|
|
3117
|
+
const sortedByImportance = [...columns].sort((a, b) => {
|
|
3118
|
+
const priorityA = IMPORTANCE_PRIORITY[a.importance ?? "tertiary"];
|
|
3119
|
+
const priorityB = IMPORTANCE_PRIORITY[b.importance ?? "tertiary"];
|
|
3120
|
+
return priorityA - priorityB;
|
|
3121
|
+
});
|
|
3122
|
+
const modes = {};
|
|
3123
|
+
columns.forEach((col) => modes[col.field] = "full");
|
|
3124
|
+
let currentWidth = calculateAdaptiveWidth(columns, modes);
|
|
3125
|
+
if (currentWidth + buffer <= containerWidth) {
|
|
3126
|
+
return { modes, degradationLevel: 0 };
|
|
3127
|
+
}
|
|
3128
|
+
let degradationLevel = 1;
|
|
3129
|
+
for (const col of sortedByImportance) {
|
|
3130
|
+
if (protectedColumns.has(col.field)) continue;
|
|
3131
|
+
const priority = IMPORTANCE_PRIORITY[col.importance ?? "tertiary"];
|
|
3132
|
+
if (priority > 2) break;
|
|
3133
|
+
modes[col.field] = "compact";
|
|
3134
|
+
currentWidth = calculateAdaptiveWidth(columns, modes);
|
|
3135
|
+
if (currentWidth + buffer <= containerWidth) return { modes, degradationLevel };
|
|
3136
|
+
}
|
|
3137
|
+
degradationLevel = 2;
|
|
3138
|
+
for (const col of sortedByImportance) {
|
|
3139
|
+
if (protectedColumns.has(col.field)) continue;
|
|
3140
|
+
const priority = IMPORTANCE_PRIORITY[col.importance ?? "tertiary"];
|
|
3141
|
+
if (priority <= 2) continue;
|
|
3142
|
+
if (priority > 4) break;
|
|
3143
|
+
modes[col.field] = "compact";
|
|
3144
|
+
currentWidth = calculateAdaptiveWidth(columns, modes);
|
|
3145
|
+
if (currentWidth + buffer <= containerWidth) return { modes, degradationLevel };
|
|
3146
|
+
}
|
|
3147
|
+
degradationLevel = 3;
|
|
3148
|
+
let visibleCount = columns.length;
|
|
3149
|
+
for (const col of sortedByImportance) {
|
|
3150
|
+
const priority = IMPORTANCE_PRIORITY[col.importance ?? "tertiary"];
|
|
3151
|
+
if (priority > 2) break;
|
|
3152
|
+
if (visibleCount <= minColumnsVisible) break;
|
|
3153
|
+
modes[col.field] = "hidden";
|
|
3154
|
+
visibleCount--;
|
|
3155
|
+
currentWidth = calculateAdaptiveWidth(columns, modes);
|
|
3156
|
+
if (currentWidth + buffer <= containerWidth) return { modes, degradationLevel };
|
|
3157
|
+
}
|
|
3158
|
+
degradationLevel = 4;
|
|
3159
|
+
for (const col of sortedByImportance) {
|
|
3160
|
+
const priority = IMPORTANCE_PRIORITY[col.importance ?? "tertiary"];
|
|
3161
|
+
if (priority <= 2) continue;
|
|
3162
|
+
if (priority > 4) break;
|
|
3163
|
+
if (visibleCount <= minColumnsVisible) break;
|
|
3164
|
+
modes[col.field] = "hidden";
|
|
3165
|
+
visibleCount--;
|
|
3166
|
+
currentWidth = calculateAdaptiveWidth(columns, modes);
|
|
3167
|
+
if (currentWidth + buffer <= containerWidth) return { modes, degradationLevel };
|
|
3168
|
+
}
|
|
3169
|
+
degradationLevel = 5;
|
|
3170
|
+
for (const col of sortedByImportance) {
|
|
3171
|
+
if (modes[col.field] === "hidden") continue;
|
|
3172
|
+
modes[col.field] = "compact";
|
|
3173
|
+
currentWidth = calculateAdaptiveWidth(columns, modes);
|
|
3174
|
+
if (currentWidth + buffer <= containerWidth) return { modes, degradationLevel };
|
|
3175
|
+
}
|
|
3176
|
+
return { modes, degradationLevel: 6 };
|
|
3177
|
+
}
|
|
3178
|
+
function useAdaptiveTable(options) {
|
|
3179
|
+
const {
|
|
3180
|
+
columns,
|
|
3181
|
+
protectedColumns = [],
|
|
3182
|
+
minColumnsVisible = 2,
|
|
3183
|
+
minWidthForTable = TABLE_BREAKPOINTS.minForTable,
|
|
3184
|
+
debounceMs = 100,
|
|
3185
|
+
onModeChange
|
|
3186
|
+
} = options;
|
|
3187
|
+
const containerRef = React.useRef(null);
|
|
3188
|
+
const [containerWidth, setContainerWidth] = React.useState(0);
|
|
3189
|
+
const debounceTimerRef = React.useRef(null);
|
|
3190
|
+
const protectedSet = React.useMemo(() => new Set(protectedColumns), [protectedColumns]);
|
|
3191
|
+
const { modes: columnModes, degradationLevel } = React.useMemo(() => {
|
|
3192
|
+
if (containerWidth === 0) {
|
|
3193
|
+
const modes = {};
|
|
3194
|
+
columns.forEach((col) => modes[col.field] = "full");
|
|
3195
|
+
return { modes, degradationLevel: 0 };
|
|
3196
|
+
}
|
|
3197
|
+
return calculateColumnModes(columns, containerWidth, protectedSet, minColumnsVisible);
|
|
3198
|
+
}, [columns, containerWidth, protectedSet, minColumnsVisible]);
|
|
3199
|
+
const visibleColumns = React.useMemo(() => {
|
|
3200
|
+
return columns.filter((col) => columnModes[col.field] !== "hidden").map(
|
|
3201
|
+
(col) => columnModes[col.field] === "compact" ? { ...col, label: getCompactLabel(col.field, col.label) } : col
|
|
3202
|
+
);
|
|
3203
|
+
}, [columns, columnModes]);
|
|
3204
|
+
const calculatedWidth = React.useMemo(
|
|
3205
|
+
() => calculateAdaptiveWidth(columns, columnModes),
|
|
3206
|
+
[columns, columnModes]
|
|
3207
|
+
);
|
|
3208
|
+
const viewMode = React.useMemo(() => {
|
|
3209
|
+
if (containerWidth > 0 && containerWidth < minWidthForTable) return "cards";
|
|
3210
|
+
if (visibleColumns.length < minColumnsVisible) return "cards";
|
|
3211
|
+
return "table";
|
|
3212
|
+
}, [containerWidth, minWidthForTable, visibleColumns.length, minColumnsVisible]);
|
|
3213
|
+
React.useEffect(() => {
|
|
3214
|
+
const updateWidth = () => {
|
|
3215
|
+
if (containerRef.current) setContainerWidth(containerRef.current.clientWidth);
|
|
3216
|
+
};
|
|
3217
|
+
const initialTimer = setTimeout(updateWidth, 50);
|
|
3218
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
3219
|
+
if (debounceTimerRef.current) clearTimeout(debounceTimerRef.current);
|
|
3220
|
+
debounceTimerRef.current = setTimeout(updateWidth, debounceMs);
|
|
3221
|
+
});
|
|
3222
|
+
if (containerRef.current) resizeObserver.observe(containerRef.current);
|
|
3223
|
+
return () => {
|
|
3224
|
+
clearTimeout(initialTimer);
|
|
3225
|
+
if (debounceTimerRef.current) clearTimeout(debounceTimerRef.current);
|
|
3226
|
+
resizeObserver.disconnect();
|
|
3227
|
+
};
|
|
3228
|
+
}, [debounceMs]);
|
|
3229
|
+
const prevModesRef = React.useRef(columnModes);
|
|
3230
|
+
React.useEffect(() => {
|
|
3231
|
+
if (onModeChange && columnModes !== prevModesRef.current) {
|
|
3232
|
+
onModeChange(columnModes);
|
|
3233
|
+
prevModesRef.current = columnModes;
|
|
3234
|
+
}
|
|
3235
|
+
}, [columnModes, onModeChange]);
|
|
3236
|
+
return {
|
|
3237
|
+
containerRef,
|
|
3238
|
+
columnModes,
|
|
3239
|
+
visibleColumns,
|
|
3240
|
+
viewMode,
|
|
3241
|
+
calculatedWidth,
|
|
3242
|
+
containerWidth,
|
|
3243
|
+
degradationLevel
|
|
3244
|
+
};
|
|
3245
|
+
}
|
|
2776
3246
|
function useEntityData(entity, options = {}) {
|
|
2777
3247
|
var _a, _b, _c;
|
|
2778
3248
|
const {
|
|
@@ -4655,8 +5125,9 @@ function normalizeColumn(col) {
|
|
|
4655
5125
|
return col;
|
|
4656
5126
|
}
|
|
4657
5127
|
function DataTable({
|
|
4658
|
-
data,
|
|
4659
|
-
columns,
|
|
5128
|
+
data: dataProp,
|
|
5129
|
+
columns: columnsProp,
|
|
5130
|
+
query,
|
|
4660
5131
|
searchPlaceholder = "Search...",
|
|
4661
5132
|
pageSize = 10,
|
|
4662
5133
|
showPagination = true,
|
|
@@ -4665,12 +5136,12 @@ function DataTable({
|
|
|
4665
5136
|
emptyMessage = "No data available",
|
|
4666
5137
|
className = "",
|
|
4667
5138
|
hover = false,
|
|
4668
|
-
isLoading = false,
|
|
5139
|
+
isLoading: isLoadingProp = false,
|
|
4669
5140
|
loadingItemCount = 5,
|
|
4670
5141
|
responsive = true,
|
|
4671
5142
|
renderMobileCard,
|
|
4672
5143
|
ui,
|
|
4673
|
-
error = null,
|
|
5144
|
+
error: errorProp = null,
|
|
4674
5145
|
errorTitle,
|
|
4675
5146
|
errorRetry,
|
|
4676
5147
|
selectable = false,
|
|
@@ -4685,6 +5156,10 @@ function DataTable({
|
|
|
4685
5156
|
const [currentPage, setCurrentPage] = React.useState(1);
|
|
4686
5157
|
const currentBreakpoint = useBreakpoint();
|
|
4687
5158
|
const isMobile = currentBreakpoint === "xs" || currentBreakpoint === "2xs" || currentBreakpoint === "sm";
|
|
5159
|
+
const data = dataProp ?? (query == null ? void 0 : query.data) ?? [];
|
|
5160
|
+
const columns = columnsProp ?? (query == null ? void 0 : query.columns) ?? [];
|
|
5161
|
+
const isLoading = isLoadingProp || (query == null ? void 0 : query.isLoading) || (query == null ? void 0 : query.isLoadingMetadata) || false;
|
|
5162
|
+
const error = errorProp ?? (query == null ? void 0 : query.error) ?? (query == null ? void 0 : query.metadataError) ?? null;
|
|
4688
5163
|
const normalizedColumns = React.useMemo(
|
|
4689
5164
|
() => columns.map((col) => normalizeColumn(col)),
|
|
4690
5165
|
[columns]
|
|
@@ -5071,64 +5546,6 @@ const TableHead = TableHead$1;
|
|
|
5071
5546
|
const TableHeader = TableHeader$1;
|
|
5072
5547
|
const TableRow = TableRow$1;
|
|
5073
5548
|
const TableFooter = TableFooter$1;
|
|
5074
|
-
const IconBadge = ({
|
|
5075
|
-
children,
|
|
5076
|
-
icon,
|
|
5077
|
-
variant = "category",
|
|
5078
|
-
category = 1,
|
|
5079
|
-
status = "neutral",
|
|
5080
|
-
size = "md",
|
|
5081
|
-
interactive = false,
|
|
5082
|
-
onClick,
|
|
5083
|
-
className,
|
|
5084
|
-
tooltip
|
|
5085
|
-
}) => {
|
|
5086
|
-
const currentSize = useResponsiveValue(size);
|
|
5087
|
-
const sizeConfig = responsiveScales.components.iconBadge[currentSize];
|
|
5088
|
-
const sizeClasses2 = {
|
|
5089
|
-
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"}`,
|
|
5090
|
-
sm: "w-8 h-8 text-xs rounded-lg",
|
|
5091
|
-
md: "w-10 h-10 text-sm rounded-xl",
|
|
5092
|
-
lg: "w-12 h-12 text-base rounded-xl"
|
|
5093
|
-
};
|
|
5094
|
-
const baseClasses = cn(
|
|
5095
|
-
"inline-flex items-center justify-center font-bold shadow-md",
|
|
5096
|
-
sizeClasses2[currentSize],
|
|
5097
|
-
interactive && [
|
|
5098
|
-
"cursor-pointer",
|
|
5099
|
-
getAnimationClasses({
|
|
5100
|
-
...animationPresets.dataBadge,
|
|
5101
|
-
size: currentSize === "lg" ? "lg" : currentSize === "sm" || currentSize === "xs" ? "sm" : "md"
|
|
5102
|
-
})
|
|
5103
|
-
],
|
|
5104
|
-
className
|
|
5105
|
-
);
|
|
5106
|
-
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";
|
|
5107
|
-
const badge = /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5108
|
-
"div",
|
|
5109
|
-
{
|
|
5110
|
-
className: cn(baseClasses, gradientClasses, "animate-fade-in"),
|
|
5111
|
-
onClick,
|
|
5112
|
-
role: interactive ? "button" : void 0,
|
|
5113
|
-
tabIndex: interactive ? 0 : void 0,
|
|
5114
|
-
onKeyDown: interactive ? (e) => {
|
|
5115
|
-
if (e.key === "Enter" || e.key === " ") {
|
|
5116
|
-
e.preventDefault();
|
|
5117
|
-
onClick == null ? void 0 : onClick();
|
|
5118
|
-
}
|
|
5119
|
-
} : void 0,
|
|
5120
|
-
"data-component-name": "IconBadge",
|
|
5121
|
-
children: [
|
|
5122
|
-
icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-primary-foreground drop-shadow", children: icon }),
|
|
5123
|
-
children && !icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-primary-foreground font-bold", children })
|
|
5124
|
-
]
|
|
5125
|
-
}
|
|
5126
|
-
);
|
|
5127
|
-
if (tooltip) {
|
|
5128
|
-
return /* @__PURE__ */ jsxRuntime.jsx(Tooltip, { content: tooltip, position: "top", size: "sm", children: badge });
|
|
5129
|
-
}
|
|
5130
|
-
return badge;
|
|
5131
|
-
};
|
|
5132
5549
|
const Chart = ({
|
|
5133
5550
|
title,
|
|
5134
5551
|
subtitle,
|
|
@@ -5891,85 +6308,6 @@ const ProgressBar = ({
|
|
|
5891
6308
|
)
|
|
5892
6309
|
] });
|
|
5893
6310
|
};
|
|
5894
|
-
const valueColorMap = {
|
|
5895
|
-
success: "text-green-600",
|
|
5896
|
-
error: "text-red-600",
|
|
5897
|
-
warning: "text-yellow-600",
|
|
5898
|
-
info: "text-blue-600",
|
|
5899
|
-
neutral: "text-muted-foreground",
|
|
5900
|
-
default: "text-foreground"
|
|
5901
|
-
};
|
|
5902
|
-
function ListCard({
|
|
5903
|
-
icon,
|
|
5904
|
-
title,
|
|
5905
|
-
subtitle,
|
|
5906
|
-
metadata,
|
|
5907
|
-
value,
|
|
5908
|
-
badge,
|
|
5909
|
-
onClick,
|
|
5910
|
-
className,
|
|
5911
|
-
children
|
|
5912
|
-
}) {
|
|
5913
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5914
|
-
"div",
|
|
5915
|
-
{
|
|
5916
|
-
className: cn(
|
|
5917
|
-
"flex items-start gap-3 p-3 rounded-lg border border-border transition-colors",
|
|
5918
|
-
onClick && "hover:bg-muted/50 cursor-pointer",
|
|
5919
|
-
className
|
|
5920
|
-
),
|
|
5921
|
-
onClick,
|
|
5922
|
-
children: [
|
|
5923
|
-
icon && /* @__PURE__ */ jsxRuntime.jsx(
|
|
5924
|
-
IconBadge,
|
|
5925
|
-
{
|
|
5926
|
-
variant: icon.variant || "category",
|
|
5927
|
-
category: icon.variant === "category" ? icon.category || 1 : void 0,
|
|
5928
|
-
status: icon.variant === "status" ? icon.status || "neutral" : void 0,
|
|
5929
|
-
size: icon.size || "sm",
|
|
5930
|
-
icon: icon.icon,
|
|
5931
|
-
tooltip: icon.tooltip
|
|
5932
|
-
}
|
|
5933
|
-
),
|
|
5934
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
5935
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-2", children: [
|
|
5936
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1", children: [
|
|
5937
|
-
/* @__PURE__ */ jsxRuntime.jsx("h4", { className: "text-sm font-medium text-foreground truncate", children: title }),
|
|
5938
|
-
subtitle && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground mt-0.5", children: subtitle }),
|
|
5939
|
-
metadata && metadata.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-3 mt-1", children: metadata.map((item, index) => /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground", children: item }, index)) })
|
|
5940
|
-
] }),
|
|
5941
|
-
(value || badge) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-right", children: [
|
|
5942
|
-
value && /* @__PURE__ */ jsxRuntime.jsx(
|
|
5943
|
-
"p",
|
|
5944
|
-
{
|
|
5945
|
-
className: cn(
|
|
5946
|
-
"text-sm font-semibold",
|
|
5947
|
-
value.variant && valueColorMap[value.variant],
|
|
5948
|
-
value.className
|
|
5949
|
-
),
|
|
5950
|
-
children: value.text
|
|
5951
|
-
}
|
|
5952
|
-
),
|
|
5953
|
-
badge && /* @__PURE__ */ jsxRuntime.jsx(
|
|
5954
|
-
DataBadge,
|
|
5955
|
-
{
|
|
5956
|
-
variant: badge.variant,
|
|
5957
|
-
status: badge.variant === "status" ? badge.status : void 0,
|
|
5958
|
-
category: badge.variant === "category" ? badge.category : void 0,
|
|
5959
|
-
size: badge.size || "sm",
|
|
5960
|
-
icon: badge.icon,
|
|
5961
|
-
className: "mt-1",
|
|
5962
|
-
children: badge.text
|
|
5963
|
-
}
|
|
5964
|
-
)
|
|
5965
|
-
] })
|
|
5966
|
-
] }),
|
|
5967
|
-
children
|
|
5968
|
-
] })
|
|
5969
|
-
]
|
|
5970
|
-
}
|
|
5971
|
-
);
|
|
5972
|
-
}
|
|
5973
6311
|
const TruncatedText = ({
|
|
5974
6312
|
text,
|
|
5975
6313
|
className,
|
|
@@ -9290,6 +9628,13 @@ const defaultShowcaseNavigation = [
|
|
|
9290
9628
|
path: "/admin/dashboard",
|
|
9291
9629
|
category: 2
|
|
9292
9630
|
},
|
|
9631
|
+
{
|
|
9632
|
+
value: "admin-dashboard-v2",
|
|
9633
|
+
label: "Admin Dashboard V2",
|
|
9634
|
+
icon: "Shield",
|
|
9635
|
+
path: "/admin/dashboard-v2",
|
|
9636
|
+
category: 2
|
|
9637
|
+
},
|
|
9293
9638
|
{
|
|
9294
9639
|
value: "admin-users",
|
|
9295
9640
|
label: "User Management",
|
|
@@ -9560,7 +9905,6 @@ const Sidebar = ({ className }) => {
|
|
|
9560
9905
|
);
|
|
9561
9906
|
};
|
|
9562
9907
|
const AppHeader = ({ className }) => {
|
|
9563
|
-
const isTrialMode = false;
|
|
9564
9908
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
9565
9909
|
"header",
|
|
9566
9910
|
{
|
|
@@ -9573,7 +9917,7 @@ const AppHeader = ({ className }) => {
|
|
|
9573
9917
|
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-auto max-w-7xl px-4 sm:px-6 lg:px-8", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-16 items-center justify-between", children: [
|
|
9574
9918
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
9575
9919
|
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-xl font-bold text-foreground", children: "Frontend Template" }),
|
|
9576
|
-
|
|
9920
|
+
/* @__PURE__ */ jsxRuntime.jsx(DataBadge, { variant: "status", status: "info", display: "icon-text", children: "Trial Mode" })
|
|
9577
9921
|
] }),
|
|
9578
9922
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 max-w-2xl mx-8", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
9579
9923
|
GlobalSearch,
|
|
@@ -14357,18 +14701,41 @@ function createReactApp(config) {
|
|
|
14357
14701
|
enableRouting = true,
|
|
14358
14702
|
auth,
|
|
14359
14703
|
navigation,
|
|
14360
|
-
customProviders = []
|
|
14704
|
+
customProviders = [],
|
|
14705
|
+
persistQueryCache = false,
|
|
14706
|
+
queryCacheKey = "PATTERN_STACK_QUERY_CACHE"
|
|
14361
14707
|
} = appConfig;
|
|
14362
14708
|
const queryClient = new reactQuery.QueryClient({
|
|
14363
14709
|
defaultOptions: {
|
|
14364
14710
|
queries: {
|
|
14365
14711
|
retry: 1,
|
|
14366
14712
|
refetchOnWindowFocus: false,
|
|
14367
|
-
staleTime: 5 * 60 * 1e3
|
|
14713
|
+
staleTime: 5 * 60 * 1e3,
|
|
14368
14714
|
// 5 minutes
|
|
14715
|
+
// Keep data longer when persistence is enabled
|
|
14716
|
+
gcTime: persistQueryCache ? 1e3 * 60 * 60 * 24 : 1e3 * 60 * 5
|
|
14369
14717
|
}
|
|
14370
14718
|
}
|
|
14371
14719
|
});
|
|
14720
|
+
if (persistQueryCache && typeof window !== "undefined") {
|
|
14721
|
+
import("@tanstack/react-query-persist-client").then(({ persistQueryClient }) => {
|
|
14722
|
+
import("@tanstack/query-sync-storage-persister").then(({ createSyncStoragePersister }) => {
|
|
14723
|
+
const persister = createSyncStoragePersister({
|
|
14724
|
+
storage: window.localStorage,
|
|
14725
|
+
key: queryCacheKey
|
|
14726
|
+
});
|
|
14727
|
+
persistQueryClient({
|
|
14728
|
+
queryClient,
|
|
14729
|
+
persister,
|
|
14730
|
+
maxAge: 1e3 * 60 * 60 * 24
|
|
14731
|
+
// 24 hours
|
|
14732
|
+
});
|
|
14733
|
+
console.info("[app] Query cache persistence enabled");
|
|
14734
|
+
});
|
|
14735
|
+
}).catch((err) => {
|
|
14736
|
+
console.warn("[app] Query persistence not available:", err.message);
|
|
14737
|
+
});
|
|
14738
|
+
}
|
|
14372
14739
|
const routes = [];
|
|
14373
14740
|
const DefaultHome = () => /* @__PURE__ */ jsxRuntime.jsx(DashboardTemplate, { title, description, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center justify-center min-h-[400px] text-center", children: [
|
|
14374
14741
|
/* @__PURE__ */ jsxRuntime.jsxs("h1", { className: "text-4xl font-bold text-foreground mb-4", children: [
|
|
@@ -14387,7 +14754,7 @@ function createReactApp(config) {
|
|
|
14387
14754
|
] }) });
|
|
14388
14755
|
const createProviderTree = (children) => {
|
|
14389
14756
|
let tree = children;
|
|
14390
|
-
customProviders.reverse().forEach((Provider) => {
|
|
14757
|
+
[...customProviders].reverse().forEach((Provider) => {
|
|
14391
14758
|
tree = /* @__PURE__ */ jsxRuntime.jsx(Provider, { children: tree }, Provider.name);
|
|
14392
14759
|
});
|
|
14393
14760
|
if (enableRouting) {
|
|
@@ -14430,10 +14797,10 @@ function createReactApp(config) {
|
|
|
14430
14797
|
}
|
|
14431
14798
|
return component;
|
|
14432
14799
|
};
|
|
14433
|
-
const AppContent = () => /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Routes, { children: /* @__PURE__ */ jsxRuntime.jsxs(reactRouterDom.Route, { path: "/", element: /* @__PURE__ */ jsxRuntime.jsx(AppLayout, {}), children: [
|
|
14800
|
+
const AppContent = () => /* @__PURE__ */ jsxRuntime.jsx(React.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center min-h-screen", children: "Loading..." }), children: /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Routes, { children: /* @__PURE__ */ jsxRuntime.jsxs(reactRouterDom.Route, { path: "/", element: /* @__PURE__ */ jsxRuntime.jsx(AppLayout, {}), children: [
|
|
14434
14801
|
/* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Route, { index: true, element: wrapWithProtection("/", /* @__PURE__ */ jsxRuntime.jsx(DefaultHome, {})) }),
|
|
14435
14802
|
routes.map(({ path, component }, index) => /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Route, { path, element: wrapWithProtection(path, component) }, index))
|
|
14436
|
-
] }) });
|
|
14803
|
+
] }) }) });
|
|
14437
14804
|
return createProviderTree(/* @__PURE__ */ jsxRuntime.jsx(AppContent, {}));
|
|
14438
14805
|
},
|
|
14439
14806
|
mount(elementId = "root") {
|
|
@@ -17628,6 +17995,10 @@ exports.Badge = Badge;
|
|
|
17628
17995
|
exports.Breadcrumb = Breadcrumb;
|
|
17629
17996
|
exports.BulkSelectionBar = BulkSelectionBar;
|
|
17630
17997
|
exports.Button = Button;
|
|
17998
|
+
exports.COLUMN_WIDTHS = COLUMN_WIDTHS;
|
|
17999
|
+
exports.COMPACT_COLUMN_WIDTHS = COMPACT_COLUMN_WIDTHS;
|
|
18000
|
+
exports.COMPACT_FORMATTERS = COMPACT_FORMATTERS;
|
|
18001
|
+
exports.COMPACT_LABELS = COMPACT_LABELS;
|
|
17631
18002
|
exports.Card = Card;
|
|
17632
18003
|
exports.CardContent = CardContent;
|
|
17633
18004
|
exports.CardDescription = CardDescription;
|
|
@@ -17686,6 +18057,7 @@ exports.FileUpload = FileUpload;
|
|
|
17686
18057
|
exports.FormField = FormField;
|
|
17687
18058
|
exports.FormGroup = FormGroup;
|
|
17688
18059
|
exports.GlobalSearch = GlobalSearch;
|
|
18060
|
+
exports.IMPORTANCE_VISIBILITY = IMPORTANCE_VISIBILITY;
|
|
17689
18061
|
exports.Icon = Icon;
|
|
17690
18062
|
exports.IconBadge = IconBadge;
|
|
17691
18063
|
exports.Input = Input;
|
|
@@ -17741,6 +18113,7 @@ exports.Spinner = Spinner;
|
|
|
17741
18113
|
exports.StatCard = StatCard;
|
|
17742
18114
|
exports.StyleGuide = StyleGuide;
|
|
17743
18115
|
exports.Switch = Switch;
|
|
18116
|
+
exports.TABLE_BREAKPOINTS = TABLE_BREAKPOINTS;
|
|
17744
18117
|
exports.Table = Table;
|
|
17745
18118
|
exports.TableBody = TableBody;
|
|
17746
18119
|
exports.TableCaption = TableCaption;
|
|
@@ -17763,6 +18136,7 @@ exports.UserMenu = UserMenu;
|
|
|
17763
18136
|
exports.animationPresets = animationPresets;
|
|
17764
18137
|
exports.apiClient = apiClient;
|
|
17765
18138
|
exports.breakpoints = breakpoints;
|
|
18139
|
+
exports.calculateTableWidth = calculateTableWidth;
|
|
17766
18140
|
exports.cn = cn;
|
|
17767
18141
|
exports.createAPIDataTemplate = createAPIDataTemplate;
|
|
17768
18142
|
exports.createApiClient = createApiClient;
|
|
@@ -17772,6 +18146,7 @@ exports.createSimpleApp = createSimpleApp;
|
|
|
17772
18146
|
exports.defaultFieldRenderers = defaultFieldRenderers;
|
|
17773
18147
|
exports.detectBulkOperationType = detectBulkOperationType;
|
|
17774
18148
|
exports.detectUIConfig = detectUIConfig;
|
|
18149
|
+
exports.determineTableMode = determineTableMode;
|
|
17775
18150
|
exports.entityToListCardProps = entityToListCardProps;
|
|
17776
18151
|
exports.env = env;
|
|
17777
18152
|
exports.formatNumberWithTooltip = formatNumberWithTooltip;
|
|
@@ -17779,6 +18154,9 @@ exports.generateBulkOperationName = generateBulkOperationName;
|
|
|
17779
18154
|
exports.generateCompactColumns = generateCompactColumns;
|
|
17780
18155
|
exports.getAnimationClasses = getAnimationClasses;
|
|
17781
18156
|
exports.getChartHeight = getChartHeight;
|
|
18157
|
+
exports.getColumnWidth = getColumnWidth;
|
|
18158
|
+
exports.getCompactFormatter = getCompactFormatter;
|
|
18159
|
+
exports.getCompactLabel = getCompactLabel;
|
|
17782
18160
|
exports.getContainerHeightClass = getContainerHeightClass;
|
|
17783
18161
|
exports.getCurrentBreakpoint = getCurrentBreakpoint;
|
|
17784
18162
|
exports.getFieldType = getFieldType;
|
|
@@ -17797,6 +18175,7 @@ exports.renderField = renderField;
|
|
|
17797
18175
|
exports.responsiveScales = responsiveScales;
|
|
17798
18176
|
exports.setGlobalAuthService = setGlobalAuthService;
|
|
17799
18177
|
exports.tooltipContent = tooltipContent;
|
|
18178
|
+
exports.useAdaptiveTable = useAdaptiveTable;
|
|
17800
18179
|
exports.useApiMutation = useApiMutation;
|
|
17801
18180
|
exports.useApiQuery = useApiQuery;
|
|
17802
18181
|
exports.useAuth = useAuth;
|