@dmsi/wedgekit-react 0.0.88 → 0.0.90

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.
@@ -0,0 +1,125 @@
1
+ import {
2
+ Icon
3
+ } from "./chunk-IGQVA7SC.js";
4
+ import {
5
+ typography
6
+ } from "./chunk-RDLEIAQU.js";
7
+ import {
8
+ __objRest,
9
+ __spreadProps,
10
+ __spreadValues
11
+ } from "./chunk-ORMEWXMH.js";
12
+
13
+ // src/components/Caption.tsx
14
+ import clsx from "clsx";
15
+ import { jsx, jsxs } from "react/jsx-runtime";
16
+ var Caption = (_a) => {
17
+ var _b = _a, {
18
+ className,
19
+ children,
20
+ as = "span",
21
+ style = "default",
22
+ color,
23
+ align,
24
+ id
25
+ } = _b, props = __objRest(_b, [
26
+ "className",
27
+ "children",
28
+ "as",
29
+ "style",
30
+ "color",
31
+ "align",
32
+ "id"
33
+ ]);
34
+ const Element = as;
35
+ return /* @__PURE__ */ jsxs("div", { id, className: "flex gap-1", children: [
36
+ /* @__PURE__ */ jsx(
37
+ WhichIcon,
38
+ {
39
+ id,
40
+ style,
41
+ size: 16,
42
+ className: "mt-[3px] desktop:mt-0"
43
+ }
44
+ ),
45
+ /* @__PURE__ */ jsx(
46
+ Element,
47
+ __spreadProps(__spreadValues({
48
+ id: id ? `${id}-text` : void 0,
49
+ className: clsx(
50
+ typography.caption.replace("text-text-primary-normal", ""),
51
+ (style === "default" || style === "info") && "text-text-secondary-normal",
52
+ style === "success" && "text-text-success-normal",
53
+ style === "warning" && "text-text-warning-normal",
54
+ style === "error" && "text-text-critical-normal",
55
+ align === "left" && "text-left",
56
+ align === "center" && "text-center",
57
+ align === "right" && "text-right",
58
+ className
59
+ )
60
+ }, props), {
61
+ style: {
62
+ color: color ? `var(--color-${color})` : void 0
63
+ },
64
+ children
65
+ })
66
+ )
67
+ ] });
68
+ };
69
+ var WhichIcon = ({
70
+ style,
71
+ size,
72
+ className,
73
+ id
74
+ }) => {
75
+ if (style === "success") {
76
+ return /* @__PURE__ */ jsx("span", { className: "text-icon-success-normal contents", children: /* @__PURE__ */ jsx(
77
+ Icon,
78
+ {
79
+ id: id ? `${id}-icon` : void 0,
80
+ className,
81
+ name: "check_circle",
82
+ size
83
+ }
84
+ ) });
85
+ }
86
+ if (style === "warning") {
87
+ return /* @__PURE__ */ jsx("span", { className: "text-icon-warning-normal contents", children: /* @__PURE__ */ jsx(
88
+ Icon,
89
+ {
90
+ id: id ? `${id}-icon` : void 0,
91
+ className,
92
+ name: "warning",
93
+ size
94
+ }
95
+ ) });
96
+ }
97
+ if (style === "error") {
98
+ return /* @__PURE__ */ jsx("span", { className: "text-icon-critical-normal contents", children: /* @__PURE__ */ jsx(
99
+ Icon,
100
+ {
101
+ id: id ? `${id}-icon` : void 0,
102
+ className,
103
+ name: "info",
104
+ size
105
+ }
106
+ ) });
107
+ }
108
+ if (style === "info") {
109
+ return /* @__PURE__ */ jsx("span", { className: "text-icon-primary-normal contents", children: /* @__PURE__ */ jsx(
110
+ Icon,
111
+ {
112
+ id: id ? `${id}-icon` : void 0,
113
+ className,
114
+ name: "info",
115
+ size
116
+ }
117
+ ) });
118
+ }
119
+ return null;
120
+ };
121
+ Caption.displayName = "Caption";
122
+
123
+ export {
124
+ Caption
125
+ };
@@ -1,124 +1,9 @@
1
1
  import {
2
- Icon
3
- } from "../chunk-IGQVA7SC.js";
4
- import {
5
- typography
6
- } from "../chunk-RDLEIAQU.js";
7
- import {
8
- __objRest,
9
- __spreadProps,
10
- __spreadValues
11
- } from "../chunk-ORMEWXMH.js";
12
-
13
- // src/components/Caption.tsx
14
- import clsx from "clsx";
15
- import { jsx, jsxs } from "react/jsx-runtime";
16
- var Caption = (_a) => {
17
- var _b = _a, {
18
- className,
19
- children,
20
- as = "span",
21
- style = "default",
22
- color,
23
- align,
24
- id
25
- } = _b, props = __objRest(_b, [
26
- "className",
27
- "children",
28
- "as",
29
- "style",
30
- "color",
31
- "align",
32
- "id"
33
- ]);
34
- const Element = as;
35
- return /* @__PURE__ */ jsxs("div", { id, className: "flex gap-1", children: [
36
- /* @__PURE__ */ jsx(
37
- WhichIcon,
38
- {
39
- id,
40
- style,
41
- size: 16,
42
- className: "mt-[3px] desktop:mt-0"
43
- }
44
- ),
45
- /* @__PURE__ */ jsx(
46
- Element,
47
- __spreadProps(__spreadValues({
48
- id: id ? `${id}-text` : void 0,
49
- className: clsx(
50
- typography.caption.replace("text-text-primary-normal", ""),
51
- (style === "default" || style === "info") && "text-text-secondary-normal",
52
- style === "success" && "text-text-success-normal",
53
- style === "warning" && "text-text-warning-normal",
54
- style === "error" && "text-text-critical-normal",
55
- align === "left" && "text-left",
56
- align === "center" && "text-center",
57
- align === "right" && "text-right",
58
- className
59
- )
60
- }, props), {
61
- style: {
62
- color: color ? `var(--color-${color})` : void 0
63
- },
64
- children
65
- })
66
- )
67
- ] });
68
- };
69
- var WhichIcon = ({
70
- style,
71
- size,
72
- className,
73
- id
74
- }) => {
75
- if (style === "success") {
76
- return /* @__PURE__ */ jsx("span", { className: "text-icon-success-normal contents", children: /* @__PURE__ */ jsx(
77
- Icon,
78
- {
79
- id: id ? `${id}-icon` : void 0,
80
- className,
81
- name: "check_circle",
82
- size
83
- }
84
- ) });
85
- }
86
- if (style === "warning") {
87
- return /* @__PURE__ */ jsx("span", { className: "text-icon-warning-normal contents", children: /* @__PURE__ */ jsx(
88
- Icon,
89
- {
90
- id: id ? `${id}-icon` : void 0,
91
- className,
92
- name: "warning",
93
- size
94
- }
95
- ) });
96
- }
97
- if (style === "error") {
98
- return /* @__PURE__ */ jsx("span", { className: "text-icon-critical-normal contents", children: /* @__PURE__ */ jsx(
99
- Icon,
100
- {
101
- id: id ? `${id}-icon` : void 0,
102
- className,
103
- name: "info",
104
- size
105
- }
106
- ) });
107
- }
108
- if (style === "info") {
109
- return /* @__PURE__ */ jsx("span", { className: "text-icon-primary-normal contents", children: /* @__PURE__ */ jsx(
110
- Icon,
111
- {
112
- id: id ? `${id}-icon` : void 0,
113
- className,
114
- name: "info",
115
- size
116
- }
117
- ) });
118
- }
119
- return null;
120
- };
121
- Caption.displayName = "Caption";
2
+ Caption
3
+ } from "../chunk-6HIALT5L.js";
4
+ import "../chunk-IGQVA7SC.js";
5
+ import "../chunk-RDLEIAQU.js";
6
+ import "../chunk-ORMEWXMH.js";
122
7
  export {
123
8
  Caption
124
9
  };
