@dmsi/wedgekit-react 0.0.171 → 0.0.173

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.
@@ -241,6 +241,8 @@ export function DataCellHeader<T>({
241
241
  predeterminedPinned.current = [...left, ...right].includes(
242
242
  header.column.id,
243
243
  );
244
+ // header is stable for the lifetime of the header cell
245
+ // eslint-disable-next-line react-hooks/exhaustive-deps
244
246
  }, []);
245
247
 
246
248
  useEffect(() => {
@@ -251,12 +253,14 @@ export function DataCellHeader<T>({
251
253
  return () => {
252
254
  clearTimeout(handler);
253
255
  };
256
+ // We only want to react to filter changes; header.column methods are stable
257
+ // eslint-disable-next-line react-hooks/exhaustive-deps
254
258
  }, [filter]);
255
259
 
256
260
  const style: CSSProperties = {
257
261
  position: "relative",
258
262
  whiteSpace: "nowrap",
259
- width: header.column.getSize(),
263
+ width: header.column.columnDef.meta?.headerWidth ?? header.column.getSize(),
260
264
  "--color-text-primary-normal": "var(--color-text-brand-primary-normal)",
261
265
  "--color-icon-on-action-primary-normal":
262
266
  "var(--color-text-brand-primary-normal)",
@@ -466,7 +470,7 @@ export function DraggableCellHeader<T extends Record<string, any>>({
466
470
  transition: "width transform 0.2s ease-in-out",
467
471
  whiteSpace: "nowrap",
468
472
  zIndex: isDragging ? 1 : 0,
469
- width: header.column.getSize(),
473
+ width: header.column.columnDef.meta?.headerWidth ?? header.column.getSize(),
470
474
  "--color-text-primary-normal": "var(--color-action-000)",
471
475
  "--color-icon-on-action-primary-normal": "var(--color-action-000)",
472
476
  userSelect: "none",
@@ -506,12 +510,20 @@ export function DragAlongCell<T extends RowData, TValue>({
506
510
  position: "relative",
507
511
  transform: CSS.Translate.toString(transform),
508
512
  transition: "width transform 0.2s ease-in-out",
509
- width: cell.column.getSize(),
513
+ width: cell.column.columnDef.meta?.headerWidth ?? cell.column.getSize(),
510
514
  zIndex: isDragging ? 1 : 0,
511
515
  };
512
516
 
513
517
  return (
514
- <DataGridCell style={style} ref={setNodeRef} {...props}>
518
+ <DataGridCell
519
+ style={style}
520
+ ref={setNodeRef}
521
+ width={
522
+ (cell.column.columnDef.meta?.headerWidth as string | undefined) ??
523
+ `${cell.column.getSize()}px`
524
+ }
525
+ {...props}
526
+ >
515
527
  {children}
516
528
  </DataGridCell>
517
529
  );
@@ -25,6 +25,7 @@ type ModalProps = PropsWithChildren<{
25
25
  showButtons?: boolean;
26
26
  hideCloseIcon?: boolean;
27
27
  headerIcon?: React.ReactNode;
28
+ headerIconAlign?: "left" | "center" | "right";
28
29
  fixedHeightScrolling?: boolean;
29
30
  customActions?: React.ReactNode;
30
31
  }>;
@@ -117,6 +118,7 @@ export const Modal = ({
117
118
  showButtons = false,
118
119
  hideCloseIcon = false,
119
120
  headerIcon,
121
+ headerIconAlign,
120
122
  fixedHeightScrolling = false,
121
123
  customActions,
122
124
  }: ModalProps) => {
@@ -150,7 +152,7 @@ export const Modal = ({
150
152
  fadeInScale(modalRef.current);
151
153
  bgFadeIn(bgRef.current);
152
154
  }
153
- }, [mounted, open]);
155
+ }, [mounted, onClose, open, wasOpen]);
154
156
 
155
157
  const handleKeyDown = useCallback(
156
158
  (e: KeyboardEvent) => {
@@ -161,7 +163,7 @@ export const Modal = ({
161
163
  }
162
164
  }
163
165
  },
164
- [onClose, bgRef, modalRef],
166
+ [onClose],
165
167
  );
166
168
 
167
169
  const handleClose = useCallback(() => {
@@ -259,6 +261,7 @@ export const Modal = ({
259
261
  onClose={handleClose}
260
262
  hideCloseIcon={hideCloseIcon}
261
263
  headerIcon={headerIcon}
264
+ headerIconAlign={headerIconAlign}
262
265
  />
263
266
  {children && (
264
267
  <ModalContent
@@ -9,6 +9,7 @@ type ModalHeaderProps = {
9
9
  title?: string;
10
10
  hideCloseIcon?: boolean;
11
11
  headerIcon?: React.ReactNode;
12
+ headerIconAlign?: "left" | "center" | "right";
12
13
  onClose?: () => void;
13
14
  id?: string;
14
15
  testid?: string;
@@ -18,6 +19,7 @@ export const ModalHeader = ({
18
19
  title,
19
20
  hideCloseIcon,
20
21
  headerIcon,
22
+ headerIconAlign,
21
23
  onClose,
22
24
  id,
23
25
  testid,
@@ -28,6 +30,9 @@ export const ModalHeader = ({
28
30
  data-testid={testid}
29
31
  className={clsx(
30
32
  "flex justify-between items-center",
33
+ headerIconAlign === "center" && "justify-center",
34
+ headerIconAlign === "right" && "justify-end",
35
+ headerIconAlign === "left" && "justify-start",
31
36
  layoutPaddding,
32
37
  layoutGroupGap,
33
38
  )}
@@ -35,7 +40,11 @@ export const ModalHeader = ({
35
40
  <div className={clsx("flex items-center", layoutGroupGap)}>
36
41
  {headerIcon}
37
42
  {title && (
38
- <Heading2 id={id ? `${id}-title` : undefined} testid={testid ? `${testid}-title` : undefined} as="p">
43
+ <Heading2
44
+ id={id ? `${id}-title` : undefined}
45
+ testid={testid ? `${testid}-title` : undefined}
46
+ as="p"
47
+ >
39
48
  {title}
40
49
  </Heading2>
41
50
  )}
@@ -8,6 +8,8 @@ import { Icon } from "./Icon";
8
8
  import { Stack } from "./Stack";
9
9
  import { Caption } from "./Caption";
10
10
  import { Spinner } from "./Spinner";
11
+ import { Paragraph } from "./Paragraph";
12
+ import { Heading3 } from "./Heading";
11
13
 
12
14
  type PDFViewerProps = {
13
15
  isOpen: boolean;
@@ -42,13 +44,34 @@ export function PDFViewer(props: PDFViewerProps) {
42
44
 
43
45
  if (!encodedPdfs.length) return null;
44
46
 
47
+ function handleNextFile() {
48
+ if (currentIndex < encodedPdfs.length - 1) {
49
+ setCurrentIndex((prev) => prev + 1);
50
+ }
51
+ }
52
+
53
+ function handlePreviousFile() {
54
+ if (currentIndex > 0) {
55
+ setCurrentIndex((prev) => prev - 1);
56
+ }
57
+ }
58
+
59
+ function handleClose() {
60
+ setCurrentIndex(0);
61
+ setIsDownloading(false);
62
+ onClose();
63
+ }
64
+
45
65
  return (
46
66
  <Modal
47
67
  testid={testid}
48
68
  open={isOpen}
49
- onClose={onClose}
69
+ onClose={handleClose}
50
70
  showButtons={!!customActions}
51
71
  customActions={customActions}
72
+ size="large"
73
+ fixedHeightScrolling
74
+ headerIconAlign="right"
52
75
  headerIcon={
53
76
  <DownloadIcon
54
77
  testid={testid ? `${testid}-download-icon` : undefined}
@@ -56,11 +79,44 @@ export function PDFViewer(props: PDFViewerProps) {
56
79
  isDownloading={isDownloading}
57
80
  />
58
81
  }
82
+ className="!max-w-fit"
59
83
  >
60
- <Stack sizing="layout">
84
+ <Stack sizing="layout" items="center">
61
85
  <PDFElement testid={testid} b64={encodedPdfs[currentIndex].base64} />
62
- <Stack horizontal overflowX="auto" sizing="layout-group">
63
- {encodedPdfs.map((pdf, index) => (
86
+ {!!encodedPdfs[currentIndex].fileName && (
87
+ <Paragraph>
88
+ {encodedPdfs[currentIndex].fileName.endsWith(".pdf")
89
+ ? encodedPdfs[currentIndex].fileName
90
+ : `${encodedPdfs[currentIndex].fileName}.pdf`}
91
+ </Paragraph>
92
+ )}
93
+ <Stack
94
+ horizontal
95
+ overflowX="auto"
96
+ justify="center"
97
+ items="center"
98
+ sizing="layout-group"
99
+ >
100
+ <Button
101
+ iconOnly
102
+ variant="tertiary"
103
+ onClick={handlePreviousFile}
104
+ leftIcon={<Icon name="chevron_backward" />}
105
+ disabled={currentIndex === 0}
106
+ testid={testid ? `${testid}-pdf-file-previous-button` : undefined}
107
+ />
108
+ <Heading3 className="text-text-primary-normal">
109
+ {currentIndex + 1} / {encodedPdfs.length}
110
+ </Heading3>
111
+ <Button
112
+ iconOnly
113
+ variant="tertiary"
114
+ onClick={handleNextFile}
115
+ rightIcon={<Icon name="chevron_forward" />}
116
+ disabled={currentIndex === encodedPdfs.length - 1}
117
+ testid={testid ? `${testid}-pdf-file-next-button` : undefined}
118
+ />
119
+ {/* {encodedPdfs.map((pdf, index) => (
64
120
  <Button
65
121
  testid={testid ? `${testid}-${pdf.fileName}-button` : undefined}
66
122
  variant={index === currentIndex ? "primary" : "secondary"}
@@ -84,7 +140,7 @@ export function PDFViewer(props: PDFViewerProps) {
84
140
  {!pdf.base64 && <Spinner />}
85
141
  {pdf.fileName}
86
142
  </Button>
87
- ))}
143
+ ))} */}
88
144
  </Stack>
89
145
  </Stack>
90
146
  </Modal>
@@ -120,20 +176,32 @@ function PDFElement({ b64, testid }: { b64: string; testid?: string }) {
120
176
  workerSrc: "/scripts/pdf.worker.min.mjs",
121
177
  page,
122
178
  canvasRef,
123
- scale: 1,
179
+ scale: 1.1,
124
180
  });
125
181
 
126
182
  return (
127
- <div className="flex flex-col space-y-4">
128
- {pdfDocument ? (
183
+ <div
184
+ className="flex flex-col space-y-4 "
185
+ style={{
186
+ minHeight: 871,
187
+ minWidth: 654,
188
+ }}
189
+ >
190
+ {!!pdfDocument && !!b64 ? (
129
191
  <canvas
130
192
  data-testid={testid ? `${testid}-pdf-content` : undefined}
131
193
  ref={canvasRef}
132
194
  />
133
195
  ) : (
134
- <div data-testid={testid ? `${testid}-pdf-loading` : undefined}>
135
- Loading PDF...
136
- </div>
196
+ <Stack
197
+ justify="center"
198
+ items="center"
199
+ height="full"
200
+ flexGrow={1}
201
+ data-testid={testid ? `${testid}-pdf-loading` : undefined}
202
+ >
203
+ <Spinner size="large" />
204
+ </Stack>
137
205
  )}
138
206
  {pdfDocument?.numPages && pdfDocument.numPages > 1 && (
139
207
  <ul
@@ -149,12 +217,14 @@ function PDFElement({ b64, testid }: { b64: string; testid?: string }) {
149
217
  onClick={() => setPage(page - 1)}
150
218
  className="not-disabled:cursor-pointer not-disabled:hover:underline "
151
219
  >
152
- <Caption>Previous</Caption>
220
+ <Caption className="not-disabled:cursor-pointer not-disabled:hover:underline not-disabled:text-text-primary-normal">
221
+ Previous
222
+ </Caption>
153
223
  </button>
154
224
  </li>
155
225
  <li
156
226
  data-testid={testid ? `${testid}-pdf-pagination-text` : undefined}
157
- className="text-label-desktop text-text-on-action-primary-normal"
227
+ className="text-label-desktop text-text-primary-normal"
158
228
  >
159
229
  Page{" "}
160
230
  <span
@@ -182,9 +252,10 @@ function PDFElement({ b64, testid }: { b64: string; testid?: string }) {
182
252
  }
183
253
  disabled={page === pdfDocument!.numPages}
184
254
  onClick={() => setPage(page + 1)}
185
- className="not-disabled:cursor-pointer not-disabled:hover:underline "
186
255
  >
187
- <Caption>Next</Caption>
256
+ <Caption className="not-disabled:cursor-pointer not-disabled:hover:underline not-disabled:text-text-primary-normal">
257
+ Next
258
+ </Caption>
188
259
  </button>
189
260
  </li>
190
261
  </ul>