@almadar/ui 2.5.0 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-42WRQA7T.js → chunk-2QM732NQ.js} +46 -3
- package/dist/{chunk-YLKXEXBP.js → chunk-DKQN5FVU.js} +24 -24
- package/dist/{chunk-FYYU3CHN.js → chunk-LEWQP2UP.js} +2538 -430
- package/dist/{chunk-GOZKH7QW.js → chunk-WGJIL4YR.js} +267 -2
- package/dist/components/index.d.ts +419 -7
- package/dist/components/index.js +84 -73
- package/dist/context/index.js +2 -2
- package/dist/hooks/index.d.ts +133 -3
- package/dist/hooks/index.js +2 -2
- package/dist/providers/index.js +4 -4
- package/package.json +1 -1
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { useTheme, useUISlots } from './chunk-
|
|
2
|
-
import { useTranslate, useQuerySingleton } from './chunk-
|
|
1
|
+
import { useTheme, useUISlots } from './chunk-DKQN5FVU.js';
|
|
2
|
+
import { useTranslate, useInfiniteScroll, useQuerySingleton, useLongPress, useSwipeGesture, useDragReorder, usePullToRefresh } from './chunk-WGJIL4YR.js';
|
|
3
3
|
import { useEventBus } from './chunk-YXZM3WCF.js';
|
|
4
4
|
import { cn, debugGroup, debug, debugGroupEnd, getNestedValue, isDebugEnabled } from './chunk-KKCVDUK7.js';
|
|
5
5
|
import { isPortalSlot } from './chunk-K2D5D3WK.js';
|
|
6
6
|
import { __publicField } from './chunk-PKBMQBKP.js';
|
|
7
7
|
import * as LucideIcons from 'lucide-react';
|
|
8
|
-
import { Loader2, ChevronDown, X, Check, Copy, AlertCircle, User, Sun, Moon, FileQuestion, Inbox, Search, Info, XCircle, CheckCircle, AlertTriangle, ChevronRight, Filter, Plus, ChevronLeft, HelpCircle, ChevronUp,
|
|
8
|
+
import { Loader2, ChevronDown, X, ArrowRight, TrendingDown, TrendingUp, Check, Copy, AlertCircle, User, Sun, Moon, FileQuestion, Inbox, Search, Info, XCircle, CheckCircle, AlertTriangle, ChevronRight, Filter, Plus, ChevronLeft, HelpCircle, ChevronUp, Minus, Star, FileWarning, Upload, MoreHorizontal, ArrowLeft, Calendar, Tag, Clock, CheckCircle2, DollarSign, FileText, Package } from 'lucide-react';
|
|
9
9
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
10
|
-
import * as
|
|
11
|
-
import
|
|
10
|
+
import * as React68 from 'react';
|
|
11
|
+
import React68__default, { useCallback, useState, useRef, useLayoutEffect, useEffect, lazy, createContext, useMemo, useId, useContext, Suspense } from 'react';
|
|
12
12
|
import { evaluate, createMinimalContext } from '@almadar/evaluator';
|
|
13
13
|
import { createPortal } from 'react-dom';
|
|
14
14
|
import ReactMarkdown from 'react-markdown';
|
|
@@ -157,7 +157,7 @@ var iconSizeStyles = {
|
|
|
157
157
|
md: "h-4 w-4",
|
|
158
158
|
lg: "h-5 w-5"
|
|
159
159
|
};
|
|
160
|
-
var Button =
|
|
160
|
+
var Button = React68__default.forwardRef(
|
|
161
161
|
({
|
|
162
162
|
className,
|
|
163
163
|
variant = "primary",
|
|
@@ -215,7 +215,7 @@ var Button = React50__default.forwardRef(
|
|
|
215
215
|
}
|
|
216
216
|
);
|
|
217
217
|
Button.displayName = "Button";
|
|
218
|
-
var Input =
|
|
218
|
+
var Input = React68__default.forwardRef(
|
|
219
219
|
({
|
|
220
220
|
className,
|
|
221
221
|
inputType,
|
|
@@ -327,7 +327,7 @@ var Input = React50__default.forwardRef(
|
|
|
327
327
|
}
|
|
328
328
|
);
|
|
329
329
|
Input.displayName = "Input";
|
|
330
|
-
var Label =
|
|
330
|
+
var Label = React68__default.forwardRef(
|
|
331
331
|
({ className, required, children, ...props }, ref) => {
|
|
332
332
|
return /* @__PURE__ */ jsxs(
|
|
333
333
|
"label",
|
|
@@ -347,7 +347,7 @@ var Label = React50__default.forwardRef(
|
|
|
347
347
|
}
|
|
348
348
|
);
|
|
349
349
|
Label.displayName = "Label";
|
|
350
|
-
var Textarea =
|
|
350
|
+
var Textarea = React68__default.forwardRef(
|
|
351
351
|
({ className, error, ...props }, ref) => {
|
|
352
352
|
return /* @__PURE__ */ jsx(
|
|
353
353
|
"textarea",
|
|
@@ -370,7 +370,7 @@ var Textarea = React50__default.forwardRef(
|
|
|
370
370
|
}
|
|
371
371
|
);
|
|
372
372
|
Textarea.displayName = "Textarea";
|
|
373
|
-
var Select =
|
|
373
|
+
var Select = React68__default.forwardRef(
|
|
374
374
|
({ className, options, placeholder, error, ...props }, ref) => {
|
|
375
375
|
return /* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
376
376
|
/* @__PURE__ */ jsxs(
|
|
@@ -406,7 +406,7 @@ var Select = React50__default.forwardRef(
|
|
|
406
406
|
}
|
|
407
407
|
);
|
|
408
408
|
Select.displayName = "Select";
|
|
409
|
-
var Checkbox =
|
|
409
|
+
var Checkbox = React68__default.forwardRef(
|
|
410
410
|
({ className, label, id, ...props }, ref) => {
|
|
411
411
|
const inputId = id || `checkbox-${Math.random().toString(36).substr(2, 9)}`;
|
|
412
412
|
return /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
|
|
@@ -472,7 +472,7 @@ var shadowStyles = {
|
|
|
472
472
|
md: "shadow-[var(--shadow-main)]",
|
|
473
473
|
lg: "shadow-[var(--shadow-lg)]"
|
|
474
474
|
};
|
|
475
|
-
var Card =
|
|
475
|
+
var Card = React68__default.forwardRef(
|
|
476
476
|
({
|
|
477
477
|
className,
|
|
478
478
|
variant = "bordered",
|
|
@@ -508,9 +508,9 @@ var Card = React50__default.forwardRef(
|
|
|
508
508
|
}
|
|
509
509
|
);
|
|
510
510
|
Card.displayName = "Card";
|
|
511
|
-
var CardHeader =
|
|
511
|
+
var CardHeader = React68__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("mb-4", className), ...props }));
|
|
512
512
|
CardHeader.displayName = "CardHeader";
|
|
513
|
-
var CardTitle =
|
|
513
|
+
var CardTitle = React68__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
514
514
|
"h3",
|
|
515
515
|
{
|
|
516
516
|
ref,
|
|
@@ -523,11 +523,11 @@ var CardTitle = React50__default.forwardRef(({ className, ...props }, ref) => /*
|
|
|
523
523
|
}
|
|
524
524
|
));
|
|
525
525
|
CardTitle.displayName = "CardTitle";
|
|
526
|
-
var CardContent =
|
|
526
|
+
var CardContent = React68__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("", className), ...props }));
|
|
527
527
|
CardContent.displayName = "CardContent";
|
|
528
528
|
var CardBody = CardContent;
|
|
529
529
|
CardBody.displayName = "CardBody";
|
|
530
|
-
var CardFooter =
|
|
530
|
+
var CardFooter = React68__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
531
531
|
"div",
|
|
532
532
|
{
|
|
533
533
|
ref,
|
|
@@ -573,7 +573,7 @@ var sizeStyles2 = {
|
|
|
573
573
|
md: "px-2.5 py-1 text-sm",
|
|
574
574
|
lg: "px-3 py-1.5 text-base"
|
|
575
575
|
};
|
|
576
|
-
var Badge =
|
|
576
|
+
var Badge = React68__default.forwardRef(
|
|
577
577
|
({ className, variant = "default", size = "sm", label, icon, children, ...props }, ref) => {
|
|
578
578
|
const iconSizes2 = { sm: "w-3 h-3", md: "w-3.5 h-3.5", lg: "w-4 h-4" };
|
|
579
579
|
const resolvedIcon = typeof icon === "string" ? (() => {
|
|
@@ -606,7 +606,7 @@ var sizeStyles3 = {
|
|
|
606
606
|
md: "h-6 w-6",
|
|
607
607
|
lg: "h-8 w-8"
|
|
608
608
|
};
|
|
609
|
-
var Spinner =
|
|
609
|
+
var Spinner = React68__default.forwardRef(
|
|
610
610
|
({ className, size = "md", ...props }, ref) => {
|
|
611
611
|
return /* @__PURE__ */ jsx(
|
|
612
612
|
"div",
|
|
@@ -871,7 +871,7 @@ var positionStyles = {
|
|
|
871
871
|
fixed: "fixed",
|
|
872
872
|
sticky: "sticky"
|
|
873
873
|
};
|
|
874
|
-
var Box =
|
|
874
|
+
var Box = React68__default.forwardRef(
|
|
875
875
|
({
|
|
876
876
|
padding,
|
|
877
877
|
paddingX,
|
|
@@ -1216,7 +1216,7 @@ var ProgressBar = ({
|
|
|
1216
1216
|
return null;
|
|
1217
1217
|
};
|
|
1218
1218
|
ProgressBar.displayName = "ProgressBar";
|
|
1219
|
-
var Radio =
|
|
1219
|
+
var Radio = React68__default.forwardRef(
|
|
1220
1220
|
({
|
|
1221
1221
|
label,
|
|
1222
1222
|
helperText,
|
|
@@ -1320,7 +1320,7 @@ var Radio = React50__default.forwardRef(
|
|
|
1320
1320
|
}
|
|
1321
1321
|
);
|
|
1322
1322
|
Radio.displayName = "Radio";
|
|
1323
|
-
var Switch =
|
|
1323
|
+
var Switch = React68.forwardRef(
|
|
1324
1324
|
({
|
|
1325
1325
|
checked,
|
|
1326
1326
|
defaultChecked = false,
|
|
@@ -1331,10 +1331,10 @@ var Switch = React50.forwardRef(
|
|
|
1331
1331
|
name,
|
|
1332
1332
|
className
|
|
1333
1333
|
}, ref) => {
|
|
1334
|
-
const [isChecked, setIsChecked] =
|
|
1334
|
+
const [isChecked, setIsChecked] = React68.useState(
|
|
1335
1335
|
checked !== void 0 ? checked : defaultChecked
|
|
1336
1336
|
);
|
|
1337
|
-
|
|
1337
|
+
React68.useEffect(() => {
|
|
1338
1338
|
if (checked !== void 0) {
|
|
1339
1339
|
setIsChecked(checked);
|
|
1340
1340
|
}
|
|
@@ -1467,7 +1467,8 @@ var Stack = ({
|
|
|
1467
1467
|
role,
|
|
1468
1468
|
tabIndex,
|
|
1469
1469
|
action,
|
|
1470
|
-
actionPayload
|
|
1470
|
+
actionPayload,
|
|
1471
|
+
responsive = false
|
|
1471
1472
|
}) => {
|
|
1472
1473
|
const eventBus = useEventBus();
|
|
1473
1474
|
const handleClick = (e) => {
|
|
@@ -1476,7 +1477,8 @@ var Stack = ({
|
|
|
1476
1477
|
}
|
|
1477
1478
|
onClick?.(e);
|
|
1478
1479
|
};
|
|
1479
|
-
const
|
|
1480
|
+
const isHorizontal = direction === "horizontal";
|
|
1481
|
+
const directionClass = responsive && isHorizontal ? reverse ? "flex-col-reverse md:flex-row-reverse" : "flex-col md:flex-row" : isHorizontal ? reverse ? "flex-row-reverse" : "flex-row" : reverse ? "flex-col-reverse" : "flex-col";
|
|
1480
1482
|
return /* @__PURE__ */ jsx(
|
|
1481
1483
|
Component,
|
|
1482
1484
|
{
|
|
@@ -2005,8 +2007,8 @@ var LawReferenceTooltip = ({
|
|
|
2005
2007
|
position = "top",
|
|
2006
2008
|
className
|
|
2007
2009
|
}) => {
|
|
2008
|
-
const [isVisible, setIsVisible] =
|
|
2009
|
-
const timeoutRef =
|
|
2010
|
+
const [isVisible, setIsVisible] = React68__default.useState(false);
|
|
2011
|
+
const timeoutRef = React68__default.useRef(null);
|
|
2010
2012
|
const handleMouseEnter = () => {
|
|
2011
2013
|
if (timeoutRef.current) clearTimeout(timeoutRef.current);
|
|
2012
2014
|
timeoutRef.current = setTimeout(() => setIsVisible(true), 200);
|
|
@@ -2015,7 +2017,7 @@ var LawReferenceTooltip = ({
|
|
|
2015
2017
|
if (timeoutRef.current) clearTimeout(timeoutRef.current);
|
|
2016
2018
|
setIsVisible(false);
|
|
2017
2019
|
};
|
|
2018
|
-
|
|
2020
|
+
React68__default.useEffect(() => {
|
|
2019
2021
|
return () => {
|
|
2020
2022
|
if (timeoutRef.current) clearTimeout(timeoutRef.current);
|
|
2021
2023
|
};
|
|
@@ -2182,6 +2184,567 @@ function TimeSlotCell({
|
|
|
2182
2184
|
);
|
|
2183
2185
|
}
|
|
2184
2186
|
TimeSlotCell.displayName = "TimeSlotCell";
|
|
2187
|
+
var statusColors = {
|
|
2188
|
+
online: "bg-[var(--color-success)]",
|
|
2189
|
+
offline: "bg-[var(--color-muted-foreground)]",
|
|
2190
|
+
away: "bg-[var(--color-warning)]",
|
|
2191
|
+
busy: "bg-[var(--color-error)]",
|
|
2192
|
+
warning: "bg-[var(--color-warning)]",
|
|
2193
|
+
critical: "bg-[var(--color-error)]"
|
|
2194
|
+
};
|
|
2195
|
+
var pulseRingColors = {
|
|
2196
|
+
online: "ring-[var(--color-success)]",
|
|
2197
|
+
offline: "ring-[var(--color-muted-foreground)]",
|
|
2198
|
+
away: "ring-[var(--color-warning)]",
|
|
2199
|
+
busy: "ring-[var(--color-error)]",
|
|
2200
|
+
warning: "ring-[var(--color-warning)]",
|
|
2201
|
+
critical: "ring-[var(--color-error)]"
|
|
2202
|
+
};
|
|
2203
|
+
var sizeStyles5 = {
|
|
2204
|
+
sm: "w-2 h-2",
|
|
2205
|
+
md: "w-2.5 h-2.5",
|
|
2206
|
+
lg: "w-3 h-3"
|
|
2207
|
+
};
|
|
2208
|
+
var StatusDot = React68__default.forwardRef(
|
|
2209
|
+
({ className, status = "offline", pulse = false, size = "md", label, ...props }, ref) => {
|
|
2210
|
+
return /* @__PURE__ */ jsx(
|
|
2211
|
+
"span",
|
|
2212
|
+
{
|
|
2213
|
+
ref,
|
|
2214
|
+
className: cn(
|
|
2215
|
+
"inline-block rounded-full flex-shrink-0",
|
|
2216
|
+
statusColors[status],
|
|
2217
|
+
sizeStyles5[size],
|
|
2218
|
+
pulse && [
|
|
2219
|
+
"animate-pulse",
|
|
2220
|
+
"ring-2 ring-offset-1",
|
|
2221
|
+
pulseRingColors[status],
|
|
2222
|
+
"ring-opacity-40"
|
|
2223
|
+
],
|
|
2224
|
+
className
|
|
2225
|
+
),
|
|
2226
|
+
role: "status",
|
|
2227
|
+
"aria-label": label ?? status,
|
|
2228
|
+
...props
|
|
2229
|
+
}
|
|
2230
|
+
);
|
|
2231
|
+
}
|
|
2232
|
+
);
|
|
2233
|
+
StatusDot.displayName = "StatusDot";
|
|
2234
|
+
var sizeStyles6 = {
|
|
2235
|
+
sm: { icon: "w-3 h-3", text: "text-xs" },
|
|
2236
|
+
md: { icon: "w-4 h-4", text: "text-sm" },
|
|
2237
|
+
lg: { icon: "w-5 h-5", text: "text-base" }
|
|
2238
|
+
};
|
|
2239
|
+
function resolveDirection(value, direction) {
|
|
2240
|
+
if (direction) return direction;
|
|
2241
|
+
if (value === void 0 || value === 0) return "flat";
|
|
2242
|
+
return value > 0 ? "up" : "down";
|
|
2243
|
+
}
|
|
2244
|
+
function resolveColor(dir, invert) {
|
|
2245
|
+
if (dir === "flat") return "text-[var(--color-muted-foreground)]";
|
|
2246
|
+
const isPositive = dir === "up";
|
|
2247
|
+
const isGood = invert ? !isPositive : isPositive;
|
|
2248
|
+
return isGood ? "text-[var(--color-success)]" : "text-[var(--color-error)]";
|
|
2249
|
+
}
|
|
2250
|
+
var iconMap = {
|
|
2251
|
+
up: TrendingUp,
|
|
2252
|
+
down: TrendingDown,
|
|
2253
|
+
flat: ArrowRight
|
|
2254
|
+
};
|
|
2255
|
+
var TrendIndicator = React68__default.forwardRef(
|
|
2256
|
+
({
|
|
2257
|
+
className,
|
|
2258
|
+
value,
|
|
2259
|
+
direction,
|
|
2260
|
+
showValue = true,
|
|
2261
|
+
invert = false,
|
|
2262
|
+
label,
|
|
2263
|
+
size = "md",
|
|
2264
|
+
...props
|
|
2265
|
+
}, ref) => {
|
|
2266
|
+
const dir = resolveDirection(value, direction);
|
|
2267
|
+
const colorClass = resolveColor(dir, invert);
|
|
2268
|
+
const IconComponent = iconMap[dir];
|
|
2269
|
+
const styles = sizeStyles6[size];
|
|
2270
|
+
const formattedValue = value !== void 0 ? `${value > 0 ? "+" : ""}${value}%` : void 0;
|
|
2271
|
+
const ariaLabel = label ?? (formattedValue ? `${dir} ${formattedValue}` : dir);
|
|
2272
|
+
return /* @__PURE__ */ jsxs(
|
|
2273
|
+
"span",
|
|
2274
|
+
{
|
|
2275
|
+
ref,
|
|
2276
|
+
className: cn(
|
|
2277
|
+
"inline-flex items-center gap-1 font-medium",
|
|
2278
|
+
colorClass,
|
|
2279
|
+
styles.text,
|
|
2280
|
+
className
|
|
2281
|
+
),
|
|
2282
|
+
role: "status",
|
|
2283
|
+
"aria-label": ariaLabel,
|
|
2284
|
+
...props,
|
|
2285
|
+
children: [
|
|
2286
|
+
/* @__PURE__ */ jsx(IconComponent, { className: styles.icon }),
|
|
2287
|
+
showValue && formattedValue && /* @__PURE__ */ jsx("span", { children: formattedValue })
|
|
2288
|
+
]
|
|
2289
|
+
}
|
|
2290
|
+
);
|
|
2291
|
+
}
|
|
2292
|
+
);
|
|
2293
|
+
TrendIndicator.displayName = "TrendIndicator";
|
|
2294
|
+
function useSafeEventBus() {
|
|
2295
|
+
try {
|
|
2296
|
+
return useEventBus();
|
|
2297
|
+
} catch {
|
|
2298
|
+
return { emit: () => {
|
|
2299
|
+
}, on: () => () => {
|
|
2300
|
+
}, once: () => {
|
|
2301
|
+
} };
|
|
2302
|
+
}
|
|
2303
|
+
}
|
|
2304
|
+
var trackSizes = {
|
|
2305
|
+
sm: "h-1",
|
|
2306
|
+
md: "h-1.5",
|
|
2307
|
+
lg: "h-2"
|
|
2308
|
+
};
|
|
2309
|
+
var thumbSizes = {
|
|
2310
|
+
sm: "w-3 h-3",
|
|
2311
|
+
md: "w-4 h-4",
|
|
2312
|
+
lg: "w-5 h-5"
|
|
2313
|
+
};
|
|
2314
|
+
var RangeSlider = React68__default.forwardRef(
|
|
2315
|
+
({
|
|
2316
|
+
className,
|
|
2317
|
+
min = 0,
|
|
2318
|
+
max = 100,
|
|
2319
|
+
value = 0,
|
|
2320
|
+
step = 1,
|
|
2321
|
+
showTooltip = false,
|
|
2322
|
+
showTicks = false,
|
|
2323
|
+
buffered,
|
|
2324
|
+
size = "md",
|
|
2325
|
+
disabled = false,
|
|
2326
|
+
action,
|
|
2327
|
+
actionPayload,
|
|
2328
|
+
onChange,
|
|
2329
|
+
formatValue: formatValue3,
|
|
2330
|
+
...props
|
|
2331
|
+
}, ref) => {
|
|
2332
|
+
const [isDragging, setIsDragging] = useState(false);
|
|
2333
|
+
const [showTip, setShowTip] = useState(false);
|
|
2334
|
+
const inputRef = useRef(null);
|
|
2335
|
+
const eventBus = useSafeEventBus();
|
|
2336
|
+
const percentage = max !== min ? (value - min) / (max - min) * 100 : 0;
|
|
2337
|
+
const bufferedPercentage = buffered !== void 0 ? Math.min(buffered, 100) : void 0;
|
|
2338
|
+
const displayValue = formatValue3 ? formatValue3(value) : String(value);
|
|
2339
|
+
const handleChange = useCallback(
|
|
2340
|
+
(e) => {
|
|
2341
|
+
const newValue = Number(e.target.value);
|
|
2342
|
+
onChange?.(newValue);
|
|
2343
|
+
if (action) {
|
|
2344
|
+
eventBus.emit(`UI:${action}`, { ...actionPayload, value: newValue });
|
|
2345
|
+
}
|
|
2346
|
+
},
|
|
2347
|
+
[onChange, action, actionPayload, eventBus]
|
|
2348
|
+
);
|
|
2349
|
+
const tickCount = showTicks ? Math.min(Math.floor((max - min) / step), 20) : 0;
|
|
2350
|
+
return /* @__PURE__ */ jsxs(
|
|
2351
|
+
"div",
|
|
2352
|
+
{
|
|
2353
|
+
ref,
|
|
2354
|
+
className: cn(
|
|
2355
|
+
"relative w-full",
|
|
2356
|
+
disabled && "opacity-50 cursor-not-allowed",
|
|
2357
|
+
className
|
|
2358
|
+
),
|
|
2359
|
+
...props,
|
|
2360
|
+
children: [
|
|
2361
|
+
/* @__PURE__ */ jsxs("div", { className: "relative w-full py-2", children: [
|
|
2362
|
+
/* @__PURE__ */ jsx(
|
|
2363
|
+
"div",
|
|
2364
|
+
{
|
|
2365
|
+
className: cn(
|
|
2366
|
+
"absolute inset-x-0 rounded-full bg-[var(--color-muted)]",
|
|
2367
|
+
trackSizes[size]
|
|
2368
|
+
),
|
|
2369
|
+
style: { top: "50%", transform: "translateY(-50%)" }
|
|
2370
|
+
}
|
|
2371
|
+
),
|
|
2372
|
+
bufferedPercentage !== void 0 && /* @__PURE__ */ jsx(
|
|
2373
|
+
"div",
|
|
2374
|
+
{
|
|
2375
|
+
className: cn(
|
|
2376
|
+
"absolute rounded-full bg-[var(--color-muted-foreground)] opacity-30",
|
|
2377
|
+
trackSizes[size]
|
|
2378
|
+
),
|
|
2379
|
+
style: {
|
|
2380
|
+
top: "50%",
|
|
2381
|
+
transform: "translateY(-50%)",
|
|
2382
|
+
left: 0,
|
|
2383
|
+
width: `${bufferedPercentage}%`
|
|
2384
|
+
}
|
|
2385
|
+
}
|
|
2386
|
+
),
|
|
2387
|
+
/* @__PURE__ */ jsx(
|
|
2388
|
+
"div",
|
|
2389
|
+
{
|
|
2390
|
+
className: cn(
|
|
2391
|
+
"absolute rounded-full bg-[var(--color-primary)]",
|
|
2392
|
+
trackSizes[size]
|
|
2393
|
+
),
|
|
2394
|
+
style: {
|
|
2395
|
+
top: "50%",
|
|
2396
|
+
transform: "translateY(-50%)",
|
|
2397
|
+
left: 0,
|
|
2398
|
+
width: `${percentage}%`
|
|
2399
|
+
}
|
|
2400
|
+
}
|
|
2401
|
+
),
|
|
2402
|
+
/* @__PURE__ */ jsx(
|
|
2403
|
+
"input",
|
|
2404
|
+
{
|
|
2405
|
+
ref: inputRef,
|
|
2406
|
+
type: "range",
|
|
2407
|
+
min,
|
|
2408
|
+
max,
|
|
2409
|
+
step,
|
|
2410
|
+
value,
|
|
2411
|
+
disabled,
|
|
2412
|
+
onChange: handleChange,
|
|
2413
|
+
onMouseDown: () => {
|
|
2414
|
+
setIsDragging(true);
|
|
2415
|
+
setShowTip(true);
|
|
2416
|
+
},
|
|
2417
|
+
onMouseUp: () => {
|
|
2418
|
+
setIsDragging(false);
|
|
2419
|
+
setShowTip(false);
|
|
2420
|
+
},
|
|
2421
|
+
onTouchStart: () => {
|
|
2422
|
+
setIsDragging(true);
|
|
2423
|
+
setShowTip(true);
|
|
2424
|
+
},
|
|
2425
|
+
onTouchEnd: () => {
|
|
2426
|
+
setIsDragging(false);
|
|
2427
|
+
setShowTip(false);
|
|
2428
|
+
},
|
|
2429
|
+
onFocus: () => setShowTip(true),
|
|
2430
|
+
onBlur: () => {
|
|
2431
|
+
if (!isDragging) setShowTip(false);
|
|
2432
|
+
},
|
|
2433
|
+
className: cn(
|
|
2434
|
+
"absolute inset-0 w-full opacity-0 cursor-pointer",
|
|
2435
|
+
disabled && "cursor-not-allowed",
|
|
2436
|
+
// Thumb sizing via pseudo-element
|
|
2437
|
+
"[&::-webkit-slider-thumb]:appearance-none",
|
|
2438
|
+
"[&::-webkit-slider-thumb]:w-5 [&::-webkit-slider-thumb]:h-5",
|
|
2439
|
+
"[&::-moz-range-thumb]:w-5 [&::-moz-range-thumb]:h-5"
|
|
2440
|
+
),
|
|
2441
|
+
style: { height: "100%", margin: 0 },
|
|
2442
|
+
"aria-label": props["aria-label"] ?? "Range slider",
|
|
2443
|
+
"aria-valuemin": min,
|
|
2444
|
+
"aria-valuemax": max,
|
|
2445
|
+
"aria-valuenow": value,
|
|
2446
|
+
"aria-valuetext": displayValue
|
|
2447
|
+
}
|
|
2448
|
+
),
|
|
2449
|
+
/* @__PURE__ */ jsx(
|
|
2450
|
+
"div",
|
|
2451
|
+
{
|
|
2452
|
+
className: cn(
|
|
2453
|
+
"absolute rounded-full bg-[var(--color-primary-foreground)]",
|
|
2454
|
+
"border-2 border-[var(--color-primary)]",
|
|
2455
|
+
"shadow-[var(--shadow-sm)]",
|
|
2456
|
+
"pointer-events-none",
|
|
2457
|
+
"transition-transform duration-100",
|
|
2458
|
+
isDragging && "scale-110",
|
|
2459
|
+
thumbSizes[size]
|
|
2460
|
+
),
|
|
2461
|
+
style: {
|
|
2462
|
+
top: "50%",
|
|
2463
|
+
transform: `translateY(-50%) translateX(-50%)${isDragging ? " scale(1.1)" : ""}`,
|
|
2464
|
+
left: `${percentage}%`
|
|
2465
|
+
}
|
|
2466
|
+
}
|
|
2467
|
+
),
|
|
2468
|
+
showTooltip && showTip && /* @__PURE__ */ jsx(
|
|
2469
|
+
"div",
|
|
2470
|
+
{
|
|
2471
|
+
className: cn(
|
|
2472
|
+
"absolute -top-8 px-2 py-0.5 rounded",
|
|
2473
|
+
"bg-[var(--color-foreground)] text-[var(--color-background)]",
|
|
2474
|
+
"text-xs font-medium whitespace-nowrap",
|
|
2475
|
+
"pointer-events-none"
|
|
2476
|
+
),
|
|
2477
|
+
style: {
|
|
2478
|
+
left: `${percentage}%`,
|
|
2479
|
+
transform: "translateX(-50%)"
|
|
2480
|
+
},
|
|
2481
|
+
children: displayValue
|
|
2482
|
+
}
|
|
2483
|
+
)
|
|
2484
|
+
] }),
|
|
2485
|
+
showTicks && tickCount > 0 && /* @__PURE__ */ jsx("div", { className: "relative w-full h-2 mt-1", children: Array.from({ length: tickCount + 1 }, (_, i) => {
|
|
2486
|
+
const tickPercent = i / tickCount * 100;
|
|
2487
|
+
return /* @__PURE__ */ jsx(
|
|
2488
|
+
"div",
|
|
2489
|
+
{
|
|
2490
|
+
className: "absolute w-px h-1.5 bg-[var(--color-muted-foreground)]",
|
|
2491
|
+
style: { left: `${tickPercent}%` }
|
|
2492
|
+
},
|
|
2493
|
+
i
|
|
2494
|
+
);
|
|
2495
|
+
}) })
|
|
2496
|
+
]
|
|
2497
|
+
}
|
|
2498
|
+
);
|
|
2499
|
+
}
|
|
2500
|
+
);
|
|
2501
|
+
RangeSlider.displayName = "RangeSlider";
|
|
2502
|
+
function easeOut(t) {
|
|
2503
|
+
return t * (2 - t);
|
|
2504
|
+
}
|
|
2505
|
+
var AnimatedCounter = ({
|
|
2506
|
+
value,
|
|
2507
|
+
duration = 600,
|
|
2508
|
+
prefix,
|
|
2509
|
+
suffix,
|
|
2510
|
+
className
|
|
2511
|
+
}) => {
|
|
2512
|
+
const [displayValue, setDisplayValue] = useState(value);
|
|
2513
|
+
const previousValueRef = useRef(value);
|
|
2514
|
+
const animationFrameRef = useRef(null);
|
|
2515
|
+
useEffect(() => {
|
|
2516
|
+
const from = previousValueRef.current;
|
|
2517
|
+
const to = value;
|
|
2518
|
+
previousValueRef.current = value;
|
|
2519
|
+
if (from === to) {
|
|
2520
|
+
setDisplayValue(to);
|
|
2521
|
+
return;
|
|
2522
|
+
}
|
|
2523
|
+
const startTime = performance.now();
|
|
2524
|
+
const diff = to - from;
|
|
2525
|
+
function animate(currentTime) {
|
|
2526
|
+
const elapsed = currentTime - startTime;
|
|
2527
|
+
const progress = Math.min(elapsed / duration, 1);
|
|
2528
|
+
const easedProgress = easeOut(progress);
|
|
2529
|
+
setDisplayValue(from + diff * easedProgress);
|
|
2530
|
+
if (progress < 1) {
|
|
2531
|
+
animationFrameRef.current = requestAnimationFrame(animate);
|
|
2532
|
+
} else {
|
|
2533
|
+
setDisplayValue(to);
|
|
2534
|
+
}
|
|
2535
|
+
}
|
|
2536
|
+
animationFrameRef.current = requestAnimationFrame(animate);
|
|
2537
|
+
return () => {
|
|
2538
|
+
if (animationFrameRef.current !== null) {
|
|
2539
|
+
cancelAnimationFrame(animationFrameRef.current);
|
|
2540
|
+
}
|
|
2541
|
+
};
|
|
2542
|
+
}, [value, duration]);
|
|
2543
|
+
const decimalPlaces = Number.isInteger(value) ? 0 : String(value).split(".")[1]?.length ?? 0;
|
|
2544
|
+
const formattedValue = displayValue.toFixed(decimalPlaces);
|
|
2545
|
+
return /* @__PURE__ */ jsxs(Typography, { variant: "h3", className: cn("tabular-nums", className), children: [
|
|
2546
|
+
prefix,
|
|
2547
|
+
formattedValue,
|
|
2548
|
+
suffix
|
|
2549
|
+
] });
|
|
2550
|
+
};
|
|
2551
|
+
AnimatedCounter.displayName = "AnimatedCounter";
|
|
2552
|
+
var InfiniteScrollSentinel = ({
|
|
2553
|
+
loadMoreEvent,
|
|
2554
|
+
loadMorePayload,
|
|
2555
|
+
isLoading = false,
|
|
2556
|
+
hasMore = true,
|
|
2557
|
+
threshold = "200px",
|
|
2558
|
+
className
|
|
2559
|
+
}) => {
|
|
2560
|
+
const eventBus = useEventBus();
|
|
2561
|
+
const onLoadMore = useCallback(() => {
|
|
2562
|
+
eventBus.emit(`UI:${loadMoreEvent}`, loadMorePayload ?? {});
|
|
2563
|
+
}, [eventBus, loadMoreEvent, loadMorePayload]);
|
|
2564
|
+
const { sentinelRef } = useInfiniteScroll(onLoadMore, {
|
|
2565
|
+
rootMargin: threshold,
|
|
2566
|
+
hasMore,
|
|
2567
|
+
isLoading
|
|
2568
|
+
});
|
|
2569
|
+
return /* @__PURE__ */ jsxs(
|
|
2570
|
+
Box,
|
|
2571
|
+
{
|
|
2572
|
+
className: cn("flex items-center justify-center py-4", className),
|
|
2573
|
+
children: [
|
|
2574
|
+
/* @__PURE__ */ jsx(Box, { ref: sentinelRef, className: "h-1 w-full", "aria-hidden": "true" }),
|
|
2575
|
+
isLoading && /* @__PURE__ */ jsx(Spinner, { size: "sm" })
|
|
2576
|
+
]
|
|
2577
|
+
}
|
|
2578
|
+
);
|
|
2579
|
+
};
|
|
2580
|
+
InfiniteScrollSentinel.displayName = "InfiniteScrollSentinel";
|
|
2581
|
+
var CONFETTI_COLORS = [
|
|
2582
|
+
"var(--color-primary)",
|
|
2583
|
+
"var(--color-success)",
|
|
2584
|
+
"var(--color-warning)",
|
|
2585
|
+
"var(--color-error)",
|
|
2586
|
+
"gold",
|
|
2587
|
+
"dodgerblue"
|
|
2588
|
+
];
|
|
2589
|
+
var particleIdCounter = 0;
|
|
2590
|
+
function createParticles(count) {
|
|
2591
|
+
return Array.from({ length: count }, () => {
|
|
2592
|
+
particleIdCounter += 1;
|
|
2593
|
+
return {
|
|
2594
|
+
id: particleIdCounter,
|
|
2595
|
+
color: CONFETTI_COLORS[Math.floor(Math.random() * CONFETTI_COLORS.length)],
|
|
2596
|
+
left: 30 + Math.random() * 40,
|
|
2597
|
+
delay: Math.random() * 300,
|
|
2598
|
+
angle: Math.random() * 360,
|
|
2599
|
+
distance: 40 + Math.random() * 80,
|
|
2600
|
+
rotation: Math.random() * 720 - 360,
|
|
2601
|
+
size: 4 + Math.random() * 6
|
|
2602
|
+
};
|
|
2603
|
+
});
|
|
2604
|
+
}
|
|
2605
|
+
var ConfettiEffect = ({
|
|
2606
|
+
trigger,
|
|
2607
|
+
duration = 2e3,
|
|
2608
|
+
particleCount = 30,
|
|
2609
|
+
className
|
|
2610
|
+
}) => {
|
|
2611
|
+
const [particles, setParticles] = useState([]);
|
|
2612
|
+
const previousTriggerRef = useRef(false);
|
|
2613
|
+
useEffect(() => {
|
|
2614
|
+
const wasFalse = !previousTriggerRef.current;
|
|
2615
|
+
previousTriggerRef.current = trigger;
|
|
2616
|
+
if (trigger && wasFalse) {
|
|
2617
|
+
const newParticles = createParticles(particleCount);
|
|
2618
|
+
setParticles(newParticles);
|
|
2619
|
+
const timer = window.setTimeout(() => {
|
|
2620
|
+
setParticles([]);
|
|
2621
|
+
}, duration);
|
|
2622
|
+
return () => {
|
|
2623
|
+
window.clearTimeout(timer);
|
|
2624
|
+
};
|
|
2625
|
+
}
|
|
2626
|
+
return void 0;
|
|
2627
|
+
}, [trigger, particleCount, duration]);
|
|
2628
|
+
if (particles.length === 0) {
|
|
2629
|
+
return null;
|
|
2630
|
+
}
|
|
2631
|
+
return /* @__PURE__ */ jsxs(
|
|
2632
|
+
Box,
|
|
2633
|
+
{
|
|
2634
|
+
position: "absolute",
|
|
2635
|
+
className: cn(
|
|
2636
|
+
"inset-0 pointer-events-none overflow-hidden z-50",
|
|
2637
|
+
className
|
|
2638
|
+
),
|
|
2639
|
+
"aria-hidden": "true",
|
|
2640
|
+
children: [
|
|
2641
|
+
particles.map((p) => {
|
|
2642
|
+
const rad = p.angle * Math.PI / 180;
|
|
2643
|
+
const tx = Math.cos(rad) * p.distance;
|
|
2644
|
+
const ty = Math.sin(rad) * p.distance - 20;
|
|
2645
|
+
return /* @__PURE__ */ jsx(
|
|
2646
|
+
Box,
|
|
2647
|
+
{
|
|
2648
|
+
className: "absolute rounded-sm",
|
|
2649
|
+
style: {
|
|
2650
|
+
left: `${p.left}%`,
|
|
2651
|
+
top: "50%",
|
|
2652
|
+
width: p.size,
|
|
2653
|
+
height: p.size,
|
|
2654
|
+
backgroundColor: p.color,
|
|
2655
|
+
animation: `confetti-burst ${duration - p.delay}ms ease-out ${p.delay}ms forwards`,
|
|
2656
|
+
opacity: 0,
|
|
2657
|
+
// Use CSS custom properties for the animation endpoint
|
|
2658
|
+
// @ts-expect-error -- CSS custom properties are not typed in CSSProperties
|
|
2659
|
+
"--confetti-tx": `${tx}px`,
|
|
2660
|
+
"--confetti-ty": `${ty}px`,
|
|
2661
|
+
"--confetti-rotate": `${p.rotation}deg`
|
|
2662
|
+
}
|
|
2663
|
+
},
|
|
2664
|
+
p.id
|
|
2665
|
+
);
|
|
2666
|
+
}),
|
|
2667
|
+
/* @__PURE__ */ jsx("style", { children: `
|
|
2668
|
+
@keyframes confetti-burst {
|
|
2669
|
+
0% {
|
|
2670
|
+
opacity: 1;
|
|
2671
|
+
transform: translate(0, 0) rotate(0deg) scale(1);
|
|
2672
|
+
}
|
|
2673
|
+
70% {
|
|
2674
|
+
opacity: 1;
|
|
2675
|
+
}
|
|
2676
|
+
100% {
|
|
2677
|
+
opacity: 0;
|
|
2678
|
+
transform: translate(var(--confetti-tx), var(--confetti-ty)) rotate(var(--confetti-rotate)) scale(0.5);
|
|
2679
|
+
}
|
|
2680
|
+
}
|
|
2681
|
+
` })
|
|
2682
|
+
]
|
|
2683
|
+
}
|
|
2684
|
+
);
|
|
2685
|
+
};
|
|
2686
|
+
ConfettiEffect.displayName = "ConfettiEffect";
|
|
2687
|
+
var TypewriterText = ({
|
|
2688
|
+
text,
|
|
2689
|
+
speed = 40,
|
|
2690
|
+
startDelay = 0,
|
|
2691
|
+
className,
|
|
2692
|
+
onComplete
|
|
2693
|
+
}) => {
|
|
2694
|
+
const [charCount, setCharCount] = useState(0);
|
|
2695
|
+
const [started, setStarted] = useState(startDelay === 0);
|
|
2696
|
+
const onCompleteRef = useRef(onComplete);
|
|
2697
|
+
onCompleteRef.current = onComplete;
|
|
2698
|
+
useEffect(() => {
|
|
2699
|
+
if (startDelay <= 0) {
|
|
2700
|
+
setStarted(true);
|
|
2701
|
+
return void 0;
|
|
2702
|
+
}
|
|
2703
|
+
setStarted(false);
|
|
2704
|
+
setCharCount(0);
|
|
2705
|
+
const delayTimer = window.setTimeout(() => {
|
|
2706
|
+
setStarted(true);
|
|
2707
|
+
}, startDelay);
|
|
2708
|
+
return () => {
|
|
2709
|
+
window.clearTimeout(delayTimer);
|
|
2710
|
+
};
|
|
2711
|
+
}, [startDelay, text]);
|
|
2712
|
+
useEffect(() => {
|
|
2713
|
+
setCharCount(0);
|
|
2714
|
+
}, [text]);
|
|
2715
|
+
useEffect(() => {
|
|
2716
|
+
if (!started) return void 0;
|
|
2717
|
+
if (charCount >= text.length) {
|
|
2718
|
+
onCompleteRef.current?.();
|
|
2719
|
+
return void 0;
|
|
2720
|
+
}
|
|
2721
|
+
const interval = window.setInterval(() => {
|
|
2722
|
+
setCharCount((prev) => {
|
|
2723
|
+
const next = prev + 1;
|
|
2724
|
+
if (next >= text.length) {
|
|
2725
|
+
window.clearInterval(interval);
|
|
2726
|
+
}
|
|
2727
|
+
return next;
|
|
2728
|
+
});
|
|
2729
|
+
}, speed);
|
|
2730
|
+
return () => {
|
|
2731
|
+
window.clearInterval(interval);
|
|
2732
|
+
};
|
|
2733
|
+
}, [started, text, speed, charCount]);
|
|
2734
|
+
const isComplete = charCount >= text.length;
|
|
2735
|
+
const displayedText = text.slice(0, charCount);
|
|
2736
|
+
return /* @__PURE__ */ jsxs(Typography, { variant: "body", className: cn("inline", className), children: [
|
|
2737
|
+
displayedText,
|
|
2738
|
+
!isComplete && /* @__PURE__ */ jsx(
|
|
2739
|
+
"span",
|
|
2740
|
+
{
|
|
2741
|
+
className: "inline-block w-[2px] h-[1em] bg-[var(--color-foreground)] ml-[1px] align-text-bottom animate-pulse",
|
|
2742
|
+
"aria-hidden": "true"
|
|
2743
|
+
}
|
|
2744
|
+
)
|
|
2745
|
+
] });
|
|
2746
|
+
};
|
|
2747
|
+
TypewriterText.displayName = "TypewriterText";
|
|
2185
2748
|
var heartIcon = (filled, size) => /* @__PURE__ */ jsx(
|
|
2186
2749
|
"svg",
|
|
2187
2750
|
{
|
|
@@ -2264,9 +2827,9 @@ function ScoreDisplay({
|
|
|
2264
2827
|
animated = true,
|
|
2265
2828
|
locale = "en-US"
|
|
2266
2829
|
}) {
|
|
2267
|
-
const [displayValue, setDisplayValue] =
|
|
2268
|
-
const [isAnimating, setIsAnimating] =
|
|
2269
|
-
|
|
2830
|
+
const [displayValue, setDisplayValue] = React68.useState(value);
|
|
2831
|
+
const [isAnimating, setIsAnimating] = React68.useState(false);
|
|
2832
|
+
React68.useEffect(() => {
|
|
2270
2833
|
if (!animated || displayValue === value) {
|
|
2271
2834
|
setDisplayValue(value);
|
|
2272
2835
|
return;
|
|
@@ -2339,9 +2902,9 @@ function ControlButton({
|
|
|
2339
2902
|
className
|
|
2340
2903
|
}) {
|
|
2341
2904
|
const eventBus = useEventBus();
|
|
2342
|
-
const [isPressed, setIsPressed] =
|
|
2905
|
+
const [isPressed, setIsPressed] = React68.useState(false);
|
|
2343
2906
|
const actualPressed = pressed ?? isPressed;
|
|
2344
|
-
const handlePointerDown =
|
|
2907
|
+
const handlePointerDown = React68.useCallback(
|
|
2345
2908
|
(e) => {
|
|
2346
2909
|
e.preventDefault();
|
|
2347
2910
|
if (disabled) return;
|
|
@@ -2351,7 +2914,7 @@ function ControlButton({
|
|
|
2351
2914
|
},
|
|
2352
2915
|
[disabled, pressEvent, eventBus, onPress]
|
|
2353
2916
|
);
|
|
2354
|
-
const handlePointerUp =
|
|
2917
|
+
const handlePointerUp = React68.useCallback(
|
|
2355
2918
|
(e) => {
|
|
2356
2919
|
e.preventDefault();
|
|
2357
2920
|
if (disabled) return;
|
|
@@ -2361,7 +2924,7 @@ function ControlButton({
|
|
|
2361
2924
|
},
|
|
2362
2925
|
[disabled, releaseEvent, eventBus, onRelease]
|
|
2363
2926
|
);
|
|
2364
|
-
const handlePointerLeave =
|
|
2927
|
+
const handlePointerLeave = React68.useCallback(
|
|
2365
2928
|
(e) => {
|
|
2366
2929
|
if (isPressed) {
|
|
2367
2930
|
setIsPressed(false);
|
|
@@ -2589,7 +3152,7 @@ var ErrorState = ({
|
|
|
2589
3152
|
);
|
|
2590
3153
|
};
|
|
2591
3154
|
ErrorState.displayName = "ErrorState";
|
|
2592
|
-
var ErrorBoundary = class extends
|
|
3155
|
+
var ErrorBoundary = class extends React68__default.Component {
|
|
2593
3156
|
constructor(props) {
|
|
2594
3157
|
super(props);
|
|
2595
3158
|
__publicField(this, "reset", () => {
|
|
@@ -2993,7 +3556,7 @@ var variantIconColors = {
|
|
|
2993
3556
|
warning: "text-[var(--color-warning)]",
|
|
2994
3557
|
error: "text-[var(--color-error)]"
|
|
2995
3558
|
};
|
|
2996
|
-
var
|
|
3559
|
+
var iconMap2 = {
|
|
2997
3560
|
info: Info,
|
|
2998
3561
|
success: CheckCircle,
|
|
2999
3562
|
warning: AlertTriangle,
|
|
@@ -3032,7 +3595,7 @@ var Alert = ({
|
|
|
3032
3595
|
/* @__PURE__ */ jsx("div", { className: "flex-shrink-0 mt-0.5", children: /* @__PURE__ */ jsx(
|
|
3033
3596
|
Icon,
|
|
3034
3597
|
{
|
|
3035
|
-
icon:
|
|
3598
|
+
icon: iconMap2[variant],
|
|
3036
3599
|
size: "md",
|
|
3037
3600
|
className: variantIconColors[variant]
|
|
3038
3601
|
}
|
|
@@ -3144,7 +3707,7 @@ var Breadcrumb = ({
|
|
|
3144
3707
|
);
|
|
3145
3708
|
};
|
|
3146
3709
|
Breadcrumb.displayName = "Breadcrumb";
|
|
3147
|
-
function
|
|
3710
|
+
function useSafeEventBus2() {
|
|
3148
3711
|
try {
|
|
3149
3712
|
return useEventBus();
|
|
3150
3713
|
} catch {
|
|
@@ -3165,7 +3728,7 @@ var ButtonGroup = ({
|
|
|
3165
3728
|
entity: _entity,
|
|
3166
3729
|
filters
|
|
3167
3730
|
}) => {
|
|
3168
|
-
const eventBus =
|
|
3731
|
+
const eventBus = useSafeEventBus2();
|
|
3169
3732
|
const variantClasses2 = {
|
|
3170
3733
|
default: "gap-0",
|
|
3171
3734
|
segmented: "gap-0 [&>button]:rounded-none [&>button:first-child]:rounded-l-lg [&>button:last-child]:rounded-r-lg [&>button:not(:first-child)]:border-l-0",
|
|
@@ -3631,11 +4194,19 @@ function Card2({
|
|
|
3631
4194
|
children,
|
|
3632
4195
|
onClick,
|
|
3633
4196
|
className = "",
|
|
3634
|
-
action
|
|
4197
|
+
action,
|
|
4198
|
+
longPressEvent,
|
|
4199
|
+
longPressPayload
|
|
3635
4200
|
}) {
|
|
3636
4201
|
const eventBus = useEventBus();
|
|
3637
4202
|
const { t } = useTranslate();
|
|
3638
4203
|
const isClickable = !!onClick || !!action;
|
|
4204
|
+
const handleLongPress = useCallback(() => {
|
|
4205
|
+
if (longPressEvent) {
|
|
4206
|
+
eventBus.emit(`UI:${longPressEvent}`, longPressPayload ?? {});
|
|
4207
|
+
}
|
|
4208
|
+
}, [longPressEvent, longPressPayload, eventBus]);
|
|
4209
|
+
const longPress = useLongPress(handleLongPress);
|
|
3639
4210
|
const handleClick = () => {
|
|
3640
4211
|
if (action) eventBus.emit(`UI:${action}`, {});
|
|
3641
4212
|
onClick?.();
|
|
@@ -3654,6 +4225,12 @@ function Card2({
|
|
|
3654
4225
|
role: isClickable ? "button" : void 0,
|
|
3655
4226
|
tabIndex: isClickable ? 0 : void 0,
|
|
3656
4227
|
onKeyDown: isClickable ? (e) => e.key === "Enter" && handleClick() : void 0,
|
|
4228
|
+
...longPressEvent ? {
|
|
4229
|
+
onPointerDown: longPress.onPointerDown,
|
|
4230
|
+
onPointerMove: longPress.onPointerMove,
|
|
4231
|
+
onPointerUp: longPress.onPointerUp,
|
|
4232
|
+
onPointerCancel: longPress.onPointerCancel
|
|
4233
|
+
} : {},
|
|
3657
4234
|
children: [
|
|
3658
4235
|
image && /* @__PURE__ */ jsx("div", { className: "aspect-video w-full overflow-hidden rounded-t-lg", children: /* @__PURE__ */ jsx(
|
|
3659
4236
|
"img",
|
|
@@ -3694,7 +4271,7 @@ function Card2({
|
|
|
3694
4271
|
);
|
|
3695
4272
|
}
|
|
3696
4273
|
Card2.displayName = "Card";
|
|
3697
|
-
var
|
|
4274
|
+
var sizeStyles7 = {
|
|
3698
4275
|
xs: "max-w-xs",
|
|
3699
4276
|
// 320px
|
|
3700
4277
|
sm: "max-w-screen-sm",
|
|
@@ -3731,7 +4308,7 @@ var Container = ({
|
|
|
3731
4308
|
{
|
|
3732
4309
|
className: cn(
|
|
3733
4310
|
"w-full",
|
|
3734
|
-
|
|
4311
|
+
sizeStyles7[resolvedSize],
|
|
3735
4312
|
paddingStyles3[padding],
|
|
3736
4313
|
center && "mx-auto",
|
|
3737
4314
|
className
|
|
@@ -4197,8 +4774,8 @@ var Menu = ({
|
|
|
4197
4774
|
"bottom-start": "top-full left-0 mt-2",
|
|
4198
4775
|
"bottom-end": "top-full right-0 mt-2"
|
|
4199
4776
|
};
|
|
4200
|
-
const triggerChild =
|
|
4201
|
-
const triggerElement =
|
|
4777
|
+
const triggerChild = React68__default.isValidElement(trigger) ? trigger : /* @__PURE__ */ jsx("span", { children: trigger });
|
|
4778
|
+
const triggerElement = React68__default.cloneElement(
|
|
4202
4779
|
triggerChild,
|
|
4203
4780
|
{
|
|
4204
4781
|
ref: triggerRef,
|
|
@@ -4314,11 +4891,15 @@ var Modal = ({
|
|
|
4314
4891
|
closeOnOverlayClick = true,
|
|
4315
4892
|
closeOnEscape = true,
|
|
4316
4893
|
className,
|
|
4317
|
-
closeEvent
|
|
4894
|
+
closeEvent,
|
|
4895
|
+
swipeDownToClose = true
|
|
4318
4896
|
}) => {
|
|
4319
4897
|
const eventBus = useEventBus();
|
|
4320
4898
|
const modalRef = useRef(null);
|
|
4321
4899
|
const previousActiveElement = useRef(null);
|
|
4900
|
+
const [dragY, setDragY] = useState(0);
|
|
4901
|
+
const dragStartY = useRef(0);
|
|
4902
|
+
const isDragging = useRef(false);
|
|
4322
4903
|
useEffect(() => {
|
|
4323
4904
|
if (isOpen) {
|
|
4324
4905
|
previousActiveElement.current = document.activeElement;
|
|
@@ -4371,7 +4952,11 @@ var Modal = ({
|
|
|
4371
4952
|
className: "z-40"
|
|
4372
4953
|
}
|
|
4373
4954
|
),
|
|
4374
|
-
/* @__PURE__ */ jsx("div", { className:
|
|
4955
|
+
/* @__PURE__ */ jsx("div", { className: cn(
|
|
4956
|
+
"fixed inset-0 z-50 pointer-events-none",
|
|
4957
|
+
"flex items-center justify-center p-4",
|
|
4958
|
+
"max-sm:items-end max-sm:p-0"
|
|
4959
|
+
), children: /* @__PURE__ */ jsxs(
|
|
4375
4960
|
Box,
|
|
4376
4961
|
{
|
|
4377
4962
|
ref: modalRef,
|
|
@@ -4382,12 +4967,47 @@ var Modal = ({
|
|
|
4382
4967
|
className: cn(
|
|
4383
4968
|
"pointer-events-auto w-full flex flex-col max-h-[90vh]",
|
|
4384
4969
|
sizeClasses4[size],
|
|
4970
|
+
"max-sm:max-w-full max-sm:max-h-[85vh] max-sm:rounded-b-none max-sm:rounded-t-2xl",
|
|
4385
4971
|
className
|
|
4386
4972
|
),
|
|
4973
|
+
style: dragY > 0 ? {
|
|
4974
|
+
transform: `translateY(${dragY}px)`,
|
|
4975
|
+
transition: isDragging.current ? "none" : "transform 200ms ease-out"
|
|
4976
|
+
} : void 0,
|
|
4387
4977
|
role: "dialog",
|
|
4388
4978
|
"aria-modal": "true",
|
|
4389
4979
|
...title && { "aria-labelledby": "modal-title" },
|
|
4390
4980
|
children: [
|
|
4981
|
+
/* @__PURE__ */ jsx(
|
|
4982
|
+
"div",
|
|
4983
|
+
{
|
|
4984
|
+
className: "hidden max-sm:flex justify-center py-2 cursor-grab active:cursor-grabbing touch-none",
|
|
4985
|
+
onPointerDown: (e) => {
|
|
4986
|
+
if (!swipeDownToClose) return;
|
|
4987
|
+
dragStartY.current = e.clientY;
|
|
4988
|
+
isDragging.current = true;
|
|
4989
|
+
e.target.setPointerCapture(e.pointerId);
|
|
4990
|
+
},
|
|
4991
|
+
onPointerMove: (e) => {
|
|
4992
|
+
if (!isDragging.current) return;
|
|
4993
|
+
const dy = Math.max(0, e.clientY - dragStartY.current);
|
|
4994
|
+
setDragY(dy);
|
|
4995
|
+
},
|
|
4996
|
+
onPointerUp: () => {
|
|
4997
|
+
if (!isDragging.current) return;
|
|
4998
|
+
isDragging.current = false;
|
|
4999
|
+
if (dragY > 100) {
|
|
5000
|
+
handleClose();
|
|
5001
|
+
}
|
|
5002
|
+
setDragY(0);
|
|
5003
|
+
},
|
|
5004
|
+
onPointerCancel: () => {
|
|
5005
|
+
isDragging.current = false;
|
|
5006
|
+
setDragY(0);
|
|
5007
|
+
},
|
|
5008
|
+
children: /* @__PURE__ */ jsx("div", { className: "w-10 h-1 rounded-full bg-[var(--color-border)]" })
|
|
5009
|
+
}
|
|
5010
|
+
),
|
|
4391
5011
|
(title || showCloseButton) && /* @__PURE__ */ jsxs(
|
|
4392
5012
|
"div",
|
|
4393
5013
|
{
|
|
@@ -4660,8 +5280,8 @@ var Popover = ({
|
|
|
4660
5280
|
onMouseEnter: handleOpen,
|
|
4661
5281
|
onMouseLeave: handleClose
|
|
4662
5282
|
};
|
|
4663
|
-
const childElement =
|
|
4664
|
-
const triggerElement =
|
|
5283
|
+
const childElement = React68__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
|
|
5284
|
+
const triggerElement = React68__default.cloneElement(
|
|
4665
5285
|
childElement,
|
|
4666
5286
|
{
|
|
4667
5287
|
ref: triggerRef,
|
|
@@ -5241,7 +5861,7 @@ var variantClasses = {
|
|
|
5241
5861
|
info: "bg-[var(--color-card)] border-[length:var(--border-width)] border-[var(--color-info)]",
|
|
5242
5862
|
warning: "bg-[var(--color-card)] border-[length:var(--border-width)] border-[var(--color-warning)]"
|
|
5243
5863
|
};
|
|
5244
|
-
var
|
|
5864
|
+
var iconMap3 = {
|
|
5245
5865
|
success: CheckCircle,
|
|
5246
5866
|
error: AlertCircle,
|
|
5247
5867
|
info: Info,
|
|
@@ -5299,7 +5919,7 @@ var Toast = ({
|
|
|
5299
5919
|
/* @__PURE__ */ jsx("div", { className: "flex-shrink-0 mt-0.5", children: /* @__PURE__ */ jsx(
|
|
5300
5920
|
Icon,
|
|
5301
5921
|
{
|
|
5302
|
-
icon:
|
|
5922
|
+
icon: iconMap3[variant],
|
|
5303
5923
|
size: "md",
|
|
5304
5924
|
className: iconColors[variant]
|
|
5305
5925
|
}
|
|
@@ -5391,8 +6011,8 @@ var Tooltip = ({
|
|
|
5391
6011
|
if (hideTimeoutRef.current) clearTimeout(hideTimeoutRef.current);
|
|
5392
6012
|
};
|
|
5393
6013
|
}, []);
|
|
5394
|
-
const triggerElement =
|
|
5395
|
-
const trigger =
|
|
6014
|
+
const triggerElement = React68__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
|
|
6015
|
+
const trigger = React68__default.cloneElement(triggerElement, {
|
|
5396
6016
|
ref: triggerRef,
|
|
5397
6017
|
onMouseEnter: handleMouseEnter,
|
|
5398
6018
|
onMouseLeave: handleMouseLeave,
|
|
@@ -5641,7 +6261,7 @@ var WizardProgress = ({
|
|
|
5641
6261
|
children: /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: steps.map((step, index) => {
|
|
5642
6262
|
const isActive = index === currentStep;
|
|
5643
6263
|
const isCompleted = index < currentStep;
|
|
5644
|
-
return /* @__PURE__ */ jsxs(
|
|
6264
|
+
return /* @__PURE__ */ jsxs(React68__default.Fragment, { children: [
|
|
5645
6265
|
/* @__PURE__ */ jsx(
|
|
5646
6266
|
"button",
|
|
5647
6267
|
{
|
|
@@ -5690,7 +6310,7 @@ var WizardProgress = ({
|
|
|
5690
6310
|
);
|
|
5691
6311
|
};
|
|
5692
6312
|
WizardProgress.displayName = "WizardProgress";
|
|
5693
|
-
function
|
|
6313
|
+
function useSafeEventBus3() {
|
|
5694
6314
|
try {
|
|
5695
6315
|
return useEventBus();
|
|
5696
6316
|
} catch {
|
|
@@ -5719,7 +6339,7 @@ var WizardNavigation = ({
|
|
|
5719
6339
|
compact = false,
|
|
5720
6340
|
className
|
|
5721
6341
|
}) => {
|
|
5722
|
-
const eventBus =
|
|
6342
|
+
const eventBus = useSafeEventBus3();
|
|
5723
6343
|
const { t } = useTranslate();
|
|
5724
6344
|
const resolvedBackLabel = backLabel ?? t("wizard.back");
|
|
5725
6345
|
const resolvedNextLabel = nextLabel ?? t("wizard.next");
|
|
@@ -5771,7 +6391,7 @@ var WizardNavigation = ({
|
|
|
5771
6391
|
);
|
|
5772
6392
|
};
|
|
5773
6393
|
WizardNavigation.displayName = "WizardNavigation";
|
|
5774
|
-
var MarkdownContent =
|
|
6394
|
+
var MarkdownContent = React68__default.memo(
|
|
5775
6395
|
({ content, direction, className }) => {
|
|
5776
6396
|
const { t: _t } = useTranslate();
|
|
5777
6397
|
return /* @__PURE__ */ jsx(
|
|
@@ -5872,7 +6492,7 @@ var MarkdownContent = React50__default.memo(
|
|
|
5872
6492
|
(prev, next) => prev.content === next.content && prev.className === next.className && prev.direction === next.direction
|
|
5873
6493
|
);
|
|
5874
6494
|
MarkdownContent.displayName = "MarkdownContent";
|
|
5875
|
-
var CodeBlock =
|
|
6495
|
+
var CodeBlock = React68__default.memo(
|
|
5876
6496
|
({
|
|
5877
6497
|
code,
|
|
5878
6498
|
language = "text",
|
|
@@ -6133,8 +6753,14 @@ function CalendarGrid({
|
|
|
6133
6753
|
onSlotClick,
|
|
6134
6754
|
onDayClick,
|
|
6135
6755
|
onEventClick,
|
|
6136
|
-
className
|
|
6756
|
+
className,
|
|
6757
|
+
longPressEvent,
|
|
6758
|
+
longPressPayload,
|
|
6759
|
+
swipeLeftEvent,
|
|
6760
|
+
swipeRightEvent
|
|
6137
6761
|
}) {
|
|
6762
|
+
const eventBus = useEventBus();
|
|
6763
|
+
const longPressTimer = useRef(null);
|
|
6138
6764
|
const resolvedWeekStart = useMemo(
|
|
6139
6765
|
() => weekStart ? getStartOfWeek(weekStart) : getStartOfWeek(/* @__PURE__ */ new Date()),
|
|
6140
6766
|
[weekStart]
|
|
@@ -6166,6 +6792,23 @@ function CalendarGrid({
|
|
|
6166
6792
|
).length,
|
|
6167
6793
|
[events]
|
|
6168
6794
|
);
|
|
6795
|
+
const swipeCallbacks = useMemo(() => ({
|
|
6796
|
+
onSwipeLeft: swipeLeftEvent ? () => eventBus.emit(`UI:${swipeLeftEvent}`, {}) : void 0,
|
|
6797
|
+
onSwipeRight: swipeRightEvent ? () => eventBus.emit(`UI:${swipeRightEvent}`, {}) : void 0
|
|
6798
|
+
}), [swipeLeftEvent, swipeRightEvent, eventBus]);
|
|
6799
|
+
const swipe = useSwipeGesture(swipeCallbacks);
|
|
6800
|
+
const clearLongPress = useCallback(() => {
|
|
6801
|
+
if (longPressTimer.current) {
|
|
6802
|
+
clearTimeout(longPressTimer.current);
|
|
6803
|
+
longPressTimer.current = null;
|
|
6804
|
+
}
|
|
6805
|
+
}, []);
|
|
6806
|
+
const startLongPress = useCallback((day, time) => {
|
|
6807
|
+
if (!longPressEvent) return;
|
|
6808
|
+
longPressTimer.current = setTimeout(() => {
|
|
6809
|
+
eventBus.emit(`UI:${longPressEvent}`, { date: day.toISOString(), time, ...longPressPayload });
|
|
6810
|
+
}, 500);
|
|
6811
|
+
}, [longPressEvent, longPressPayload, eventBus]);
|
|
6169
6812
|
const renderEvent = (event) => /* @__PURE__ */ jsx(
|
|
6170
6813
|
Box,
|
|
6171
6814
|
{
|
|
@@ -6181,70 +6824,87 @@ function CalendarGrid({
|
|
|
6181
6824
|
},
|
|
6182
6825
|
event.id
|
|
6183
6826
|
);
|
|
6184
|
-
return /* @__PURE__ */ jsx(
|
|
6185
|
-
|
|
6186
|
-
|
|
6187
|
-
|
|
6188
|
-
|
|
6189
|
-
|
|
6190
|
-
|
|
6827
|
+
return /* @__PURE__ */ jsx(
|
|
6828
|
+
Box,
|
|
6829
|
+
{
|
|
6830
|
+
className: cn("overflow-x-auto", className),
|
|
6831
|
+
...swipeLeftEvent || swipeRightEvent ? {
|
|
6832
|
+
onPointerDown: swipe.onPointerDown,
|
|
6833
|
+
onPointerMove: swipe.onPointerMove,
|
|
6834
|
+
onPointerUp: swipe.onPointerUp,
|
|
6835
|
+
onPointerCancel: swipe.onPointerCancel
|
|
6836
|
+
} : {},
|
|
6837
|
+
children: /* @__PURE__ */ jsxs(Box, { className: "min-w-[800px]", children: [
|
|
6838
|
+
/* @__PURE__ */ jsxs(Box, { className: "grid grid-cols-8 border-b border-[var(--color-border)]", children: [
|
|
6839
|
+
/* @__PURE__ */ jsx(Box, { className: "p-2" }),
|
|
6840
|
+
weekDays.map((day) => {
|
|
6841
|
+
const isToday = day.toDateString() === (/* @__PURE__ */ new Date()).toDateString();
|
|
6842
|
+
const count = eventsForDayCount(day);
|
|
6843
|
+
return /* @__PURE__ */ jsxs(
|
|
6844
|
+
Box,
|
|
6845
|
+
{
|
|
6846
|
+
className: "border-l border-[var(--color-border)]",
|
|
6847
|
+
children: [
|
|
6848
|
+
/* @__PURE__ */ jsx(
|
|
6849
|
+
DayCell,
|
|
6850
|
+
{
|
|
6851
|
+
date: day,
|
|
6852
|
+
isToday,
|
|
6853
|
+
onClick: onDayClick
|
|
6854
|
+
}
|
|
6855
|
+
),
|
|
6856
|
+
count > 0 && /* @__PURE__ */ jsx(Box, { className: "text-center pb-1", children: /* @__PURE__ */ jsx(Badge, { variant: "default", size: "sm", children: count }) })
|
|
6857
|
+
]
|
|
6858
|
+
},
|
|
6859
|
+
day.toISOString()
|
|
6860
|
+
);
|
|
6861
|
+
})
|
|
6862
|
+
] }),
|
|
6863
|
+
/* @__PURE__ */ jsx(Box, { className: "max-h-[500px] overflow-y-auto", children: resolvedTimeSlots.map((time) => /* @__PURE__ */ jsxs(
|
|
6191
6864
|
Box,
|
|
6192
6865
|
{
|
|
6193
|
-
className: "border-
|
|
6866
|
+
className: "grid grid-cols-8 border-b border-[var(--color-border)]",
|
|
6194
6867
|
children: [
|
|
6195
|
-
/* @__PURE__ */ jsx(
|
|
6196
|
-
|
|
6868
|
+
/* @__PURE__ */ jsx(Box, { className: "p-2 text-right pr-3", children: /* @__PURE__ */ jsx(
|
|
6869
|
+
Typography,
|
|
6197
6870
|
{
|
|
6198
|
-
|
|
6199
|
-
|
|
6200
|
-
|
|
6871
|
+
variant: "small",
|
|
6872
|
+
className: "text-[var(--color-muted-foreground)]",
|
|
6873
|
+
children: time
|
|
6201
6874
|
}
|
|
6202
|
-
),
|
|
6203
|
-
|
|
6875
|
+
) }),
|
|
6876
|
+
weekDays.map((day) => {
|
|
6877
|
+
const slotEvents = events.filter(
|
|
6878
|
+
(ev) => eventInSlot(ev, day, time)
|
|
6879
|
+
);
|
|
6880
|
+
const isToday = day.toDateString() === (/* @__PURE__ */ new Date()).toDateString();
|
|
6881
|
+
return /* @__PURE__ */ jsx(
|
|
6882
|
+
TimeSlotCell,
|
|
6883
|
+
{
|
|
6884
|
+
time,
|
|
6885
|
+
isOccupied: slotEvents.length > 0,
|
|
6886
|
+
onClick: () => handleSlotClick(day, time),
|
|
6887
|
+
className: cn(
|
|
6888
|
+
"border-l border-[var(--color-border)]",
|
|
6889
|
+
isToday && "bg-blue-50/30"
|
|
6890
|
+
),
|
|
6891
|
+
...longPressEvent ? {
|
|
6892
|
+
onPointerDown: () => startLongPress(day, time),
|
|
6893
|
+
onPointerUp: clearLongPress,
|
|
6894
|
+
onPointerCancel: clearLongPress
|
|
6895
|
+
} : {},
|
|
6896
|
+
children: /* @__PURE__ */ jsx(VStack, { gap: "xs", children: slotEvents.map(renderEvent) })
|
|
6897
|
+
},
|
|
6898
|
+
`${day.toISOString()}-${time}`
|
|
6899
|
+
);
|
|
6900
|
+
})
|
|
6204
6901
|
]
|
|
6205
6902
|
},
|
|
6206
|
-
|
|
6207
|
-
)
|
|
6208
|
-
})
|
|
6209
|
-
|
|
6210
|
-
|
|
6211
|
-
Box,
|
|
6212
|
-
{
|
|
6213
|
-
className: "grid grid-cols-8 border-b border-[var(--color-border)]",
|
|
6214
|
-
children: [
|
|
6215
|
-
/* @__PURE__ */ jsx(Box, { className: "p-2 text-right pr-3", children: /* @__PURE__ */ jsx(
|
|
6216
|
-
Typography,
|
|
6217
|
-
{
|
|
6218
|
-
variant: "small",
|
|
6219
|
-
className: "text-[var(--color-muted-foreground)]",
|
|
6220
|
-
children: time
|
|
6221
|
-
}
|
|
6222
|
-
) }),
|
|
6223
|
-
weekDays.map((day) => {
|
|
6224
|
-
const slotEvents = events.filter(
|
|
6225
|
-
(ev) => eventInSlot(ev, day, time)
|
|
6226
|
-
);
|
|
6227
|
-
const isToday = day.toDateString() === (/* @__PURE__ */ new Date()).toDateString();
|
|
6228
|
-
return /* @__PURE__ */ jsx(
|
|
6229
|
-
TimeSlotCell,
|
|
6230
|
-
{
|
|
6231
|
-
time,
|
|
6232
|
-
isOccupied: slotEvents.length > 0,
|
|
6233
|
-
onClick: () => handleSlotClick(day, time),
|
|
6234
|
-
className: cn(
|
|
6235
|
-
"border-l border-[var(--color-border)]",
|
|
6236
|
-
isToday && "bg-blue-50/30"
|
|
6237
|
-
),
|
|
6238
|
-
children: /* @__PURE__ */ jsx(VStack, { gap: "xs", children: slotEvents.map(renderEvent) })
|
|
6239
|
-
},
|
|
6240
|
-
`${day.toISOString()}-${time}`
|
|
6241
|
-
);
|
|
6242
|
-
})
|
|
6243
|
-
]
|
|
6244
|
-
},
|
|
6245
|
-
time
|
|
6246
|
-
)) })
|
|
6247
|
-
] }) });
|
|
6903
|
+
time
|
|
6904
|
+
)) })
|
|
6905
|
+
] })
|
|
6906
|
+
}
|
|
6907
|
+
);
|
|
6248
6908
|
}
|
|
6249
6909
|
CalendarGrid.displayName = "CalendarGrid";
|
|
6250
6910
|
var RepeatableFormSection = ({
|
|
@@ -6880,8 +7540,8 @@ function DPad({
|
|
|
6880
7540
|
}) {
|
|
6881
7541
|
const eventBus = useEventBus();
|
|
6882
7542
|
const sizes = sizeMap5[size];
|
|
6883
|
-
const [activeDirections, setActiveDirections] =
|
|
6884
|
-
const handlePress =
|
|
7543
|
+
const [activeDirections, setActiveDirections] = React68.useState(/* @__PURE__ */ new Set());
|
|
7544
|
+
const handlePress = React68.useCallback(
|
|
6885
7545
|
(direction) => {
|
|
6886
7546
|
setActiveDirections((prev) => new Set(prev).add(direction));
|
|
6887
7547
|
if (directionEvent) eventBus.emit(`UI:${directionEvent}`, { direction, pressed: true });
|
|
@@ -6889,7 +7549,7 @@ function DPad({
|
|
|
6889
7549
|
},
|
|
6890
7550
|
[directionEvent, eventBus, onDirection]
|
|
6891
7551
|
);
|
|
6892
|
-
const handleRelease =
|
|
7552
|
+
const handleRelease = React68.useCallback(
|
|
6893
7553
|
(direction) => {
|
|
6894
7554
|
setActiveDirections((prev) => {
|
|
6895
7555
|
const next = new Set(prev);
|
|
@@ -6947,8 +7607,8 @@ function ActionButtons({
|
|
|
6947
7607
|
disabled
|
|
6948
7608
|
}) {
|
|
6949
7609
|
const eventBus = useEventBus();
|
|
6950
|
-
const [activeButtons, setActiveButtons] =
|
|
6951
|
-
const handlePress =
|
|
7610
|
+
const [activeButtons, setActiveButtons] = React68.useState(/* @__PURE__ */ new Set());
|
|
7611
|
+
const handlePress = React68.useCallback(
|
|
6952
7612
|
(id) => {
|
|
6953
7613
|
setActiveButtons((prev) => new Set(prev).add(id));
|
|
6954
7614
|
if (actionEvent) eventBus.emit(`UI:${actionEvent}`, { id, pressed: true });
|
|
@@ -6956,7 +7616,7 @@ function ActionButtons({
|
|
|
6956
7616
|
},
|
|
6957
7617
|
[actionEvent, eventBus, onAction]
|
|
6958
7618
|
);
|
|
6959
|
-
const handleRelease =
|
|
7619
|
+
const handleRelease = React68.useCallback(
|
|
6960
7620
|
(id) => {
|
|
6961
7621
|
setActiveButtons((prev) => {
|
|
6962
7622
|
const next = new Set(prev);
|
|
@@ -7545,211 +8205,939 @@ function MapView({
|
|
|
7545
8205
|
}
|
|
7546
8206
|
);
|
|
7547
8207
|
}
|
|
7548
|
-
function
|
|
7549
|
-
|
|
7550
|
-
|
|
7551
|
-
|
|
7552
|
-
|
|
7553
|
-
|
|
7554
|
-
|
|
7555
|
-
|
|
7556
|
-
if (["new", "created", "scheduled", "queued", "info"].includes(v)) return "info";
|
|
7557
|
-
return "default";
|
|
7558
|
-
}
|
|
7559
|
-
function formatDate(value) {
|
|
7560
|
-
if (!value) return "";
|
|
7561
|
-
const d = new Date(String(value));
|
|
7562
|
-
if (isNaN(d.getTime())) return String(value);
|
|
7563
|
-
return d.toLocaleDateString(void 0, { year: "numeric", month: "short", day: "numeric" });
|
|
7564
|
-
}
|
|
7565
|
-
function formatValue(value, format) {
|
|
7566
|
-
if (value === void 0 || value === null) return "";
|
|
7567
|
-
switch (format) {
|
|
7568
|
-
case "date":
|
|
7569
|
-
return formatDate(value);
|
|
7570
|
-
case "currency":
|
|
7571
|
-
return typeof value === "number" ? `$${value.toFixed(2)}` : String(value);
|
|
7572
|
-
case "number":
|
|
7573
|
-
return typeof value === "number" ? value.toLocaleString() : String(value);
|
|
7574
|
-
case "percent":
|
|
7575
|
-
return typeof value === "number" ? `${Math.round(value)}%` : String(value);
|
|
7576
|
-
case "boolean":
|
|
7577
|
-
return value ? "Yes" : "No";
|
|
7578
|
-
default:
|
|
7579
|
-
return String(value);
|
|
8208
|
+
function useSafeEventBus4() {
|
|
8209
|
+
try {
|
|
8210
|
+
return useEventBus();
|
|
8211
|
+
} catch {
|
|
8212
|
+
return { emit: () => {
|
|
8213
|
+
}, on: () => () => {
|
|
8214
|
+
}, once: () => {
|
|
8215
|
+
} };
|
|
7580
8216
|
}
|
|
7581
8217
|
}
|
|
7582
|
-
var
|
|
7583
|
-
|
|
7584
|
-
|
|
7585
|
-
|
|
7586
|
-
|
|
7587
|
-
|
|
8218
|
+
var sizeStyles8 = {
|
|
8219
|
+
sm: {
|
|
8220
|
+
button: "w-7 h-7",
|
|
8221
|
+
text: "text-sm min-w-[2rem]",
|
|
8222
|
+
icon: "w-3 h-3"
|
|
8223
|
+
},
|
|
8224
|
+
md: {
|
|
8225
|
+
button: "w-9 h-9",
|
|
8226
|
+
text: "text-base min-w-[2.5rem]",
|
|
8227
|
+
icon: "w-4 h-4"
|
|
8228
|
+
},
|
|
8229
|
+
lg: {
|
|
8230
|
+
button: "w-11 h-11",
|
|
8231
|
+
text: "text-lg min-w-[3rem]",
|
|
8232
|
+
icon: "w-5 h-5"
|
|
8233
|
+
}
|
|
7588
8234
|
};
|
|
7589
|
-
var
|
|
7590
|
-
|
|
7591
|
-
|
|
7592
|
-
|
|
7593
|
-
|
|
7594
|
-
|
|
7595
|
-
|
|
7596
|
-
|
|
8235
|
+
var LONG_PRESS_DELAY = 400;
|
|
8236
|
+
var LONG_PRESS_INTERVAL = 100;
|
|
8237
|
+
var NumberStepper = ({
|
|
8238
|
+
value = 0,
|
|
8239
|
+
min,
|
|
8240
|
+
max,
|
|
8241
|
+
step = 1,
|
|
8242
|
+
size = "md",
|
|
8243
|
+
disabled = false,
|
|
8244
|
+
onChange,
|
|
8245
|
+
action,
|
|
8246
|
+
actionPayload,
|
|
7597
8247
|
className,
|
|
7598
|
-
|
|
7599
|
-
error = null,
|
|
7600
|
-
imageField
|
|
8248
|
+
label
|
|
7601
8249
|
}) => {
|
|
7602
|
-
const eventBus =
|
|
7603
|
-
const
|
|
7604
|
-
const
|
|
7605
|
-
const
|
|
7606
|
-
const
|
|
7607
|
-
const
|
|
7608
|
-
const
|
|
7609
|
-
|
|
7610
|
-
|
|
7611
|
-
|
|
7612
|
-
|
|
7613
|
-
|
|
8250
|
+
const eventBus = useSafeEventBus4();
|
|
8251
|
+
const intervalRef = useRef(null);
|
|
8252
|
+
const timeoutRef = useRef(null);
|
|
8253
|
+
const isAtMin = min !== void 0 && value <= min;
|
|
8254
|
+
const isAtMax = max !== void 0 && value >= max;
|
|
8255
|
+
const styles = sizeStyles8[size];
|
|
8256
|
+
const emitChange = useCallback(
|
|
8257
|
+
(newValue) => {
|
|
8258
|
+
const clamped = Math.round(newValue / step) * step;
|
|
8259
|
+
const finalValue = Math.max(min ?? -Infinity, Math.min(max ?? Infinity, clamped));
|
|
8260
|
+
onChange?.(finalValue);
|
|
8261
|
+
if (action) {
|
|
8262
|
+
eventBus.emit(`UI:${action}`, { ...actionPayload, value: finalValue });
|
|
8263
|
+
}
|
|
8264
|
+
},
|
|
8265
|
+
[onChange, action, actionPayload, eventBus, min, max, step]
|
|
8266
|
+
);
|
|
8267
|
+
const startLongPress = useCallback(
|
|
8268
|
+
(delta) => {
|
|
8269
|
+
timeoutRef.current = setTimeout(() => {
|
|
8270
|
+
intervalRef.current = setInterval(() => {
|
|
8271
|
+
emitChange(value + delta);
|
|
8272
|
+
}, LONG_PRESS_INTERVAL);
|
|
8273
|
+
}, LONG_PRESS_DELAY);
|
|
8274
|
+
},
|
|
8275
|
+
[emitChange, value]
|
|
8276
|
+
);
|
|
8277
|
+
const stopLongPress = useCallback(() => {
|
|
8278
|
+
if (timeoutRef.current) {
|
|
8279
|
+
clearTimeout(timeoutRef.current);
|
|
8280
|
+
timeoutRef.current = null;
|
|
8281
|
+
}
|
|
8282
|
+
if (intervalRef.current) {
|
|
8283
|
+
clearInterval(intervalRef.current);
|
|
8284
|
+
intervalRef.current = null;
|
|
8285
|
+
}
|
|
8286
|
+
}, []);
|
|
8287
|
+
useEffect(() => {
|
|
8288
|
+
return () => {
|
|
8289
|
+
stopLongPress();
|
|
8290
|
+
};
|
|
8291
|
+
}, [stopLongPress]);
|
|
8292
|
+
const handleDecrement = () => {
|
|
8293
|
+
if (!isAtMin) emitChange(value - step);
|
|
7614
8294
|
};
|
|
7615
|
-
const
|
|
7616
|
-
|
|
7617
|
-
|
|
7618
|
-
|
|
7619
|
-
|
|
7620
|
-
|
|
7621
|
-
|
|
7622
|
-
|
|
7623
|
-
|
|
7624
|
-
|
|
7625
|
-
|
|
7626
|
-
|
|
7627
|
-
|
|
7628
|
-
|
|
7629
|
-
|
|
7630
|
-
|
|
7631
|
-
|
|
8295
|
+
const handleIncrement = () => {
|
|
8296
|
+
if (!isAtMax) emitChange(value + step);
|
|
8297
|
+
};
|
|
8298
|
+
return /* @__PURE__ */ jsxs(
|
|
8299
|
+
"div",
|
|
8300
|
+
{
|
|
8301
|
+
className: cn(
|
|
8302
|
+
"inline-flex items-center",
|
|
8303
|
+
"rounded-[var(--radius-sm)]",
|
|
8304
|
+
"border-[length:var(--border-width)] border-[var(--color-border)]",
|
|
8305
|
+
"bg-[var(--color-surface)]",
|
|
8306
|
+
disabled && "opacity-50 cursor-not-allowed",
|
|
8307
|
+
className
|
|
8308
|
+
),
|
|
8309
|
+
role: "group",
|
|
8310
|
+
"aria-label": label ?? "Number stepper",
|
|
8311
|
+
children: [
|
|
8312
|
+
/* @__PURE__ */ jsx(
|
|
8313
|
+
"button",
|
|
8314
|
+
{
|
|
8315
|
+
type: "button",
|
|
8316
|
+
onClick: handleDecrement,
|
|
8317
|
+
onMouseDown: () => !isAtMin && startLongPress(-step),
|
|
8318
|
+
onMouseUp: stopLongPress,
|
|
8319
|
+
onMouseLeave: stopLongPress,
|
|
8320
|
+
onTouchStart: () => !isAtMin && startLongPress(-step),
|
|
8321
|
+
onTouchEnd: stopLongPress,
|
|
8322
|
+
disabled: disabled || isAtMin,
|
|
8323
|
+
className: cn(
|
|
8324
|
+
"inline-flex items-center justify-center",
|
|
8325
|
+
"rounded-l-[var(--radius-sm)]",
|
|
8326
|
+
"text-[var(--color-foreground)]",
|
|
8327
|
+
"hover:bg-[var(--color-muted)]",
|
|
8328
|
+
"active:bg-[var(--color-muted)]",
|
|
8329
|
+
"transition-colors duration-100",
|
|
8330
|
+
"disabled:opacity-40 disabled:cursor-not-allowed disabled:hover:bg-transparent",
|
|
8331
|
+
"focus:outline-none focus:ring-[length:var(--focus-ring-width)] focus:ring-[var(--color-ring)] focus:ring-inset",
|
|
8332
|
+
styles.button
|
|
8333
|
+
),
|
|
8334
|
+
"aria-label": "Decrease",
|
|
8335
|
+
children: /* @__PURE__ */ jsx(Minus, { className: styles.icon })
|
|
8336
|
+
}
|
|
8337
|
+
),
|
|
8338
|
+
/* @__PURE__ */ jsx(
|
|
8339
|
+
"span",
|
|
8340
|
+
{
|
|
8341
|
+
className: cn(
|
|
8342
|
+
"text-center font-medium tabular-nums",
|
|
8343
|
+
"text-[var(--color-foreground)]",
|
|
8344
|
+
"border-x-[length:var(--border-width)] border-[var(--color-border)]",
|
|
8345
|
+
"px-1 select-none",
|
|
8346
|
+
styles.text
|
|
8347
|
+
),
|
|
8348
|
+
"aria-live": "polite",
|
|
8349
|
+
"aria-atomic": "true",
|
|
8350
|
+
children: value
|
|
8351
|
+
}
|
|
8352
|
+
),
|
|
8353
|
+
/* @__PURE__ */ jsx(
|
|
8354
|
+
"button",
|
|
8355
|
+
{
|
|
8356
|
+
type: "button",
|
|
8357
|
+
onClick: handleIncrement,
|
|
8358
|
+
onMouseDown: () => !isAtMax && startLongPress(step),
|
|
8359
|
+
onMouseUp: stopLongPress,
|
|
8360
|
+
onMouseLeave: stopLongPress,
|
|
8361
|
+
onTouchStart: () => !isAtMax && startLongPress(step),
|
|
8362
|
+
onTouchEnd: stopLongPress,
|
|
8363
|
+
disabled: disabled || isAtMax,
|
|
8364
|
+
className: cn(
|
|
8365
|
+
"inline-flex items-center justify-center",
|
|
8366
|
+
"rounded-r-[var(--radius-sm)]",
|
|
8367
|
+
"text-[var(--color-foreground)]",
|
|
8368
|
+
"hover:bg-[var(--color-muted)]",
|
|
8369
|
+
"active:bg-[var(--color-muted)]",
|
|
8370
|
+
"transition-colors duration-100",
|
|
8371
|
+
"disabled:opacity-40 disabled:cursor-not-allowed disabled:hover:bg-transparent",
|
|
8372
|
+
"focus:outline-none focus:ring-[length:var(--focus-ring-width)] focus:ring-[var(--color-ring)] focus:ring-inset",
|
|
8373
|
+
styles.button
|
|
8374
|
+
),
|
|
8375
|
+
"aria-label": "Increase",
|
|
8376
|
+
children: /* @__PURE__ */ jsx(Plus, { className: styles.icon })
|
|
8377
|
+
}
|
|
8378
|
+
)
|
|
8379
|
+
]
|
|
8380
|
+
}
|
|
8381
|
+
);
|
|
8382
|
+
};
|
|
8383
|
+
NumberStepper.displayName = "NumberStepper";
|
|
8384
|
+
function useSafeEventBus5() {
|
|
8385
|
+
try {
|
|
8386
|
+
return useEventBus();
|
|
8387
|
+
} catch {
|
|
8388
|
+
return { emit: () => {
|
|
8389
|
+
}, on: () => () => {
|
|
8390
|
+
}, once: () => {
|
|
8391
|
+
} };
|
|
7632
8392
|
}
|
|
8393
|
+
}
|
|
8394
|
+
var sizeStyles9 = {
|
|
8395
|
+
sm: { star: "w-4 h-4", gap: "gap-0.5" },
|
|
8396
|
+
md: { star: "w-6 h-6", gap: "gap-1" },
|
|
8397
|
+
lg: { star: "w-8 h-8", gap: "gap-1.5" }
|
|
8398
|
+
};
|
|
8399
|
+
var StarRating = ({
|
|
8400
|
+
value = 0,
|
|
8401
|
+
max = 5,
|
|
8402
|
+
readOnly = false,
|
|
8403
|
+
precision = "full",
|
|
8404
|
+
size = "md",
|
|
8405
|
+
action,
|
|
8406
|
+
actionPayload,
|
|
8407
|
+
onChange,
|
|
8408
|
+
className,
|
|
8409
|
+
label
|
|
8410
|
+
}) => {
|
|
8411
|
+
const [hoverValue, setHoverValue] = useState(null);
|
|
8412
|
+
const eventBus = useSafeEventBus5();
|
|
8413
|
+
const styles = sizeStyles9[size];
|
|
8414
|
+
const displayValue = hoverValue ?? value;
|
|
8415
|
+
const emitChange = useCallback(
|
|
8416
|
+
(newValue) => {
|
|
8417
|
+
onChange?.(newValue);
|
|
8418
|
+
if (action) {
|
|
8419
|
+
eventBus.emit(`UI:${action}`, { ...actionPayload, value: newValue });
|
|
8420
|
+
}
|
|
8421
|
+
},
|
|
8422
|
+
[onChange, action, actionPayload, eventBus]
|
|
8423
|
+
);
|
|
8424
|
+
const handleStarClick = (starIndex, isHalf) => {
|
|
8425
|
+
if (readOnly) return;
|
|
8426
|
+
const newValue = isHalf && precision === "half" ? starIndex + 0.5 : starIndex + 1;
|
|
8427
|
+
emitChange(newValue);
|
|
8428
|
+
};
|
|
8429
|
+
const handleStarHover = (starIndex, isHalf) => {
|
|
8430
|
+
if (readOnly) return;
|
|
8431
|
+
const newValue = isHalf && precision === "half" ? starIndex + 0.5 : starIndex + 1;
|
|
8432
|
+
setHoverValue(newValue);
|
|
8433
|
+
};
|
|
8434
|
+
const handleKeyDown = (e) => {
|
|
8435
|
+
if (readOnly) return;
|
|
8436
|
+
const stepSize = precision === "half" ? 0.5 : 1;
|
|
8437
|
+
if (e.key === "ArrowRight" || e.key === "ArrowUp") {
|
|
8438
|
+
e.preventDefault();
|
|
8439
|
+
emitChange(Math.min(max, value + stepSize));
|
|
8440
|
+
} else if (e.key === "ArrowLeft" || e.key === "ArrowDown") {
|
|
8441
|
+
e.preventDefault();
|
|
8442
|
+
emitChange(Math.max(0, value - stepSize));
|
|
8443
|
+
}
|
|
8444
|
+
};
|
|
7633
8445
|
return /* @__PURE__ */ jsx(
|
|
7634
|
-
|
|
8446
|
+
"div",
|
|
7635
8447
|
{
|
|
7636
|
-
className: cn(
|
|
7637
|
-
|
|
7638
|
-
|
|
7639
|
-
|
|
7640
|
-
|
|
7641
|
-
|
|
8448
|
+
className: cn(
|
|
8449
|
+
"inline-flex items-center",
|
|
8450
|
+
styles.gap,
|
|
8451
|
+
!readOnly && "cursor-pointer",
|
|
8452
|
+
className
|
|
8453
|
+
),
|
|
8454
|
+
role: readOnly ? "img" : "slider",
|
|
8455
|
+
"aria-label": label ?? `Rating: ${value} out of ${max}`,
|
|
8456
|
+
"aria-valuemin": 0,
|
|
8457
|
+
"aria-valuemax": max,
|
|
8458
|
+
"aria-valuenow": value,
|
|
8459
|
+
tabIndex: readOnly ? void 0 : 0,
|
|
8460
|
+
onKeyDown: handleKeyDown,
|
|
8461
|
+
onMouseLeave: () => setHoverValue(null),
|
|
8462
|
+
children: Array.from({ length: max }, (_, i) => {
|
|
8463
|
+
const fillLevel = Math.max(0, Math.min(1, displayValue - i));
|
|
8464
|
+
const isFull = fillLevel >= 1;
|
|
8465
|
+
const isHalf = fillLevel >= 0.5 && fillLevel < 1;
|
|
7642
8466
|
return /* @__PURE__ */ jsxs(
|
|
7643
|
-
|
|
8467
|
+
"span",
|
|
7644
8468
|
{
|
|
7645
|
-
"
|
|
7646
|
-
|
|
7647
|
-
|
|
7648
|
-
|
|
7649
|
-
|
|
7650
|
-
|
|
7651
|
-
|
|
7652
|
-
|
|
8469
|
+
className: "relative inline-block",
|
|
8470
|
+
onClick: () => handleStarClick(i, false),
|
|
8471
|
+
onMouseMove: (e) => {
|
|
8472
|
+
if (readOnly) return;
|
|
8473
|
+
const rect = e.currentTarget.getBoundingClientRect();
|
|
8474
|
+
const isLeftHalf = e.clientX - rect.left < rect.width / 2;
|
|
8475
|
+
handleStarHover(i, isLeftHalf);
|
|
8476
|
+
},
|
|
7653
8477
|
children: [
|
|
7654
|
-
|
|
7655
|
-
|
|
7656
|
-
|
|
7657
|
-
|
|
7658
|
-
|
|
7659
|
-
|
|
7660
|
-
|
|
7661
|
-
|
|
7662
|
-
|
|
7663
|
-
|
|
7664
|
-
|
|
7665
|
-
|
|
7666
|
-
|
|
7667
|
-
|
|
7668
|
-
|
|
7669
|
-
|
|
7670
|
-
|
|
7671
|
-
|
|
7672
|
-
|
|
7673
|
-
|
|
7674
|
-
|
|
7675
|
-
|
|
7676
|
-
|
|
7677
|
-
|
|
7678
|
-
|
|
7679
|
-
|
|
7680
|
-
|
|
7681
|
-
|
|
7682
|
-
|
|
7683
|
-
|
|
7684
|
-
|
|
7685
|
-
|
|
8478
|
+
/* @__PURE__ */ jsx(
|
|
8479
|
+
Star,
|
|
8480
|
+
{
|
|
8481
|
+
className: cn(
|
|
8482
|
+
styles.star,
|
|
8483
|
+
"text-[var(--color-muted)]",
|
|
8484
|
+
"transition-colors duration-100"
|
|
8485
|
+
),
|
|
8486
|
+
strokeWidth: 1.5
|
|
8487
|
+
}
|
|
8488
|
+
),
|
|
8489
|
+
(isFull || isHalf) && /* @__PURE__ */ jsx(
|
|
8490
|
+
Star,
|
|
8491
|
+
{
|
|
8492
|
+
className: cn(
|
|
8493
|
+
styles.star,
|
|
8494
|
+
"absolute inset-0",
|
|
8495
|
+
"text-[var(--color-warning)] fill-[var(--color-warning)]",
|
|
8496
|
+
"transition-colors duration-100"
|
|
8497
|
+
),
|
|
8498
|
+
strokeWidth: 1.5,
|
|
8499
|
+
style: isHalf ? { clipPath: "inset(0 50% 0 0)" } : void 0
|
|
8500
|
+
}
|
|
8501
|
+
),
|
|
8502
|
+
!readOnly && precision === "half" && /* @__PURE__ */ jsx(
|
|
8503
|
+
"span",
|
|
8504
|
+
{
|
|
8505
|
+
className: "absolute inset-0 w-1/2",
|
|
8506
|
+
onClick: (e) => {
|
|
8507
|
+
e.stopPropagation();
|
|
8508
|
+
handleStarClick(i, true);
|
|
8509
|
+
}
|
|
8510
|
+
}
|
|
8511
|
+
)
|
|
8512
|
+
]
|
|
8513
|
+
},
|
|
8514
|
+
i
|
|
8515
|
+
);
|
|
8516
|
+
})
|
|
8517
|
+
}
|
|
8518
|
+
);
|
|
8519
|
+
};
|
|
8520
|
+
StarRating.displayName = "StarRating";
|
|
8521
|
+
function useSafeEventBus6() {
|
|
8522
|
+
try {
|
|
8523
|
+
return useEventBus();
|
|
8524
|
+
} catch {
|
|
8525
|
+
return { emit: () => {
|
|
8526
|
+
}, on: () => () => {
|
|
8527
|
+
}, once: () => {
|
|
8528
|
+
} };
|
|
8529
|
+
}
|
|
8530
|
+
}
|
|
8531
|
+
function formatFileSize(bytes) {
|
|
8532
|
+
if (bytes < 1024) return `${bytes}B`;
|
|
8533
|
+
if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)}KB`;
|
|
8534
|
+
return `${Math.round(bytes / (1024 * 1024))}MB`;
|
|
8535
|
+
}
|
|
8536
|
+
var UploadDropZone = ({
|
|
8537
|
+
accept,
|
|
8538
|
+
maxSize,
|
|
8539
|
+
maxFiles = 1,
|
|
8540
|
+
label = "Drop files here or click to browse",
|
|
8541
|
+
description,
|
|
8542
|
+
disabled = false,
|
|
8543
|
+
action,
|
|
8544
|
+
actionPayload,
|
|
8545
|
+
onFiles,
|
|
8546
|
+
className
|
|
8547
|
+
}) => {
|
|
8548
|
+
const [isDragOver, setIsDragOver] = useState(false);
|
|
8549
|
+
const [error, setError] = useState(null);
|
|
8550
|
+
const inputRef = useRef(null);
|
|
8551
|
+
const eventBus = useSafeEventBus6();
|
|
8552
|
+
const defaultDescription = [
|
|
8553
|
+
accept ? `Accepted: ${accept}` : null,
|
|
8554
|
+
maxSize ? `Max size: ${formatFileSize(maxSize)}` : null,
|
|
8555
|
+
maxFiles > 1 ? `Up to ${maxFiles} files` : null
|
|
8556
|
+
].filter(Boolean).join(". ");
|
|
8557
|
+
const validateFiles = useCallback(
|
|
8558
|
+
(files) => {
|
|
8559
|
+
if (files.length > maxFiles) {
|
|
8560
|
+
return { valid: [], error: `Maximum ${maxFiles} file${maxFiles > 1 ? "s" : ""} allowed` };
|
|
8561
|
+
}
|
|
8562
|
+
if (accept) {
|
|
8563
|
+
const acceptedTypes = accept.split(",").map((t) => t.trim());
|
|
8564
|
+
const invalid = files.filter((file) => {
|
|
8565
|
+
return !acceptedTypes.some((type) => {
|
|
8566
|
+
if (type.endsWith("/*")) {
|
|
8567
|
+
return file.type.startsWith(type.replace("/*", "/"));
|
|
8568
|
+
}
|
|
8569
|
+
return file.type === type || file.name.endsWith(type);
|
|
8570
|
+
});
|
|
8571
|
+
});
|
|
8572
|
+
if (invalid.length > 0) {
|
|
8573
|
+
return { valid: [], error: `Invalid file type: ${invalid[0].name}` };
|
|
8574
|
+
}
|
|
8575
|
+
}
|
|
8576
|
+
if (maxSize) {
|
|
8577
|
+
const tooLarge = files.filter((file) => file.size > maxSize);
|
|
8578
|
+
if (tooLarge.length > 0) {
|
|
8579
|
+
return {
|
|
8580
|
+
valid: [],
|
|
8581
|
+
error: `File too large: ${tooLarge[0].name} (max ${formatFileSize(maxSize)})`
|
|
8582
|
+
};
|
|
8583
|
+
}
|
|
8584
|
+
}
|
|
8585
|
+
return { valid: files, error: null };
|
|
8586
|
+
},
|
|
8587
|
+
[accept, maxSize, maxFiles]
|
|
8588
|
+
);
|
|
8589
|
+
const handleFiles = useCallback(
|
|
8590
|
+
(files) => {
|
|
8591
|
+
const { valid, error: validationError } = validateFiles(files);
|
|
8592
|
+
setError(validationError);
|
|
8593
|
+
if (valid.length > 0) {
|
|
8594
|
+
onFiles?.(valid);
|
|
8595
|
+
if (action) {
|
|
8596
|
+
eventBus.emit(`UI:${action}`, {
|
|
8597
|
+
...actionPayload,
|
|
8598
|
+
files: valid.map((f) => ({ name: f.name, size: f.size, type: f.type }))
|
|
8599
|
+
});
|
|
8600
|
+
}
|
|
8601
|
+
}
|
|
8602
|
+
},
|
|
8603
|
+
[validateFiles, onFiles, action, actionPayload, eventBus]
|
|
8604
|
+
);
|
|
8605
|
+
const handleDragOver = (e) => {
|
|
8606
|
+
e.preventDefault();
|
|
8607
|
+
e.stopPropagation();
|
|
8608
|
+
if (!disabled) setIsDragOver(true);
|
|
8609
|
+
};
|
|
8610
|
+
const handleDragLeave = (e) => {
|
|
8611
|
+
e.preventDefault();
|
|
8612
|
+
e.stopPropagation();
|
|
8613
|
+
setIsDragOver(false);
|
|
8614
|
+
};
|
|
8615
|
+
const handleDrop = (e) => {
|
|
8616
|
+
e.preventDefault();
|
|
8617
|
+
e.stopPropagation();
|
|
8618
|
+
setIsDragOver(false);
|
|
8619
|
+
if (disabled) return;
|
|
8620
|
+
const files = Array.from(e.dataTransfer.files);
|
|
8621
|
+
handleFiles(files);
|
|
8622
|
+
};
|
|
8623
|
+
const handleClick = () => {
|
|
8624
|
+
if (!disabled) inputRef.current?.click();
|
|
8625
|
+
};
|
|
8626
|
+
const handleInputChange = (e) => {
|
|
8627
|
+
const files = Array.from(e.target.files ?? []);
|
|
8628
|
+
if (files.length > 0) handleFiles(files);
|
|
8629
|
+
e.target.value = "";
|
|
8630
|
+
};
|
|
8631
|
+
return /* @__PURE__ */ jsxs(
|
|
8632
|
+
"div",
|
|
8633
|
+
{
|
|
8634
|
+
className: cn(
|
|
8635
|
+
"relative flex flex-col items-center justify-center",
|
|
8636
|
+
"p-8 rounded-[var(--radius-sm)]",
|
|
8637
|
+
"border-2 border-dashed",
|
|
8638
|
+
"transition-colors duration-150",
|
|
8639
|
+
"cursor-pointer",
|
|
8640
|
+
isDragOver ? "border-[var(--color-primary)] bg-[var(--color-primary)] bg-opacity-5" : "border-[var(--color-border)] bg-[var(--color-surface)]",
|
|
8641
|
+
error && "border-[var(--color-error)]",
|
|
8642
|
+
disabled && "opacity-50 cursor-not-allowed",
|
|
8643
|
+
"hover:border-[var(--color-primary)] hover:bg-[var(--color-muted)]",
|
|
8644
|
+
className
|
|
8645
|
+
),
|
|
8646
|
+
onDragOver: handleDragOver,
|
|
8647
|
+
onDragLeave: handleDragLeave,
|
|
8648
|
+
onDrop: handleDrop,
|
|
8649
|
+
onClick: handleClick,
|
|
8650
|
+
role: "button",
|
|
8651
|
+
tabIndex: disabled ? -1 : 0,
|
|
8652
|
+
onKeyDown: (e) => {
|
|
8653
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
8654
|
+
e.preventDefault();
|
|
8655
|
+
handleClick();
|
|
8656
|
+
}
|
|
8657
|
+
},
|
|
8658
|
+
"aria-label": label,
|
|
8659
|
+
children: [
|
|
8660
|
+
/* @__PURE__ */ jsx(
|
|
8661
|
+
"input",
|
|
8662
|
+
{
|
|
8663
|
+
ref: inputRef,
|
|
8664
|
+
type: "file",
|
|
8665
|
+
accept,
|
|
8666
|
+
multiple: maxFiles > 1,
|
|
8667
|
+
onChange: handleInputChange,
|
|
8668
|
+
className: "hidden",
|
|
8669
|
+
disabled,
|
|
8670
|
+
"aria-hidden": "true"
|
|
8671
|
+
}
|
|
8672
|
+
),
|
|
8673
|
+
error ? /* @__PURE__ */ jsx(Icon, { icon: FileWarning, size: "lg", className: "text-[var(--color-error)] mb-2" }) : /* @__PURE__ */ jsx(Icon, { icon: Upload, size: "lg", className: "text-[var(--color-muted-foreground)] mb-2" }),
|
|
8674
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body1", className: "text-center font-medium mb-1", children: isDragOver ? "Drop files here" : label }),
|
|
8675
|
+
error ? /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "error", className: "text-center", children: error }) : /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "muted", className: "text-center", children: description ?? defaultDescription })
|
|
8676
|
+
]
|
|
8677
|
+
}
|
|
8678
|
+
);
|
|
8679
|
+
};
|
|
8680
|
+
UploadDropZone.displayName = "UploadDropZone";
|
|
8681
|
+
function useSafeEventBus7() {
|
|
8682
|
+
try {
|
|
8683
|
+
return useEventBus();
|
|
8684
|
+
} catch {
|
|
8685
|
+
return { emit: () => {
|
|
8686
|
+
}, on: () => () => {
|
|
8687
|
+
}, once: () => {
|
|
8688
|
+
} };
|
|
8689
|
+
}
|
|
8690
|
+
}
|
|
8691
|
+
var Lightbox = ({
|
|
8692
|
+
images,
|
|
8693
|
+
currentIndex = 0,
|
|
8694
|
+
isOpen = false,
|
|
8695
|
+
showCounter = true,
|
|
8696
|
+
closeAction,
|
|
8697
|
+
onClose,
|
|
8698
|
+
onIndexChange,
|
|
8699
|
+
className
|
|
8700
|
+
}) => {
|
|
8701
|
+
const [index, setIndex] = useState(currentIndex);
|
|
8702
|
+
const [touchStartX, setTouchStartX] = useState(null);
|
|
8703
|
+
const eventBus = useSafeEventBus7();
|
|
8704
|
+
useEffect(() => {
|
|
8705
|
+
setIndex(currentIndex);
|
|
8706
|
+
}, [currentIndex]);
|
|
8707
|
+
const handleClose = useCallback(() => {
|
|
8708
|
+
if (closeAction) {
|
|
8709
|
+
eventBus.emit(`UI:${closeAction}`, {});
|
|
8710
|
+
}
|
|
8711
|
+
onClose?.();
|
|
8712
|
+
}, [closeAction, eventBus, onClose]);
|
|
8713
|
+
const goTo = useCallback(
|
|
8714
|
+
(newIndex) => {
|
|
8715
|
+
const clamped = Math.max(0, Math.min(images.length - 1, newIndex));
|
|
8716
|
+
setIndex(clamped);
|
|
8717
|
+
onIndexChange?.(clamped);
|
|
8718
|
+
},
|
|
8719
|
+
[images.length, onIndexChange]
|
|
8720
|
+
);
|
|
8721
|
+
const goPrev = useCallback(() => goTo(index - 1), [goTo, index]);
|
|
8722
|
+
const goNext = useCallback(() => goTo(index + 1), [goTo, index]);
|
|
8723
|
+
useEffect(() => {
|
|
8724
|
+
if (!isOpen) return;
|
|
8725
|
+
const handleKeyDown = (e) => {
|
|
8726
|
+
switch (e.key) {
|
|
8727
|
+
case "Escape":
|
|
8728
|
+
handleClose();
|
|
8729
|
+
break;
|
|
8730
|
+
case "ArrowLeft":
|
|
8731
|
+
goPrev();
|
|
8732
|
+
break;
|
|
8733
|
+
case "ArrowRight":
|
|
8734
|
+
goNext();
|
|
8735
|
+
break;
|
|
8736
|
+
}
|
|
8737
|
+
};
|
|
8738
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
8739
|
+
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
8740
|
+
}, [isOpen, handleClose, goPrev, goNext]);
|
|
8741
|
+
useEffect(() => {
|
|
8742
|
+
if (isOpen) {
|
|
8743
|
+
document.body.style.overflow = "hidden";
|
|
8744
|
+
return () => {
|
|
8745
|
+
document.body.style.overflow = "";
|
|
8746
|
+
};
|
|
8747
|
+
}
|
|
8748
|
+
}, [isOpen]);
|
|
8749
|
+
if (!isOpen || images.length === 0) return null;
|
|
8750
|
+
const currentImage = images[index];
|
|
8751
|
+
const hasPrev = index > 0;
|
|
8752
|
+
const hasNext = index < images.length - 1;
|
|
8753
|
+
const handleTouchStart = (e) => {
|
|
8754
|
+
setTouchStartX(e.touches[0].clientX);
|
|
8755
|
+
};
|
|
8756
|
+
const handleTouchEnd = (e) => {
|
|
8757
|
+
if (touchStartX === null) return;
|
|
8758
|
+
const diff = e.changedTouches[0].clientX - touchStartX;
|
|
8759
|
+
const threshold = 50;
|
|
8760
|
+
if (diff > threshold && hasPrev) goPrev();
|
|
8761
|
+
if (diff < -threshold && hasNext) goNext();
|
|
8762
|
+
setTouchStartX(null);
|
|
8763
|
+
};
|
|
8764
|
+
return /* @__PURE__ */ jsxs(
|
|
8765
|
+
"div",
|
|
8766
|
+
{
|
|
8767
|
+
className: cn(
|
|
8768
|
+
"fixed inset-0 z-50 flex items-center justify-center",
|
|
8769
|
+
"bg-black bg-opacity-90",
|
|
8770
|
+
className
|
|
8771
|
+
),
|
|
8772
|
+
onClick: handleClose,
|
|
8773
|
+
role: "dialog",
|
|
8774
|
+
"aria-modal": "true",
|
|
8775
|
+
"aria-label": currentImage?.alt ?? "Image viewer",
|
|
8776
|
+
children: [
|
|
8777
|
+
/* @__PURE__ */ jsx(
|
|
8778
|
+
"button",
|
|
8779
|
+
{
|
|
8780
|
+
type: "button",
|
|
8781
|
+
onClick: (e) => {
|
|
8782
|
+
e.stopPropagation();
|
|
8783
|
+
handleClose();
|
|
8784
|
+
},
|
|
8785
|
+
className: cn(
|
|
8786
|
+
"absolute top-4 right-4 z-10",
|
|
8787
|
+
"p-2 rounded-full",
|
|
8788
|
+
"text-white bg-black bg-opacity-50",
|
|
8789
|
+
"hover:bg-opacity-70 transition-opacity",
|
|
8790
|
+
"focus:outline-none focus:ring-2 focus:ring-white"
|
|
8791
|
+
),
|
|
8792
|
+
"aria-label": "Close",
|
|
8793
|
+
children: /* @__PURE__ */ jsx(X, { className: "w-6 h-6" })
|
|
8794
|
+
}
|
|
8795
|
+
),
|
|
8796
|
+
hasPrev && images.length > 1 && /* @__PURE__ */ jsx(
|
|
8797
|
+
"button",
|
|
8798
|
+
{
|
|
8799
|
+
type: "button",
|
|
8800
|
+
onClick: (e) => {
|
|
8801
|
+
e.stopPropagation();
|
|
8802
|
+
goPrev();
|
|
8803
|
+
},
|
|
8804
|
+
className: cn(
|
|
8805
|
+
"absolute left-4 z-10",
|
|
8806
|
+
"p-2 rounded-full",
|
|
8807
|
+
"text-white bg-black bg-opacity-50",
|
|
8808
|
+
"hover:bg-opacity-70 transition-opacity",
|
|
8809
|
+
"focus:outline-none focus:ring-2 focus:ring-white"
|
|
8810
|
+
),
|
|
8811
|
+
"aria-label": "Previous image",
|
|
8812
|
+
children: /* @__PURE__ */ jsx(ChevronLeft, { className: "w-8 h-8" })
|
|
8813
|
+
}
|
|
8814
|
+
),
|
|
8815
|
+
/* @__PURE__ */ jsx(
|
|
8816
|
+
"div",
|
|
8817
|
+
{
|
|
8818
|
+
className: "flex items-center justify-center w-full h-full p-12",
|
|
8819
|
+
onClick: (e) => e.stopPropagation(),
|
|
8820
|
+
onTouchStart: handleTouchStart,
|
|
8821
|
+
onTouchEnd: handleTouchEnd,
|
|
8822
|
+
children: currentImage && /* @__PURE__ */ jsx(
|
|
8823
|
+
"img",
|
|
8824
|
+
{
|
|
8825
|
+
src: currentImage.src,
|
|
8826
|
+
alt: currentImage.alt ?? "",
|
|
8827
|
+
className: "max-w-full max-h-full object-contain select-none",
|
|
8828
|
+
draggable: false
|
|
8829
|
+
}
|
|
8830
|
+
)
|
|
8831
|
+
}
|
|
8832
|
+
),
|
|
8833
|
+
hasNext && images.length > 1 && /* @__PURE__ */ jsx(
|
|
8834
|
+
"button",
|
|
8835
|
+
{
|
|
8836
|
+
type: "button",
|
|
8837
|
+
onClick: (e) => {
|
|
8838
|
+
e.stopPropagation();
|
|
8839
|
+
goNext();
|
|
8840
|
+
},
|
|
8841
|
+
className: cn(
|
|
8842
|
+
"absolute right-4 z-10",
|
|
8843
|
+
"p-2 rounded-full",
|
|
8844
|
+
"text-white bg-black bg-opacity-50",
|
|
8845
|
+
"hover:bg-opacity-70 transition-opacity",
|
|
8846
|
+
"focus:outline-none focus:ring-2 focus:ring-white"
|
|
8847
|
+
),
|
|
8848
|
+
"aria-label": "Next image",
|
|
8849
|
+
children: /* @__PURE__ */ jsx(ChevronRight, { className: "w-8 h-8" })
|
|
8850
|
+
}
|
|
8851
|
+
),
|
|
8852
|
+
/* @__PURE__ */ jsxs("div", { className: "absolute bottom-4 left-0 right-0 text-center", children: [
|
|
8853
|
+
showCounter && images.length > 1 && /* @__PURE__ */ jsxs("div", { className: "text-white text-sm mb-1", children: [
|
|
8854
|
+
index + 1,
|
|
8855
|
+
" of ",
|
|
8856
|
+
images.length
|
|
8857
|
+
] }),
|
|
8858
|
+
currentImage?.caption && /* @__PURE__ */ jsx("div", { className: "text-white text-sm opacity-80 px-8", children: currentImage.caption })
|
|
8859
|
+
] })
|
|
8860
|
+
]
|
|
8861
|
+
}
|
|
8862
|
+
);
|
|
8863
|
+
};
|
|
8864
|
+
Lightbox.displayName = "Lightbox";
|
|
8865
|
+
function fieldLabel(key) {
|
|
8866
|
+
return key.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/[_-]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
8867
|
+
}
|
|
8868
|
+
function statusVariant(value) {
|
|
8869
|
+
const v = value.toLowerCase();
|
|
8870
|
+
if (["active", "completed", "done", "approved", "published", "resolved", "open", "online"].includes(v)) return "success";
|
|
8871
|
+
if (["pending", "in_progress", "in-progress", "review", "draft", "processing", "warning"].includes(v)) return "warning";
|
|
8872
|
+
if (["inactive", "deleted", "rejected", "failed", "error", "blocked", "closed", "offline"].includes(v)) return "error";
|
|
8873
|
+
if (["new", "created", "scheduled", "queued", "info"].includes(v)) return "info";
|
|
8874
|
+
return "default";
|
|
8875
|
+
}
|
|
8876
|
+
function formatDate(value) {
|
|
8877
|
+
if (!value) return "";
|
|
8878
|
+
const d = new Date(String(value));
|
|
8879
|
+
if (isNaN(d.getTime())) return String(value);
|
|
8880
|
+
return d.toLocaleDateString(void 0, { year: "numeric", month: "short", day: "numeric" });
|
|
8881
|
+
}
|
|
8882
|
+
function formatValue(value, format) {
|
|
8883
|
+
if (value === void 0 || value === null) return "";
|
|
8884
|
+
switch (format) {
|
|
8885
|
+
case "date":
|
|
8886
|
+
return formatDate(value);
|
|
8887
|
+
case "currency":
|
|
8888
|
+
return typeof value === "number" ? `$${value.toFixed(2)}` : String(value);
|
|
8889
|
+
case "number":
|
|
8890
|
+
return typeof value === "number" ? value.toLocaleString() : String(value);
|
|
8891
|
+
case "percent":
|
|
8892
|
+
return typeof value === "number" ? `${Math.round(value)}%` : String(value);
|
|
8893
|
+
case "boolean":
|
|
8894
|
+
return value ? "Yes" : "No";
|
|
8895
|
+
default:
|
|
8896
|
+
return String(value);
|
|
8897
|
+
}
|
|
8898
|
+
}
|
|
8899
|
+
var gapStyles5 = {
|
|
8900
|
+
none: "gap-0",
|
|
8901
|
+
sm: "gap-2",
|
|
8902
|
+
md: "gap-4",
|
|
8903
|
+
lg: "gap-6",
|
|
8904
|
+
xl: "gap-8"
|
|
8905
|
+
};
|
|
8906
|
+
var DataGrid = ({
|
|
8907
|
+
entity,
|
|
8908
|
+
fields: fieldsProp,
|
|
8909
|
+
columns: columnsProp,
|
|
8910
|
+
itemActions,
|
|
8911
|
+
cols,
|
|
8912
|
+
gap = "md",
|
|
8913
|
+
minCardWidth = 280,
|
|
8914
|
+
className,
|
|
8915
|
+
isLoading = false,
|
|
8916
|
+
error = null,
|
|
8917
|
+
imageField,
|
|
8918
|
+
selectable = false,
|
|
8919
|
+
selectionEvent,
|
|
8920
|
+
infiniteScroll,
|
|
8921
|
+
loadMoreEvent,
|
|
8922
|
+
hasMore
|
|
8923
|
+
}) => {
|
|
8924
|
+
const eventBus = useEventBus();
|
|
8925
|
+
const { t } = useTranslate();
|
|
8926
|
+
const [selectedIds, setSelectedIds] = useState(/* @__PURE__ */ new Set());
|
|
8927
|
+
const fields = fieldsProp ?? columnsProp ?? [];
|
|
8928
|
+
const data = Array.isArray(entity) ? entity : entity ? [entity] : [];
|
|
8929
|
+
const toggleSelection = useCallback((id) => {
|
|
8930
|
+
setSelectedIds((prev) => {
|
|
8931
|
+
const next = new Set(prev);
|
|
8932
|
+
if (next.has(id)) next.delete(id);
|
|
8933
|
+
else next.add(id);
|
|
8934
|
+
if (selectionEvent) {
|
|
8935
|
+
eventBus.emit(`UI:${selectionEvent}`, { selectedIds: Array.from(next) });
|
|
8936
|
+
}
|
|
8937
|
+
return next;
|
|
8938
|
+
});
|
|
8939
|
+
}, [selectionEvent, eventBus]);
|
|
8940
|
+
const toggleAll = useCallback(() => {
|
|
8941
|
+
setSelectedIds((prev) => {
|
|
8942
|
+
const allIds2 = data.map((item, i) => item.id || String(i));
|
|
8943
|
+
const allSelected2 = allIds2.length > 0 && allIds2.every((id) => prev.has(id));
|
|
8944
|
+
const next = allSelected2 ? /* @__PURE__ */ new Set() : new Set(allIds2);
|
|
8945
|
+
if (selectionEvent) {
|
|
8946
|
+
eventBus.emit(`UI:${selectionEvent}`, { selectedIds: Array.from(next) });
|
|
8947
|
+
}
|
|
8948
|
+
return next;
|
|
8949
|
+
});
|
|
8950
|
+
}, [data, selectionEvent, eventBus]);
|
|
8951
|
+
const titleField = fields.find((f) => f.variant === "h3" || f.variant === "h4") ?? fields[0];
|
|
8952
|
+
const badgeFields = fields.filter((f) => f.variant === "badge" && f !== titleField);
|
|
8953
|
+
const bodyFields = fields.filter((f) => f !== titleField && !badgeFields.includes(f));
|
|
8954
|
+
const primaryActions = itemActions?.filter((a) => a.variant !== "danger") ?? [];
|
|
8955
|
+
const dangerActions = itemActions?.filter((a) => a.variant === "danger") ?? [];
|
|
8956
|
+
const handleActionClick = (action, itemData) => (e) => {
|
|
8957
|
+
e.stopPropagation();
|
|
8958
|
+
eventBus.emit(`UI:${action.event}`, { row: itemData });
|
|
8959
|
+
};
|
|
8960
|
+
const gridTemplateColumns = cols ? void 0 : `repeat(auto-fit, minmax(min(${minCardWidth}px, 100%), 1fr))`;
|
|
8961
|
+
const colsClass = cols ? {
|
|
8962
|
+
1: "grid-cols-1",
|
|
8963
|
+
2: "sm:grid-cols-2",
|
|
8964
|
+
3: "sm:grid-cols-2 lg:grid-cols-3",
|
|
8965
|
+
4: "sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4",
|
|
8966
|
+
5: "sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-5",
|
|
8967
|
+
6: "sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-6"
|
|
8968
|
+
}[cols] : void 0;
|
|
8969
|
+
if (isLoading) {
|
|
8970
|
+
return /* @__PURE__ */ jsx(Box, { className: "text-center py-8", children: /* @__PURE__ */ jsx(Typography, { variant: "body", color: "secondary", children: t("loading.items") || "Loading..." }) });
|
|
8971
|
+
}
|
|
8972
|
+
if (error) {
|
|
8973
|
+
return /* @__PURE__ */ jsx(Box, { className: "text-center py-8", children: /* @__PURE__ */ jsx(Typography, { variant: "body", color: "error", children: error.message }) });
|
|
8974
|
+
}
|
|
8975
|
+
if (data.length === 0) {
|
|
8976
|
+
return /* @__PURE__ */ jsx(Box, { className: "text-center py-12", children: /* @__PURE__ */ jsx(Typography, { variant: "body", color: "secondary", children: t("empty.noItems") || "No items found" }) });
|
|
8977
|
+
}
|
|
8978
|
+
const allIds = data.map((item, i) => item.id || String(i));
|
|
8979
|
+
const allSelected = allIds.length > 0 && allIds.every((id) => selectedIds.has(id));
|
|
8980
|
+
const someSelected = selectedIds.size > 0;
|
|
8981
|
+
return /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
8982
|
+
selectable && someSelected && /* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "items-center px-2 py-2 bg-[var(--color-muted)] rounded-[var(--radius-sm)]", children: [
|
|
8983
|
+
/* @__PURE__ */ jsx(
|
|
8984
|
+
"input",
|
|
8985
|
+
{
|
|
8986
|
+
type: "checkbox",
|
|
8987
|
+
checked: allSelected,
|
|
8988
|
+
onChange: toggleAll,
|
|
8989
|
+
className: "w-4 h-4 accent-[var(--color-primary)]",
|
|
8990
|
+
"aria-label": "Select all"
|
|
8991
|
+
}
|
|
8992
|
+
),
|
|
8993
|
+
/* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "font-semibold", children: [
|
|
8994
|
+
selectedIds.size,
|
|
8995
|
+
" ",
|
|
8996
|
+
t("common.selected") || "selected"
|
|
8997
|
+
] })
|
|
8998
|
+
] }),
|
|
8999
|
+
/* @__PURE__ */ jsx(
|
|
9000
|
+
Box,
|
|
9001
|
+
{
|
|
9002
|
+
className: cn("grid", gapStyles5[gap], colsClass, className),
|
|
9003
|
+
style: gridTemplateColumns ? { gridTemplateColumns } : void 0,
|
|
9004
|
+
children: data.map((item, index) => {
|
|
9005
|
+
const itemData = item;
|
|
9006
|
+
const id = itemData.id || String(index);
|
|
9007
|
+
const titleValue = getNestedValue(itemData, titleField?.name ?? "");
|
|
9008
|
+
const isSelected = selectedIds.has(id);
|
|
9009
|
+
return /* @__PURE__ */ jsxs(
|
|
9010
|
+
Box,
|
|
9011
|
+
{
|
|
9012
|
+
"data-entity-row": true,
|
|
9013
|
+
className: cn(
|
|
9014
|
+
"bg-[var(--color-card)] rounded-[var(--radius-lg)]",
|
|
9015
|
+
"border border-[var(--color-border)]",
|
|
9016
|
+
"shadow-[var(--shadow-sm)] hover:shadow-[var(--shadow-hover)]",
|
|
9017
|
+
"hover:border-[var(--color-primary)] transition-all",
|
|
9018
|
+
"flex flex-col",
|
|
9019
|
+
isSelected && "ring-2 ring-[var(--color-primary)] border-[var(--color-primary)]"
|
|
9020
|
+
),
|
|
9021
|
+
children: [
|
|
9022
|
+
imageField && (() => {
|
|
9023
|
+
const imgUrl = getNestedValue(itemData, imageField);
|
|
9024
|
+
if (!imgUrl || typeof imgUrl !== "string") return null;
|
|
9025
|
+
return /* @__PURE__ */ jsx(Box, { className: "w-full aspect-video overflow-hidden rounded-t-[var(--radius-lg)]", children: /* @__PURE__ */ jsx(
|
|
9026
|
+
"img",
|
|
9027
|
+
{
|
|
9028
|
+
src: imgUrl,
|
|
9029
|
+
alt: titleValue !== void 0 ? String(titleValue) : "",
|
|
9030
|
+
className: "w-full h-full object-cover",
|
|
9031
|
+
loading: "lazy"
|
|
9032
|
+
}
|
|
9033
|
+
) });
|
|
9034
|
+
})(),
|
|
9035
|
+
/* @__PURE__ */ jsx(Box, { className: "p-4 pb-0", children: /* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "justify-between items-start", children: [
|
|
9036
|
+
selectable && /* @__PURE__ */ jsx(
|
|
9037
|
+
"input",
|
|
9038
|
+
{
|
|
9039
|
+
type: "checkbox",
|
|
9040
|
+
checked: isSelected,
|
|
9041
|
+
onChange: () => toggleSelection(id),
|
|
9042
|
+
onClick: (e) => e.stopPropagation(),
|
|
9043
|
+
className: "w-4 h-4 mt-1 flex-shrink-0 accent-[var(--color-primary)]",
|
|
9044
|
+
"aria-label": `Select ${titleValue !== void 0 ? String(titleValue) : "item"}`
|
|
9045
|
+
}
|
|
9046
|
+
),
|
|
9047
|
+
/* @__PURE__ */ jsxs(VStack, { gap: "xs", className: "flex-1 min-w-0", children: [
|
|
9048
|
+
titleValue !== void 0 && titleValue !== null && /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center", children: [
|
|
9049
|
+
titleField?.icon && /* @__PURE__ */ jsx(Icon, { name: titleField.icon, size: "sm", className: "text-[var(--color-primary)] flex-shrink-0" }),
|
|
9050
|
+
/* @__PURE__ */ jsx(
|
|
9051
|
+
Typography,
|
|
9052
|
+
{
|
|
9053
|
+
variant: titleField?.variant === "h3" ? "h3" : "h4",
|
|
9054
|
+
className: "font-semibold truncate",
|
|
9055
|
+
children: String(titleValue)
|
|
9056
|
+
}
|
|
9057
|
+
)
|
|
9058
|
+
] }),
|
|
9059
|
+
badgeFields.length > 0 && /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-wrap", children: badgeFields.map((field) => {
|
|
9060
|
+
const val = getNestedValue(itemData, field.name);
|
|
9061
|
+
if (val === void 0 || val === null) return null;
|
|
9062
|
+
return /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center", children: [
|
|
9063
|
+
field.icon && /* @__PURE__ */ jsx(Icon, { name: field.icon, size: "xs" }),
|
|
9064
|
+
/* @__PURE__ */ jsx(Badge, { variant: statusVariant(String(val)), children: String(val) })
|
|
9065
|
+
] }, field.name);
|
|
9066
|
+
}) })
|
|
9067
|
+
] }),
|
|
9068
|
+
dangerActions.length > 0 && /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-shrink-0", children: dangerActions.map((action, idx) => /* @__PURE__ */ jsxs(
|
|
9069
|
+
Button,
|
|
9070
|
+
{
|
|
9071
|
+
variant: "ghost",
|
|
9072
|
+
size: "sm",
|
|
9073
|
+
onClick: handleActionClick(action, itemData),
|
|
9074
|
+
"data-testid": `action-${action.event}`,
|
|
9075
|
+
className: "text-[var(--color-error)] hover:bg-[var(--color-error)]/10 px-2",
|
|
9076
|
+
children: [
|
|
9077
|
+
action.icon && /* @__PURE__ */ jsx(Icon, { name: action.icon, size: "xs" }),
|
|
9078
|
+
action.label
|
|
9079
|
+
]
|
|
9080
|
+
},
|
|
9081
|
+
idx
|
|
9082
|
+
)) })
|
|
9083
|
+
] }) }),
|
|
9084
|
+
bodyFields.length > 0 && /* @__PURE__ */ jsx(Box, { className: "px-4 py-3 flex-1", children: /* @__PURE__ */ jsx(VStack, { gap: "xs", children: bodyFields.map((field) => {
|
|
9085
|
+
const value = getNestedValue(itemData, field.name);
|
|
9086
|
+
if (value === void 0 || value === null || value === "") return null;
|
|
9087
|
+
if (field.format === "boolean") {
|
|
9088
|
+
return /* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "justify-between items-center", children: [
|
|
9089
|
+
/* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center", children: [
|
|
9090
|
+
field.icon && /* @__PURE__ */ jsx(Icon, { name: field.icon, size: "xs", className: "text-[var(--color-muted-foreground)]" }),
|
|
9091
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: field.label ?? fieldLabel(field.name) })
|
|
9092
|
+
] }),
|
|
9093
|
+
/* @__PURE__ */ jsx(Badge, { variant: value ? "success" : "neutral", children: value ? t("common.yes") || "Yes" : t("common.no") || "No" })
|
|
7686
9094
|
] }, field.name);
|
|
7687
|
-
}
|
|
7688
|
-
|
|
7689
|
-
|
|
9095
|
+
}
|
|
9096
|
+
return /* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "justify-between items-center", children: [
|
|
9097
|
+
/* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center", children: [
|
|
9098
|
+
field.icon && /* @__PURE__ */ jsx(Icon, { name: field.icon, size: "xs", className: "text-[var(--color-muted-foreground)]" }),
|
|
9099
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: field.label ?? fieldLabel(field.name) })
|
|
9100
|
+
] }),
|
|
9101
|
+
/* @__PURE__ */ jsx(
|
|
9102
|
+
Typography,
|
|
9103
|
+
{
|
|
9104
|
+
variant: field.variant === "caption" ? "caption" : "small",
|
|
9105
|
+
className: "text-right truncate max-w-[60%]",
|
|
9106
|
+
children: formatValue(value, field.format)
|
|
9107
|
+
}
|
|
9108
|
+
)
|
|
9109
|
+
] }, field.name);
|
|
9110
|
+
}) }) }),
|
|
9111
|
+
primaryActions.length > 0 && /* @__PURE__ */ jsx(Box, { className: "px-4 py-3 mt-auto border-t border-[var(--color-border)]", children: /* @__PURE__ */ jsx(HStack, { gap: "sm", className: "justify-end", children: primaryActions.map((action, idx) => /* @__PURE__ */ jsxs(
|
|
7690
9112
|
Button,
|
|
7691
9113
|
{
|
|
7692
|
-
variant: "ghost",
|
|
9114
|
+
variant: action.variant === "primary" ? "primary" : "ghost",
|
|
7693
9115
|
size: "sm",
|
|
7694
9116
|
onClick: handleActionClick(action, itemData),
|
|
7695
9117
|
"data-testid": `action-${action.event}`,
|
|
7696
|
-
className: "text-[var(--color-error)] hover:bg-[var(--color-error)]/10 px-2",
|
|
7697
9118
|
children: [
|
|
7698
|
-
action.icon && /* @__PURE__ */ jsx(Icon, { name: action.icon, size: "xs" }),
|
|
9119
|
+
action.icon && /* @__PURE__ */ jsx(Icon, { name: action.icon, size: "xs", className: "mr-1" }),
|
|
7699
9120
|
action.label
|
|
7700
9121
|
]
|
|
7701
9122
|
},
|
|
7702
9123
|
idx
|
|
7703
|
-
)) })
|
|
7704
|
-
]
|
|
7705
|
-
|
|
7706
|
-
|
|
7707
|
-
|
|
7708
|
-
|
|
7709
|
-
|
|
7710
|
-
|
|
7711
|
-
|
|
7712
|
-
|
|
7713
|
-
|
|
7714
|
-
|
|
7715
|
-
|
|
7716
|
-
|
|
7717
|
-
|
|
7718
|
-
|
|
7719
|
-
|
|
7720
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: field.label ?? fieldLabel(field.name) })
|
|
7721
|
-
] }),
|
|
7722
|
-
/* @__PURE__ */ jsx(
|
|
7723
|
-
Typography,
|
|
7724
|
-
{
|
|
7725
|
-
variant: field.variant === "caption" ? "caption" : "small",
|
|
7726
|
-
className: "text-right truncate max-w-[60%]",
|
|
7727
|
-
children: formatValue(value, field.format)
|
|
7728
|
-
}
|
|
7729
|
-
)
|
|
7730
|
-
] }, field.name);
|
|
7731
|
-
}) }) }),
|
|
7732
|
-
primaryActions.length > 0 && /* @__PURE__ */ jsx(Box, { className: "px-4 py-3 mt-auto border-t border-[var(--color-border)]", children: /* @__PURE__ */ jsx(HStack, { gap: "sm", className: "justify-end", children: primaryActions.map((action, idx) => /* @__PURE__ */ jsxs(
|
|
7733
|
-
Button,
|
|
7734
|
-
{
|
|
7735
|
-
variant: action.variant === "primary" ? "primary" : "ghost",
|
|
7736
|
-
size: "sm",
|
|
7737
|
-
onClick: handleActionClick(action, itemData),
|
|
7738
|
-
"data-testid": `action-${action.event}`,
|
|
7739
|
-
children: [
|
|
7740
|
-
action.icon && /* @__PURE__ */ jsx(Icon, { name: action.icon, size: "xs", className: "mr-1" }),
|
|
7741
|
-
action.label
|
|
7742
|
-
]
|
|
7743
|
-
},
|
|
7744
|
-
idx
|
|
7745
|
-
)) }) })
|
|
7746
|
-
]
|
|
7747
|
-
},
|
|
7748
|
-
id
|
|
7749
|
-
);
|
|
7750
|
-
})
|
|
7751
|
-
}
|
|
7752
|
-
);
|
|
9124
|
+
)) }) })
|
|
9125
|
+
]
|
|
9126
|
+
},
|
|
9127
|
+
id
|
|
9128
|
+
);
|
|
9129
|
+
})
|
|
9130
|
+
}
|
|
9131
|
+
),
|
|
9132
|
+
infiniteScroll && loadMoreEvent && /* @__PURE__ */ jsx(
|
|
9133
|
+
InfiniteScrollSentinel,
|
|
9134
|
+
{
|
|
9135
|
+
loadMoreEvent,
|
|
9136
|
+
isLoading,
|
|
9137
|
+
hasMore
|
|
9138
|
+
}
|
|
9139
|
+
)
|
|
9140
|
+
] });
|
|
7753
9141
|
};
|
|
7754
9142
|
DataGrid.displayName = "DataGrid";
|
|
7755
9143
|
function fieldLabel2(key) {
|
|
@@ -7786,6 +9174,16 @@ function formatValue2(value, format) {
|
|
|
7786
9174
|
return String(value);
|
|
7787
9175
|
}
|
|
7788
9176
|
}
|
|
9177
|
+
function groupData(items, field) {
|
|
9178
|
+
const groups = /* @__PURE__ */ new Map();
|
|
9179
|
+
for (const item of items) {
|
|
9180
|
+
const key = String(getNestedValue(item, field) ?? "");
|
|
9181
|
+
const group = groups.get(key);
|
|
9182
|
+
if (group) group.push(item);
|
|
9183
|
+
else groups.set(key, [item]);
|
|
9184
|
+
}
|
|
9185
|
+
return Array.from(groups.entries()).map(([label, groupItems]) => ({ label, items: groupItems }));
|
|
9186
|
+
}
|
|
7789
9187
|
var DataList = ({
|
|
7790
9188
|
entity,
|
|
7791
9189
|
fields: fieldsProp,
|
|
@@ -7793,9 +9191,25 @@ var DataList = ({
|
|
|
7793
9191
|
itemActions,
|
|
7794
9192
|
gap = "none",
|
|
7795
9193
|
variant = "default",
|
|
9194
|
+
groupBy,
|
|
9195
|
+
senderField,
|
|
9196
|
+
currentUser,
|
|
7796
9197
|
className,
|
|
7797
9198
|
isLoading = false,
|
|
7798
|
-
error = null
|
|
9199
|
+
error = null,
|
|
9200
|
+
// Gesture props: reorderable, swipeLeftEvent, swipeRightEvent, longPressEvent
|
|
9201
|
+
// are consumed by the compiler to wrap items in SwipeableRow/SortableList.
|
|
9202
|
+
// DataList destructures them here to prevent DOM passthrough.
|
|
9203
|
+
reorderable: _reorderable,
|
|
9204
|
+
reorderEvent: _reorderEvent,
|
|
9205
|
+
swipeLeftEvent: _swipeLeftEvent,
|
|
9206
|
+
swipeLeftActions: _swipeLeftActions,
|
|
9207
|
+
swipeRightEvent: _swipeRightEvent,
|
|
9208
|
+
swipeRightActions: _swipeRightActions,
|
|
9209
|
+
longPressEvent: _longPressEvent,
|
|
9210
|
+
infiniteScroll,
|
|
9211
|
+
loadMoreEvent,
|
|
9212
|
+
hasMore
|
|
7799
9213
|
}) => {
|
|
7800
9214
|
const eventBus = useEventBus();
|
|
7801
9215
|
const { t } = useTranslate();
|
|
@@ -7828,118 +9242,783 @@ var DataList = ({
|
|
|
7828
9242
|
}[gap];
|
|
7829
9243
|
const isCard = variant === "card";
|
|
7830
9244
|
const isCompact = variant === "compact";
|
|
7831
|
-
|
|
9245
|
+
const isMessage = variant === "message";
|
|
9246
|
+
if (isMessage) {
|
|
9247
|
+
const items2 = data.map((item) => item);
|
|
9248
|
+
const groups2 = groupBy ? groupData(items2, groupBy) : [{ label: "", items: items2 }];
|
|
9249
|
+
const contentField = titleField?.name ?? fields[0]?.name ?? "";
|
|
9250
|
+
return /* @__PURE__ */ jsx(VStack, { gap: "sm", className: cn("py-2", className), children: groups2.map((group, gi) => /* @__PURE__ */ jsxs(React68__default.Fragment, { children: [
|
|
9251
|
+
group.label && /* @__PURE__ */ jsx(Divider, { label: group.label, className: "my-2" }),
|
|
9252
|
+
group.items.map((itemData, index) => {
|
|
9253
|
+
const id = itemData.id || `${gi}-${index}`;
|
|
9254
|
+
const sender = senderField ? String(getNestedValue(itemData, senderField) ?? "") : "";
|
|
9255
|
+
const isSent = Boolean(currentUser && sender === currentUser);
|
|
9256
|
+
const content = getNestedValue(itemData, contentField);
|
|
9257
|
+
const timestampField = fields.find((f) => f.format === "date");
|
|
9258
|
+
const timestamp = timestampField ? getNestedValue(itemData, timestampField.name) : null;
|
|
9259
|
+
return /* @__PURE__ */ jsx(
|
|
9260
|
+
Box,
|
|
9261
|
+
{
|
|
9262
|
+
className: cn(
|
|
9263
|
+
"flex px-4",
|
|
9264
|
+
isSent ? "justify-end" : "justify-start"
|
|
9265
|
+
),
|
|
9266
|
+
children: /* @__PURE__ */ jsxs(
|
|
9267
|
+
Box,
|
|
9268
|
+
{
|
|
9269
|
+
className: cn(
|
|
9270
|
+
"max-w-[75%] px-4 py-2",
|
|
9271
|
+
isSent ? "bg-[var(--color-primary)] text-[var(--color-primary-foreground)] rounded-2xl rounded-br-sm" : "bg-[var(--color-muted)] text-[var(--color-foreground)] rounded-2xl rounded-bl-sm"
|
|
9272
|
+
),
|
|
9273
|
+
children: [
|
|
9274
|
+
!isSent && senderField && /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "font-semibold mb-0.5", children: sender }),
|
|
9275
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", children: content !== void 0 && content !== null ? String(content) : "" }),
|
|
9276
|
+
timestamp != null ? /* @__PURE__ */ jsx(
|
|
9277
|
+
Typography,
|
|
9278
|
+
{
|
|
9279
|
+
variant: "caption",
|
|
9280
|
+
className: cn(
|
|
9281
|
+
"mt-1 text-[0.65rem]",
|
|
9282
|
+
isSent ? "opacity-70" : "text-[var(--color-muted-foreground)]"
|
|
9283
|
+
),
|
|
9284
|
+
children: formatDate2(timestamp)
|
|
9285
|
+
}
|
|
9286
|
+
) : null
|
|
9287
|
+
]
|
|
9288
|
+
}
|
|
9289
|
+
)
|
|
9290
|
+
},
|
|
9291
|
+
id
|
|
9292
|
+
);
|
|
9293
|
+
})
|
|
9294
|
+
] }, gi)) });
|
|
9295
|
+
}
|
|
9296
|
+
const items = data.map((item) => item);
|
|
9297
|
+
const groups = groupBy ? groupData(items, groupBy) : [{ label: "", items }];
|
|
9298
|
+
const renderItem = (itemData, index, isLast) => {
|
|
9299
|
+
const id = itemData.id || String(index);
|
|
9300
|
+
const titleValue = getNestedValue(itemData, titleField?.name ?? "");
|
|
9301
|
+
return /* @__PURE__ */ jsxs(Box, { "data-entity-row": true, children: [
|
|
9302
|
+
/* @__PURE__ */ jsxs(
|
|
9303
|
+
Box,
|
|
9304
|
+
{
|
|
9305
|
+
className: cn(
|
|
9306
|
+
"group flex items-center gap-4 transition-all duration-200",
|
|
9307
|
+
isCompact ? "px-4 py-2" : "px-6 py-4",
|
|
9308
|
+
"hover:bg-[var(--color-muted)]/80",
|
|
9309
|
+
!isCard && !isCompact && "rounded-[var(--radius-lg)] border border-transparent hover:border-[var(--color-border)]"
|
|
9310
|
+
),
|
|
9311
|
+
children: [
|
|
9312
|
+
/* @__PURE__ */ jsxs(Box, { className: "flex-1 min-w-0", children: [
|
|
9313
|
+
/* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "items-center", children: [
|
|
9314
|
+
titleField?.icon && /* @__PURE__ */ jsx(
|
|
9315
|
+
Icon,
|
|
9316
|
+
{
|
|
9317
|
+
name: titleField.icon,
|
|
9318
|
+
size: isCompact ? "xs" : "sm",
|
|
9319
|
+
className: "text-[var(--color-primary)] flex-shrink-0"
|
|
9320
|
+
}
|
|
9321
|
+
),
|
|
9322
|
+
titleValue !== void 0 && titleValue !== null && /* @__PURE__ */ jsx(
|
|
9323
|
+
Typography,
|
|
9324
|
+
{
|
|
9325
|
+
variant: titleField?.variant === "h3" ? "h3" : "h4",
|
|
9326
|
+
className: cn("font-semibold truncate flex-1", isCompact && "text-sm"),
|
|
9327
|
+
children: String(titleValue)
|
|
9328
|
+
}
|
|
9329
|
+
),
|
|
9330
|
+
badgeFields.map((field) => {
|
|
9331
|
+
const val = getNestedValue(itemData, field.name);
|
|
9332
|
+
if (val === void 0 || val === null) return null;
|
|
9333
|
+
return /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center flex-shrink-0", children: [
|
|
9334
|
+
field.icon && /* @__PURE__ */ jsx(Icon, { name: field.icon, size: "xs" }),
|
|
9335
|
+
/* @__PURE__ */ jsx(Badge, { variant: statusVariant2(String(val)), children: String(val) })
|
|
9336
|
+
] }, field.name);
|
|
9337
|
+
})
|
|
9338
|
+
] }),
|
|
9339
|
+
bodyFields.length > 0 && !isCompact && /* @__PURE__ */ jsx(HStack, { gap: "md", className: "mt-1.5 flex-wrap", children: bodyFields.map((field) => {
|
|
9340
|
+
const value = getNestedValue(itemData, field.name);
|
|
9341
|
+
if (value === void 0 || value === null || value === "") return null;
|
|
9342
|
+
return /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center", children: [
|
|
9343
|
+
field.icon && /* @__PURE__ */ jsx(Icon, { name: field.icon, size: "xs", className: "text-[var(--color-muted-foreground)]" }),
|
|
9344
|
+
/* @__PURE__ */ jsxs(Typography, { variant: "caption", color: "secondary", children: [
|
|
9345
|
+
field.label ?? fieldLabel2(field.name),
|
|
9346
|
+
":"
|
|
9347
|
+
] }),
|
|
9348
|
+
/* @__PURE__ */ jsx(Typography, { variant: "small", children: formatValue2(value, field.format) })
|
|
9349
|
+
] }, field.name);
|
|
9350
|
+
}) }),
|
|
9351
|
+
progressFields.map((field) => {
|
|
9352
|
+
const value = getNestedValue(itemData, field.name);
|
|
9353
|
+
if (typeof value !== "number") return null;
|
|
9354
|
+
return /* @__PURE__ */ jsxs(Box, { className: "mt-2 max-w-xs", children: [
|
|
9355
|
+
/* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center mb-1", children: [
|
|
9356
|
+
field.icon && /* @__PURE__ */ jsx(Icon, { name: field.icon, size: "xs", className: "text-[var(--color-muted-foreground)]" }),
|
|
9357
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: field.label ?? fieldLabel2(field.name) })
|
|
9358
|
+
] }),
|
|
9359
|
+
/* @__PURE__ */ jsx(ProgressBar, { value, max: 100 })
|
|
9360
|
+
] }, field.name);
|
|
9361
|
+
})
|
|
9362
|
+
] }),
|
|
9363
|
+
itemActions && itemActions.length > 0 && /* @__PURE__ */ jsx(
|
|
9364
|
+
HStack,
|
|
9365
|
+
{
|
|
9366
|
+
gap: "xs",
|
|
9367
|
+
className: cn(
|
|
9368
|
+
"flex-shrink-0 transition-opacity duration-200",
|
|
9369
|
+
"opacity-0 group-hover:opacity-100"
|
|
9370
|
+
),
|
|
9371
|
+
children: itemActions.map((action, idx) => /* @__PURE__ */ jsxs(
|
|
9372
|
+
Button,
|
|
9373
|
+
{
|
|
9374
|
+
variant: action.variant ?? "ghost",
|
|
9375
|
+
size: "sm",
|
|
9376
|
+
onClick: handleActionClick(action, itemData),
|
|
9377
|
+
"data-testid": `action-${action.event}`,
|
|
9378
|
+
className: cn(
|
|
9379
|
+
action.variant === "danger" && "text-[var(--color-error)] hover:bg-[var(--color-error)]/10"
|
|
9380
|
+
),
|
|
9381
|
+
children: [
|
|
9382
|
+
action.icon && /* @__PURE__ */ jsx(Icon, { name: action.icon, size: "xs", className: "mr-1" }),
|
|
9383
|
+
action.label
|
|
9384
|
+
]
|
|
9385
|
+
},
|
|
9386
|
+
idx
|
|
9387
|
+
))
|
|
9388
|
+
}
|
|
9389
|
+
)
|
|
9390
|
+
]
|
|
9391
|
+
}
|
|
9392
|
+
),
|
|
9393
|
+
isCard && !isLast && /* @__PURE__ */ jsx(Box, { className: "mx-6 border-b border-[var(--color-border)]/40" })
|
|
9394
|
+
] }, id);
|
|
9395
|
+
};
|
|
9396
|
+
return /* @__PURE__ */ jsxs(
|
|
9397
|
+
Box,
|
|
9398
|
+
{
|
|
9399
|
+
className: cn(
|
|
9400
|
+
isCard && "bg-[var(--color-card)] rounded-[var(--radius-xl)] border border-[var(--color-border)] shadow-[var(--shadow-lg)] overflow-hidden",
|
|
9401
|
+
!isCard && gapClass,
|
|
9402
|
+
className
|
|
9403
|
+
),
|
|
9404
|
+
children: [
|
|
9405
|
+
groups.map((group, gi) => /* @__PURE__ */ jsxs(React68__default.Fragment, { children: [
|
|
9406
|
+
group.label && /* @__PURE__ */ jsx(Divider, { label: group.label, className: gi > 0 ? "mt-4" : "mt-0" }),
|
|
9407
|
+
group.items.map(
|
|
9408
|
+
(itemData, index) => renderItem(itemData, index, gi === groups.length - 1 && index === group.items.length - 1)
|
|
9409
|
+
)
|
|
9410
|
+
] }, gi)),
|
|
9411
|
+
infiniteScroll && loadMoreEvent && /* @__PURE__ */ jsx(
|
|
9412
|
+
InfiniteScrollSentinel,
|
|
9413
|
+
{
|
|
9414
|
+
loadMoreEvent,
|
|
9415
|
+
isLoading,
|
|
9416
|
+
hasMore
|
|
9417
|
+
}
|
|
9418
|
+
)
|
|
9419
|
+
]
|
|
9420
|
+
}
|
|
9421
|
+
);
|
|
9422
|
+
};
|
|
9423
|
+
DataList.displayName = "DataList";
|
|
9424
|
+
function useSafeEventBus8() {
|
|
9425
|
+
try {
|
|
9426
|
+
return useEventBus();
|
|
9427
|
+
} catch {
|
|
9428
|
+
return { emit: () => {
|
|
9429
|
+
}, on: () => () => {
|
|
9430
|
+
}, once: () => {
|
|
9431
|
+
} };
|
|
9432
|
+
}
|
|
9433
|
+
}
|
|
9434
|
+
var SwipeableRow = ({
|
|
9435
|
+
leftActions = [],
|
|
9436
|
+
rightActions = [],
|
|
9437
|
+
threshold = 80,
|
|
9438
|
+
children,
|
|
9439
|
+
itemData,
|
|
9440
|
+
className
|
|
9441
|
+
}) => {
|
|
9442
|
+
const eventBus = useSafeEventBus8();
|
|
9443
|
+
const [revealState, setRevealState] = useState("closed");
|
|
9444
|
+
const [offsetX, setOffsetX] = useState(0);
|
|
9445
|
+
const [isSwiping, setIsSwiping] = useState(false);
|
|
9446
|
+
const startXRef = useRef(0);
|
|
9447
|
+
const startYRef = useRef(0);
|
|
9448
|
+
const trackingRef = useRef(false);
|
|
9449
|
+
const lockedAxisRef = useRef(null);
|
|
9450
|
+
const actionsWidth = threshold;
|
|
9451
|
+
const handleActionClick = useCallback(
|
|
9452
|
+
(action) => {
|
|
9453
|
+
eventBus.emit(`UI:${action.event}`, {
|
|
9454
|
+
...action.eventPayload,
|
|
9455
|
+
row: itemData
|
|
9456
|
+
});
|
|
9457
|
+
setRevealState("closed");
|
|
9458
|
+
setOffsetX(0);
|
|
9459
|
+
},
|
|
9460
|
+
[eventBus, itemData]
|
|
9461
|
+
);
|
|
9462
|
+
const handlePointerDown = useCallback(
|
|
9463
|
+
(e) => {
|
|
9464
|
+
if (e.button !== 0) return;
|
|
9465
|
+
startXRef.current = e.clientX;
|
|
9466
|
+
startYRef.current = e.clientY;
|
|
9467
|
+
trackingRef.current = true;
|
|
9468
|
+
lockedAxisRef.current = null;
|
|
9469
|
+
setIsSwiping(false);
|
|
9470
|
+
e.currentTarget.setPointerCapture(e.pointerId);
|
|
9471
|
+
},
|
|
9472
|
+
[]
|
|
9473
|
+
);
|
|
9474
|
+
const handlePointerMove = useCallback(
|
|
9475
|
+
(e) => {
|
|
9476
|
+
if (!trackingRef.current) return;
|
|
9477
|
+
const dx = e.clientX - startXRef.current;
|
|
9478
|
+
const dy = e.clientY - startYRef.current;
|
|
9479
|
+
if (lockedAxisRef.current === null && (Math.abs(dx) > 5 || Math.abs(dy) > 5)) {
|
|
9480
|
+
lockedAxisRef.current = Math.abs(dx) > Math.abs(dy) ? "horizontal" : "vertical";
|
|
9481
|
+
}
|
|
9482
|
+
if (lockedAxisRef.current !== "horizontal") return;
|
|
9483
|
+
setIsSwiping(true);
|
|
9484
|
+
let newOffset = dx;
|
|
9485
|
+
if (revealState === "left") {
|
|
9486
|
+
newOffset = actionsWidth + dx;
|
|
9487
|
+
} else if (revealState === "right") {
|
|
9488
|
+
newOffset = -actionsWidth + dx;
|
|
9489
|
+
}
|
|
9490
|
+
const maxLeft = leftActions.length > 0 ? actionsWidth : 0;
|
|
9491
|
+
const maxRight = rightActions.length > 0 ? actionsWidth : 0;
|
|
9492
|
+
const clamped = Math.max(-maxRight, Math.min(maxLeft, newOffset));
|
|
9493
|
+
setOffsetX(clamped);
|
|
9494
|
+
},
|
|
9495
|
+
[revealState, actionsWidth, leftActions.length, rightActions.length]
|
|
9496
|
+
);
|
|
9497
|
+
const handlePointerUp = useCallback(
|
|
9498
|
+
() => {
|
|
9499
|
+
trackingRef.current = false;
|
|
9500
|
+
if (!isSwiping) {
|
|
9501
|
+
if (revealState !== "closed") {
|
|
9502
|
+
setRevealState("closed");
|
|
9503
|
+
setOffsetX(0);
|
|
9504
|
+
}
|
|
9505
|
+
setIsSwiping(false);
|
|
9506
|
+
return;
|
|
9507
|
+
}
|
|
9508
|
+
setIsSwiping(false);
|
|
9509
|
+
if (offsetX > threshold / 2 && leftActions.length > 0) {
|
|
9510
|
+
setRevealState("right");
|
|
9511
|
+
setOffsetX(actionsWidth);
|
|
9512
|
+
} else if (offsetX < -(threshold / 2) && rightActions.length > 0) {
|
|
9513
|
+
setRevealState("left");
|
|
9514
|
+
setOffsetX(-actionsWidth);
|
|
9515
|
+
} else {
|
|
9516
|
+
setRevealState("closed");
|
|
9517
|
+
setOffsetX(0);
|
|
9518
|
+
}
|
|
9519
|
+
},
|
|
9520
|
+
[isSwiping, offsetX, threshold, leftActions.length, rightActions.length, actionsWidth, revealState]
|
|
9521
|
+
);
|
|
9522
|
+
const handlePointerCancel = useCallback(() => {
|
|
9523
|
+
trackingRef.current = false;
|
|
9524
|
+
setIsSwiping(false);
|
|
9525
|
+
setRevealState("closed");
|
|
9526
|
+
setOffsetX(0);
|
|
9527
|
+
}, []);
|
|
9528
|
+
const renderActions = (actions, side) => {
|
|
9529
|
+
if (actions.length === 0) return null;
|
|
9530
|
+
return /* @__PURE__ */ jsx(
|
|
9531
|
+
HStack,
|
|
9532
|
+
{
|
|
9533
|
+
gap: "xs",
|
|
9534
|
+
align: "stretch",
|
|
9535
|
+
className: cn(
|
|
9536
|
+
"absolute top-0 bottom-0",
|
|
9537
|
+
side === "left" ? "left-0" : "right-0"
|
|
9538
|
+
),
|
|
9539
|
+
style: {
|
|
9540
|
+
width: `${actionsWidth}px`
|
|
9541
|
+
},
|
|
9542
|
+
children: actions.map((action, idx) => /* @__PURE__ */ jsxs(
|
|
9543
|
+
Button,
|
|
9544
|
+
{
|
|
9545
|
+
variant: action.variant ?? "secondary",
|
|
9546
|
+
size: "sm",
|
|
9547
|
+
icon: action.icon,
|
|
9548
|
+
onClick: () => handleActionClick(action),
|
|
9549
|
+
className: "flex-1 rounded-none h-full",
|
|
9550
|
+
children: [
|
|
9551
|
+
action.icon ? /* @__PURE__ */ jsx(Icon, { name: action.icon, size: "sm" }) : null,
|
|
9552
|
+
action.label
|
|
9553
|
+
]
|
|
9554
|
+
},
|
|
9555
|
+
`${action.event}-${idx}`
|
|
9556
|
+
))
|
|
9557
|
+
}
|
|
9558
|
+
);
|
|
9559
|
+
};
|
|
9560
|
+
return /* @__PURE__ */ jsxs(
|
|
7832
9561
|
Box,
|
|
7833
9562
|
{
|
|
9563
|
+
overflow: "hidden",
|
|
9564
|
+
position: "relative",
|
|
7834
9565
|
className: cn(
|
|
7835
|
-
|
|
7836
|
-
!isCard && gapClass,
|
|
9566
|
+
"touch-pan-y",
|
|
7837
9567
|
className
|
|
7838
9568
|
),
|
|
7839
|
-
children:
|
|
7840
|
-
|
|
7841
|
-
|
|
7842
|
-
|
|
7843
|
-
|
|
7844
|
-
|
|
7845
|
-
|
|
9569
|
+
children: [
|
|
9570
|
+
renderActions(leftActions, "left"),
|
|
9571
|
+
renderActions(rightActions, "right"),
|
|
9572
|
+
/* @__PURE__ */ jsx(
|
|
9573
|
+
Box,
|
|
9574
|
+
{
|
|
9575
|
+
style: {
|
|
9576
|
+
transform: `translateX(${offsetX}px)`,
|
|
9577
|
+
transition: isSwiping ? "none" : "transform 200ms ease-out"
|
|
9578
|
+
},
|
|
9579
|
+
className: cn(
|
|
9580
|
+
"relative bg-[var(--color-surface)]",
|
|
9581
|
+
"select-none"
|
|
9582
|
+
),
|
|
9583
|
+
onPointerDown: handlePointerDown,
|
|
9584
|
+
onPointerMove: handlePointerMove,
|
|
9585
|
+
onPointerUp: handlePointerUp,
|
|
9586
|
+
onPointerCancel: handlePointerCancel,
|
|
9587
|
+
children
|
|
9588
|
+
}
|
|
9589
|
+
)
|
|
9590
|
+
]
|
|
9591
|
+
}
|
|
9592
|
+
);
|
|
9593
|
+
};
|
|
9594
|
+
SwipeableRow.displayName = "SwipeableRow";
|
|
9595
|
+
function useSafeEventBus9() {
|
|
9596
|
+
try {
|
|
9597
|
+
return useEventBus();
|
|
9598
|
+
} catch {
|
|
9599
|
+
return { emit: () => {
|
|
9600
|
+
}, on: () => () => {
|
|
9601
|
+
}, once: () => {
|
|
9602
|
+
} };
|
|
9603
|
+
}
|
|
9604
|
+
}
|
|
9605
|
+
function SortableListInner({
|
|
9606
|
+
items: initialItems,
|
|
9607
|
+
renderItem,
|
|
9608
|
+
reorderEvent,
|
|
9609
|
+
reorderPayload,
|
|
9610
|
+
dragHandlePosition = "left",
|
|
9611
|
+
className
|
|
9612
|
+
}) {
|
|
9613
|
+
const eventBus = useSafeEventBus9();
|
|
9614
|
+
const handleReorder = useCallback(
|
|
9615
|
+
(fromIndex, toIndex, item) => {
|
|
9616
|
+
eventBus.emit(`UI:${reorderEvent}`, {
|
|
9617
|
+
fromIndex,
|
|
9618
|
+
toIndex,
|
|
9619
|
+
item,
|
|
9620
|
+
...reorderPayload
|
|
9621
|
+
});
|
|
9622
|
+
},
|
|
9623
|
+
[eventBus, reorderEvent, reorderPayload]
|
|
9624
|
+
);
|
|
9625
|
+
const {
|
|
9626
|
+
items,
|
|
9627
|
+
dragIndex,
|
|
9628
|
+
dragOverIndex,
|
|
9629
|
+
isDragging,
|
|
9630
|
+
getDragHandleProps,
|
|
9631
|
+
getItemProps
|
|
9632
|
+
} = useDragReorder(initialItems, handleReorder);
|
|
9633
|
+
return /* @__PURE__ */ jsx(VStack, { gap: "none", className: cn("w-full", className), children: items.map((item, index) => {
|
|
9634
|
+
const { "aria-dropeffect": ariaDropEffect, ...itemProps } = getItemProps(index);
|
|
9635
|
+
const { "aria-grabbed": ariaGrabbed, ...handleRest } = getDragHandleProps(index);
|
|
9636
|
+
const isBeingDragged = dragIndex === index;
|
|
9637
|
+
const showDropIndicator = isDragging && dragOverIndex === index && dragOverIndex !== dragIndex;
|
|
9638
|
+
const dragHandle = /* @__PURE__ */ jsx(
|
|
9639
|
+
Box,
|
|
9640
|
+
{
|
|
9641
|
+
className: cn(
|
|
9642
|
+
"flex items-center justify-center",
|
|
9643
|
+
"text-[var(--color-muted-foreground)]",
|
|
9644
|
+
"hover:text-[var(--color-foreground)]",
|
|
9645
|
+
"transition-colors duration-100",
|
|
9646
|
+
"px-1"
|
|
9647
|
+
),
|
|
9648
|
+
"aria-grabbed": ariaGrabbed,
|
|
9649
|
+
...handleRest,
|
|
9650
|
+
children: /* @__PURE__ */ jsx(Icon, { name: "grip-vertical", size: "sm" })
|
|
9651
|
+
}
|
|
9652
|
+
);
|
|
9653
|
+
return /* @__PURE__ */ jsxs(
|
|
9654
|
+
Box,
|
|
9655
|
+
{
|
|
9656
|
+
"aria-dropeffect": ariaDropEffect,
|
|
9657
|
+
...itemProps,
|
|
9658
|
+
children: [
|
|
9659
|
+
showDropIndicator && /* @__PURE__ */ jsx(
|
|
7846
9660
|
Box,
|
|
7847
9661
|
{
|
|
9662
|
+
className: "h-0.5 bg-[var(--color-primary)] rounded-full",
|
|
9663
|
+
style: { margin: "0 8px" }
|
|
9664
|
+
}
|
|
9665
|
+
),
|
|
9666
|
+
/* @__PURE__ */ jsxs(
|
|
9667
|
+
HStack,
|
|
9668
|
+
{
|
|
9669
|
+
gap: "sm",
|
|
9670
|
+
align: "center",
|
|
7848
9671
|
className: cn(
|
|
7849
|
-
"
|
|
7850
|
-
|
|
7851
|
-
"hover:bg-[var(--color-muted)]/80",
|
|
7852
|
-
!isCard && !isCompact && "rounded-[var(--radius-lg)] border border-transparent hover:border-[var(--color-border)]"
|
|
9672
|
+
"transition-opacity duration-150",
|
|
9673
|
+
isBeingDragged && "opacity-50"
|
|
7853
9674
|
),
|
|
7854
9675
|
children: [
|
|
7855
|
-
|
|
7856
|
-
|
|
7857
|
-
|
|
7858
|
-
Icon,
|
|
7859
|
-
{
|
|
7860
|
-
name: titleField.icon,
|
|
7861
|
-
size: isCompact ? "xs" : "sm",
|
|
7862
|
-
className: "text-[var(--color-primary)] flex-shrink-0"
|
|
7863
|
-
}
|
|
7864
|
-
),
|
|
7865
|
-
titleValue !== void 0 && titleValue !== null && /* @__PURE__ */ jsx(
|
|
7866
|
-
Typography,
|
|
7867
|
-
{
|
|
7868
|
-
variant: titleField?.variant === "h3" ? "h3" : "h4",
|
|
7869
|
-
className: cn("font-semibold truncate flex-1", isCompact && "text-sm"),
|
|
7870
|
-
children: String(titleValue)
|
|
7871
|
-
}
|
|
7872
|
-
),
|
|
7873
|
-
badgeFields.map((field) => {
|
|
7874
|
-
const val = getNestedValue(itemData, field.name);
|
|
7875
|
-
if (val === void 0 || val === null) return null;
|
|
7876
|
-
return /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center flex-shrink-0", children: [
|
|
7877
|
-
field.icon && /* @__PURE__ */ jsx(Icon, { name: field.icon, size: "xs" }),
|
|
7878
|
-
/* @__PURE__ */ jsx(Badge, { variant: statusVariant2(String(val)), children: String(val) })
|
|
7879
|
-
] }, field.name);
|
|
7880
|
-
})
|
|
7881
|
-
] }),
|
|
7882
|
-
bodyFields.length > 0 && !isCompact && /* @__PURE__ */ jsx(HStack, { gap: "md", className: "mt-1.5 flex-wrap", children: bodyFields.map((field) => {
|
|
7883
|
-
const value = getNestedValue(itemData, field.name);
|
|
7884
|
-
if (value === void 0 || value === null || value === "") return null;
|
|
7885
|
-
return /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center", children: [
|
|
7886
|
-
field.icon && /* @__PURE__ */ jsx(Icon, { name: field.icon, size: "xs", className: "text-[var(--color-muted-foreground)]" }),
|
|
7887
|
-
/* @__PURE__ */ jsxs(Typography, { variant: "caption", color: "secondary", children: [
|
|
7888
|
-
field.label ?? fieldLabel2(field.name),
|
|
7889
|
-
":"
|
|
7890
|
-
] }),
|
|
7891
|
-
/* @__PURE__ */ jsx(Typography, { variant: "small", children: formatValue2(value, field.format) })
|
|
7892
|
-
] }, field.name);
|
|
7893
|
-
}) }),
|
|
7894
|
-
progressFields.map((field) => {
|
|
7895
|
-
const value = getNestedValue(itemData, field.name);
|
|
7896
|
-
if (typeof value !== "number") return null;
|
|
7897
|
-
return /* @__PURE__ */ jsxs(Box, { className: "mt-2 max-w-xs", children: [
|
|
7898
|
-
/* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center mb-1", children: [
|
|
7899
|
-
field.icon && /* @__PURE__ */ jsx(Icon, { name: field.icon, size: "xs", className: "text-[var(--color-muted-foreground)]" }),
|
|
7900
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: field.label ?? fieldLabel2(field.name) })
|
|
7901
|
-
] }),
|
|
7902
|
-
/* @__PURE__ */ jsx(ProgressBar, { value, max: 100 })
|
|
7903
|
-
] }, field.name);
|
|
7904
|
-
})
|
|
7905
|
-
] }),
|
|
7906
|
-
itemActions && itemActions.length > 0 && /* @__PURE__ */ jsx(
|
|
7907
|
-
HStack,
|
|
7908
|
-
{
|
|
7909
|
-
gap: "xs",
|
|
7910
|
-
className: cn(
|
|
7911
|
-
"flex-shrink-0 transition-opacity duration-200",
|
|
7912
|
-
"opacity-0 group-hover:opacity-100"
|
|
7913
|
-
),
|
|
7914
|
-
children: itemActions.map((action, idx) => /* @__PURE__ */ jsxs(
|
|
7915
|
-
Button,
|
|
7916
|
-
{
|
|
7917
|
-
variant: action.variant ?? "ghost",
|
|
7918
|
-
size: "sm",
|
|
7919
|
-
onClick: handleActionClick(action, itemData),
|
|
7920
|
-
"data-testid": `action-${action.event}`,
|
|
7921
|
-
className: cn(
|
|
7922
|
-
action.variant === "danger" && "text-[var(--color-error)] hover:bg-[var(--color-error)]/10"
|
|
7923
|
-
),
|
|
7924
|
-
children: [
|
|
7925
|
-
action.icon && /* @__PURE__ */ jsx(Icon, { name: action.icon, size: "xs", className: "mr-1" }),
|
|
7926
|
-
action.label
|
|
7927
|
-
]
|
|
7928
|
-
},
|
|
7929
|
-
idx
|
|
7930
|
-
))
|
|
7931
|
-
}
|
|
7932
|
-
)
|
|
9676
|
+
dragHandlePosition === "left" && dragHandle,
|
|
9677
|
+
/* @__PURE__ */ jsx(Box, { className: "flex-1 min-w-0", children: renderItem(item, index) }),
|
|
9678
|
+
dragHandlePosition === "right" && dragHandle
|
|
7933
9679
|
]
|
|
7934
9680
|
}
|
|
7935
|
-
)
|
|
7936
|
-
|
|
7937
|
-
|
|
7938
|
-
|
|
7939
|
-
|
|
9681
|
+
)
|
|
9682
|
+
]
|
|
9683
|
+
},
|
|
9684
|
+
index
|
|
9685
|
+
);
|
|
9686
|
+
}) });
|
|
9687
|
+
}
|
|
9688
|
+
var SortableList = SortableListInner;
|
|
9689
|
+
SortableList.displayName = "SortableList";
|
|
9690
|
+
function useSafeEventBus10() {
|
|
9691
|
+
try {
|
|
9692
|
+
return useEventBus();
|
|
9693
|
+
} catch {
|
|
9694
|
+
return { emit: () => {
|
|
9695
|
+
}, on: () => () => {
|
|
9696
|
+
}, once: () => {
|
|
9697
|
+
} };
|
|
9698
|
+
}
|
|
9699
|
+
}
|
|
9700
|
+
var Carousel = ({
|
|
9701
|
+
items,
|
|
9702
|
+
renderItem,
|
|
9703
|
+
autoPlay = false,
|
|
9704
|
+
autoPlayInterval = 5e3,
|
|
9705
|
+
showDots = true,
|
|
9706
|
+
showArrows = true,
|
|
9707
|
+
loop = false,
|
|
9708
|
+
slideChangeEvent,
|
|
9709
|
+
slideChangePayload,
|
|
9710
|
+
className
|
|
9711
|
+
}) => {
|
|
9712
|
+
const [activeIndex, setActiveIndex] = useState(0);
|
|
9713
|
+
const scrollRef = useRef(null);
|
|
9714
|
+
const autoPlayRef = useRef(null);
|
|
9715
|
+
const eventBus = useSafeEventBus10();
|
|
9716
|
+
const totalSlides = items.length;
|
|
9717
|
+
const emitSlideChange = useCallback(
|
|
9718
|
+
(newIndex) => {
|
|
9719
|
+
if (slideChangeEvent) {
|
|
9720
|
+
eventBus.emit(`UI:${slideChangeEvent}`, {
|
|
9721
|
+
index: newIndex,
|
|
9722
|
+
...slideChangePayload
|
|
9723
|
+
});
|
|
9724
|
+
}
|
|
9725
|
+
},
|
|
9726
|
+
[slideChangeEvent, slideChangePayload, eventBus]
|
|
9727
|
+
);
|
|
9728
|
+
const scrollToSlide = useCallback(
|
|
9729
|
+
(index) => {
|
|
9730
|
+
const container = scrollRef.current;
|
|
9731
|
+
if (!container) return;
|
|
9732
|
+
const slideWidth = container.offsetWidth;
|
|
9733
|
+
container.scrollTo({
|
|
9734
|
+
left: slideWidth * index,
|
|
9735
|
+
behavior: "smooth"
|
|
9736
|
+
});
|
|
9737
|
+
},
|
|
9738
|
+
[]
|
|
9739
|
+
);
|
|
9740
|
+
const goToSlide = useCallback(
|
|
9741
|
+
(index) => {
|
|
9742
|
+
let targetIndex = index;
|
|
9743
|
+
if (loop) {
|
|
9744
|
+
if (targetIndex < 0) targetIndex = totalSlides - 1;
|
|
9745
|
+
if (targetIndex >= totalSlides) targetIndex = 0;
|
|
9746
|
+
} else {
|
|
9747
|
+
targetIndex = Math.max(0, Math.min(totalSlides - 1, targetIndex));
|
|
9748
|
+
}
|
|
9749
|
+
setActiveIndex(targetIndex);
|
|
9750
|
+
scrollToSlide(targetIndex);
|
|
9751
|
+
emitSlideChange(targetIndex);
|
|
9752
|
+
},
|
|
9753
|
+
[loop, totalSlides, scrollToSlide, emitSlideChange]
|
|
9754
|
+
);
|
|
9755
|
+
const goNext = useCallback(() => {
|
|
9756
|
+
goToSlide(activeIndex + 1);
|
|
9757
|
+
}, [goToSlide, activeIndex]);
|
|
9758
|
+
const goPrev = useCallback(() => {
|
|
9759
|
+
goToSlide(activeIndex - 1);
|
|
9760
|
+
}, [goToSlide, activeIndex]);
|
|
9761
|
+
const swipeHandlers = useSwipeGesture(
|
|
9762
|
+
{
|
|
9763
|
+
onSwipeLeft: goNext,
|
|
9764
|
+
onSwipeRight: goPrev
|
|
9765
|
+
},
|
|
9766
|
+
{ threshold: 40 }
|
|
7940
9767
|
);
|
|
9768
|
+
useEffect(() => {
|
|
9769
|
+
if (!autoPlay || totalSlides <= 1) return;
|
|
9770
|
+
autoPlayRef.current = setInterval(() => {
|
|
9771
|
+
setActiveIndex((prev) => {
|
|
9772
|
+
const next = loop ? (prev + 1) % totalSlides : Math.min(prev + 1, totalSlides - 1);
|
|
9773
|
+
setTimeout(() => {
|
|
9774
|
+
scrollToSlide(next);
|
|
9775
|
+
emitSlideChange(next);
|
|
9776
|
+
}, 0);
|
|
9777
|
+
return next;
|
|
9778
|
+
});
|
|
9779
|
+
}, autoPlayInterval);
|
|
9780
|
+
return () => {
|
|
9781
|
+
if (autoPlayRef.current) {
|
|
9782
|
+
clearInterval(autoPlayRef.current);
|
|
9783
|
+
autoPlayRef.current = null;
|
|
9784
|
+
}
|
|
9785
|
+
};
|
|
9786
|
+
}, [autoPlay, autoPlayInterval, loop, totalSlides, scrollToSlide, emitSlideChange]);
|
|
9787
|
+
const handleScroll = useCallback(() => {
|
|
9788
|
+
const container = scrollRef.current;
|
|
9789
|
+
if (!container) return;
|
|
9790
|
+
const slideWidth = container.offsetWidth;
|
|
9791
|
+
if (slideWidth === 0) return;
|
|
9792
|
+
const newIndex = Math.round(container.scrollLeft / slideWidth);
|
|
9793
|
+
setActiveIndex((prev) => {
|
|
9794
|
+
if (prev !== newIndex && newIndex >= 0 && newIndex < totalSlides) {
|
|
9795
|
+
return newIndex;
|
|
9796
|
+
}
|
|
9797
|
+
return prev;
|
|
9798
|
+
});
|
|
9799
|
+
}, [totalSlides]);
|
|
9800
|
+
const hasPrev = loop || activeIndex > 0;
|
|
9801
|
+
const hasNext = loop || activeIndex < totalSlides - 1;
|
|
9802
|
+
if (totalSlides === 0) return null;
|
|
9803
|
+
return /* @__PURE__ */ jsxs(Box, { position: "relative", overflow: "hidden", className: cn("w-full", className), children: [
|
|
9804
|
+
/* @__PURE__ */ jsx(
|
|
9805
|
+
Box,
|
|
9806
|
+
{
|
|
9807
|
+
ref: scrollRef,
|
|
9808
|
+
display: "flex",
|
|
9809
|
+
overflow: "auto",
|
|
9810
|
+
className: cn(
|
|
9811
|
+
"w-full",
|
|
9812
|
+
"scroll-smooth",
|
|
9813
|
+
"scrollbar-none",
|
|
9814
|
+
"[scroll-snap-type:x_mandatory]",
|
|
9815
|
+
"[&::-webkit-scrollbar]:hidden",
|
|
9816
|
+
"[-ms-overflow-style:none]"
|
|
9817
|
+
),
|
|
9818
|
+
style: {
|
|
9819
|
+
scrollSnapType: "x mandatory",
|
|
9820
|
+
WebkitOverflowScrolling: "touch"
|
|
9821
|
+
},
|
|
9822
|
+
onScroll: handleScroll,
|
|
9823
|
+
onPointerDown: swipeHandlers.onPointerDown,
|
|
9824
|
+
onPointerMove: swipeHandlers.onPointerMove,
|
|
9825
|
+
onPointerUp: swipeHandlers.onPointerUp,
|
|
9826
|
+
onPointerCancel: swipeHandlers.onPointerCancel,
|
|
9827
|
+
children: items.map((item, index) => /* @__PURE__ */ jsx(
|
|
9828
|
+
Box,
|
|
9829
|
+
{
|
|
9830
|
+
className: cn(
|
|
9831
|
+
"flex-shrink-0 w-full",
|
|
9832
|
+
"[scroll-snap-align:start]"
|
|
9833
|
+
),
|
|
9834
|
+
style: {
|
|
9835
|
+
scrollSnapAlign: "start"
|
|
9836
|
+
},
|
|
9837
|
+
children: renderItem(item, index)
|
|
9838
|
+
},
|
|
9839
|
+
index
|
|
9840
|
+
))
|
|
9841
|
+
}
|
|
9842
|
+
),
|
|
9843
|
+
showArrows && hasPrev && totalSlides > 1 && /* @__PURE__ */ jsx(
|
|
9844
|
+
Box,
|
|
9845
|
+
{
|
|
9846
|
+
position: "absolute",
|
|
9847
|
+
className: "left-2 top-1/2 -translate-y-1/2 z-10",
|
|
9848
|
+
children: /* @__PURE__ */ jsx(
|
|
9849
|
+
Button,
|
|
9850
|
+
{
|
|
9851
|
+
variant: "ghost",
|
|
9852
|
+
size: "sm",
|
|
9853
|
+
onClick: goPrev,
|
|
9854
|
+
"aria-label": "Previous slide",
|
|
9855
|
+
className: cn(
|
|
9856
|
+
"rounded-full",
|
|
9857
|
+
"bg-[var(--color-surface)]/80",
|
|
9858
|
+
"backdrop-blur-sm",
|
|
9859
|
+
"shadow-[var(--shadow-sm)]",
|
|
9860
|
+
"hover:bg-[var(--color-surface)]"
|
|
9861
|
+
),
|
|
9862
|
+
children: /* @__PURE__ */ jsx(ChevronLeft, { className: "w-5 h-5" })
|
|
9863
|
+
}
|
|
9864
|
+
)
|
|
9865
|
+
}
|
|
9866
|
+
),
|
|
9867
|
+
showArrows && hasNext && totalSlides > 1 && /* @__PURE__ */ jsx(
|
|
9868
|
+
Box,
|
|
9869
|
+
{
|
|
9870
|
+
position: "absolute",
|
|
9871
|
+
className: "right-2 top-1/2 -translate-y-1/2 z-10",
|
|
9872
|
+
children: /* @__PURE__ */ jsx(
|
|
9873
|
+
Button,
|
|
9874
|
+
{
|
|
9875
|
+
variant: "ghost",
|
|
9876
|
+
size: "sm",
|
|
9877
|
+
onClick: goNext,
|
|
9878
|
+
"aria-label": "Next slide",
|
|
9879
|
+
className: cn(
|
|
9880
|
+
"rounded-full",
|
|
9881
|
+
"bg-[var(--color-surface)]/80",
|
|
9882
|
+
"backdrop-blur-sm",
|
|
9883
|
+
"shadow-[var(--shadow-sm)]",
|
|
9884
|
+
"hover:bg-[var(--color-surface)]"
|
|
9885
|
+
),
|
|
9886
|
+
children: /* @__PURE__ */ jsx(ChevronRight, { className: "w-5 h-5" })
|
|
9887
|
+
}
|
|
9888
|
+
)
|
|
9889
|
+
}
|
|
9890
|
+
),
|
|
9891
|
+
showDots && totalSlides > 1 && /* @__PURE__ */ jsx(
|
|
9892
|
+
Box,
|
|
9893
|
+
{
|
|
9894
|
+
position: "absolute",
|
|
9895
|
+
className: "bottom-3 left-0 right-0 z-10",
|
|
9896
|
+
children: /* @__PURE__ */ jsx(HStack, { gap: "xs", align: "center", justify: "center", children: items.map((_, index) => {
|
|
9897
|
+
const isActive = index === activeIndex;
|
|
9898
|
+
return /* @__PURE__ */ jsx(
|
|
9899
|
+
Box,
|
|
9900
|
+
{
|
|
9901
|
+
className: cn(
|
|
9902
|
+
"rounded-full cursor-pointer transition-all duration-200"
|
|
9903
|
+
),
|
|
9904
|
+
style: {
|
|
9905
|
+
width: isActive ? 10 : 8,
|
|
9906
|
+
height: isActive ? 10 : 8,
|
|
9907
|
+
backgroundColor: isActive ? "var(--color-primary)" : "var(--color-muted, #d4d4d8)",
|
|
9908
|
+
opacity: isActive ? 1 : 0.6
|
|
9909
|
+
},
|
|
9910
|
+
onClick: () => goToSlide(index),
|
|
9911
|
+
role: "button",
|
|
9912
|
+
"aria-label": `Go to slide ${index + 1}`
|
|
9913
|
+
},
|
|
9914
|
+
index
|
|
9915
|
+
);
|
|
9916
|
+
}) })
|
|
9917
|
+
}
|
|
9918
|
+
)
|
|
9919
|
+
] });
|
|
7941
9920
|
};
|
|
7942
|
-
|
|
9921
|
+
Carousel.displayName = "Carousel";
|
|
9922
|
+
function useSafeEventBus11() {
|
|
9923
|
+
try {
|
|
9924
|
+
return useEventBus();
|
|
9925
|
+
} catch {
|
|
9926
|
+
return { emit: () => {
|
|
9927
|
+
}, on: () => () => {
|
|
9928
|
+
}, once: () => {
|
|
9929
|
+
} };
|
|
9930
|
+
}
|
|
9931
|
+
}
|
|
9932
|
+
var SAFETY_TIMEOUT_MS = 5e3;
|
|
9933
|
+
var PullToRefresh = ({
|
|
9934
|
+
refreshEvent,
|
|
9935
|
+
refreshPayload,
|
|
9936
|
+
threshold = 60,
|
|
9937
|
+
children,
|
|
9938
|
+
className
|
|
9939
|
+
}) => {
|
|
9940
|
+
const eventBus = useSafeEventBus11();
|
|
9941
|
+
const safetyTimerRef = useRef(null);
|
|
9942
|
+
const handleRefresh = useCallback(() => {
|
|
9943
|
+
eventBus.emit(`UI:${refreshEvent}`, refreshPayload ?? {});
|
|
9944
|
+
}, [eventBus, refreshEvent, refreshPayload]);
|
|
9945
|
+
const { pullDistance, isPulling, isRefreshing, containerProps, endRefresh } = usePullToRefresh(handleRefresh, { threshold });
|
|
9946
|
+
useEffect(() => {
|
|
9947
|
+
if (isRefreshing) {
|
|
9948
|
+
safetyTimerRef.current = setTimeout(() => {
|
|
9949
|
+
endRefresh();
|
|
9950
|
+
}, SAFETY_TIMEOUT_MS);
|
|
9951
|
+
return () => {
|
|
9952
|
+
if (safetyTimerRef.current) {
|
|
9953
|
+
clearTimeout(safetyTimerRef.current);
|
|
9954
|
+
safetyTimerRef.current = null;
|
|
9955
|
+
}
|
|
9956
|
+
};
|
|
9957
|
+
}
|
|
9958
|
+
}, [isRefreshing, endRefresh]);
|
|
9959
|
+
useEffect(() => {
|
|
9960
|
+
return () => {
|
|
9961
|
+
if (safetyTimerRef.current) {
|
|
9962
|
+
clearTimeout(safetyTimerRef.current);
|
|
9963
|
+
}
|
|
9964
|
+
};
|
|
9965
|
+
}, []);
|
|
9966
|
+
const pullProgress = Math.min(pullDistance / threshold, 1);
|
|
9967
|
+
const showIndicator = pullDistance > 0 || isRefreshing;
|
|
9968
|
+
return /* @__PURE__ */ jsxs(Box, { position: "relative", overflow: "hidden", className: cn("w-full", className), children: [
|
|
9969
|
+
/* @__PURE__ */ jsx(
|
|
9970
|
+
Box,
|
|
9971
|
+
{
|
|
9972
|
+
position: "absolute",
|
|
9973
|
+
display: "flex",
|
|
9974
|
+
className: cn(
|
|
9975
|
+
"top-0 left-0 right-0 z-10",
|
|
9976
|
+
"items-center justify-center",
|
|
9977
|
+
"transition-opacity duration-200",
|
|
9978
|
+
showIndicator ? "opacity-100" : "opacity-0"
|
|
9979
|
+
),
|
|
9980
|
+
style: {
|
|
9981
|
+
height: threshold,
|
|
9982
|
+
transform: `translateY(${showIndicator ? 0 : -threshold}px)`,
|
|
9983
|
+
pointerEvents: "none"
|
|
9984
|
+
},
|
|
9985
|
+
children: /* @__PURE__ */ jsx(
|
|
9986
|
+
Box,
|
|
9987
|
+
{
|
|
9988
|
+
className: "transition-transform duration-150",
|
|
9989
|
+
style: {
|
|
9990
|
+
transform: `scale(${isRefreshing ? 1 : pullProgress})`,
|
|
9991
|
+
opacity: isRefreshing ? 1 : pullProgress
|
|
9992
|
+
},
|
|
9993
|
+
children: /* @__PURE__ */ jsx(
|
|
9994
|
+
Spinner,
|
|
9995
|
+
{
|
|
9996
|
+
size: pullProgress >= 0.5 ? "md" : "sm",
|
|
9997
|
+
className: cn(
|
|
9998
|
+
"text-[var(--color-primary)]",
|
|
9999
|
+
isRefreshing && "animate-spin"
|
|
10000
|
+
)
|
|
10001
|
+
}
|
|
10002
|
+
)
|
|
10003
|
+
}
|
|
10004
|
+
)
|
|
10005
|
+
}
|
|
10006
|
+
),
|
|
10007
|
+
/* @__PURE__ */ jsx(
|
|
10008
|
+
Box,
|
|
10009
|
+
{
|
|
10010
|
+
fullWidth: true,
|
|
10011
|
+
className: cn(
|
|
10012
|
+
"min-h-0",
|
|
10013
|
+
isPulling && "select-none"
|
|
10014
|
+
),
|
|
10015
|
+
...containerProps,
|
|
10016
|
+
children
|
|
10017
|
+
}
|
|
10018
|
+
)
|
|
10019
|
+
] });
|
|
10020
|
+
};
|
|
10021
|
+
PullToRefresh.displayName = "PullToRefresh";
|
|
7943
10022
|
|
|
7944
10023
|
// components/organisms/types.ts
|
|
7945
10024
|
var EntityDisplayEvents = {
|
|
@@ -8368,6 +10447,7 @@ var StatCard = ({
|
|
|
8368
10447
|
// Schema-based props
|
|
8369
10448
|
entity,
|
|
8370
10449
|
metrics,
|
|
10450
|
+
sparklineData,
|
|
8371
10451
|
isLoading: externalLoading,
|
|
8372
10452
|
error: externalError
|
|
8373
10453
|
}) => {
|
|
@@ -8375,7 +10455,7 @@ var StatCard = ({
|
|
|
8375
10455
|
const labelToUse = propLabel ?? propTitle;
|
|
8376
10456
|
const eventBus = useEventBus();
|
|
8377
10457
|
const { t } = useTranslate();
|
|
8378
|
-
const handleActionClick =
|
|
10458
|
+
const handleActionClick = React68__default.useCallback(() => {
|
|
8379
10459
|
if (action?.event) {
|
|
8380
10460
|
eventBus.emit(`UI:${action.event}`, {});
|
|
8381
10461
|
}
|
|
@@ -8386,7 +10466,7 @@ var StatCard = ({
|
|
|
8386
10466
|
const data = Array.isArray(entity) ? entity : entity ? [entity] : [];
|
|
8387
10467
|
const isLoading = externalLoading ?? false;
|
|
8388
10468
|
const error = externalError;
|
|
8389
|
-
const computeMetricValue =
|
|
10469
|
+
const computeMetricValue = React68__default.useCallback(
|
|
8390
10470
|
(metric, items) => {
|
|
8391
10471
|
if (metric.value !== void 0) {
|
|
8392
10472
|
return metric.value;
|
|
@@ -8425,7 +10505,7 @@ var StatCard = ({
|
|
|
8425
10505
|
},
|
|
8426
10506
|
[]
|
|
8427
10507
|
);
|
|
8428
|
-
const schemaStats =
|
|
10508
|
+
const schemaStats = React68__default.useMemo(() => {
|
|
8429
10509
|
if (!metrics || metrics.length === 0) return null;
|
|
8430
10510
|
return metrics.map((metric) => ({
|
|
8431
10511
|
label: metric.label,
|
|
@@ -8433,7 +10513,7 @@ var StatCard = ({
|
|
|
8433
10513
|
format: metric.format
|
|
8434
10514
|
}));
|
|
8435
10515
|
}, [metrics, data, computeMetricValue]);
|
|
8436
|
-
const calculatedTrend =
|
|
10516
|
+
const calculatedTrend = React68__default.useMemo(() => {
|
|
8437
10517
|
if (manualTrend !== void 0) return manualTrend;
|
|
8438
10518
|
if (previousValue === void 0 || currentValue === void 0)
|
|
8439
10519
|
return void 0;
|
|
@@ -8513,7 +10593,35 @@ var StatCard = ({
|
|
|
8513
10593
|
] }),
|
|
8514
10594
|
subtitle && !calculatedTrend && /* @__PURE__ */ jsx(Typography, { variant: "small", color: "secondary", children: subtitle })
|
|
8515
10595
|
] }),
|
|
8516
|
-
|
|
10596
|
+
/* @__PURE__ */ jsxs(VStack, { gap: "xs", align: "end", children: [
|
|
10597
|
+
Icon2 && /* @__PURE__ */ jsx(Box, { className: cn("p-3", iconBg), children: /* @__PURE__ */ jsx(Icon2, { className: cn("h-6 w-6", iconColor) }) }),
|
|
10598
|
+
sparklineData && sparklineData.length > 1 && (() => {
|
|
10599
|
+
const w = 80;
|
|
10600
|
+
const h = 32;
|
|
10601
|
+
const pad = 2;
|
|
10602
|
+
const min = Math.min(...sparklineData);
|
|
10603
|
+
const max = Math.max(...sparklineData);
|
|
10604
|
+
const range = max - min || 1;
|
|
10605
|
+
const points = sparklineData.map((v, i) => {
|
|
10606
|
+
const x = pad + i / (sparklineData.length - 1) * (w - pad * 2);
|
|
10607
|
+
const y = pad + (1 - (v - min) / range) * (h - pad * 2);
|
|
10608
|
+
return `${x},${y}`;
|
|
10609
|
+
}).join(" ");
|
|
10610
|
+
const trending = sparklineData[sparklineData.length - 1] >= sparklineData[0];
|
|
10611
|
+
const strokeColor = trending ? "var(--color-success)" : "var(--color-error)";
|
|
10612
|
+
return /* @__PURE__ */ jsx("svg", { width: w, height: h, viewBox: `0 0 ${w} ${h}`, className: "flex-shrink-0", children: /* @__PURE__ */ jsx(
|
|
10613
|
+
"polyline",
|
|
10614
|
+
{
|
|
10615
|
+
fill: "none",
|
|
10616
|
+
stroke: strokeColor,
|
|
10617
|
+
strokeWidth: "2",
|
|
10618
|
+
strokeLinecap: "round",
|
|
10619
|
+
strokeLinejoin: "round",
|
|
10620
|
+
points
|
|
10621
|
+
}
|
|
10622
|
+
) });
|
|
10623
|
+
})()
|
|
10624
|
+
] })
|
|
8517
10625
|
] }),
|
|
8518
10626
|
action && /* @__PURE__ */ jsxs(
|
|
8519
10627
|
Button,
|
|
@@ -8561,7 +10669,7 @@ var PageHeader = ({
|
|
|
8561
10669
|
action.onClick();
|
|
8562
10670
|
}
|
|
8563
10671
|
};
|
|
8564
|
-
const
|
|
10672
|
+
const statusColors2 = {
|
|
8565
10673
|
default: "bg-[var(--color-muted)] text-[var(--color-foreground)]",
|
|
8566
10674
|
success: "bg-[var(--color-success)]/10 text-[var(--color-success)]",
|
|
8567
10675
|
warning: "bg-[var(--color-warning)]/10 text-[var(--color-warning)]",
|
|
@@ -8569,7 +10677,7 @@ var PageHeader = ({
|
|
|
8569
10677
|
info: "bg-[var(--color-info)]/10 text-[var(--color-info)]"
|
|
8570
10678
|
};
|
|
8571
10679
|
return /* @__PURE__ */ jsxs(Box, { className: cn("mb-6", className), children: [
|
|
8572
|
-
breadcrumbs && breadcrumbs.length > 0 && /* @__PURE__ */ jsx(Box, { as: "nav", className: "mb-4", children: /* @__PURE__ */ jsx(Box, { as: "ol", className: "flex items-center gap-2 text-sm", children: breadcrumbs.map((crumb, idx) => /* @__PURE__ */ jsxs(
|
|
10680
|
+
breadcrumbs && breadcrumbs.length > 0 && /* @__PURE__ */ jsx(Box, { as: "nav", className: "mb-4", children: /* @__PURE__ */ jsx(Box, { as: "ol", className: "flex items-center gap-2 text-sm", children: breadcrumbs.map((crumb, idx) => /* @__PURE__ */ jsxs(React68__default.Fragment, { children: [
|
|
8573
10681
|
idx > 0 && /* @__PURE__ */ jsx(Typography, { variant: "small", color: "muted", children: "/" }),
|
|
8574
10682
|
crumb.href ? /* @__PURE__ */ jsx(
|
|
8575
10683
|
"a",
|
|
@@ -8600,7 +10708,7 @@ var PageHeader = ({
|
|
|
8600
10708
|
variant: "small",
|
|
8601
10709
|
className: cn(
|
|
8602
10710
|
"px-2.5 py-1 rounded-[var(--radius-full)] text-xs font-medium",
|
|
8603
|
-
|
|
10711
|
+
statusColors2[status.variant || "default"]
|
|
8604
10712
|
),
|
|
8605
10713
|
children: status.label
|
|
8606
10714
|
}
|
|
@@ -9202,7 +11310,7 @@ var Form = ({
|
|
|
9202
11310
|
const normalizedInitialData = initialData ?? {};
|
|
9203
11311
|
const resolvedEntity = entity && typeof entity === "object" && !Array.isArray(entity) ? entity : void 0;
|
|
9204
11312
|
const entityName = typeof entity === "string" ? entity : resolvedEntity?.name;
|
|
9205
|
-
const entityDerivedFields =
|
|
11313
|
+
const entityDerivedFields = React68__default.useMemo(() => {
|
|
9206
11314
|
if (fields && fields.length > 0) return void 0;
|
|
9207
11315
|
if (!resolvedEntity) return void 0;
|
|
9208
11316
|
return resolvedEntity.fields.map(
|
|
@@ -9221,14 +11329,14 @@ var Form = ({
|
|
|
9221
11329
|
const conditionalFields = typeof conditionalFieldsRaw === "boolean" ? {} : conditionalFieldsRaw;
|
|
9222
11330
|
const hiddenCalculations = typeof hiddenCalculationsRaw === "boolean" ? [] : hiddenCalculationsRaw;
|
|
9223
11331
|
const violationTriggers = typeof violationTriggersRaw === "boolean" ? [] : violationTriggersRaw;
|
|
9224
|
-
const [formData, setFormData] =
|
|
11332
|
+
const [formData, setFormData] = React68__default.useState(
|
|
9225
11333
|
normalizedInitialData
|
|
9226
11334
|
);
|
|
9227
|
-
const [collapsedSections, setCollapsedSections] =
|
|
11335
|
+
const [collapsedSections, setCollapsedSections] = React68__default.useState(
|
|
9228
11336
|
/* @__PURE__ */ new Set()
|
|
9229
11337
|
);
|
|
9230
11338
|
const shouldShowCancel = showCancel ?? (fields && fields.length > 0);
|
|
9231
|
-
const evalContext =
|
|
11339
|
+
const evalContext = React68__default.useMemo(
|
|
9232
11340
|
() => ({
|
|
9233
11341
|
formValues: formData,
|
|
9234
11342
|
globalVariables: externalContext?.globalVariables ?? {},
|
|
@@ -9237,13 +11345,13 @@ var Form = ({
|
|
|
9237
11345
|
}),
|
|
9238
11346
|
[formData, externalContext]
|
|
9239
11347
|
);
|
|
9240
|
-
|
|
11348
|
+
React68__default.useEffect(() => {
|
|
9241
11349
|
const data = initialData;
|
|
9242
11350
|
if (data && Object.keys(data).length > 0) {
|
|
9243
11351
|
setFormData(data);
|
|
9244
11352
|
}
|
|
9245
11353
|
}, [initialData]);
|
|
9246
|
-
const processCalculations =
|
|
11354
|
+
const processCalculations = React68__default.useCallback(
|
|
9247
11355
|
(changedFieldId, newFormData) => {
|
|
9248
11356
|
if (!hiddenCalculations.length) return;
|
|
9249
11357
|
const context = {
|
|
@@ -9268,7 +11376,7 @@ var Form = ({
|
|
|
9268
11376
|
},
|
|
9269
11377
|
[hiddenCalculations, externalContext, eventBus]
|
|
9270
11378
|
);
|
|
9271
|
-
const checkViolations =
|
|
11379
|
+
const checkViolations = React68__default.useCallback(
|
|
9272
11380
|
(changedFieldId, newFormData) => {
|
|
9273
11381
|
if (!violationTriggers.length) return;
|
|
9274
11382
|
const context = {
|
|
@@ -9305,7 +11413,7 @@ var Form = ({
|
|
|
9305
11413
|
processCalculations(name, newFormData);
|
|
9306
11414
|
checkViolations(name, newFormData);
|
|
9307
11415
|
};
|
|
9308
|
-
const isFieldVisible =
|
|
11416
|
+
const isFieldVisible = React68__default.useCallback(
|
|
9309
11417
|
(fieldName) => {
|
|
9310
11418
|
const condition = conditionalFields[fieldName];
|
|
9311
11419
|
if (!condition) return true;
|
|
@@ -9313,7 +11421,7 @@ var Form = ({
|
|
|
9313
11421
|
},
|
|
9314
11422
|
[conditionalFields, evalContext]
|
|
9315
11423
|
);
|
|
9316
|
-
const isSectionVisible =
|
|
11424
|
+
const isSectionVisible = React68__default.useCallback(
|
|
9317
11425
|
(section) => {
|
|
9318
11426
|
if (!section.condition) return true;
|
|
9319
11427
|
return Boolean(evaluateFormExpression(section.condition, evalContext));
|
|
@@ -9345,7 +11453,7 @@ var Form = ({
|
|
|
9345
11453
|
eventBus.emit(`UI:${onCancel}`);
|
|
9346
11454
|
}
|
|
9347
11455
|
};
|
|
9348
|
-
const renderField =
|
|
11456
|
+
const renderField = React68__default.useCallback(
|
|
9349
11457
|
(field) => {
|
|
9350
11458
|
const fieldName = field.name || field.field;
|
|
9351
11459
|
if (!fieldName) return null;
|
|
@@ -9366,7 +11474,7 @@ var Form = ({
|
|
|
9366
11474
|
[formData, isFieldVisible, relationsData, relationsLoading, isLoading]
|
|
9367
11475
|
);
|
|
9368
11476
|
const effectiveFields = entityDerivedFields ?? fields;
|
|
9369
|
-
const normalizedFields =
|
|
11477
|
+
const normalizedFields = React68__default.useMemo(() => {
|
|
9370
11478
|
if (!effectiveFields || effectiveFields.length === 0) return [];
|
|
9371
11479
|
return effectiveFields.map((field) => {
|
|
9372
11480
|
if (typeof field === "string") {
|
|
@@ -9375,7 +11483,7 @@ var Form = ({
|
|
|
9375
11483
|
return field;
|
|
9376
11484
|
});
|
|
9377
11485
|
}, [effectiveFields]);
|
|
9378
|
-
const schemaFields =
|
|
11486
|
+
const schemaFields = React68__default.useMemo(() => {
|
|
9379
11487
|
if (normalizedFields.length === 0) return null;
|
|
9380
11488
|
if (isDebugEnabled()) {
|
|
9381
11489
|
debugGroup(`Form: ${entityName || "unknown"}`);
|
|
@@ -9385,7 +11493,7 @@ var Form = ({
|
|
|
9385
11493
|
}
|
|
9386
11494
|
return normalizedFields.map(renderField).filter(Boolean);
|
|
9387
11495
|
}, [normalizedFields, renderField, entityName, conditionalFields]);
|
|
9388
|
-
const sectionElements =
|
|
11496
|
+
const sectionElements = React68__default.useMemo(() => {
|
|
9389
11497
|
if (!sections || sections.length === 0) return null;
|
|
9390
11498
|
return sections.map((section) => {
|
|
9391
11499
|
if (!isSectionVisible(section)) {
|
|
@@ -10236,7 +12344,7 @@ function InputPattern({
|
|
|
10236
12344
|
className
|
|
10237
12345
|
}) {
|
|
10238
12346
|
const { emit } = useEventBus();
|
|
10239
|
-
const [localValue, setLocalValue] =
|
|
12347
|
+
const [localValue, setLocalValue] = React68__default.useState(value);
|
|
10240
12348
|
const handleChange = (e) => {
|
|
10241
12349
|
setLocalValue(e.target.value);
|
|
10242
12350
|
if (onChange) {
|
|
@@ -10273,7 +12381,7 @@ function TextareaPattern({
|
|
|
10273
12381
|
className
|
|
10274
12382
|
}) {
|
|
10275
12383
|
const { emit } = useEventBus();
|
|
10276
|
-
const [localValue, setLocalValue] =
|
|
12384
|
+
const [localValue, setLocalValue] = React68__default.useState(value);
|
|
10277
12385
|
const handleChange = (e) => {
|
|
10278
12386
|
setLocalValue(e.target.value);
|
|
10279
12387
|
if (onChange) {
|
|
@@ -10304,7 +12412,7 @@ function SelectPattern({
|
|
|
10304
12412
|
className
|
|
10305
12413
|
}) {
|
|
10306
12414
|
const { emit } = useEventBus();
|
|
10307
|
-
const [localValue, setLocalValue] =
|
|
12415
|
+
const [localValue, setLocalValue] = React68__default.useState(value);
|
|
10308
12416
|
const handleChange = (e) => {
|
|
10309
12417
|
setLocalValue(e.target.value);
|
|
10310
12418
|
if (onChange) {
|
|
@@ -10333,7 +12441,7 @@ function CheckboxPattern({
|
|
|
10333
12441
|
className
|
|
10334
12442
|
}) {
|
|
10335
12443
|
const { emit } = useEventBus();
|
|
10336
|
-
const [localChecked, setLocalChecked] =
|
|
12444
|
+
const [localChecked, setLocalChecked] = React68__default.useState(checked);
|
|
10337
12445
|
const handleChange = (e) => {
|
|
10338
12446
|
setLocalChecked(e.target.checked);
|
|
10339
12447
|
if (onChange) {
|
|
@@ -10763,7 +12871,7 @@ function SuspenseConfigProvider({
|
|
|
10763
12871
|
config,
|
|
10764
12872
|
children
|
|
10765
12873
|
}) {
|
|
10766
|
-
return
|
|
12874
|
+
return React68__default.createElement(
|
|
10767
12875
|
SuspenseConfigContext.Provider,
|
|
10768
12876
|
{ value: config },
|
|
10769
12877
|
children
|
|
@@ -11248,4 +13356,4 @@ function UISlotRenderer({
|
|
|
11248
13356
|
}
|
|
11249
13357
|
UISlotRenderer.displayName = "UISlotRenderer";
|
|
11250
13358
|
|
|
11251
|
-
export { Accordion, ActionButtons, Alert, Avatar, Badge, Box, Breadcrumb, Button, ButtonGroup, CalendarGrid, Card, Card2, CardBody, CardContent, CardFooter, CardGrid, CardHeader, CardTitle, Center, ChartLegend, Checkbox, CodeBlock, ConditionalWrapper, Container, ControlButton, DPad, DataGrid, DataList, DataTable, DateRangeSelector, DayCell, DetailPanel, Divider, Drawer, EmptyState, EntityDisplayEvents, ErrorBoundary, ErrorState, FilterGroup, Flex, FlipCard, FlipContainer, FloatingActionButton, Form, FormField, FormSectionHeader, GraphView, Grid, HStack, Heading, HealthBar, Icon, Input, InputGroup, Label, LawReferenceTooltip, LineChart, LoadingState, MapView, MarkdownContent, MasterDetail, Menu, Modal, Overlay, PageHeader, Pagination, Popover, ProgressBar, ProgressDots, QuizBlock, Radio, RelationSelect, RepeatableFormSection, ScaledDiagram, ScoreDisplay, SearchInput, Select, SidePanel, SimpleGrid, Skeleton, SlotContentRenderer, Spacer, Spinner, Sprite, Stack, StatBadge, StatCard, StateIndicator, SuspenseConfigProvider, Switch, Tabs, Text, TextHighlight, Textarea, ThemeSelector, ThemeToggle, TimeSlotCell, Toast, Tooltip, Typography, UISlotComponent, UISlotRenderer, VStack, ViolationAlert, WizardNavigation, WizardProgress, drawSprite };
|
|
13359
|
+
export { Accordion, ActionButtons, Alert, AnimatedCounter, Avatar, Badge, Box, Breadcrumb, Button, ButtonGroup, CalendarGrid, Card, Card2, CardBody, CardContent, CardFooter, CardGrid, CardHeader, CardTitle, Carousel, Center, ChartLegend, Checkbox, CodeBlock, ConditionalWrapper, ConfettiEffect, Container, ControlButton, DPad, DataGrid, DataList, DataTable, DateRangeSelector, DayCell, DetailPanel, Divider, Drawer, EmptyState, EntityDisplayEvents, ErrorBoundary, ErrorState, FilterGroup, Flex, FlipCard, FlipContainer, FloatingActionButton, Form, FormField, FormSectionHeader, GraphView, Grid, HStack, Heading, HealthBar, Icon, InfiniteScrollSentinel, Input, InputGroup, Label, LawReferenceTooltip, Lightbox, LineChart, LoadingState, MapView, MarkdownContent, MasterDetail, Menu, Modal, NumberStepper, Overlay, PageHeader, Pagination, Popover, ProgressBar, ProgressDots, PullToRefresh, QuizBlock, Radio, RangeSlider, RelationSelect, RepeatableFormSection, ScaledDiagram, ScoreDisplay, SearchInput, Select, SidePanel, SimpleGrid, Skeleton, SlotContentRenderer, SortableList, Spacer, Spinner, Sprite, Stack, StarRating, StatBadge, StatCard, StateIndicator, StatusDot, SuspenseConfigProvider, SwipeableRow, Switch, Tabs, Text, TextHighlight, Textarea, ThemeSelector, ThemeToggle, TimeSlotCell, Toast, Tooltip, TrendIndicator, TypewriterText, Typography, UISlotComponent, UISlotRenderer, UploadDropZone, VStack, ViolationAlert, WizardNavigation, WizardProgress, drawSprite };
|