@@ -841,49 +841,377 @@ var Modal = ({
841
841
  };
842
842
  Modal.displayName = "Modal";
843
843
 
844
- // src/components/PDFViewer.tsx
844
+ // src/components/Stack.tsx
845
+ var import_clsx10 = __toESM(require("clsx"), 1);
845
846
  var import_jsx_runtime9 = require("react/jsx-runtime");
847
+ var getFlexClassNames = ({ items, justify, grow }) => (0, import_clsx10.default)(
848
+ "flex",
849
+ items === "start" && "items-start",
850
+ grow && "grow",
851
+ items === "start" && "items-start",
852
+ items === "center" && "items-center",
853
+ items === "end" && "items-end",
854
+ items === "start-center" && "items-start desktop:items-center",
855
+ justify === "start" && "justify-start",
856
+ justify === "center" && "justify-center",
857
+ justify === "end" && "justify-end",
858
+ justify === "end" && "justify-end",
859
+ justify === "between" && "justify-between",
860
+ justify === "around" && "justify-around"
861
+ );
862
+ var useGapClassNames = (sizing) => {
863
+ return (0, import_clsx10.default)(
864
+ sizing === "layout-group" && "gap-mobile-layout-group-gap desktop:gap-desktop-layout-group-gap compact:gap-compact-layout-group-gap",
865
+ sizing === "layout" && "gap-mobile-layout-gap desktop:gap-desktop-layout-gap compact:gap-compact-layout-gap",
866
+ sizing === "container" && "gap-mobile-container-gap desktop:gap-desktop-container-gap compact:gap-compact-container-gap",
867
+ sizing === "component" && "gap-mobile-component-gap desktop:gap-desktop-component-gap compact:gap-compact-component-gap"
868
+ );
869
+ };
870
+ var Stack = (_a) => {
871
+ var _b = _a, {
872
+ children,
873
+ items,
874
+ justify,
875
+ grow,
876
+ padding,
877
+ paddingX,
878
+ paddingY,
879
+ margin,
880
+ marginX,
881
+ marginY,
882
+ horizontal,
883
+ horizontalMobile,
884
+ elevation = 0,
885
+ rounded,
886
+ centered,
887
+ width,
888
+ minHeight,
889
+ maxWidth,
890
+ minWidth,
891
+ height,
892
+ maxHeight,
893
+ borderColor,
894
+ backgroundColor,
895
+ sizing = "none",
896
+ overflowY = "inherit",
897
+ overflowX = "inherit",
898
+ flexShrink,
899
+ flexGrow,
900
+ position,
901
+ top,
902
+ left,
903
+ id,
904
+ noGap,
905
+ marginTop,
906
+ marginBottom
907
+ } = _b, props = __objRest(_b, [
908
+ "children",
909
+ "items",
910
+ "justify",
911
+ "grow",
912
+ "padding",
913
+ "paddingX",
914
+ "paddingY",
915
+ "margin",
916
+ "marginX",
917
+ "marginY",
918
+ "horizontal",
919
+ "horizontalMobile",
920
+ "elevation",
921
+ "rounded",
922
+ "centered",
923
+ "width",
924
+ "minHeight",
925
+ "maxWidth",
926
+ "minWidth",
927
+ "height",
928
+ "maxHeight",
929
+ "borderColor",
930
+ "backgroundColor",
931
+ "sizing",
932
+ "overflowY",
933
+ "overflowX",
934
+ "flexShrink",
935
+ "flexGrow",
936
+ "position",
937
+ "top",
938
+ "left",
939
+ "id",
940
+ "noGap",
941
+ "marginTop",
942
+ "marginBottom"
943
+ ]);
944
+ const flexClassNames = getFlexClassNames({ items, justify, grow });
945
+ const gapClassNames = useGapClassNames(sizing);
946
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
947
+ "div",
948
+ __spreadProps(__spreadValues({
949
+ id
950
+ }, props), {
951
+ style: {
952
+ height: height === "full" ? "100%" : height !== void 0 ? `${height}px` : void 0,
953
+ maxHeight: maxHeight !== void 0 ? `${maxHeight}px` : void 0,
954
+ minHeight: minHeight !== void 0 ? `${minHeight}px` : void 0,
955
+ maxWidth: maxWidth !== void 0 ? `${maxWidth}px` : void 0,
956
+ width: width !== void 0 && typeof width === "number" ? `${width}px` : void 0,
957
+ minWidth: minWidth !== void 0 ? `${minWidth}px` : void 0,
958
+ border: borderColor ? `1px solid var(--color-${borderColor})` : void 0,
959
+ backgroundColor: backgroundColor ? `var(--color-${backgroundColor})` : void 0,
960
+ flexGrow: flexGrow !== void 0 ? flexGrow : void 0,
961
+ flexShrink: flexShrink !== void 0 ? flexShrink : void 0,
962
+ position: position !== void 0 ? position : void 0,
963
+ top: top !== void 0 ? `${top}px` : void 0,
964
+ left: left !== void 0 ? `${left}px` : void 0
965
+ },
966
+ className: (0, import_clsx10.default)(
967
+ "scrollbar-thin",
968
+ "max-w-screen",
969
+ width !== "fit" && "w-full",
970
+ width === "full" && "w-full",
971
+ width === "max" && "w-max",
972
+ centered && "mx-auto",
973
+ overflowY == "auto" && "overflow-y-auto",
974
+ overflowY == "hidden" && "overflow-y-hidden",
975
+ overflowY == "scroll" && "overflow-y-scroll",
976
+ overflowX == "auto" && "overflow-x-auto",
977
+ overflowX == "hidden" && "overflow-x-hidden",
978
+ overflowX == "scroll" && "overflow-x-scroll",
979
+ padding && sizing === "container" && "p-mobile-container-padding desktop:p-desktop-container-padding compact:p-desktop-compact-container-padding",
980
+ padding && sizing === "layout" && "p-mobile-layout-padding desktop:p-desktop-layout-padding compact:p-desktop-compact-layout-padding",
981
+ padding && sizing === "layout-group" && "p-mobile-layout-group-padding desktop:p-desktop-layout-group-padding compact:p-desktop-compact-layout-group-padding",
982
+ padding && sizing === "component" && "p-mobile-component-padding desktop:p-desktop-component-padding compact:p-desktop-compact-component-padding",
983
+ paddingX && sizing === "container" && "px-mobile-container-padding desktop:px-desktop-container-padding compact:px-desktop-compact-container-padding",
984
+ paddingX && sizing === "layout" && "px-mobile-layout-padding desktop:px-desktop-layout-padding compact:px-desktop-compact-layout-padding",
985
+ paddingX && sizing === "layout-group" && "px-mobile-layout-group-padding desktop:px-desktop-layout-group-padding compact:px-desktop-compact-layout-group-padding",
986
+ paddingX && sizing === "component" && "px-mobile-component-padding desktop:px-desktop-component-padding compact:px-desktop-compact-component-padding",
987
+ paddingY && sizing === "container" && "py-mobile-container-padding desktop:py-desktop-container-padding compact:py-desktop-compact-container-padding",
988
+ paddingY && sizing === "layout" && "py-mobile-layout-padding desktop:py-desktop-layout-padding compact:py-desktop-compact-layout-padding",
989
+ paddingY && sizing === "layout-group" && paddingYUsingLayoutGroupGap,
990
+ paddingY && sizing === "component" && "py-mobile-component-padding desktop:py-desktop-component-padding compact:py-desktop-compact-component-padding",
991
+ margin && sizing === "container" && "m-mobile-container-padding desktop:m-desktop-container-padding compact:m-compact-container-padding",
992
+ marginX && sizing === "container" && "mx-mobile-container-padding desktop:mx-desktop-container-padding compact:mx-compact-container-padding",
993
+ marginTop && sizing === "container" && "mt-mobile-container-padding desktop:mt-desktop-container-padding compact:mt-compact-container-padding",
994
+ marginBottom && sizing === "container" && "mb-mobile-container-padding desktop:mb-desktop-container-padding compact:mb-compact-container-padding",
995
+ marginY && sizing === "container" && "my-mobile-container-padding desktop:my-desktop-container-padding compact:my-compact-container-padding",
996
+ horizontal ? "desktop:flex-row" : "desktop:flex-col",
997
+ horizontalMobile ? "flex-row" : "flex-col",
998
+ flexClassNames,
999
+ !noGap && gapClassNames,
1000
+ elevation === 0 && "shadow-none",
1001
+ elevation === 2 && "shadow-2",
1002
+ elevation === 4 && "shadow-4",
1003
+ elevation === 16 && "shadow-16",
1004
+ rounded && "rounded"
1005
+ ),
1006
+ children
1007
+ })
1008
+ );
1009
+ };
1010
+
1011
+ // src/components/Caption.tsx
1012
+ var import_clsx11 = __toESM(require("clsx"), 1);
1013
+ var import_jsx_runtime10 = require("react/jsx-runtime");
1014
+ var Caption = (_a) => {
1015
+ var _b = _a, {
1016
+ className,
1017
+ children,
1018
+ as = "span",
1019
+ style = "default",
1020
+ color,
1021
+ align,
1022
+ id
1023
+ } = _b, props = __objRest(_b, [
1024
+ "className",
1025
+ "children",
1026
+ "as",
1027
+ "style",
1028
+ "color",
1029
+ "align",
1030
+ "id"
1031
+ ]);
1032
+ const Element = as;
1033
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { id, className: "flex gap-1", children: [
1034
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1035
+ WhichIcon,
1036
+ {
1037
+ id,
1038
+ style,
1039
+ size: 16,
1040
+ className: "mt-[3px] desktop:mt-0"
1041
+ }
1042
+ ),
1043
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1044
+ Element,
1045
+ __spreadProps(__spreadValues({
1046
+ id: id ? `${id}-text` : void 0,
1047
+ className: (0, import_clsx11.default)(
1048
+ typography.caption.replace("text-text-primary-normal", ""),
1049
+ (style === "default" || style === "info") && "text-text-secondary-normal",
1050
+ style === "success" && "text-text-success-normal",
1051
+ style === "warning" && "text-text-warning-normal",
1052
+ style === "error" && "text-text-critical-normal",
1053
+ align === "left" && "text-left",
1054
+ align === "center" && "text-center",
1055
+ align === "right" && "text-right",
1056
+ className
1057
+ )
1058
+ }, props), {
1059
+ style: {
1060
+ color: color ? `var(--color-${color})` : void 0
1061
+ },
1062
+ children
1063
+ })
1064
+ )
1065
+ ] });
1066
+ };
1067
+ var WhichIcon = ({
1068
+ style,
1069
+ size,
1070
+ className,
1071
+ id
1072
+ }) => {
1073
+ if (style === "success") {
1074
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-icon-success-normal contents", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1075
+ Icon,
1076
+ {
1077
+ id: id ? `${id}-icon` : void 0,
1078
+ className,
1079
+ name: "check_circle",
1080
+ size
1081
+ }
1082
+ ) });
1083
+ }
1084
+ if (style === "warning") {
1085
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-icon-warning-normal contents", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1086
+ Icon,
1087
+ {
1088
+ id: id ? `${id}-icon` : void 0,
1089
+ className,
1090
+ name: "warning",
1091
+ size
1092
+ }
1093
+ ) });
1094
+ }
1095
+ if (style === "error") {
1096
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-icon-critical-normal contents", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1097
+ Icon,
1098
+ {
1099
+ id: id ? `${id}-icon` : void 0,
1100
+ className,
1101
+ name: "info",
1102
+ size
1103
+ }
1104
+ ) });
1105
+ }
1106
+ if (style === "info") {
1107
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-icon-primary-normal contents", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1108
+ Icon,
1109
+ {
1110
+ id: id ? `${id}-icon` : void 0,
1111
+ className,
1112
+ name: "info",
1113
+ size
1114
+ }
1115
+ ) });
1116
+ }
1117
+ return null;
1118
+ };
1119
+ Caption.displayName = "Caption";
1120
+
1121
+ // src/components/PDFViewer.tsx
1122
+ var import_jsx_runtime11 = require("react/jsx-runtime");
846
1123
  function PDFViewer(props) {
847
- const { base64, isOpen, onClose, datab64 } = props;
1124
+ const { isOpen, onClose, encodedPdfs, customActions } = props;
1125
+ const [currentIndex, setCurrentIndex] = (0, import_react6.useState)(0);
1126
+ const [isDownloading, setIsDownloading] = (0, import_react6.useState)(false);
1127
+ const handleDownload = (0, import_react6.useCallback)(() => {
1128
+ setIsDownloading(true);
1129
+ const link = document.createElement("a");
1130
+ link.href = `data:application/pdf;base64,${encodedPdfs[currentIndex].base64}`;
1131
+ link.download = encodedPdfs[currentIndex].fileName.endsWith(".pdf") ? encodedPdfs[currentIndex].fileName : `${encodedPdfs[currentIndex].fileName}.pdf`;
1132
+ document.body.appendChild(link);
1133
+ link.click();
1134
+ document.body.removeChild(link);
1135
+ setIsDownloading(false);
1136
+ }, [currentIndex, encodedPdfs]);
1137
+ if (!encodedPdfs.length) return null;
1138
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1139
+ Modal,
1140
+ {
1141
+ open: isOpen,
1142
+ onClose,
1143
+ showButtons: !!customActions,
1144
+ customActions,
1145
+ headerIcon: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(DownloadIcon, { onClick: handleDownload, isDownloading }),
1146
+ children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Stack, { sizing: "layout", children: [
1147
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(PDFElement, { b64: encodedPdfs[currentIndex].base64 }),
1148
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Stack, { horizontal: true, sizing: "layout-group", children: encodedPdfs.map((pdf, index) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1149
+ Button,
1150
+ {
1151
+ variant: index === currentIndex ? "primary" : "secondary",
1152
+ onClick: () => setCurrentIndex(index),
1153
+ disabled: isDownloading || currentIndex === index,
1154
+ children: pdf.fileName
1155
+ },
1156
+ `${pdf.fileName}-${index}`
1157
+ )) })
1158
+ ] })
1159
+ }
1160
+ );
1161
+ }
1162
+ function DownloadIcon({
1163
+ onClick,
1164
+ isDownloading
1165
+ }) {
1166
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1167
+ Button,
1168
+ {
1169
+ iconOnly: true,
1170
+ variant: "tertiary",
1171
+ leftIcon: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Icon, { name: isDownloading ? "cached" : "download" }),
1172
+ onClick
1173
+ }
1174
+ );
1175
+ }
1176
+ function PDFElement({ b64 }) {
848
1177
  const [page, setPage] = (0, import_react6.useState)(1);
849
1178
  const canvasRef = (0, import_react6.useRef)(null);
850
1179
  const { pdfDocument } = (0, import_react_pdf.usePdf)({
851
- file: datab64 ? datab64 : `data:application/pdf;base64,${base64}`,
1180
+ file: `data:application/pdf;base64,${b64}`,
852
1181
  workerSrc: "/scripts/pdf.worker.min.mjs",
853
1182
  page,
854
1183
  canvasRef,
855
1184
  scale: 1
856
1185
  });
857
- if (!base64 && !datab64) return null;
858
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Modal, { open: isOpen, onClose, hideCloseIcon: true, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex flex-col space-y-4", children: [
859
- pdfDocument ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("canvas", { ref: canvasRef }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { children: "Loading PDF..." }),
860
- Boolean(pdfDocument && pdfDocument.numPages) && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("ul", { className: "flex flex-row justify-between items-center", children: [
861
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("li", { className: "previous", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
862
- Button,
1186
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex flex-col space-y-4", children: [
1187
+ pdfDocument ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("canvas", { ref: canvasRef }) : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { children: "Loading PDF..." }),
1188
+ (pdfDocument == null ? void 0 : pdfDocument.numPages) && pdfDocument.numPages > 1 && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("ul", { className: "flex flex-row justify-between items-center", children: [
1189
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("li", { className: "previous", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1190
+ "button",
863
1191
  {
864
1192
  disabled: page === 1,
865
1193
  onClick: () => setPage(page - 1),
866
- variant: "navigation",
867
- children: "Previous"
1194
+ className: "not-disabled:cursor-pointer not-disabled:hover:underline ",
1195
+ children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Caption, { children: "Previous" })
868
1196
  }
869
1197
  ) }),
870
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("li", { className: "text-label-desktop text-text-on-action-primary-normal", children: [
1198
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("li", { className: "text-label-desktop text-text-on-action-primary-normal", children: [
871
1199
  "Page ",
872
1200
  page,
873
1201
  " of ",
874
1202
  pdfDocument.numPages
875
1203
  ] }),
876
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("li", { className: "next", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
877
- Button,
1204
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("li", { className: "next", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1205
+ "button",
878
1206
  {
879
1207
  disabled: page === pdfDocument.numPages,
880
1208
  onClick: () => setPage(page + 1),
881
- variant: "navigation",
882
- children: "Next"
1209
+ className: "not-disabled:cursor-pointer not-disabled:hover:underline ",
1210
+ children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Caption, { children: "Next" })
883
1211
  }
884
1212
  ) })
885
1213
  ] })
886
- ] }) });
1214
+ ] });
887
1215
  }
