@bmsuisse/ui 0.12.0 → 0.15.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/index.d.ts +147 -1
- package/dist/index.js +398 -197
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -219,7 +219,7 @@ DialogDescription.displayName = "DialogDescription";
|
|
|
219
219
|
var DialogFooter = ({
|
|
220
220
|
className,
|
|
221
221
|
...props
|
|
222
|
-
}) => /* @__PURE__ */ jsx7("div", { className: cn("flex justify-end gap-2", className), ...props });
|
|
222
|
+
}) => /* @__PURE__ */ jsx7("div", { className: cn("mt-4 flex justify-end gap-2", className), ...props });
|
|
223
223
|
|
|
224
224
|
// src/primitives/popover.tsx
|
|
225
225
|
import * as PopoverPrimitive from "@radix-ui/react-popover";
|
|
@@ -802,8 +802,42 @@ var Modal = ({
|
|
|
802
802
|
] }) });
|
|
803
803
|
|
|
804
804
|
// src/patterns/modal/ConfirmDialog.tsx
|
|
805
|
-
import { useState as
|
|
806
|
-
|
|
805
|
+
import { useState as useState3 } from "react";
|
|
806
|
+
|
|
807
|
+
// src/patterns/modal/DialogActions.tsx
|
|
808
|
+
import { Fragment, useState as useState2 } from "react";
|
|
809
|
+
|
|
810
|
+
// src/lib/platform.ts
|
|
811
|
+
function isWindowsPlatform() {
|
|
812
|
+
if (typeof navigator === "undefined") return false;
|
|
813
|
+
return /Windows/i.test(navigator.userAgent);
|
|
814
|
+
}
|
|
815
|
+
function getConfirmButtonPlacement() {
|
|
816
|
+
return isWindowsPlatform() ? "leading" : "trailing";
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
// src/patterns/modal/DialogActions.tsx
|
|
820
|
+
import { Fragment as Fragment2, jsx as jsx21, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
821
|
+
function DialogActions({ actions, cancel }) {
|
|
822
|
+
const [placement] = useState2(getConfirmButtonPlacement);
|
|
823
|
+
const cancelLeading = placement === "trailing";
|
|
824
|
+
const ordered = cancelLeading ? actions : [...actions].reverse();
|
|
825
|
+
const renderedActions = ordered.map((action, index) => /* @__PURE__ */ jsx21(Fragment, { children: action }, actionKey(action, index)));
|
|
826
|
+
return cancelLeading ? /* @__PURE__ */ jsxs7(Fragment2, { children: [
|
|
827
|
+
cancel,
|
|
828
|
+
renderedActions
|
|
829
|
+
] }) : /* @__PURE__ */ jsxs7(Fragment2, { children: [
|
|
830
|
+
renderedActions,
|
|
831
|
+
cancel
|
|
832
|
+
] });
|
|
833
|
+
}
|
|
834
|
+
function actionKey(action, index) {
|
|
835
|
+
if (action && typeof action === "object" && "key" in action && action.key !== null) return action.key;
|
|
836
|
+
return index;
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
// src/patterns/modal/ConfirmDialog.tsx
|
|
840
|
+
import { jsx as jsx22 } from "react/jsx-runtime";
|
|
807
841
|
var ConfirmDialog = ({
|
|
808
842
|
open,
|
|
809
843
|
onOpenChange,
|
|
@@ -816,7 +850,7 @@ var ConfirmDialog = ({
|
|
|
816
850
|
confirmTestId,
|
|
817
851
|
cancelTestId
|
|
818
852
|
}) => {
|
|
819
|
-
const [pending, setPending] =
|
|
853
|
+
const [pending, setPending] = useState3(false);
|
|
820
854
|
const handleCancel = () => {
|
|
821
855
|
onOpenChange(false);
|
|
822
856
|
};
|
|
@@ -831,34 +865,33 @@ var ConfirmDialog = ({
|
|
|
831
865
|
setPending(false);
|
|
832
866
|
}
|
|
833
867
|
};
|
|
834
|
-
|
|
868
|
+
const cancelButton = /* @__PURE__ */ jsx22(Button, { variant: "outline", onClick: handleCancel, disabled: pending, "data-testid": cancelTestId, children: cancelLabel });
|
|
869
|
+
const confirmButton = /* @__PURE__ */ jsx22(
|
|
870
|
+
Button,
|
|
871
|
+
{
|
|
872
|
+
variant: variant === "destructive" ? "destructive" : "default",
|
|
873
|
+
onClick: handleConfirm,
|
|
874
|
+
disabled: pending,
|
|
875
|
+
"data-testid": confirmTestId,
|
|
876
|
+
children: pending ? `${confirmLabel}\u2026` : confirmLabel
|
|
877
|
+
}
|
|
878
|
+
);
|
|
879
|
+
return /* @__PURE__ */ jsx22(
|
|
835
880
|
Modal,
|
|
836
881
|
{
|
|
837
882
|
open,
|
|
838
883
|
onOpenChange,
|
|
839
884
|
title,
|
|
840
885
|
description,
|
|
841
|
-
footer: /* @__PURE__ */
|
|
842
|
-
/* @__PURE__ */ jsx21(Button, { variant: "outline", onClick: handleCancel, disabled: pending, "data-testid": cancelTestId, children: cancelLabel }),
|
|
843
|
-
/* @__PURE__ */ jsx21(
|
|
844
|
-
Button,
|
|
845
|
-
{
|
|
846
|
-
variant: variant === "destructive" ? "destructive" : "default",
|
|
847
|
-
onClick: handleConfirm,
|
|
848
|
-
disabled: pending,
|
|
849
|
-
"data-testid": confirmTestId,
|
|
850
|
-
children: pending ? `${confirmLabel}\u2026` : confirmLabel
|
|
851
|
-
}
|
|
852
|
-
)
|
|
853
|
-
] }),
|
|
886
|
+
footer: /* @__PURE__ */ jsx22(DialogActions, { actions: [confirmButton], cancel: cancelButton }),
|
|
854
887
|
children: null
|
|
855
888
|
}
|
|
856
889
|
);
|
|
857
890
|
};
|
|
858
891
|
|
|
859
892
|
// src/patterns/modal/FormModal.tsx
|
|
860
|
-
import { useState as
|
|
861
|
-
import { jsx as
|
|
893
|
+
import { useState as useState4 } from "react";
|
|
894
|
+
import { jsx as jsx23, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
862
895
|
var FormModal = ({
|
|
863
896
|
open,
|
|
864
897
|
onOpenChange,
|
|
@@ -873,7 +906,7 @@ var FormModal = ({
|
|
|
873
906
|
submitTestId,
|
|
874
907
|
cancelTestId
|
|
875
908
|
}) => {
|
|
876
|
-
const [pending, setPending] =
|
|
909
|
+
const [pending, setPending] = useState4(false);
|
|
877
910
|
const handleSubmit = async (event) => {
|
|
878
911
|
event.preventDefault();
|
|
879
912
|
setPending(true);
|
|
@@ -886,14 +919,14 @@ var FormModal = ({
|
|
|
886
919
|
const handleCancel = () => {
|
|
887
920
|
onOpenChange(false);
|
|
888
921
|
};
|
|
889
|
-
return /* @__PURE__ */
|
|
922
|
+
return /* @__PURE__ */ jsx23(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsx23(DialogContent, { className, children: /* @__PURE__ */ jsxs8("form", { onSubmit: handleSubmit, children: [
|
|
890
923
|
/* @__PURE__ */ jsxs8(DialogHeader, { children: [
|
|
891
|
-
/* @__PURE__ */
|
|
892
|
-
description ? /* @__PURE__ */
|
|
924
|
+
/* @__PURE__ */ jsx23(DialogTitle, { children: title }),
|
|
925
|
+
description ? /* @__PURE__ */ jsx23(DialogDescription, { children: description }) : null
|
|
893
926
|
] }),
|
|
894
927
|
children,
|
|
895
928
|
/* @__PURE__ */ jsxs8(DialogFooter, { children: [
|
|
896
|
-
/* @__PURE__ */
|
|
929
|
+
/* @__PURE__ */ jsx23(
|
|
897
930
|
Button,
|
|
898
931
|
{
|
|
899
932
|
type: "button",
|
|
@@ -904,18 +937,18 @@ var FormModal = ({
|
|
|
904
937
|
children: cancelLabel
|
|
905
938
|
}
|
|
906
939
|
),
|
|
907
|
-
/* @__PURE__ */
|
|
940
|
+
/* @__PURE__ */ jsx23(Button, { type: "submit", disabled: pending || submitDisabled, "data-testid": submitTestId, children: pending ? `${submitLabel}\u2026` : submitLabel })
|
|
908
941
|
] })
|
|
909
942
|
] }) }) });
|
|
910
943
|
};
|
|
911
944
|
|
|
912
945
|
// src/patterns/modal/ResponsivePanel.tsx
|
|
913
|
-
import { useRef as useRef2, useState as
|
|
946
|
+
import { useRef as useRef2, useState as useState6 } from "react";
|
|
914
947
|
|
|
915
948
|
// src/lib/useMediaQuery.ts
|
|
916
|
-
import { useEffect as useEffect2, useState as
|
|
949
|
+
import { useEffect as useEffect2, useState as useState5 } from "react";
|
|
917
950
|
function useMediaQuery(query) {
|
|
918
|
-
const [matches, setMatches] =
|
|
951
|
+
const [matches, setMatches] = useState5(
|
|
919
952
|
() => typeof window !== "undefined" ? window.matchMedia(query).matches : false
|
|
920
953
|
);
|
|
921
954
|
useEffect2(() => {
|
|
@@ -929,7 +962,7 @@ function useMediaQuery(query) {
|
|
|
929
962
|
}
|
|
930
963
|
|
|
931
964
|
// src/patterns/modal/ResponsivePanel.tsx
|
|
932
|
-
import { jsx as
|
|
965
|
+
import { jsx as jsx24, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
933
966
|
var desktopSizeClasses = {
|
|
934
967
|
sm: "max-w-md",
|
|
935
968
|
md: "max-w-xl",
|
|
@@ -964,8 +997,8 @@ var cornerGripPosition = {
|
|
|
964
997
|
"bottom-right": "right-1 bottom-1 border-r-2 border-b-2"
|
|
965
998
|
};
|
|
966
999
|
function useDesktopPanelGeometry() {
|
|
967
|
-
const [style, setStyle] =
|
|
968
|
-
const [isDragging, setIsDragging] =
|
|
1000
|
+
const [style, setStyle] = useState6(void 0);
|
|
1001
|
+
const [isDragging, setIsDragging] = useState6(false);
|
|
969
1002
|
const drag = useRef2(null);
|
|
970
1003
|
const lastRect = useRef2(null);
|
|
971
1004
|
const beginDrag = (mode, corner) => (e) => {
|
|
@@ -1055,7 +1088,7 @@ var ResponsivePanel = ({
|
|
|
1055
1088
|
const onInteractOutside = closeOnOutsideClick ? void 0 : (e) => e.preventDefault();
|
|
1056
1089
|
if (isDesktop) {
|
|
1057
1090
|
const corners = ["top-left", "top-right", "bottom-left", "bottom-right"];
|
|
1058
|
-
return /* @__PURE__ */
|
|
1091
|
+
return /* @__PURE__ */ jsx24(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs9(
|
|
1059
1092
|
DialogContent,
|
|
1060
1093
|
{
|
|
1061
1094
|
"data-slot": "dialog-content",
|
|
@@ -1068,7 +1101,7 @@ var ResponsivePanel = ({
|
|
|
1068
1101
|
className
|
|
1069
1102
|
),
|
|
1070
1103
|
children: [
|
|
1071
|
-
resizable && corners.map((corner) => /* @__PURE__ */
|
|
1104
|
+
resizable && corners.map((corner) => /* @__PURE__ */ jsx24(
|
|
1072
1105
|
"div",
|
|
1073
1106
|
{
|
|
1074
1107
|
"data-testid": `panel-resize-handle-${corner}`,
|
|
@@ -1081,7 +1114,7 @@ var ResponsivePanel = ({
|
|
|
1081
1114
|
onPointerMove: geometry.onPointerMove,
|
|
1082
1115
|
onPointerUp: geometry.onPointerUp,
|
|
1083
1116
|
onPointerCancel: geometry.onPointerUp,
|
|
1084
|
-
children: /* @__PURE__ */
|
|
1117
|
+
children: /* @__PURE__ */ jsx24(
|
|
1085
1118
|
"div",
|
|
1086
1119
|
{
|
|
1087
1120
|
className: cn(
|
|
@@ -1102,18 +1135,18 @@ var ResponsivePanel = ({
|
|
|
1102
1135
|
onPointerUp: draggable ? geometry.onPointerUp : void 0,
|
|
1103
1136
|
onPointerCancel: draggable ? geometry.onPointerUp : void 0,
|
|
1104
1137
|
children: [
|
|
1105
|
-
/* @__PURE__ */
|
|
1106
|
-
description ? /* @__PURE__ */
|
|
1138
|
+
/* @__PURE__ */ jsx24(DialogTitle, { children: title }),
|
|
1139
|
+
description ? /* @__PURE__ */ jsx24(DialogDescription, { children: description }) : null
|
|
1107
1140
|
]
|
|
1108
1141
|
}
|
|
1109
1142
|
),
|
|
1110
1143
|
children,
|
|
1111
|
-
footer ? /* @__PURE__ */
|
|
1144
|
+
footer ? /* @__PURE__ */ jsx24(DialogFooter, { children: footer }) : null
|
|
1112
1145
|
]
|
|
1113
1146
|
}
|
|
1114
1147
|
) });
|
|
1115
1148
|
}
|
|
1116
|
-
return /* @__PURE__ */
|
|
1149
|
+
return /* @__PURE__ */ jsx24(Sheet, { open, onOpenChange, children: /* @__PURE__ */ jsxs9(
|
|
1117
1150
|
SheetContent,
|
|
1118
1151
|
{
|
|
1119
1152
|
side: "bottom",
|
|
@@ -1126,19 +1159,76 @@ var ResponsivePanel = ({
|
|
|
1126
1159
|
),
|
|
1127
1160
|
children: [
|
|
1128
1161
|
/* @__PURE__ */ jsxs9(SheetHeader, { children: [
|
|
1129
|
-
/* @__PURE__ */
|
|
1130
|
-
description ? /* @__PURE__ */
|
|
1162
|
+
/* @__PURE__ */ jsx24(SheetTitle, { children: title }),
|
|
1163
|
+
description ? /* @__PURE__ */ jsx24(SheetDescription, { children: description }) : null
|
|
1131
1164
|
] }),
|
|
1132
1165
|
children,
|
|
1133
|
-
footer ? /* @__PURE__ */
|
|
1166
|
+
footer ? /* @__PURE__ */ jsx24(SheetFooter, { children: footer }) : null
|
|
1134
1167
|
]
|
|
1135
1168
|
}
|
|
1136
1169
|
) });
|
|
1137
1170
|
};
|
|
1138
1171
|
|
|
1172
|
+
// src/patterns/modal/QuestionDialog.tsx
|
|
1173
|
+
import { useState as useState7 } from "react";
|
|
1174
|
+
import { jsx as jsx25 } from "react/jsx-runtime";
|
|
1175
|
+
var QuestionDialog = ({
|
|
1176
|
+
open,
|
|
1177
|
+
onOpenChange,
|
|
1178
|
+
title,
|
|
1179
|
+
description,
|
|
1180
|
+
actions,
|
|
1181
|
+
cancelLabel = "Cancel",
|
|
1182
|
+
cancelTestId
|
|
1183
|
+
}) => {
|
|
1184
|
+
const [pendingIndex, setPendingIndex] = useState7(null);
|
|
1185
|
+
const pending = pendingIndex !== null;
|
|
1186
|
+
const handleCancel = () => {
|
|
1187
|
+
onOpenChange(false);
|
|
1188
|
+
};
|
|
1189
|
+
const handleActionClick = async (action, index) => {
|
|
1190
|
+
setPendingIndex(index);
|
|
1191
|
+
try {
|
|
1192
|
+
await action.onClick();
|
|
1193
|
+
onOpenChange(false);
|
|
1194
|
+
} catch (error) {
|
|
1195
|
+
console.error(error);
|
|
1196
|
+
} finally {
|
|
1197
|
+
setPendingIndex(null);
|
|
1198
|
+
}
|
|
1199
|
+
};
|
|
1200
|
+
return /* @__PURE__ */ jsx25(
|
|
1201
|
+
Modal,
|
|
1202
|
+
{
|
|
1203
|
+
open,
|
|
1204
|
+
onOpenChange,
|
|
1205
|
+
title,
|
|
1206
|
+
description,
|
|
1207
|
+
footer: /* @__PURE__ */ jsx25(
|
|
1208
|
+
DialogActions,
|
|
1209
|
+
{
|
|
1210
|
+
actions: actions.map((action, index) => /* @__PURE__ */ jsx25(
|
|
1211
|
+
Button,
|
|
1212
|
+
{
|
|
1213
|
+
variant: action.variant ?? "default",
|
|
1214
|
+
onClick: () => handleActionClick(action, index),
|
|
1215
|
+
disabled: pending,
|
|
1216
|
+
"data-testid": action.testId,
|
|
1217
|
+
children: pendingIndex === index ? `${action.label}\u2026` : action.label
|
|
1218
|
+
},
|
|
1219
|
+
action.label
|
|
1220
|
+
)),
|
|
1221
|
+
cancel: /* @__PURE__ */ jsx25(Button, { variant: "outline", onClick: handleCancel, disabled: pending, "data-testid": cancelTestId, children: cancelLabel })
|
|
1222
|
+
}
|
|
1223
|
+
),
|
|
1224
|
+
children: null
|
|
1225
|
+
}
|
|
1226
|
+
);
|
|
1227
|
+
};
|
|
1228
|
+
|
|
1139
1229
|
// src/patterns/form-field/FormField.tsx
|
|
1140
1230
|
import { cloneElement, isValidElement, useId } from "react";
|
|
1141
|
-
import { jsx as
|
|
1231
|
+
import { jsx as jsx26, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1142
1232
|
function FormField({
|
|
1143
1233
|
label,
|
|
1144
1234
|
htmlFor,
|
|
@@ -1172,13 +1262,13 @@ function FormField({
|
|
|
1172
1262
|
] }) : null
|
|
1173
1263
|
] }),
|
|
1174
1264
|
child,
|
|
1175
|
-
error ? /* @__PURE__ */
|
|
1265
|
+
error ? /* @__PURE__ */ jsx26("p", { id: messageId, className: "text-sm text-destructive", children: error }) : description ? /* @__PURE__ */ jsx26("p", { id: messageId, className: "text-sm text-muted-foreground", children: description }) : null
|
|
1176
1266
|
] });
|
|
1177
1267
|
}
|
|
1178
1268
|
|
|
1179
1269
|
// src/patterns/combobox/Combobox.tsx
|
|
1180
1270
|
import { Check as Check4, ChevronsUpDown, X as X3 } from "lucide-react";
|
|
1181
|
-
import { useEffect as useEffect3, useMemo, useRef as useRef3, useState as
|
|
1271
|
+
import { useEffect as useEffect3, useMemo, useRef as useRef3, useState as useState8 } from "react";
|
|
1182
1272
|
|
|
1183
1273
|
// src/lib/optionGrouping.ts
|
|
1184
1274
|
function groupMembers(options, group) {
|
|
@@ -1207,7 +1297,7 @@ function buildRenderChunks(visibleOptions) {
|
|
|
1207
1297
|
}
|
|
1208
1298
|
|
|
1209
1299
|
// src/lib/optionGrid.tsx
|
|
1210
|
-
import { jsx as
|
|
1300
|
+
import { jsx as jsx27, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1211
1301
|
function renderGridOptions({
|
|
1212
1302
|
columns,
|
|
1213
1303
|
options,
|
|
@@ -1219,9 +1309,9 @@ function renderGridOptions({
|
|
|
1219
1309
|
testId
|
|
1220
1310
|
}) {
|
|
1221
1311
|
return /* @__PURE__ */ jsxs11(Table, { className: "text-sm", children: [
|
|
1222
|
-
/* @__PURE__ */
|
|
1223
|
-
multiple && /* @__PURE__ */
|
|
1224
|
-
columns.map((column) => /* @__PURE__ */
|
|
1312
|
+
/* @__PURE__ */ jsx27(TableHeader, { children: /* @__PURE__ */ jsxs11(TableRow, { className: "hover:bg-transparent", children: [
|
|
1313
|
+
multiple && /* @__PURE__ */ jsx27(TableHead, { className: "sticky top-0 z-10 w-6 bg-muted" }),
|
|
1314
|
+
columns.map((column) => /* @__PURE__ */ jsx27(
|
|
1225
1315
|
TableHead,
|
|
1226
1316
|
{
|
|
1227
1317
|
className: cn("sticky top-0 z-10 whitespace-nowrap bg-muted text-xs", column.className),
|
|
@@ -1230,7 +1320,7 @@ function renderGridOptions({
|
|
|
1230
1320
|
column.key
|
|
1231
1321
|
))
|
|
1232
1322
|
] }) }),
|
|
1233
|
-
/* @__PURE__ */
|
|
1323
|
+
/* @__PURE__ */ jsx27(TableBody, { children: options.map((option, index) => {
|
|
1234
1324
|
const selected = isSelected(option);
|
|
1235
1325
|
const active = index === activeIndex;
|
|
1236
1326
|
return /* @__PURE__ */ jsxs11(
|
|
@@ -1257,7 +1347,7 @@ function renderGridOptions({
|
|
|
1257
1347
|
option.disabled && "pointer-events-none opacity-50"
|
|
1258
1348
|
),
|
|
1259
1349
|
children: [
|
|
1260
|
-
multiple && /* @__PURE__ */
|
|
1350
|
+
multiple && /* @__PURE__ */ jsx27(TableCell, { className: "w-6", children: /* @__PURE__ */ jsx27(
|
|
1261
1351
|
"input",
|
|
1262
1352
|
{
|
|
1263
1353
|
type: "checkbox",
|
|
@@ -1267,7 +1357,7 @@ function renderGridOptions({
|
|
|
1267
1357
|
className: "pointer-events-none h-3.5 w-3.5 shrink-0 accent-primary"
|
|
1268
1358
|
}
|
|
1269
1359
|
) }),
|
|
1270
|
-
columns.map((column) => /* @__PURE__ */
|
|
1360
|
+
columns.map((column) => /* @__PURE__ */ jsx27(TableCell, { className: cn("truncate", column.className), children: column.key === "label" ? option.label : option.data?.[column.key] }, column.key))
|
|
1271
1361
|
]
|
|
1272
1362
|
},
|
|
1273
1363
|
option.value
|
|
@@ -1277,7 +1367,7 @@ function renderGridOptions({
|
|
|
1277
1367
|
}
|
|
1278
1368
|
|
|
1279
1369
|
// src/patterns/combobox/Combobox.tsx
|
|
1280
|
-
import { jsx as
|
|
1370
|
+
import { jsx as jsx28, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1281
1371
|
function resolveGroupTriggerLabel(options, selectedValues, groupLabel) {
|
|
1282
1372
|
const selectedSet = new Set(selectedValues);
|
|
1283
1373
|
const groupsPresent = Array.from(
|
|
@@ -1316,9 +1406,9 @@ function Combobox(props) {
|
|
|
1316
1406
|
columns
|
|
1317
1407
|
} = props;
|
|
1318
1408
|
const testId = props["data-testid"];
|
|
1319
|
-
const [open, setOpen] =
|
|
1320
|
-
const [search, setSearch] =
|
|
1321
|
-
const [activeIndex, setActiveIndex] =
|
|
1409
|
+
const [open, setOpen] = useState8(false);
|
|
1410
|
+
const [search, setSearch] = useState8("");
|
|
1411
|
+
const [activeIndex, setActiveIndex] = useState8(0);
|
|
1322
1412
|
const inputRef = useRef3(null);
|
|
1323
1413
|
const selectedValues = useMemo(
|
|
1324
1414
|
() => props.multiple ? props.value : props.value ? [props.value] : [],
|
|
@@ -1397,7 +1487,7 @@ function Combobox(props) {
|
|
|
1397
1487
|
isActive && "bg-accent text-accent-foreground"
|
|
1398
1488
|
),
|
|
1399
1489
|
children: [
|
|
1400
|
-
props.multiple ? /* @__PURE__ */
|
|
1490
|
+
props.multiple ? /* @__PURE__ */ jsx28(
|
|
1401
1491
|
"input",
|
|
1402
1492
|
{
|
|
1403
1493
|
type: "checkbox",
|
|
@@ -1406,15 +1496,15 @@ function Combobox(props) {
|
|
|
1406
1496
|
tabIndex: -1,
|
|
1407
1497
|
className: "pointer-events-none h-3.5 w-3.5 shrink-0 accent-primary"
|
|
1408
1498
|
}
|
|
1409
|
-
) : /* @__PURE__ */
|
|
1410
|
-
/* @__PURE__ */
|
|
1499
|
+
) : /* @__PURE__ */ jsx28(Check4, { className: cn("h-4 w-4 shrink-0", isSelected ? "opacity-100" : "opacity-0") }),
|
|
1500
|
+
/* @__PURE__ */ jsx28("span", { className: "truncate", children: option.label })
|
|
1411
1501
|
]
|
|
1412
1502
|
},
|
|
1413
1503
|
option.value
|
|
1414
1504
|
);
|
|
1415
1505
|
}
|
|
1416
1506
|
return /* @__PURE__ */ jsxs12(Popover, { open, onOpenChange: setOpen, children: [
|
|
1417
|
-
/* @__PURE__ */
|
|
1507
|
+
/* @__PURE__ */ jsx28(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs12(
|
|
1418
1508
|
Button,
|
|
1419
1509
|
{
|
|
1420
1510
|
id,
|
|
@@ -1430,9 +1520,9 @@ function Combobox(props) {
|
|
|
1430
1520
|
className
|
|
1431
1521
|
),
|
|
1432
1522
|
children: [
|
|
1433
|
-
/* @__PURE__ */
|
|
1523
|
+
/* @__PURE__ */ jsx28("span", { className: "truncate", children: triggerLabel }),
|
|
1434
1524
|
/* @__PURE__ */ jsxs12("span", { className: "flex items-center gap-1", children: [
|
|
1435
|
-
clearable && !loading && selectedValues.length > 0 ? /* @__PURE__ */
|
|
1525
|
+
clearable && !loading && selectedValues.length > 0 ? /* @__PURE__ */ jsx28(
|
|
1436
1526
|
"span",
|
|
1437
1527
|
{
|
|
1438
1528
|
role: "button",
|
|
@@ -1447,15 +1537,15 @@ function Combobox(props) {
|
|
|
1447
1537
|
props.onChange(null);
|
|
1448
1538
|
}
|
|
1449
1539
|
},
|
|
1450
|
-
children: /* @__PURE__ */
|
|
1540
|
+
children: /* @__PURE__ */ jsx28(X3, { className: "h-3.5 w-3.5" })
|
|
1451
1541
|
}
|
|
1452
1542
|
) : null,
|
|
1453
|
-
/* @__PURE__ */
|
|
1543
|
+
/* @__PURE__ */ jsx28(ChevronsUpDown, { className: "h-4 w-4 shrink-0 opacity-50", "aria-hidden": "true" })
|
|
1454
1544
|
] })
|
|
1455
1545
|
]
|
|
1456
1546
|
}
|
|
1457
1547
|
) }),
|
|
1458
|
-
/* @__PURE__ */
|
|
1548
|
+
/* @__PURE__ */ jsx28(
|
|
1459
1549
|
PopoverContent,
|
|
1460
1550
|
{
|
|
1461
1551
|
align: "start",
|
|
@@ -1466,7 +1556,7 @@ function Combobox(props) {
|
|
|
1466
1556
|
),
|
|
1467
1557
|
onOpenAutoFocus: (event) => event.preventDefault(),
|
|
1468
1558
|
children: /* @__PURE__ */ jsxs12("div", { className: "flex flex-col gap-2", children: [
|
|
1469
|
-
/* @__PURE__ */
|
|
1559
|
+
/* @__PURE__ */ jsx28(
|
|
1470
1560
|
Input,
|
|
1471
1561
|
{
|
|
1472
1562
|
ref: inputRef,
|
|
@@ -1480,7 +1570,7 @@ function Combobox(props) {
|
|
|
1480
1570
|
"aria-label": searchPlaceholder
|
|
1481
1571
|
}
|
|
1482
1572
|
),
|
|
1483
|
-
/* @__PURE__ */
|
|
1573
|
+
/* @__PURE__ */ jsx28("div", { role: "listbox", className: cn("max-h-60 overflow-y-auto", !columns && "flex flex-col gap-0.5"), children: visibleOptions.length === 0 ? /* @__PURE__ */ jsx28("p", { className: "py-2 text-center text-sm text-muted-foreground", children: emptyMessage }) : columns ? renderGridOptions({
|
|
1484
1574
|
columns,
|
|
1485
1575
|
options: visibleOptions,
|
|
1486
1576
|
activeIndex,
|
|
@@ -1507,7 +1597,7 @@ function Combobox(props) {
|
|
|
1507
1597
|
"data-group-header": true,
|
|
1508
1598
|
className: "sticky top-0 z-10 flex items-center gap-2 rounded-sm bg-muted px-2 py-1.5 text-sm font-semibold text-foreground",
|
|
1509
1599
|
children: [
|
|
1510
|
-
props.multiple ? /* @__PURE__ */
|
|
1600
|
+
props.multiple ? /* @__PURE__ */ jsx28(
|
|
1511
1601
|
"input",
|
|
1512
1602
|
{
|
|
1513
1603
|
type: "checkbox",
|
|
@@ -1521,7 +1611,7 @@ function Combobox(props) {
|
|
|
1521
1611
|
"aria-label": `Select all of ${groupLabel(chunk.group)}`
|
|
1522
1612
|
}
|
|
1523
1613
|
) : null,
|
|
1524
|
-
/* @__PURE__ */
|
|
1614
|
+
/* @__PURE__ */ jsx28("span", { className: "truncate", children: groupLabel(chunk.group) })
|
|
1525
1615
|
]
|
|
1526
1616
|
}
|
|
1527
1617
|
),
|
|
@@ -1537,8 +1627,8 @@ function Combobox(props) {
|
|
|
1537
1627
|
|
|
1538
1628
|
// src/patterns/tag-combobox/TagCombobox.tsx
|
|
1539
1629
|
import { X as X4 } from "lucide-react";
|
|
1540
|
-
import { useEffect as useEffect4, useMemo as useMemo2, useRef as useRef4, useState as
|
|
1541
|
-
import { jsx as
|
|
1630
|
+
import { useEffect as useEffect4, useMemo as useMemo2, useRef as useRef4, useState as useState9 } from "react";
|
|
1631
|
+
import { jsx as jsx29, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1542
1632
|
function TagCombobox({
|
|
1543
1633
|
options,
|
|
1544
1634
|
value,
|
|
@@ -1557,9 +1647,9 @@ function TagCombobox({
|
|
|
1557
1647
|
...rest
|
|
1558
1648
|
}) {
|
|
1559
1649
|
const testId = rest["data-testid"];
|
|
1560
|
-
const [open, setOpen] =
|
|
1561
|
-
const [search, setSearch] =
|
|
1562
|
-
const [activeIndex, setActiveIndex] =
|
|
1650
|
+
const [open, setOpen] = useState9(false);
|
|
1651
|
+
const [search, setSearch] = useState9("");
|
|
1652
|
+
const [activeIndex, setActiveIndex] = useState9(0);
|
|
1563
1653
|
const inputRef = useRef4(null);
|
|
1564
1654
|
const fieldRef = useRef4(null);
|
|
1565
1655
|
const selectedOptions = useMemo2(
|
|
@@ -1645,7 +1735,7 @@ function TagCombobox({
|
|
|
1645
1735
|
isActive && "bg-accent text-accent-foreground"
|
|
1646
1736
|
),
|
|
1647
1737
|
children: [
|
|
1648
|
-
/* @__PURE__ */
|
|
1738
|
+
/* @__PURE__ */ jsx29(
|
|
1649
1739
|
"input",
|
|
1650
1740
|
{
|
|
1651
1741
|
type: "checkbox",
|
|
@@ -1655,14 +1745,14 @@ function TagCombobox({
|
|
|
1655
1745
|
className: "pointer-events-none h-3.5 w-3.5 shrink-0 accent-primary"
|
|
1656
1746
|
}
|
|
1657
1747
|
),
|
|
1658
|
-
/* @__PURE__ */
|
|
1748
|
+
/* @__PURE__ */ jsx29("span", { className: "truncate", children: option.label })
|
|
1659
1749
|
]
|
|
1660
1750
|
},
|
|
1661
1751
|
option.value
|
|
1662
1752
|
);
|
|
1663
1753
|
}
|
|
1664
1754
|
return /* @__PURE__ */ jsxs13(Popover, { open, onOpenChange: setOpen, children: [
|
|
1665
|
-
/* @__PURE__ */
|
|
1755
|
+
/* @__PURE__ */ jsx29(PopoverAnchor, { asChild: true, children: /* @__PURE__ */ jsxs13(
|
|
1666
1756
|
"div",
|
|
1667
1757
|
{
|
|
1668
1758
|
ref: fieldRef,
|
|
@@ -1685,8 +1775,8 @@ function TagCombobox({
|
|
|
1685
1775
|
{
|
|
1686
1776
|
className: "inline-flex items-center gap-1 rounded-full bg-muted py-0.5 pr-1 pl-2.5 text-xs font-medium text-muted-foreground",
|
|
1687
1777
|
children: [
|
|
1688
|
-
/* @__PURE__ */
|
|
1689
|
-
!disabled && /* @__PURE__ */
|
|
1778
|
+
/* @__PURE__ */ jsx29("span", { className: "max-w-48 truncate", children: option.label }),
|
|
1779
|
+
!disabled && /* @__PURE__ */ jsx29(
|
|
1690
1780
|
"button",
|
|
1691
1781
|
{
|
|
1692
1782
|
type: "button",
|
|
@@ -1696,14 +1786,14 @@ function TagCombobox({
|
|
|
1696
1786
|
event.stopPropagation();
|
|
1697
1787
|
removeValue(option.value);
|
|
1698
1788
|
},
|
|
1699
|
-
children: /* @__PURE__ */
|
|
1789
|
+
children: /* @__PURE__ */ jsx29(X4, { className: "h-3 w-3" })
|
|
1700
1790
|
}
|
|
1701
1791
|
)
|
|
1702
1792
|
]
|
|
1703
1793
|
},
|
|
1704
1794
|
option.value
|
|
1705
1795
|
)),
|
|
1706
|
-
/* @__PURE__ */
|
|
1796
|
+
/* @__PURE__ */ jsx29(
|
|
1707
1797
|
"input",
|
|
1708
1798
|
{
|
|
1709
1799
|
ref: inputRef,
|
|
@@ -1721,7 +1811,7 @@ function TagCombobox({
|
|
|
1721
1811
|
]
|
|
1722
1812
|
}
|
|
1723
1813
|
) }),
|
|
1724
|
-
/* @__PURE__ */
|
|
1814
|
+
/* @__PURE__ */ jsx29(
|
|
1725
1815
|
PopoverContent,
|
|
1726
1816
|
{
|
|
1727
1817
|
align: "start",
|
|
@@ -1735,7 +1825,7 @@ function TagCombobox({
|
|
|
1735
1825
|
onInteractOutside: (event) => {
|
|
1736
1826
|
if (fieldRef.current?.contains(event.target)) event.preventDefault();
|
|
1737
1827
|
},
|
|
1738
|
-
children: /* @__PURE__ */
|
|
1828
|
+
children: /* @__PURE__ */ jsx29("div", { role: "listbox", className: cn("max-h-60 overflow-y-auto", !columns && "flex flex-col gap-0.5"), children: loading ? /* @__PURE__ */ jsx29("p", { className: "py-2 text-center text-sm text-muted-foreground", children: loadingMessage }) : visibleOptions.length === 0 ? /* @__PURE__ */ jsx29("p", { className: "py-2 text-center text-sm text-muted-foreground", children: emptyMessage }) : columns ? renderGridOptions({
|
|
1739
1829
|
columns,
|
|
1740
1830
|
options: visibleOptions,
|
|
1741
1831
|
activeIndex,
|
|
@@ -1761,7 +1851,7 @@ function TagCombobox({
|
|
|
1761
1851
|
"data-group-header": true,
|
|
1762
1852
|
className: "sticky top-0 z-10 flex items-center gap-2 rounded-sm bg-muted px-2 py-1.5 text-sm font-semibold text-foreground",
|
|
1763
1853
|
children: [
|
|
1764
|
-
/* @__PURE__ */
|
|
1854
|
+
/* @__PURE__ */ jsx29(
|
|
1765
1855
|
"input",
|
|
1766
1856
|
{
|
|
1767
1857
|
type: "checkbox",
|
|
@@ -1775,7 +1865,7 @@ function TagCombobox({
|
|
|
1775
1865
|
"aria-label": `Select all of ${groupLabel(chunk.group)}`
|
|
1776
1866
|
}
|
|
1777
1867
|
),
|
|
1778
|
-
/* @__PURE__ */
|
|
1868
|
+
/* @__PURE__ */ jsx29("span", { className: "truncate", children: groupLabel(chunk.group) })
|
|
1779
1869
|
]
|
|
1780
1870
|
}
|
|
1781
1871
|
),
|
|
@@ -1790,7 +1880,7 @@ function TagCombobox({
|
|
|
1790
1880
|
|
|
1791
1881
|
// src/patterns/alert-box/AlertBox.tsx
|
|
1792
1882
|
import { AlertCircle, AlertTriangle, CheckCircle2, Info } from "lucide-react";
|
|
1793
|
-
import { jsx as
|
|
1883
|
+
import { jsx as jsx30, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1794
1884
|
var variantStyles = {
|
|
1795
1885
|
error: "border-destructive bg-destructive/10 text-red-800 dark:text-red-300",
|
|
1796
1886
|
warning: "border-amber-500 bg-amber-500/10 text-amber-900 dark:text-amber-200",
|
|
@@ -1798,24 +1888,24 @@ var variantStyles = {
|
|
|
1798
1888
|
success: "border-emerald-500 bg-emerald-500/10 text-emerald-700 dark:text-emerald-300"
|
|
1799
1889
|
};
|
|
1800
1890
|
var defaultIcons = {
|
|
1801
|
-
error: /* @__PURE__ */
|
|
1802
|
-
warning: /* @__PURE__ */
|
|
1803
|
-
info: /* @__PURE__ */
|
|
1804
|
-
success: /* @__PURE__ */
|
|
1891
|
+
error: /* @__PURE__ */ jsx30(AlertCircle, { className: "h-4 w-4 shrink-0", "aria-hidden": "true" }),
|
|
1892
|
+
warning: /* @__PURE__ */ jsx30(AlertTriangle, { className: "h-4 w-4 shrink-0", "aria-hidden": "true" }),
|
|
1893
|
+
info: /* @__PURE__ */ jsx30(Info, { className: "h-4 w-4 shrink-0", "aria-hidden": "true" }),
|
|
1894
|
+
success: /* @__PURE__ */ jsx30(CheckCircle2, { className: "h-4 w-4 shrink-0", "aria-hidden": "true" })
|
|
1805
1895
|
};
|
|
1806
1896
|
var AlertBox = ({ variant, title, children, className, icon }) => {
|
|
1807
1897
|
const resolvedIcon = icon === void 0 ? defaultIcons[variant] : icon;
|
|
1808
|
-
return /* @__PURE__ */
|
|
1809
|
-
resolvedIcon != null && /* @__PURE__ */
|
|
1898
|
+
return /* @__PURE__ */ jsx30("div", { className: cn("rounded-md border p-3 text-sm", variantStyles[variant], className), children: /* @__PURE__ */ jsxs14("div", { className: "flex flex-row items-start gap-2", children: [
|
|
1899
|
+
resolvedIcon != null && /* @__PURE__ */ jsx30("span", { className: "mt-0.5 shrink-0", children: resolvedIcon }),
|
|
1810
1900
|
/* @__PURE__ */ jsxs14("div", { className: "flex flex-col gap-1", children: [
|
|
1811
|
-
title && /* @__PURE__ */
|
|
1812
|
-
/* @__PURE__ */
|
|
1901
|
+
title && /* @__PURE__ */ jsx30("p", { className: "font-bold", children: title }),
|
|
1902
|
+
/* @__PURE__ */ jsx30("div", { children })
|
|
1813
1903
|
] })
|
|
1814
1904
|
] }) });
|
|
1815
1905
|
};
|
|
1816
1906
|
|
|
1817
1907
|
// src/patterns/status-badge/StatusBadge.tsx
|
|
1818
|
-
import { jsx as
|
|
1908
|
+
import { jsx as jsx31 } from "react/jsx-runtime";
|
|
1819
1909
|
var TONE_CLASSES = {
|
|
1820
1910
|
success: "border-transparent bg-emerald-500/15 text-emerald-700 dark:bg-emerald-500/20 dark:text-emerald-300",
|
|
1821
1911
|
warning: "border-transparent bg-amber-500/15 text-amber-800 dark:bg-amber-500/20 dark:text-amber-300",
|
|
@@ -1862,11 +1952,11 @@ function resolveTone(status, tone, toneMap) {
|
|
|
1862
1952
|
var StatusBadge = ({ status, label, tone, toneMap, className, ...props }) => {
|
|
1863
1953
|
const resolvedTone = resolveTone(status, tone, toneMap);
|
|
1864
1954
|
const displayLabel = label ?? deriveLabel(status);
|
|
1865
|
-
return /* @__PURE__ */
|
|
1955
|
+
return /* @__PURE__ */ jsx31(Badge, { variant: "outline", className: cn(TONE_CLASSES[resolvedTone], className), ...props, children: displayLabel });
|
|
1866
1956
|
};
|
|
1867
1957
|
|
|
1868
1958
|
// src/patterns/button-group/ButtonGroup.tsx
|
|
1869
|
-
import { jsx as
|
|
1959
|
+
import { jsx as jsx32, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1870
1960
|
function ButtonGroup({
|
|
1871
1961
|
options,
|
|
1872
1962
|
value,
|
|
@@ -1876,7 +1966,7 @@ function ButtonGroup({
|
|
|
1876
1966
|
className,
|
|
1877
1967
|
...props
|
|
1878
1968
|
}) {
|
|
1879
|
-
return /* @__PURE__ */
|
|
1969
|
+
return /* @__PURE__ */ jsx32("div", { role: "group", "aria-label": props["aria-label"], className: cn("inline-flex", className), "data-testid": props["data-testid"], children: options.map((option, index) => {
|
|
1880
1970
|
const selected = option.value === value;
|
|
1881
1971
|
const Icon2 = option.icon;
|
|
1882
1972
|
return /* @__PURE__ */ jsxs15(
|
|
@@ -1897,7 +1987,7 @@ function ButtonGroup({
|
|
|
1897
1987
|
index > 0 && "-ml-px"
|
|
1898
1988
|
),
|
|
1899
1989
|
children: [
|
|
1900
|
-
Icon2 && /* @__PURE__ */
|
|
1990
|
+
Icon2 && /* @__PURE__ */ jsx32(Icon2, { className: "h-4 w-4" }),
|
|
1901
1991
|
option.label
|
|
1902
1992
|
]
|
|
1903
1993
|
},
|
|
@@ -1909,7 +1999,7 @@ function ButtonGroup({
|
|
|
1909
1999
|
// src/patterns/loading-spinner/LoadingSpinner.tsx
|
|
1910
2000
|
import { cva as cva4 } from "class-variance-authority";
|
|
1911
2001
|
import { Loader2 } from "lucide-react";
|
|
1912
|
-
import { jsx as
|
|
2002
|
+
import { jsx as jsx33, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1913
2003
|
var loadingSpinnerIconVariants = cva4("animate-spin text-muted-foreground", {
|
|
1914
2004
|
variants: {
|
|
1915
2005
|
size: {
|
|
@@ -1928,26 +2018,26 @@ var LoadingSpinner = ({
|
|
|
1928
2018
|
className,
|
|
1929
2019
|
...props
|
|
1930
2020
|
}) => /* @__PURE__ */ jsxs16("span", { role: "status", className: cn("inline-flex items-center gap-2", className), ...props, children: [
|
|
1931
|
-
/* @__PURE__ */
|
|
1932
|
-
label ? /* @__PURE__ */
|
|
2021
|
+
/* @__PURE__ */ jsx33(Loader2, { className: cn(loadingSpinnerIconVariants({ size })), "aria-hidden": "true" }),
|
|
2022
|
+
label ? /* @__PURE__ */ jsx33("span", { children: label }) : null
|
|
1933
2023
|
] });
|
|
1934
2024
|
var LoadingOverlay = ({
|
|
1935
2025
|
size = "lg",
|
|
1936
2026
|
label,
|
|
1937
2027
|
className,
|
|
1938
2028
|
...props
|
|
1939
|
-
}) => /* @__PURE__ */
|
|
2029
|
+
}) => /* @__PURE__ */ jsx33(
|
|
1940
2030
|
"div",
|
|
1941
2031
|
{
|
|
1942
2032
|
className: cn("flex h-full min-h-32 w-full items-center justify-center", className),
|
|
1943
2033
|
...props,
|
|
1944
|
-
children: /* @__PURE__ */
|
|
2034
|
+
children: /* @__PURE__ */ jsx33(LoadingSpinner, { size, label })
|
|
1945
2035
|
}
|
|
1946
2036
|
);
|
|
1947
2037
|
|
|
1948
2038
|
// src/patterns/search-bar/SearchBar.tsx
|
|
1949
2039
|
import { Search, X as X5 } from "lucide-react";
|
|
1950
|
-
import { jsx as
|
|
2040
|
+
import { jsx as jsx34, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1951
2041
|
function SearchBar({
|
|
1952
2042
|
value,
|
|
1953
2043
|
onChange,
|
|
@@ -1960,8 +2050,8 @@ function SearchBar({
|
|
|
1960
2050
|
}) {
|
|
1961
2051
|
const showClear = onClear !== false && value.length > 0;
|
|
1962
2052
|
return /* @__PURE__ */ jsxs17("div", { className: cn("relative", className), children: [
|
|
1963
|
-
/* @__PURE__ */
|
|
1964
|
-
/* @__PURE__ */
|
|
2053
|
+
/* @__PURE__ */ jsx34("span", { className: "pointer-events-none absolute top-1/2 left-4 -translate-y-1/2 text-muted-foreground", children: isLoading ? /* @__PURE__ */ jsx34(LoadingSpinner, { size: "sm" }) : /* @__PURE__ */ jsx34(Search, { className: "h-4 w-4", "aria-hidden": "true" }) }),
|
|
2054
|
+
/* @__PURE__ */ jsx34(
|
|
1965
2055
|
"input",
|
|
1966
2056
|
{
|
|
1967
2057
|
ref: inputRef,
|
|
@@ -1980,14 +2070,14 @@ function SearchBar({
|
|
|
1980
2070
|
...props
|
|
1981
2071
|
}
|
|
1982
2072
|
),
|
|
1983
|
-
showClear && /* @__PURE__ */
|
|
2073
|
+
showClear && /* @__PURE__ */ jsx34(
|
|
1984
2074
|
"button",
|
|
1985
2075
|
{
|
|
1986
2076
|
type: "button",
|
|
1987
2077
|
onClick: () => onClear ? onClear() : onChange(""),
|
|
1988
2078
|
"aria-label": clearLabel,
|
|
1989
2079
|
className: "absolute top-1/2 right-2 flex h-7 w-7 -translate-y-1/2 items-center justify-center rounded-full text-muted-foreground hover:bg-accent hover:text-foreground",
|
|
1990
|
-
children: /* @__PURE__ */
|
|
2080
|
+
children: /* @__PURE__ */ jsx34(X5, { className: "h-4 w-4", "aria-hidden": "true" })
|
|
1991
2081
|
}
|
|
1992
2082
|
)
|
|
1993
2083
|
] });
|
|
@@ -1995,7 +2085,7 @@ function SearchBar({
|
|
|
1995
2085
|
|
|
1996
2086
|
// src/patterns/kpi-card/KpiCard.tsx
|
|
1997
2087
|
import { memo } from "react";
|
|
1998
|
-
import { Fragment as
|
|
2088
|
+
import { Fragment as Fragment3, jsx as jsx35, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1999
2089
|
var DONUT_COLORS = [
|
|
2000
2090
|
"var(--chart-1, #3b82f6)",
|
|
2001
2091
|
"var(--chart-2, #22c55e)",
|
|
@@ -2018,11 +2108,11 @@ function DonutChart({
|
|
|
2018
2108
|
let offset = 0;
|
|
2019
2109
|
return /* @__PURE__ */ jsxs18("div", { className: "relative inline-flex shrink-0 items-center justify-center", style: { width: size, height: size }, children: [
|
|
2020
2110
|
/* @__PURE__ */ jsxs18("svg", { width: size, height: size, viewBox: `0 0 ${size} ${size}`, className: "-rotate-90", children: [
|
|
2021
|
-
/* @__PURE__ */
|
|
2111
|
+
/* @__PURE__ */ jsx35("circle", { cx: size / 2, cy: size / 2, r: radius, fill: "none", stroke: "currentColor", className: "text-muted/40", strokeWidth: thickness }),
|
|
2022
2112
|
data.map((segment, i) => {
|
|
2023
2113
|
const fraction = segment.value / total;
|
|
2024
2114
|
const dash = fraction * circumference;
|
|
2025
|
-
const el = /* @__PURE__ */
|
|
2115
|
+
const el = /* @__PURE__ */ jsx35(
|
|
2026
2116
|
"circle",
|
|
2027
2117
|
{
|
|
2028
2118
|
cx: size / 2,
|
|
@@ -2042,8 +2132,8 @@ function DonutChart({
|
|
|
2042
2132
|
})
|
|
2043
2133
|
] }),
|
|
2044
2134
|
(centerValue || centerLabel) && /* @__PURE__ */ jsxs18("div", { className: "absolute inset-0 flex flex-col items-center justify-center", children: [
|
|
2045
|
-
centerValue && /* @__PURE__ */
|
|
2046
|
-
centerLabel && /* @__PURE__ */
|
|
2135
|
+
centerValue && /* @__PURE__ */ jsx35("span", { className: "text-base font-black tracking-tight text-foreground tabular-nums", children: centerValue }),
|
|
2136
|
+
centerLabel && /* @__PURE__ */ jsx35("span", { className: "text-[9px] font-medium text-muted-foreground uppercase", children: centerLabel })
|
|
2047
2137
|
] })
|
|
2048
2138
|
] });
|
|
2049
2139
|
}
|
|
@@ -2055,7 +2145,7 @@ function Sparkline({ data, color }) {
|
|
|
2055
2145
|
const W = 72;
|
|
2056
2146
|
const H = 28;
|
|
2057
2147
|
const pts = data.map((v, i) => `${i / (data.length - 1) * W},${H - (v - min) / range * (H - 2) - 1}`).join(" ");
|
|
2058
|
-
return /* @__PURE__ */
|
|
2148
|
+
return /* @__PURE__ */ jsx35("svg", { width: W, height: H, viewBox: `0 0 ${W} ${H}`, className: "overflow-visible opacity-70", children: /* @__PURE__ */ jsx35("polyline", { points: pts, fill: "none", stroke: color, strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) });
|
|
2059
2149
|
}
|
|
2060
2150
|
function AreaSparkline({ data, color }) {
|
|
2061
2151
|
if (data.length < 2) return null;
|
|
@@ -2070,13 +2160,13 @@ function AreaSparkline({ data, color }) {
|
|
|
2070
2160
|
const linePts = xs.map((x, i) => `${x},${ys[i]}`).join(" ");
|
|
2071
2161
|
const areaPath = `M${xs[0]},${H} ` + xs.map((x, i) => `L${x},${ys[i]}`).join(" ") + ` L${xs[xs.length - 1]},${H} Z`;
|
|
2072
2162
|
return /* @__PURE__ */ jsxs18("svg", { width: W, height: H, viewBox: `0 0 ${W} ${H}`, className: "overflow-visible", preserveAspectRatio: "none", children: [
|
|
2073
|
-
/* @__PURE__ */
|
|
2074
|
-
/* @__PURE__ */
|
|
2075
|
-
/* @__PURE__ */
|
|
2163
|
+
/* @__PURE__ */ jsx35("defs", { children: /* @__PURE__ */ jsxs18("linearGradient", { id: "kpi-card-spark-fill", x1: "0", y1: "0", x2: "0", y2: "1", children: [
|
|
2164
|
+
/* @__PURE__ */ jsx35("stop", { offset: "0%", stopColor: color, stopOpacity: "0.22" }),
|
|
2165
|
+
/* @__PURE__ */ jsx35("stop", { offset: "100%", stopColor: color, stopOpacity: "0" })
|
|
2076
2166
|
] }) }),
|
|
2077
|
-
/* @__PURE__ */
|
|
2078
|
-
/* @__PURE__ */
|
|
2079
|
-
/* @__PURE__ */
|
|
2167
|
+
/* @__PURE__ */ jsx35("path", { d: areaPath, fill: "url(#kpi-card-spark-fill)" }),
|
|
2168
|
+
/* @__PURE__ */ jsx35("polyline", { points: linePts, fill: "none", stroke: color, strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round" }),
|
|
2169
|
+
/* @__PURE__ */ jsx35("circle", { cx: xs[xs.length - 1], cy: ys[ys.length - 1], r: "2.5", fill: color })
|
|
2080
2170
|
] });
|
|
2081
2171
|
}
|
|
2082
2172
|
var rowBetween = "flex items-center justify-between";
|
|
@@ -2111,12 +2201,12 @@ var KpiCard = memo(function KpiCard2({
|
|
|
2111
2201
|
},
|
|
2112
2202
|
children: [
|
|
2113
2203
|
/* @__PURE__ */ jsxs18("div", { className: "relative flex items-start justify-between", children: [
|
|
2114
|
-
/* @__PURE__ */
|
|
2115
|
-
Icon2 && /* @__PURE__ */
|
|
2204
|
+
/* @__PURE__ */ jsx35("p", { className: "text-[11px] font-bold tracking-[0.14em] text-white/70 uppercase", children: label }),
|
|
2205
|
+
Icon2 && /* @__PURE__ */ jsx35("div", { className: "flex h-6 w-6 items-center justify-center rounded-lg bg-white/15 ring-1 ring-white/20", children: /* @__PURE__ */ jsx35(Icon2, { className: "h-3 w-3 text-white/90", "aria-hidden": "true" }) })
|
|
2116
2206
|
] }),
|
|
2117
|
-
/* @__PURE__ */
|
|
2207
|
+
/* @__PURE__ */ jsx35("div", { className: "relative", children: loading ? /* @__PURE__ */ jsx35("div", { className: "h-6 w-28 animate-pulse rounded-lg bg-white/15" }) : /* @__PURE__ */ jsx35("p", { className: "text-2xl leading-none font-black tracking-tight text-white tabular-nums md:text-[22px]", children: value ?? "\u2014" }) }),
|
|
2118
2208
|
(badge || badgeLabel) && !loading && /* @__PURE__ */ jsxs18("div", { className: "relative flex items-center gap-2", children: [
|
|
2119
|
-
badge && /* @__PURE__ */
|
|
2209
|
+
badge && /* @__PURE__ */ jsx35(
|
|
2120
2210
|
"span",
|
|
2121
2211
|
{
|
|
2122
2212
|
className: cn(
|
|
@@ -2126,27 +2216,27 @@ var KpiCard = memo(function KpiCard2({
|
|
|
2126
2216
|
children: badge.text
|
|
2127
2217
|
}
|
|
2128
2218
|
),
|
|
2129
|
-
badgeLabel && /* @__PURE__ */
|
|
2219
|
+
badgeLabel && /* @__PURE__ */ jsx35("span", { className: "text-[11px] text-white/70", children: badgeLabel })
|
|
2130
2220
|
] }),
|
|
2131
|
-
sub && !loading && /* @__PURE__ */
|
|
2221
|
+
sub && !loading && /* @__PURE__ */ jsx35("p", { className: "relative -mt-1 text-[11px] font-medium text-white/75 tabular-nums", children: sub }),
|
|
2132
2222
|
progress != null && !loading && /* @__PURE__ */ jsxs18("div", { className: "relative flex items-center gap-1.5", children: [
|
|
2133
|
-
/* @__PURE__ */
|
|
2134
|
-
progressLabel && /* @__PURE__ */
|
|
2223
|
+
/* @__PURE__ */ jsx35("div", { className: "h-1 flex-1 overflow-hidden rounded-full bg-white/20", children: /* @__PURE__ */ jsx35("div", { className: "h-1 rounded-full bg-white/85", style: { width: `${Math.min(100, Math.max(0, progress))}%` } }) }),
|
|
2224
|
+
progressLabel && /* @__PURE__ */ jsx35("span", { className: "shrink-0 text-[11px] font-semibold text-white/80 tabular-nums", children: progressLabel })
|
|
2135
2225
|
] }),
|
|
2136
|
-
sparkline && sparkline.length > 1 && !loading && /* @__PURE__ */
|
|
2226
|
+
sparkline && sparkline.length > 1 && !loading && /* @__PURE__ */ jsx35("div", { className: "relative -mx-4 mt-auto -mb-4 md:-mx-3 md:-mb-3", children: /* @__PURE__ */ jsx35(AreaSparkline, { data: sparkline, color: "#ffffff" }) })
|
|
2137
2227
|
]
|
|
2138
2228
|
}
|
|
2139
2229
|
);
|
|
2140
2230
|
}
|
|
2141
2231
|
if (variant === "mini") {
|
|
2142
|
-
const iconSlot = Icon2 ? href ? /* @__PURE__ */
|
|
2232
|
+
const iconSlot = Icon2 ? href ? /* @__PURE__ */ jsx35(
|
|
2143
2233
|
"a",
|
|
2144
2234
|
{
|
|
2145
2235
|
href,
|
|
2146
2236
|
className: "tap-target flex h-7 w-7 shrink-0 items-center justify-center rounded-xl bg-primary/10 text-primary transition-[background-color,scale] hover:bg-primary/20 active:scale-90 motion-reduce:transition-none md:h-6 md:w-6",
|
|
2147
|
-
children: /* @__PURE__ */
|
|
2237
|
+
children: /* @__PURE__ */ jsx35(Icon2, { className: "h-4 w-4 md:h-3.5 md:w-3.5", "aria-hidden": "true" })
|
|
2148
2238
|
}
|
|
2149
|
-
) : /* @__PURE__ */
|
|
2239
|
+
) : /* @__PURE__ */ jsx35("div", { className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-xl bg-primary/10 text-primary md:h-6 md:w-6", children: /* @__PURE__ */ jsx35(Icon2, { className: "h-4 w-4 md:h-3.5 md:w-3.5", "aria-hidden": "true" }) }) : null;
|
|
2150
2240
|
return /* @__PURE__ */ jsxs18(
|
|
2151
2241
|
"div",
|
|
2152
2242
|
{
|
|
@@ -2157,12 +2247,12 @@ var KpiCard = memo(function KpiCard2({
|
|
|
2157
2247
|
),
|
|
2158
2248
|
children: [
|
|
2159
2249
|
/* @__PURE__ */ jsxs18("div", { className: rowBetween, children: [
|
|
2160
|
-
/* @__PURE__ */
|
|
2250
|
+
/* @__PURE__ */ jsx35("p", { className: "text-[11px] font-bold tracking-[0.12em] text-muted-foreground uppercase", children: label }),
|
|
2161
2251
|
iconSlot
|
|
2162
2252
|
] }),
|
|
2163
|
-
/* @__PURE__ */
|
|
2164
|
-
/* @__PURE__ */
|
|
2165
|
-
badge && /* @__PURE__ */
|
|
2253
|
+
/* @__PURE__ */ jsx35("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: loading ? /* @__PURE__ */ jsx35(Skeleton, { className: "h-6 w-16" }) : /* @__PURE__ */ jsxs18(Fragment3, { children: [
|
|
2254
|
+
/* @__PURE__ */ jsx35("p", { className: "min-w-0 animate-in truncate text-[20px] leading-none font-black tracking-tight text-foreground duration-200 fade-in-0 tabular-nums motion-reduce:animate-none md:text-[16px]", children: value ?? "\u2014" }),
|
|
2255
|
+
badge && /* @__PURE__ */ jsx35(
|
|
2166
2256
|
"span",
|
|
2167
2257
|
{
|
|
2168
2258
|
className: cn(
|
|
@@ -2174,7 +2264,7 @@ var KpiCard = memo(function KpiCard2({
|
|
|
2174
2264
|
)
|
|
2175
2265
|
] }) }),
|
|
2176
2266
|
(sub || sparkline) && !loading && /* @__PURE__ */ jsxs18("div", { className: "flex items-end justify-between gap-2", children: [
|
|
2177
|
-
sub && /* @__PURE__ */
|
|
2267
|
+
sub && /* @__PURE__ */ jsx35(
|
|
2178
2268
|
"p",
|
|
2179
2269
|
{
|
|
2180
2270
|
className: cn(
|
|
@@ -2184,7 +2274,7 @@ var KpiCard = memo(function KpiCard2({
|
|
|
2184
2274
|
children: sub
|
|
2185
2275
|
}
|
|
2186
2276
|
),
|
|
2187
|
-
sparkline && /* @__PURE__ */
|
|
2277
|
+
sparkline && /* @__PURE__ */ jsx35(Sparkline, { data: sparkline, color: sparklineColor })
|
|
2188
2278
|
] })
|
|
2189
2279
|
]
|
|
2190
2280
|
}
|
|
@@ -2194,20 +2284,20 @@ var KpiCard = memo(function KpiCard2({
|
|
|
2194
2284
|
const total = segments?.reduce((sum, s) => sum + s.value, 0) ?? 0;
|
|
2195
2285
|
return /* @__PURE__ */ jsxs18("div", { "data-testid": testId, className: "rounded-xl border border-border bg-card p-5", children: [
|
|
2196
2286
|
/* @__PURE__ */ jsxs18("div", { className: rowBetween, children: [
|
|
2197
|
-
/* @__PURE__ */
|
|
2198
|
-
Icon2 && /* @__PURE__ */
|
|
2287
|
+
/* @__PURE__ */ jsx35("p", { className: "text-[11px] font-bold tracking-[0.12em] text-muted-foreground uppercase", children: label }),
|
|
2288
|
+
Icon2 && /* @__PURE__ */ jsx35("div", { className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-xl bg-primary/8 text-primary", children: /* @__PURE__ */ jsx35(Icon2, { className: "h-3.5 w-3.5", "aria-hidden": "true" }) })
|
|
2199
2289
|
] }),
|
|
2200
2290
|
loading ? /* @__PURE__ */ jsxs18("div", { className: "mt-3 flex items-center gap-4", children: [
|
|
2201
|
-
/* @__PURE__ */
|
|
2291
|
+
/* @__PURE__ */ jsx35(Skeleton, { className: "h-24 w-24 shrink-0 rounded-full" }),
|
|
2202
2292
|
/* @__PURE__ */ jsxs18("div", { className: "flex flex-1 flex-col gap-2", children: [
|
|
2203
|
-
/* @__PURE__ */
|
|
2204
|
-
/* @__PURE__ */
|
|
2205
|
-
/* @__PURE__ */
|
|
2293
|
+
/* @__PURE__ */ jsx35(Skeleton, { className: "h-3 w-full" }),
|
|
2294
|
+
/* @__PURE__ */ jsx35(Skeleton, { className: "h-3 w-3/4" }),
|
|
2295
|
+
/* @__PURE__ */ jsx35(Skeleton, { className: "h-3 w-1/2" })
|
|
2206
2296
|
] })
|
|
2207
2297
|
] }) : segments && segments.length > 0 ? /* @__PURE__ */ jsxs18("div", { className: "mt-3 flex items-center gap-4", children: [
|
|
2208
|
-
/* @__PURE__ */
|
|
2209
|
-
/* @__PURE__ */
|
|
2210
|
-
/* @__PURE__ */
|
|
2298
|
+
/* @__PURE__ */ jsx35(DonutChart, { data: segments, centerValue: centerValue ?? String(total) }),
|
|
2299
|
+
/* @__PURE__ */ jsx35("ul", { className: "flex min-w-0 flex-1 flex-col gap-1.5", children: segments.map((segment, i) => /* @__PURE__ */ jsxs18("li", { className: "flex items-center gap-2 text-[12px]", children: [
|
|
2300
|
+
/* @__PURE__ */ jsx35(
|
|
2211
2301
|
"span",
|
|
2212
2302
|
{
|
|
2213
2303
|
className: "h-2 w-2 shrink-0 rounded-full",
|
|
@@ -2215,11 +2305,11 @@ var KpiCard = memo(function KpiCard2({
|
|
|
2215
2305
|
"aria-hidden": "true"
|
|
2216
2306
|
}
|
|
2217
2307
|
),
|
|
2218
|
-
/* @__PURE__ */
|
|
2219
|
-
/* @__PURE__ */
|
|
2308
|
+
/* @__PURE__ */ jsx35("span", { className: "min-w-0 flex-1 truncate text-muted-foreground", children: segment.label }),
|
|
2309
|
+
/* @__PURE__ */ jsx35("span", { className: "shrink-0 font-semibold text-foreground tabular-nums", children: total > 0 ? `${Math.round(segment.value / total * 100)}%` : segment.value })
|
|
2220
2310
|
] }, segment.label)) })
|
|
2221
|
-
] }) : /* @__PURE__ */
|
|
2222
|
-
sub && !loading && /* @__PURE__ */
|
|
2311
|
+
] }) : /* @__PURE__ */ jsx35("span", { className: "mt-3 block text-2xl font-black text-muted-foreground/40", children: "\u2014" }),
|
|
2312
|
+
sub && !loading && /* @__PURE__ */ jsx35("p", { className: "mt-2.5 text-[11px] text-muted-foreground tabular-nums", children: sub })
|
|
2223
2313
|
] });
|
|
2224
2314
|
}
|
|
2225
2315
|
const strValue = value != null ? String(value) : null;
|
|
@@ -2231,26 +2321,26 @@ var KpiCard = memo(function KpiCard2({
|
|
|
2231
2321
|
const suffix = isSuffix ? parts[1] : null;
|
|
2232
2322
|
return /* @__PURE__ */ jsxs18("div", { "data-testid": testId, className: "rounded-xl border border-border bg-card p-5", children: [
|
|
2233
2323
|
/* @__PURE__ */ jsxs18("div", { className: rowBetween, children: [
|
|
2234
|
-
/* @__PURE__ */
|
|
2235
|
-
Icon2 && /* @__PURE__ */
|
|
2324
|
+
/* @__PURE__ */ jsx35("p", { className: "text-[11px] font-bold tracking-[0.12em] text-muted-foreground uppercase", children: label }),
|
|
2325
|
+
Icon2 && /* @__PURE__ */ jsx35("div", { className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-xl bg-primary/8 text-primary", children: /* @__PURE__ */ jsx35(Icon2, { className: "h-3.5 w-3.5", "aria-hidden": "true" }) })
|
|
2236
2326
|
] }),
|
|
2237
2327
|
/* @__PURE__ */ jsxs18("div", { className: "mt-3", children: [
|
|
2238
|
-
loading ? /* @__PURE__ */
|
|
2328
|
+
loading ? /* @__PURE__ */ jsx35(Skeleton, { className: "h-7 w-20" }) : value == null ? /* @__PURE__ */ jsx35("span", { className: "text-2xl font-black text-muted-foreground/40", children: "\u2014" }) : plain ? /* @__PURE__ */ jsx35("span", { className: "animate-in text-2xl font-black tracking-tight text-foreground duration-200 fade-in-0 tabular-nums motion-reduce:animate-none", children: strValue }) : /* @__PURE__ */ jsxs18("span", { className: "animate-in font-black tracking-tight text-foreground duration-200 fade-in-0 tabular-nums motion-reduce:animate-none", children: [
|
|
2239
2329
|
prefix && /* @__PURE__ */ jsxs18("span", { className: "text-sm text-muted-foreground", children: [
|
|
2240
2330
|
prefix,
|
|
2241
2331
|
" "
|
|
2242
2332
|
] }),
|
|
2243
|
-
/* @__PURE__ */
|
|
2333
|
+
/* @__PURE__ */ jsx35("span", { className: "text-2xl", children: number }),
|
|
2244
2334
|
suffix && /* @__PURE__ */ jsxs18("span", { className: "text-sm text-muted-foreground", children: [
|
|
2245
2335
|
" ",
|
|
2246
2336
|
suffix
|
|
2247
2337
|
] })
|
|
2248
2338
|
] }),
|
|
2249
|
-
sub && !loading && /* @__PURE__ */
|
|
2339
|
+
sub && !loading && /* @__PURE__ */ jsx35("p", { className: "mt-0.5 text-[11px] text-muted-foreground tabular-nums", children: sub })
|
|
2250
2340
|
] }),
|
|
2251
2341
|
(badge || badgeLabel || sparkline) && !loading && /* @__PURE__ */ jsxs18("div", { className: "mt-2.5 flex items-end justify-between gap-2", children: [
|
|
2252
2342
|
/* @__PURE__ */ jsxs18("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
2253
|
-
badge && /* @__PURE__ */
|
|
2343
|
+
badge && /* @__PURE__ */ jsx35(
|
|
2254
2344
|
"span",
|
|
2255
2345
|
{
|
|
2256
2346
|
className: cn(
|
|
@@ -2260,16 +2350,16 @@ var KpiCard = memo(function KpiCard2({
|
|
|
2260
2350
|
children: badge.text
|
|
2261
2351
|
}
|
|
2262
2352
|
),
|
|
2263
|
-
badgeLabel && /* @__PURE__ */
|
|
2353
|
+
badgeLabel && /* @__PURE__ */ jsx35("span", { className: "text-[11px] text-muted-foreground", children: badgeLabel })
|
|
2264
2354
|
] }),
|
|
2265
|
-
sparkline && /* @__PURE__ */
|
|
2355
|
+
sparkline && /* @__PURE__ */ jsx35(Sparkline, { data: sparkline, color: sparklineColor })
|
|
2266
2356
|
] })
|
|
2267
2357
|
] });
|
|
2268
2358
|
});
|
|
2269
2359
|
|
|
2270
2360
|
// src/patterns/search-panel/SearchPanel.tsx
|
|
2271
2361
|
import { Search as Search2 } from "lucide-react";
|
|
2272
|
-
import { jsx as
|
|
2362
|
+
import { jsx as jsx36, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
2273
2363
|
function SearchPanel({
|
|
2274
2364
|
value,
|
|
2275
2365
|
onChange,
|
|
@@ -2294,8 +2384,8 @@ function SearchPanel({
|
|
|
2294
2384
|
),
|
|
2295
2385
|
children: [
|
|
2296
2386
|
/* @__PURE__ */ jsxs19("div", { className: "flex h-14 items-center gap-3 px-4", children: [
|
|
2297
|
-
isLoading ? /* @__PURE__ */
|
|
2298
|
-
/* @__PURE__ */
|
|
2387
|
+
isLoading ? /* @__PURE__ */ jsx36(LoadingSpinner, { size: "sm" }) : /* @__PURE__ */ jsx36(Search2, { className: "h-5 w-5 shrink-0 text-muted-foreground", "aria-hidden": "true" }),
|
|
2388
|
+
/* @__PURE__ */ jsx36(
|
|
2299
2389
|
"input",
|
|
2300
2390
|
{
|
|
2301
2391
|
ref: inputRef,
|
|
@@ -2307,7 +2397,7 @@ function SearchPanel({
|
|
|
2307
2397
|
}
|
|
2308
2398
|
),
|
|
2309
2399
|
trailingSlot,
|
|
2310
|
-
shortcutHint && /* @__PURE__ */
|
|
2400
|
+
shortcutHint && /* @__PURE__ */ jsx36(
|
|
2311
2401
|
"kbd",
|
|
2312
2402
|
{
|
|
2313
2403
|
"aria-hidden": "true",
|
|
@@ -2316,7 +2406,7 @@ function SearchPanel({
|
|
|
2316
2406
|
}
|
|
2317
2407
|
)
|
|
2318
2408
|
] }),
|
|
2319
|
-
modes && modes.length > 0 && /* @__PURE__ */
|
|
2409
|
+
modes && modes.length > 0 && /* @__PURE__ */ jsx36("div", { className: "flex items-center gap-2 px-4 pb-3", children: modes.map(({ key, label, icon: Icon2 }) => /* @__PURE__ */ jsxs19(
|
|
2320
2410
|
"button",
|
|
2321
2411
|
{
|
|
2322
2412
|
type: "button",
|
|
@@ -2326,7 +2416,7 @@ function SearchPanel({
|
|
|
2326
2416
|
activeMode === key ? "bg-primary text-primary-foreground" : "text-muted-foreground hover:bg-muted"
|
|
2327
2417
|
),
|
|
2328
2418
|
children: [
|
|
2329
|
-
Icon2 && /* @__PURE__ */
|
|
2419
|
+
Icon2 && /* @__PURE__ */ jsx36(Icon2, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
|
|
2330
2420
|
label
|
|
2331
2421
|
]
|
|
2332
2422
|
},
|
|
@@ -2339,9 +2429,9 @@ function SearchPanel({
|
|
|
2339
2429
|
|
|
2340
2430
|
// src/patterns/search-panel/SearchTrigger.tsx
|
|
2341
2431
|
import { Search as Search3 } from "lucide-react";
|
|
2342
|
-
import { jsx as
|
|
2432
|
+
import { jsx as jsx37 } from "react/jsx-runtime";
|
|
2343
2433
|
function SearchTrigger({ label = "Search", ...props }) {
|
|
2344
|
-
return /* @__PURE__ */
|
|
2434
|
+
return /* @__PURE__ */ jsx37(Button, { type: "button", variant: "ghost", size: "icon", "aria-label": label, ...props, children: /* @__PURE__ */ jsx37(Search3, { className: "h-[18px] w-[18px]", "aria-hidden": "true" }) });
|
|
2345
2435
|
}
|
|
2346
2436
|
|
|
2347
2437
|
// src/patterns/sidebar/context.ts
|
|
@@ -2353,7 +2443,7 @@ function useSidebarCollapsed() {
|
|
|
2353
2443
|
}
|
|
2354
2444
|
|
|
2355
2445
|
// src/patterns/sidebar/NavItem.tsx
|
|
2356
|
-
import { jsx as
|
|
2446
|
+
import { jsx as jsx38, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
2357
2447
|
function NavItem({
|
|
2358
2448
|
as,
|
|
2359
2449
|
icon: Icon2,
|
|
@@ -2377,7 +2467,7 @@ function NavItem({
|
|
|
2377
2467
|
),
|
|
2378
2468
|
...rest,
|
|
2379
2469
|
children: [
|
|
2380
|
-
Icon2 && /* @__PURE__ */
|
|
2470
|
+
Icon2 && /* @__PURE__ */ jsx38(
|
|
2381
2471
|
Icon2,
|
|
2382
2472
|
{
|
|
2383
2473
|
className: cn("h-[18px] w-[18px] shrink-0", active ? "text-nav-primary" : "text-muted-foreground"),
|
|
@@ -2385,7 +2475,7 @@ function NavItem({
|
|
|
2385
2475
|
"aria-hidden": true
|
|
2386
2476
|
}
|
|
2387
2477
|
),
|
|
2388
|
-
/* @__PURE__ */
|
|
2478
|
+
/* @__PURE__ */ jsx38(
|
|
2389
2479
|
"span",
|
|
2390
2480
|
{
|
|
2391
2481
|
className: cn(
|
|
@@ -2401,7 +2491,7 @@ function NavItem({
|
|
|
2401
2491
|
);
|
|
2402
2492
|
if (!collapsed) return row;
|
|
2403
2493
|
return /* @__PURE__ */ jsxs20(Tooltip, { children: [
|
|
2404
|
-
/* @__PURE__ */
|
|
2494
|
+
/* @__PURE__ */ jsx38(TooltipTrigger, { asChild: true, children: row }),
|
|
2405
2495
|
/* @__PURE__ */ jsxs20(TooltipContent, { side: "right", className: "flex items-center gap-1.5", children: [
|
|
2406
2496
|
label,
|
|
2407
2497
|
badge
|
|
@@ -2411,8 +2501,8 @@ function NavItem({
|
|
|
2411
2501
|
|
|
2412
2502
|
// src/patterns/sidebar/NavGroup.tsx
|
|
2413
2503
|
import { ChevronDown as ChevronDown2 } from "lucide-react";
|
|
2414
|
-
import { useState as
|
|
2415
|
-
import { jsx as
|
|
2504
|
+
import { useState as useState10 } from "react";
|
|
2505
|
+
import { jsx as jsx39, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
2416
2506
|
function NavGroup({
|
|
2417
2507
|
label,
|
|
2418
2508
|
defaultCollapsed = false,
|
|
@@ -2421,7 +2511,7 @@ function NavGroup({
|
|
|
2421
2511
|
children,
|
|
2422
2512
|
className
|
|
2423
2513
|
}) {
|
|
2424
|
-
const [internalCollapsed, setInternalCollapsed] =
|
|
2514
|
+
const [internalCollapsed, setInternalCollapsed] = useState10(defaultCollapsed);
|
|
2425
2515
|
const groupCollapsed = collapsed ?? internalCollapsed;
|
|
2426
2516
|
const railCollapsed = useSidebarCollapsed();
|
|
2427
2517
|
const setGroupCollapsed = (next) => {
|
|
@@ -2429,7 +2519,7 @@ function NavGroup({
|
|
|
2429
2519
|
if (collapsed === void 0) setInternalCollapsed(next);
|
|
2430
2520
|
};
|
|
2431
2521
|
return /* @__PURE__ */ jsxs21("div", { className: cn("flex flex-col gap-0.5", className), children: [
|
|
2432
|
-
label && (railCollapsed ? /* @__PURE__ */
|
|
2522
|
+
label && (railCollapsed ? /* @__PURE__ */ jsx39("div", { className: "mx-2 my-1 h-px bg-border/50", "aria-hidden": true }) : /* @__PURE__ */ jsxs21(
|
|
2433
2523
|
"button",
|
|
2434
2524
|
{
|
|
2435
2525
|
type: "button",
|
|
@@ -2437,8 +2527,8 @@ function NavGroup({
|
|
|
2437
2527
|
"aria-expanded": !groupCollapsed,
|
|
2438
2528
|
className: "group flex w-full items-center justify-between px-2.5 py-0.5 text-[11px] font-medium text-muted-foreground/80 hover:text-foreground",
|
|
2439
2529
|
children: [
|
|
2440
|
-
/* @__PURE__ */
|
|
2441
|
-
/* @__PURE__ */
|
|
2530
|
+
/* @__PURE__ */ jsx39("span", { children: label }),
|
|
2531
|
+
/* @__PURE__ */ jsx39(
|
|
2442
2532
|
ChevronDown2,
|
|
2443
2533
|
{
|
|
2444
2534
|
className: cn(
|
|
@@ -2451,7 +2541,7 @@ function NavGroup({
|
|
|
2451
2541
|
]
|
|
2452
2542
|
}
|
|
2453
2543
|
)),
|
|
2454
|
-
!groupCollapsed && /* @__PURE__ */
|
|
2544
|
+
!groupCollapsed && /* @__PURE__ */ jsx39("div", { className: "flex flex-col gap-0.5", children })
|
|
2455
2545
|
] });
|
|
2456
2546
|
}
|
|
2457
2547
|
|
|
@@ -2461,9 +2551,9 @@ import {
|
|
|
2461
2551
|
useCallback,
|
|
2462
2552
|
useEffect as useEffect5,
|
|
2463
2553
|
useRef as useRef5,
|
|
2464
|
-
useState as
|
|
2554
|
+
useState as useState11
|
|
2465
2555
|
} from "react";
|
|
2466
|
-
import { Fragment as
|
|
2556
|
+
import { Fragment as Fragment4, jsx as jsx40, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
2467
2557
|
function resolve(value, collapsed) {
|
|
2468
2558
|
return typeof value === "function" ? value(collapsed) : value;
|
|
2469
2559
|
}
|
|
@@ -2482,9 +2572,9 @@ function Sidebar({
|
|
|
2482
2572
|
children,
|
|
2483
2573
|
className
|
|
2484
2574
|
}) {
|
|
2485
|
-
const [internalWidth, setInternalWidth] =
|
|
2575
|
+
const [internalWidth, setInternalWidth] = useState11(defaultWidth);
|
|
2486
2576
|
const currentWidth = width ?? internalWidth;
|
|
2487
|
-
const [isDragging, setIsDragging] =
|
|
2577
|
+
const [isDragging, setIsDragging] = useState11(false);
|
|
2488
2578
|
const setWidth = useCallback(
|
|
2489
2579
|
(next) => {
|
|
2490
2580
|
const clamped = Math.min(maxWidth, Math.max(minWidth, next));
|
|
@@ -2510,7 +2600,7 @@ function Sidebar({
|
|
|
2510
2600
|
dragStartRef.current = null;
|
|
2511
2601
|
setIsDragging(false);
|
|
2512
2602
|
};
|
|
2513
|
-
return /* @__PURE__ */
|
|
2603
|
+
return /* @__PURE__ */ jsx40(SidebarContextProvider, { value: { collapsed }, children: /* @__PURE__ */ jsx40(TooltipProvider, { delayDuration: 200, children: /* @__PURE__ */ jsxs22(
|
|
2514
2604
|
"aside",
|
|
2515
2605
|
{
|
|
2516
2606
|
style: { width: collapsed ? railWidth : currentWidth },
|
|
@@ -2520,7 +2610,7 @@ function Sidebar({
|
|
|
2520
2610
|
className
|
|
2521
2611
|
),
|
|
2522
2612
|
children: [
|
|
2523
|
-
(header || onCollapsedChange) && /* @__PURE__ */
|
|
2613
|
+
(header || onCollapsedChange) && /* @__PURE__ */ jsx40("div", { className: "flex h-16 items-center gap-2 border-b border-border px-3", children: collapsed && onCollapsedChange ? (
|
|
2524
2614
|
// Collapsed rail: the header slot (e.g. a compact logo mark) and the
|
|
2525
2615
|
// expand toggle would otherwise compete for the narrow rail's width
|
|
2526
2616
|
// and clip each other, so they're stacked instead — the header shows
|
|
@@ -2534,8 +2624,8 @@ function Sidebar({
|
|
|
2534
2624
|
"aria-label": "Expand sidebar",
|
|
2535
2625
|
className: "group relative flex h-9 w-9 shrink-0 items-center justify-center",
|
|
2536
2626
|
children: [
|
|
2537
|
-
header && /* @__PURE__ */
|
|
2538
|
-
/* @__PURE__ */
|
|
2627
|
+
header && /* @__PURE__ */ jsx40("span", { className: "transition-opacity group-hover:opacity-0", children: resolve(header, collapsed) }),
|
|
2628
|
+
/* @__PURE__ */ jsx40(
|
|
2539
2629
|
PanelLeftOpen,
|
|
2540
2630
|
{
|
|
2541
2631
|
className: "absolute h-4 w-4 text-muted-foreground opacity-0 transition-opacity group-hover:opacity-100",
|
|
@@ -2545,22 +2635,22 @@ function Sidebar({
|
|
|
2545
2635
|
]
|
|
2546
2636
|
}
|
|
2547
2637
|
)
|
|
2548
|
-
) : /* @__PURE__ */ jsxs22(
|
|
2549
|
-
header && /* @__PURE__ */
|
|
2550
|
-
onCollapsedChange && /* @__PURE__ */
|
|
2638
|
+
) : /* @__PURE__ */ jsxs22(Fragment4, { children: [
|
|
2639
|
+
header && /* @__PURE__ */ jsx40("div", { className: "min-w-0 flex-1", children: resolve(header, collapsed) }),
|
|
2640
|
+
onCollapsedChange && /* @__PURE__ */ jsx40(
|
|
2551
2641
|
"button",
|
|
2552
2642
|
{
|
|
2553
2643
|
type: "button",
|
|
2554
2644
|
onClick: () => onCollapsedChange(!collapsed),
|
|
2555
2645
|
"aria-label": "Collapse sidebar",
|
|
2556
2646
|
className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-md text-muted-foreground hover:bg-muted hover:text-foreground",
|
|
2557
|
-
children: /* @__PURE__ */
|
|
2647
|
+
children: /* @__PURE__ */ jsx40(PanelLeftClose, { className: "h-4 w-4", "aria-hidden": true })
|
|
2558
2648
|
}
|
|
2559
2649
|
)
|
|
2560
2650
|
] }) }),
|
|
2561
|
-
/* @__PURE__ */
|
|
2562
|
-
footer && /* @__PURE__ */
|
|
2563
|
-
resizable && !collapsed && /* @__PURE__ */
|
|
2651
|
+
/* @__PURE__ */ jsx40(SidebarNav, { children }),
|
|
2652
|
+
footer && /* @__PURE__ */ jsx40("div", { className: "border-t border-border/50 px-2 py-2", children: resolve(footer, collapsed) }),
|
|
2653
|
+
resizable && !collapsed && /* @__PURE__ */ jsx40(
|
|
2564
2654
|
"div",
|
|
2565
2655
|
{
|
|
2566
2656
|
onPointerDown: handlePointerDown,
|
|
@@ -2576,7 +2666,7 @@ function Sidebar({
|
|
|
2576
2666
|
}
|
|
2577
2667
|
function SidebarNav({ children, className, ...rest }) {
|
|
2578
2668
|
const ref = useRef5(null);
|
|
2579
|
-
const [showFade, setShowFade] =
|
|
2669
|
+
const [showFade, setShowFade] = useState11(false);
|
|
2580
2670
|
useEffect5(() => {
|
|
2581
2671
|
const el = ref.current;
|
|
2582
2672
|
if (!el) return;
|
|
@@ -2591,7 +2681,7 @@ function SidebarNav({ children, className, ...rest }) {
|
|
|
2591
2681
|
};
|
|
2592
2682
|
}, []);
|
|
2593
2683
|
return /* @__PURE__ */ jsxs22("div", { className: "relative flex min-h-0 flex-1 flex-col", children: [
|
|
2594
|
-
/* @__PURE__ */
|
|
2684
|
+
/* @__PURE__ */ jsx40(
|
|
2595
2685
|
"div",
|
|
2596
2686
|
{
|
|
2597
2687
|
ref,
|
|
@@ -2600,7 +2690,7 @@ function SidebarNav({ children, className, ...rest }) {
|
|
|
2600
2690
|
children
|
|
2601
2691
|
}
|
|
2602
2692
|
),
|
|
2603
|
-
showFade && /* @__PURE__ */
|
|
2693
|
+
showFade && /* @__PURE__ */ jsx40(
|
|
2604
2694
|
"div",
|
|
2605
2695
|
{
|
|
2606
2696
|
className: "pointer-events-none absolute right-0 bottom-0 left-0 h-6 bg-gradient-to-t from-sidebar to-transparent",
|
|
@@ -2609,6 +2699,112 @@ function SidebarNav({ children, className, ...rest }) {
|
|
|
2609
2699
|
)
|
|
2610
2700
|
] });
|
|
2611
2701
|
}
|
|
2702
|
+
|
|
2703
|
+
// src/patterns/stepper/Stepper.tsx
|
|
2704
|
+
import { useEffect as useEffect6, useRef as useRef6 } from "react";
|
|
2705
|
+
import { Check as Check5, Plus } from "lucide-react";
|
|
2706
|
+
import { jsx as jsx41, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
2707
|
+
function Stepper({
|
|
2708
|
+
step,
|
|
2709
|
+
maxStep,
|
|
2710
|
+
onNavigate,
|
|
2711
|
+
onNew,
|
|
2712
|
+
steps,
|
|
2713
|
+
navLabel = "Steps",
|
|
2714
|
+
newLabel = "New",
|
|
2715
|
+
scrollTestId = "stepper-scroll",
|
|
2716
|
+
newTestId
|
|
2717
|
+
}) {
|
|
2718
|
+
const stepRefs = useRef6(/* @__PURE__ */ new Map());
|
|
2719
|
+
useEffect6(() => {
|
|
2720
|
+
const activeStep = stepRefs.current.get(step);
|
|
2721
|
+
activeStep?.scrollIntoView({ block: "nearest", inline: "center" });
|
|
2722
|
+
}, [step]);
|
|
2723
|
+
return (
|
|
2724
|
+
// onNew is pinned outside the horizontally-scrolling region below (a sibling of
|
|
2725
|
+
// it, not a child) so its own edge never scrolls off-screen along with the
|
|
2726
|
+
// later steps once the scroller's min-width doesn't fit the viewport.
|
|
2727
|
+
/* @__PURE__ */ jsxs23("div", { className: "flex w-full shrink-0 items-center gap-2", children: [
|
|
2728
|
+
/* @__PURE__ */ jsx41("nav", { "aria-label": navLabel, className: "min-w-0 flex-1", children: /* @__PURE__ */ jsx41(
|
|
2729
|
+
"div",
|
|
2730
|
+
{
|
|
2731
|
+
"data-testid": scrollTestId,
|
|
2732
|
+
className: "flex w-full items-center gap-0 overflow-x-auto px-2 py-1",
|
|
2733
|
+
children: /* @__PURE__ */ jsx41("ol", { className: "flex min-w-[700px] flex-1 items-start", children: steps.map(({ n, label, phase }, i) => {
|
|
2734
|
+
const done = step > n;
|
|
2735
|
+
const active = step === n;
|
|
2736
|
+
const navigable = n <= maxStep && n !== step;
|
|
2737
|
+
const last = i === steps.length - 1;
|
|
2738
|
+
return /* @__PURE__ */ jsxs23("li", { className: cn("flex items-start", !last && "flex-1"), children: [
|
|
2739
|
+
/* @__PURE__ */ jsxs23(
|
|
2740
|
+
"button",
|
|
2741
|
+
{
|
|
2742
|
+
ref: (element) => {
|
|
2743
|
+
if (element) stepRefs.current.set(n, element);
|
|
2744
|
+
else stepRefs.current.delete(n);
|
|
2745
|
+
},
|
|
2746
|
+
"data-testid": `step-${n}`,
|
|
2747
|
+
"aria-disabled": !navigable,
|
|
2748
|
+
"aria-current": active ? "step" : void 0,
|
|
2749
|
+
onClick: () => navigable && onNavigate(n),
|
|
2750
|
+
className: cn(
|
|
2751
|
+
"flex min-w-[68px] flex-col items-center gap-0.5 transition-opacity",
|
|
2752
|
+
navigable ? "cursor-pointer hover:opacity-80" : "cursor-default"
|
|
2753
|
+
),
|
|
2754
|
+
children: [
|
|
2755
|
+
/* @__PURE__ */ jsx41(
|
|
2756
|
+
"div",
|
|
2757
|
+
{
|
|
2758
|
+
className: cn(
|
|
2759
|
+
"flex h-7 w-7 shrink-0 items-center justify-center rounded-full text-[11px] font-bold transition-colors",
|
|
2760
|
+
done ? "bg-primary/15 text-primary" : active ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground"
|
|
2761
|
+
),
|
|
2762
|
+
children: done ? /* @__PURE__ */ jsx41(Check5, { className: "h-3 w-3" }) : n
|
|
2763
|
+
}
|
|
2764
|
+
),
|
|
2765
|
+
/* @__PURE__ */ jsx41(
|
|
2766
|
+
"span",
|
|
2767
|
+
{
|
|
2768
|
+
className: cn(
|
|
2769
|
+
"text-center whitespace-nowrap transition-colors",
|
|
2770
|
+
active ? "text-[12px] font-semibold text-foreground" : done ? "text-[12px] font-medium text-primary" : "text-[12px] font-medium text-muted-foreground"
|
|
2771
|
+
),
|
|
2772
|
+
children: label
|
|
2773
|
+
}
|
|
2774
|
+
),
|
|
2775
|
+
/* @__PURE__ */ jsx41("span", { className: "text-[9px] tracking-[0.5px] text-muted-foreground/50 uppercase", children: phase })
|
|
2776
|
+
]
|
|
2777
|
+
}
|
|
2778
|
+
),
|
|
2779
|
+
!last && /* @__PURE__ */ jsx41(
|
|
2780
|
+
"div",
|
|
2781
|
+
{
|
|
2782
|
+
className: cn(
|
|
2783
|
+
"mx-1.5 mt-3.5 h-px flex-1 transition-colors",
|
|
2784
|
+
done ? "bg-primary" : "bg-border"
|
|
2785
|
+
)
|
|
2786
|
+
}
|
|
2787
|
+
)
|
|
2788
|
+
] }, n);
|
|
2789
|
+
}) })
|
|
2790
|
+
}
|
|
2791
|
+
) }),
|
|
2792
|
+
onNew && /* @__PURE__ */ jsxs23(
|
|
2793
|
+
"button",
|
|
2794
|
+
{
|
|
2795
|
+
"data-testid": newTestId,
|
|
2796
|
+
onClick: onNew,
|
|
2797
|
+
title: newLabel,
|
|
2798
|
+
className: "flex shrink-0 items-center gap-1.5 rounded-lg border border-border px-3 py-1.5 text-[12px] font-semibold text-foreground transition-colors hover:bg-muted/50",
|
|
2799
|
+
children: [
|
|
2800
|
+
/* @__PURE__ */ jsx41(Plus, { className: "h-3.5 w-3.5" }),
|
|
2801
|
+
newLabel
|
|
2802
|
+
]
|
|
2803
|
+
}
|
|
2804
|
+
)
|
|
2805
|
+
] })
|
|
2806
|
+
);
|
|
2807
|
+
}
|
|
2612
2808
|
export {
|
|
2613
2809
|
AlertBox,
|
|
2614
2810
|
Badge,
|
|
@@ -2624,6 +2820,7 @@ export {
|
|
|
2624
2820
|
Combobox,
|
|
2625
2821
|
ConfirmDialog,
|
|
2626
2822
|
Dialog,
|
|
2823
|
+
DialogActions,
|
|
2627
2824
|
DialogContent,
|
|
2628
2825
|
DialogDescription,
|
|
2629
2826
|
DialogFooter,
|
|
@@ -2660,6 +2857,7 @@ export {
|
|
|
2660
2857
|
PopoverAnchor,
|
|
2661
2858
|
PopoverContent,
|
|
2662
2859
|
PopoverTrigger,
|
|
2860
|
+
QuestionDialog,
|
|
2663
2861
|
ResponsivePanel,
|
|
2664
2862
|
ScrollArea,
|
|
2665
2863
|
ScrollBar,
|
|
@@ -2687,6 +2885,7 @@ export {
|
|
|
2687
2885
|
Skeleton,
|
|
2688
2886
|
Sparkline,
|
|
2689
2887
|
StatusBadge,
|
|
2888
|
+
Stepper,
|
|
2690
2889
|
Switch,
|
|
2691
2890
|
Table,
|
|
2692
2891
|
TableBody,
|
|
@@ -2709,6 +2908,8 @@ export {
|
|
|
2709
2908
|
badgeVariants,
|
|
2710
2909
|
buttonVariants,
|
|
2711
2910
|
cn,
|
|
2911
|
+
getConfirmButtonPlacement,
|
|
2912
|
+
isWindowsPlatform,
|
|
2712
2913
|
loadingSpinnerIconVariants,
|
|
2713
2914
|
sheetVariants,
|
|
2714
2915
|
useMediaQuery,
|