888
1216
  // Annotate the CommonJS export names for ESM import in node:
889
1217
  0 && (module.exports = {
@@ -8,41 +8,100 @@ import "../chunk-FWPJ73IK.js";
8
8
  import "../chunk-3JRVV6QY.js";
9
9
  import "../chunk-4JLU7TAC.js";
10
10
  import "../chunk-J6LETUNM.js";
11
+ import {
12
+ Caption
13
+ } from "../chunk-6HIALT5L.js";
11
14
  import "../chunk-WNQ53SVY.js";
12
15
  import "../chunk-4T7F5BZZ.js";
16
+ import {
17
+ Stack
18
+ } from "../chunk-EO3JJWFW.js";
13
19
  import {
14
20
  Button
15
21
  } from "../chunk-L364HTYC.js";
16
- import "../chunk-IGQVA7SC.js";
22
+ import {
23
+ Icon
24
+ } from "../chunk-IGQVA7SC.js";
17
25
  import "../chunk-RDLEIAQU.js";
18
26
  import "../chunk-ORMEWXMH.js";
19
27
 
20
28
  // src/components/PDFViewer.tsx
21
29
  import { usePdf } from "@mikecousins/react-pdf";
22
- import { useRef, useState } from "react";
30
+ import { useCallback, useRef, useState } from "react";
23
31
  import { jsx, jsxs } from "react/jsx-runtime";
24
32
  function PDFViewer(props) {
25
- const { base64, isOpen, onClose, datab64 } = props;
33
+ const { isOpen, onClose, encodedPdfs, customActions } = props;
34
+ const [currentIndex, setCurrentIndex] = useState(0);
35
+ const [isDownloading, setIsDownloading] = useState(false);
36
+ const handleDownload = useCallback(() => {
37
+ setIsDownloading(true);
38
+ const link = document.createElement("a");
39
+ link.href = `data:application/pdf;base64,${encodedPdfs[currentIndex].base64}`;
40
+ link.download = encodedPdfs[currentIndex].fileName.endsWith(".pdf") ? encodedPdfs[currentIndex].fileName : `${encodedPdfs[currentIndex].fileName}.pdf`;
41
+ document.body.appendChild(link);
42
+ link.click();
43
+ document.body.removeChild(link);
44
+ setIsDownloading(false);
45
+ }, [currentIndex, encodedPdfs]);
46
+ if (!encodedPdfs.length) return null;
47
+ return /* @__PURE__ */ jsx(
48
+ Modal,
49
+ {
50
+ open: isOpen,
51
+ onClose,
52
+ showButtons: !!customActions,
53
+ customActions,
54
+ headerIcon: /* @__PURE__ */ jsx(DownloadIcon, { onClick: handleDownload, isDownloading }),
55
+ children: /* @__PURE__ */ jsxs(Stack, { sizing: "layout", children: [
56
+ /* @__PURE__ */ jsx(PDFElement, { b64: encodedPdfs[currentIndex].base64 }),
57
+ /* @__PURE__ */ jsx(Stack, { horizontal: true, sizing: "layout-group", children: encodedPdfs.map((pdf, index) => /* @__PURE__ */ jsx(
58
+ Button,
59
+ {
60
+ variant: index === currentIndex ? "primary" : "secondary",
61
+ onClick: () => setCurrentIndex(index),
62
+ disabled: isDownloading || currentIndex === index,
63
+ children: pdf.fileName
64
+ },
65
+ `${pdf.fileName}-${index}`
66
+ )) })
67
+ ] })
68
+ }
69
+ );
70
+ }
71
+ function DownloadIcon({
72
+ onClick,
73
+ isDownloading
74
+ }) {
75
+ return /* @__PURE__ */ jsx(
76
+ Button,
77
+ {
78
+ iconOnly: true,
79
+ variant: "tertiary",
80
+ leftIcon: /* @__PURE__ */ jsx(Icon, { name: isDownloading ? "cached" : "download" }),
81
+ onClick
82
+ }
83
+ );
84
+ }
85
+ function PDFElement({ b64 }) {
26
86
  const [page, setPage] = useState(1);
27
87
  const canvasRef = useRef(null);
28
88
  const { pdfDocument } = usePdf({
29
- file: datab64 ? datab64 : `data:application/pdf;base64,${base64}`,
89
+ file: `data:application/pdf;base64,${b64}`,
30
90
  workerSrc: "/scripts/pdf.worker.min.mjs",
31
91
  page,
32
92
  canvasRef,
33
93
  scale: 1
34
94
  });
35
- if (!base64 && !datab64) return null;
36
- return /* @__PURE__ */ jsx(Modal, { open: isOpen, onClose, hideCloseIcon: true, children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col space-y-4", children: [
95
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col space-y-4", children: [
37
96
  pdfDocument ? /* @__PURE__ */ jsx("canvas", { ref: canvasRef }) : /* @__PURE__ */ jsx("div", { children: "Loading PDF..." }),
38
- Boolean(pdfDocument && pdfDocument.numPages) && /* @__PURE__ */ jsxs("ul", { className: "flex flex-row justify-between items-center", children: [
97
+ (pdfDocument == null ? void 0 : pdfDocument.numPages) && pdfDocument.numPages > 1 && /* @__PURE__ */ jsxs("ul", { className: "flex flex-row justify-between items-center", children: [
39
98
  /* @__PURE__ */ jsx("li", { className: "previous", children: /* @__PURE__ */ jsx(
40
- Button,
99
+ "button",
41
100
  {
42
101
  disabled: page === 1,
43
102
  onClick: () => setPage(page - 1),
44
- variant: "navigation",
45
- children: "Previous"
103
+ className: "not-disabled:cursor-pointer not-disabled:hover:underline ",
104
+ children: /* @__PURE__ */ jsx(Caption, { children: "Previous" })
46
105
  }
47
106
  ) }),
48
107
  /* @__PURE__ */ jsxs("li", { className: "text-label-desktop text-text-on-action-primary-normal", children: [
@@ -52,16 +111,16 @@ function PDFViewer(props) {
52
111
  pdfDocument.numPages
53
112
  ] }),
54
113
  /* @__PURE__ */ jsx("li", { className: "next", children: /* @__PURE__ */ jsx(
55
- Button,
114
+ "button",
56
115
  {
57
116
  disabled: page === pdfDocument.numPages,
58
117
  onClick: () => setPage(page + 1),
59
- variant: "navigation",
60
- children: "Next"
118
+ className: "not-disabled:cursor-pointer not-disabled:hover:underline ",
119
+ children: /* @__PURE__ */ jsx(Caption, { children: "Next" })
61
120
  }
62
121
  ) })
63
122
  ] })
64
- ] }) });
123
+ ] });
65
124
  }
66
125
  export {
67
126
  PDFViewer
package/dist/index.css CHANGED
@@ -2419,6 +2419,11 @@
2419
2419
  padding-block: var(--spacing-mobile-component-padding);
2420
2420
  }
2421
2421
  }
2422
+ .not-disabled\:cursor-pointer {
2423
+ &:not(*:disabled) {
2424
+ cursor: pointer;
2425
+ }
2426
+ }
2422
2427
  .group-hover\:block {
2423
2428
  &:is(:where(.group):hover *) {
2424
2429
  @media (hover: hover) {
@@ -2976,6 +2981,15 @@
2976
2981
  }
2977
2982
  }
2978
2983
  }
2984
+ .not-disabled\:hover\:underline {
2985
+ &:not(*:disabled) {
2986
+ &:hover {
2987
+ @media (hover: hover) {
2988
+ text-decoration-line: underline;
2989
+ }
2990
+ }
2991
+ }
2992
+ }
2979
2993
  .focus\:border-background-action-critical-primary-hover {
2980
2994
  &:focus {
2981
2995
  border-color: var(--color-background-action-critical-primary-hover);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@dmsi/wedgekit-react",
3
3
  "private": false,
4
- "version": "0.0.88",
4
+ "version": "0.0.90",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "build": "tsup",
@@ -1,63 +1,128 @@
1
1
  "use client";
2
2
 
3
3
  import { usePdf } from "@mikecousins/react-pdf";
4
- import { useRef, useState } from "react";
4
+ import { useCallback, useRef, useState } from "react";
5
5
  import { Modal } from "./Modal";
6
6
  import { Button } from "./Button";
7
+ import { Icon } from "./Icon";
8
+ import { Stack } from "./Stack";
9
+ import { Caption } from "./Caption";
7
10
 
8
11
  type PDFViewerProps = {
9
12
  isOpen: boolean;
10
13
  onClose: () => void;
11
- base64: string;
12
- datab64?: string;
14
+ encodedPdfs: { fileName: string; base64: string }[];
15
+ customActions?: React.ReactNode;
13
16
  };
14
17
 
15
18
  export function PDFViewer(props: PDFViewerProps) {
16
- const { base64, isOpen, onClose, datab64 } = props;
17
- const [page, setPage] = useState(1);
19
+ const { isOpen, onClose, encodedPdfs, customActions } = props;
20
+ const [currentIndex, setCurrentIndex] = useState(0);
21
+ const [isDownloading, setIsDownloading] = useState(false);
22
+
23
+ const handleDownload = useCallback(() => {
24
+ setIsDownloading(true);
25
+ const link = document.createElement("a");
26
+ link.href = `data:application/pdf;base64,${
27
+ encodedPdfs[currentIndex].base64
28
+ }`;
29
+ link.download = encodedPdfs[currentIndex].fileName.endsWith(".pdf")
30
+ ? encodedPdfs[currentIndex].fileName
31
+ : `${encodedPdfs[currentIndex].fileName}.pdf`;
32
+ document.body.appendChild(link);
33
+ link.click();
34
+ document.body.removeChild(link);
35
+ setIsDownloading(false);
36
+ }, [currentIndex, encodedPdfs]);
37
+
38
+ if (!encodedPdfs.length) return null;
39
+
40
+ return (
41
+ <Modal
42
+ open={isOpen}
43
+ onClose={onClose}
44
+ showButtons={!!customActions}
45
+ customActions={customActions}
46
+ headerIcon={
47
+ <DownloadIcon onClick={handleDownload} isDownloading={isDownloading} />
48
+ }
49
+ >
50
+ <Stack sizing="layout">
51
+ <PDFElement b64={encodedPdfs[currentIndex].base64} />
52
+ <Stack horizontal sizing="layout-group">
53
+ {encodedPdfs.map((pdf, index) => (
54
+ <Button
55
+ variant={index === currentIndex ? "primary" : "secondary"}
56
+ key={`${pdf.fileName}-${index}`}
57
+ onClick={() => setCurrentIndex(index)}
58
+ disabled={isDownloading || currentIndex === index}
59
+ >
60
+ {pdf.fileName}
61
+ </Button>
62
+ ))}
63
+ </Stack>
64
+ </Stack>
65
+ </Modal>
66
+ );
67
+ }
18
68
 
69
+ function DownloadIcon({
70
+ onClick,
71
+ isDownloading,
72
+ }: {
73
+ onClick: () => void;
74
+ isDownloading?: boolean;
75
+ }) {
76
+ return (
77
+ <Button
78
+ iconOnly
79
+ variant="tertiary"
80
+ leftIcon={<Icon name={isDownloading ? "cached" : "download"} />}
81
+ onClick={onClick}
82
+ />
83
+ );
84
+ }
85
+
86
+ function PDFElement({ b64 }: { b64: string }) {
87
+ const [page, setPage] = useState(1);
19
88
  const canvasRef = useRef(null);
20
89
 
21
90
  const { pdfDocument } = usePdf({
22
- file: datab64 ? datab64 : `data:application/pdf;base64,${base64}`,
91
+ file: `data:application/pdf;base64,${b64}`,
23
92
  workerSrc: "/scripts/pdf.worker.min.mjs",
24
93
  page,
25
94
  canvasRef,
26
95
  scale: 1,
27
96
  });
28
97
 
29
- if (!base64 && !datab64) return null;
30
-
31
98
  return (
32
- <Modal open={isOpen} onClose={onClose} hideCloseIcon>
33
- <div className="flex flex-col space-y-4">
34
- {pdfDocument ? <canvas ref={canvasRef} /> : <div>Loading PDF...</div>}
35
- {Boolean(pdfDocument && pdfDocument.numPages) && (
36
- <ul className="flex flex-row justify-between items-center">
37
- <li className="previous">
38
- <Button
39
- disabled={page === 1}
40
- onClick={() => setPage(page - 1)}
41
- variant="navigation"
42
- >
43
- Previous
44
- </Button>
45
- </li>
46
- <li className="text-label-desktop text-text-on-action-primary-normal">
47
- Page {page} of {pdfDocument!.numPages}
48
- </li>
49
- <li className="next">
50
- <Button
51
- disabled={page === pdfDocument!.numPages}
52
- onClick={() => setPage(page + 1)}
53
- variant="navigation"
54
- >
55
- Next
56
- </Button>
57
- </li>
58
- </ul>
59
- )}
60
- </div>
61
- </Modal>
99
+ <div className="flex flex-col space-y-4">
100
+ {pdfDocument ? <canvas ref={canvasRef} /> : <div>Loading PDF...</div>}
101
+ {pdfDocument?.numPages && pdfDocument.numPages > 1 && (
102
+ <ul className="flex flex-row justify-between items-center">
103
+ <li className="previous">
104
+ <button
105
+ disabled={page === 1}
106
+ onClick={() => setPage(page - 1)}
107
+ className="not-disabled:cursor-pointer not-disabled:hover:underline "
108
+ >
109
+ <Caption>Previous</Caption>
110
+ </button>
111
+ </li>
112
+ <li className="text-label-desktop text-text-on-action-primary-normal">
113
+ Page {page} of {pdfDocument!.numPages}
114
+ </li>
115
+ <li className="next">
116
+ <button
117
+ disabled={page === pdfDocument!.numPages}
118
+ onClick={() => setPage(page + 1)}
119
+ className="not-disabled:cursor-pointer not-disabled:hover:underline "
120
+ >
121
+ <Caption>Next</Caption>
122
+ </button>
123
+ </li>
124
+ </ul>
125
+ )}
126
+ </div>
62
127
  );
63
128
  }