@ayasofyazilim/ui 0.0.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/__mocks__/canvas.ts +8 -0
- package/components.json +21 -0
- package/eslint.config.js +4 -0
- package/jest-environment.js +37 -0
- package/jest.config.ts +47 -0
- package/jest.setup.ts +69 -0
- package/package.json +124 -0
- package/postcss.config.mjs +6 -0
- package/src/aria/index.tsx +1 -0
- package/src/aria/number-field.tsx +41 -0
- package/src/components/.gitkeep +0 -0
- package/src/components/accordion.tsx +66 -0
- package/src/components/alert-dialog.tsx +157 -0
- package/src/components/alert.tsx +70 -0
- package/src/components/aspect-ratio.tsx +11 -0
- package/src/components/avatar.tsx +53 -0
- package/src/components/badge.tsx +67 -0
- package/src/components/breadcrumb.tsx +109 -0
- package/src/components/button-group.tsx +83 -0
- package/src/components/button.tsx +68 -0
- package/src/components/calendar.tsx +219 -0
- package/src/components/card.tsx +92 -0
- package/src/components/carousel.tsx +241 -0
- package/src/components/chart.tsx +363 -0
- package/src/components/checkbox.tsx +32 -0
- package/src/components/collapsible.tsx +33 -0
- package/src/components/command.tsx +184 -0
- package/src/components/context-menu.tsx +252 -0
- package/src/components/dialog.tsx +144 -0
- package/src/components/drawer.tsx +135 -0
- package/src/components/dropdown-menu.tsx +258 -0
- package/src/components/empty.tsx +100 -0
- package/src/components/field.tsx +248 -0
- package/src/components/form.tsx +169 -0
- package/src/components/hover-card.tsx +44 -0
- package/src/components/input-group.tsx +170 -0
- package/src/components/input-otp.tsx +77 -0
- package/src/components/input.tsx +21 -0
- package/src/components/item.tsx +193 -0
- package/src/components/kbd.tsx +28 -0
- package/src/components/label.tsx +24 -0
- package/src/components/menubar.tsx +276 -0
- package/src/components/navigation-menu.tsx +168 -0
- package/src/components/pagination.tsx +130 -0
- package/src/components/popover.tsx +88 -0
- package/src/components/progress.tsx +31 -0
- package/src/components/radio-group.tsx +45 -0
- package/src/components/resizable.tsx +56 -0
- package/src/components/scroll-area.tsx +58 -0
- package/src/components/select.tsx +189 -0
- package/src/components/separator.tsx +28 -0
- package/src/components/sheet.tsx +140 -0
- package/src/components/sidebar.tsx +862 -0
- package/src/components/skeleton.tsx +13 -0
- package/src/components/slider.tsx +63 -0
- package/src/components/sonner.tsx +40 -0
- package/src/components/spinner.tsx +16 -0
- package/src/components/stepper.tsx +291 -0
- package/src/components/switch.tsx +31 -0
- package/src/components/table.tsx +133 -0
- package/src/components/tabs.tsx +66 -0
- package/src/components/textarea.tsx +18 -0
- package/src/components/toggle-group.tsx +83 -0
- package/src/components/toggle.tsx +47 -0
- package/src/components/tooltip.tsx +66 -0
- package/src/custom/action-button.tsx +48 -0
- package/src/custom/async-select.tsx +287 -0
- package/src/custom/awesome-not-found.tsx +116 -0
- package/src/custom/charts/area-chart.tsx +147 -0
- package/src/custom/charts/bar-chart.tsx +233 -0
- package/src/custom/charts/chart-card.tsx +103 -0
- package/src/custom/charts/index.tsx +16 -0
- package/src/custom/charts/pie-chart.tsx +168 -0
- package/src/custom/charts/radar-chart.tsx +126 -0
- package/src/custom/checkbox-tree.tsx +100 -0
- package/src/custom/combobox.tsx +296 -0
- package/src/custom/confirm-dialog.tsx +102 -0
- package/src/custom/country-selector.tsx +204 -0
- package/src/custom/date-picker/calendar-rac.tsx +109 -0
- package/src/custom/date-picker/datefield-rac.tsx +84 -0
- package/src/custom/date-picker/index.tsx +273 -0
- package/src/custom/date-picker/types/index.ts +4 -0
- package/src/custom/date-picker/utils/index.ts +42 -0
- package/src/custom/date-picker-old.tsx +50 -0
- package/src/custom/date-tooltip.tsx +98 -0
- package/src/custom/document-scanner/consts.ts +5 -0
- package/src/custom/document-scanner/corner-adjustment/action-buttons.tsx +33 -0
- package/src/custom/document-scanner/corner-adjustment/corner-handle.tsx +43 -0
- package/src/custom/document-scanner/corner-adjustment/hooks/use-corner-drag.ts +85 -0
- package/src/custom/document-scanner/corner-adjustment/index.tsx +125 -0
- package/src/custom/document-scanner/corner-adjustment/types.ts +53 -0
- package/src/custom/document-scanner/corner-adjustment/utils/clip-path.ts +22 -0
- package/src/custom/document-scanner/corner-adjustment/zoom-magnifier.tsx +115 -0
- package/src/custom/document-scanner/hooks/use-document-capture.ts +81 -0
- package/src/custom/document-scanner/hooks/use-document-scanner.ts +80 -0
- package/src/custom/document-scanner/hooks/use-perspective-crop.ts +38 -0
- package/src/custom/document-scanner/index.tsx +255 -0
- package/src/custom/document-scanner/lib.ts +407 -0
- package/src/custom/document-scanner/types.ts +205 -0
- package/src/custom/document-scanner/utils/perspective-correction.ts +139 -0
- package/src/custom/document-viewer/controllers.tsx +98 -0
- package/src/custom/document-viewer/index.tsx +43 -0
- package/src/custom/document-viewer/renderers/image.tsx +37 -0
- package/src/custom/document-viewer/renderers/index.tsx +2 -0
- package/src/custom/document-viewer/renderers/pdf.tsx +105 -0
- package/src/custom/email-input/domains.json +159 -0
- package/src/custom/email-input/email.tsx +229 -0
- package/src/custom/email-input/index.tsx +4 -0
- package/src/custom/email-input/types.ts +104 -0
- package/src/custom/file-uploader.tsx +541 -0
- package/src/custom/filter-component/fields/async-select.tsx +33 -0
- package/src/custom/filter-component/fields/date.tsx +60 -0
- package/src/custom/filter-component/fields/multi-select.tsx +30 -0
- package/src/custom/filter-component/index.tsx +217 -0
- package/src/custom/image-canvas.tsx +260 -0
- package/src/custom/json-editor.tsx +22 -0
- package/src/custom/master-data-grid/components/dialogs/column-settings-dialog.tsx +100 -0
- package/src/custom/master-data-grid/components/dialogs/index.ts +1 -0
- package/src/custom/master-data-grid/components/filters/client-filter.tsx +368 -0
- package/src/custom/master-data-grid/components/filters/filter-input.tsx +256 -0
- package/src/custom/master-data-grid/components/filters/index.ts +3 -0
- package/src/custom/master-data-grid/components/filters/inline-column-filter.tsx +233 -0
- package/src/custom/master-data-grid/components/filters/multi-filter-dialog.tsx +90 -0
- package/src/custom/master-data-grid/components/filters/server-filter.tsx +255 -0
- package/src/custom/master-data-grid/components/master-data-grid.tsx +472 -0
- package/src/custom/master-data-grid/components/pagination/index.ts +1 -0
- package/src/custom/master-data-grid/components/pagination/pagination.tsx +178 -0
- package/src/custom/master-data-grid/components/table/cell-renderer.tsx +634 -0
- package/src/custom/master-data-grid/components/table/header-cell.tsx +162 -0
- package/src/custom/master-data-grid/components/table/index.ts +4 -0
- package/src/custom/master-data-grid/components/table/table-body-renderer.tsx +113 -0
- package/src/custom/master-data-grid/components/table/virtual-body.tsx +138 -0
- package/src/custom/master-data-grid/components/toolbar/index.ts +1 -0
- package/src/custom/master-data-grid/components/toolbar/toolbar.tsx +314 -0
- package/src/custom/master-data-grid/hooks/index.ts +3 -0
- package/src/custom/master-data-grid/hooks/use-columns.tsx +332 -0
- package/src/custom/master-data-grid/hooks/use-editing.ts +106 -0
- package/src/custom/master-data-grid/hooks/use-table-state-reducer.ts +157 -0
- package/src/custom/master-data-grid/hooks/use-table-state.ts +31 -0
- package/src/custom/master-data-grid/index.ts +16 -0
- package/src/custom/master-data-grid/types.ts +466 -0
- package/src/custom/master-data-grid/utils/column-generator.tsx +306 -0
- package/src/custom/master-data-grid/utils/export-utils.ts +67 -0
- package/src/custom/master-data-grid/utils/filter-fns.ts +290 -0
- package/src/custom/master-data-grid/utils/index.ts +8 -0
- package/src/custom/master-data-grid/utils/pinning-utils.ts +88 -0
- package/src/custom/master-data-grid/utils/translation-utils.ts +42 -0
- package/src/custom/multi-select.tsx +432 -0
- package/src/custom/password-input.tsx +194 -0
- package/src/custom/phone-input.tsx +172 -0
- package/src/custom/schema-form/custom/index.tsx +1 -0
- package/src/custom/schema-form/custom/label.tsx +53 -0
- package/src/custom/schema-form/fields/base-input-field.tsx +82 -0
- package/src/custom/schema-form/fields/field.tsx +67 -0
- package/src/custom/schema-form/fields/index.tsx +5 -0
- package/src/custom/schema-form/fields/object.tsx +12 -0
- package/src/custom/schema-form/fields/table-array/array-field-item.tsx +90 -0
- package/src/custom/schema-form/fields/table-array/array-field-template.tsx +115 -0
- package/src/custom/schema-form/index.tsx +259 -0
- package/src/custom/schema-form/templates/description.tsx +20 -0
- package/src/custom/schema-form/templates/index.tsx +2 -0
- package/src/custom/schema-form/templates/submit.tsx +32 -0
- package/src/custom/schema-form/types.ts +64 -0
- package/src/custom/schema-form/utils/index.ts +4 -0
- package/src/custom/schema-form/utils/schema-dependency.ts +655 -0
- package/src/custom/schema-form/utils/schemas.ts +289 -0
- package/src/custom/schema-form/utils/validation.ts +23 -0
- package/src/custom/schema-form/widgets/boolean.tsx +77 -0
- package/src/custom/schema-form/widgets/combobox.tsx +274 -0
- package/src/custom/schema-form/widgets/date.tsx +59 -0
- package/src/custom/schema-form/widgets/email.tsx +34 -0
- package/src/custom/schema-form/widgets/index.tsx +10 -0
- package/src/custom/schema-form/widgets/password.tsx +40 -0
- package/src/custom/schema-form/widgets/phone.tsx +40 -0
- package/src/custom/schema-form/widgets/select.tsx +105 -0
- package/src/custom/schema-form/widgets/selectable.tsx +25 -0
- package/src/custom/schema-form/widgets/string-array.tsx +296 -0
- package/src/custom/schema-form/widgets/url.tsx +56 -0
- package/src/custom/section-layout-v2.tsx +212 -0
- package/src/custom/select-tabs.tsx +109 -0
- package/src/custom/selectable.tsx +316 -0
- package/src/custom/stepper.tsx +236 -0
- package/src/custom/tab-layout.tsx +213 -0
- package/src/custom/tanstack-table/fields/index.tsx +12 -0
- package/src/custom/tanstack-table/fields/tanstack-table-action-dialogs.tsx +89 -0
- package/src/custom/tanstack-table/fields/tanstack-table-column-header.tsx +66 -0
- package/src/custom/tanstack-table/fields/tanstack-table-filter-date.tsx +180 -0
- package/src/custom/tanstack-table/fields/tanstack-table-filter-faceted.tsx +158 -0
- package/src/custom/tanstack-table/fields/tanstack-table-filter-text.tsx +76 -0
- package/src/custom/tanstack-table/fields/tanstack-table-pagination.tsx +136 -0
- package/src/custom/tanstack-table/fields/tanstack-table-plain-table.tsx +142 -0
- package/src/custom/tanstack-table/fields/tanstack-table-row-actions-confirmation.tsx +77 -0
- package/src/custom/tanstack-table/fields/tanstack-table-row-actions-custom-dialog.tsx +87 -0
- package/src/custom/tanstack-table/fields/tanstack-table-row-actions.tsx +151 -0
- package/src/custom/tanstack-table/fields/tanstack-table-table-actions-custom-dialog.tsx +88 -0
- package/src/custom/tanstack-table/fields/tanstack-table-table-actions-schemaform-dialog.tsx +47 -0
- package/src/custom/tanstack-table/fields/tanstack-table-toolbar.tsx +143 -0
- package/src/custom/tanstack-table/fields/tanstack-table-view-options.tsx +171 -0
- package/src/custom/tanstack-table/index.tsx +244 -0
- package/src/custom/tanstack-table/types/index.ts +328 -0
- package/src/custom/tanstack-table/utils/cell-with-actions.tsx +21 -0
- package/src/custom/tanstack-table/utils/column-names.ts +26 -0
- package/src/custom/tanstack-table/utils/columns-by-row-data.tsx +312 -0
- package/src/custom/tanstack-table/utils/editable-columns-by-row-data.tsx +219 -0
- package/src/custom/tanstack-table/utils/faceted-boolean-options.tsx +22 -0
- package/src/custom/tanstack-table/utils/index.tsx +10 -0
- package/src/custom/tanstack-table/utils/pinning-styles.ts +57 -0
- package/src/custom/tanstack-table/utils/table.tsx +83 -0
- package/src/custom/tanstack-table/utils/test-conditions.ts +17 -0
- package/src/custom/timeline.tsx +208 -0
- package/src/custom/tree.tsx +200 -0
- package/src/custom/tscanify/browser.ts +66 -0
- package/src/custom/tscanify/index.ts +51 -0
- package/src/custom/tscanify/tscanify-browser.ts +522 -0
- package/src/custom/tscanify/tscanify.ts +262 -0
- package/src/custom/tscanify/types.ts +22 -0
- package/src/custom/webcam.tsx +737 -0
- package/src/hooks/.gitkeep +0 -0
- package/src/hooks/use-callback-ref.ts +27 -0
- package/src/hooks/use-controllable-state.ts +67 -0
- package/src/hooks/use-debounce.ts +19 -0
- package/src/hooks/use-is-visible.ts +23 -0
- package/src/hooks/use-media-query.ts +21 -0
- package/src/hooks/use-mobile.ts +21 -0
- package/src/hooks/use-on-window-resize.ts +15 -0
- package/src/hooks/use-scroll.tsx +22 -0
- package/src/lib/utils.ts +61 -0
- package/src/lib/zod.ts +2 -0
- package/src/styles/core.css +57 -0
- package/src/styles/globals.css +130 -0
- package/src/test/email-input.test.tsx +217 -0
- package/src/test/password-input.test.tsx +92 -0
- package/src/test/select-tabs.test.tsx +302 -0
- package/src/test/selectable.test.tsx +1093 -0
- package/tsconfig.json +13 -0
- package/tsconfig.lint.json +8 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import cv from "opencv-ts";
|
|
2
|
+
import type { Mat } from "opencv-ts";
|
|
3
|
+
import { DocumentCorners } from "../types";
|
|
4
|
+
|
|
5
|
+
export interface PerspectiveCorrectionOptions {
|
|
6
|
+
imageQuality: number;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function perspectiveCorrection(
|
|
10
|
+
imageBase64: string,
|
|
11
|
+
corners: DocumentCorners,
|
|
12
|
+
videoDimensions: { width: number; height: number },
|
|
13
|
+
options: PerspectiveCorrectionOptions
|
|
14
|
+
): Promise<string> {
|
|
15
|
+
return new Promise<string>((resolve, reject) => {
|
|
16
|
+
try {
|
|
17
|
+
const img = new Image();
|
|
18
|
+
img.onload = () => {
|
|
19
|
+
try {
|
|
20
|
+
// Create canvas and get image data
|
|
21
|
+
const canvas = document.createElement("canvas");
|
|
22
|
+
canvas.width = img.width;
|
|
23
|
+
canvas.height = img.height;
|
|
24
|
+
const ctx = canvas.getContext("2d");
|
|
25
|
+
if (!ctx) {
|
|
26
|
+
reject(new Error("Failed to get canvas context"));
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
ctx.drawImage(img, 0, 0);
|
|
30
|
+
|
|
31
|
+
// Create OpenCV matrices
|
|
32
|
+
const src = cv.imread(canvas);
|
|
33
|
+
|
|
34
|
+
// Scale corners from video dimensions to actual image dimensions
|
|
35
|
+
const scaleX = img.width / videoDimensions.width;
|
|
36
|
+
const scaleY = img.height / videoDimensions.height;
|
|
37
|
+
|
|
38
|
+
// Source points (detected corners scaled to image size)
|
|
39
|
+
const srcPoints = cv.matFromArray(4, 1, cv.CV_32FC2, [
|
|
40
|
+
corners.topLeftCorner.x * scaleX,
|
|
41
|
+
corners.topLeftCorner.y * scaleY,
|
|
42
|
+
corners.topRightCorner.x * scaleX,
|
|
43
|
+
corners.topRightCorner.y * scaleY,
|
|
44
|
+
corners.bottomRightCorner.x * scaleX,
|
|
45
|
+
corners.bottomRightCorner.y * scaleY,
|
|
46
|
+
corners.bottomLeftCorner.x * scaleX,
|
|
47
|
+
corners.bottomLeftCorner.y * scaleY,
|
|
48
|
+
]);
|
|
49
|
+
|
|
50
|
+
// Calculate output dimensions
|
|
51
|
+
const { outputWidth, outputHeight } = calculateOutputDimensions(
|
|
52
|
+
corners,
|
|
53
|
+
scaleX,
|
|
54
|
+
scaleY
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
// Destination points (rectangle)
|
|
58
|
+
const dstPoints = cv.matFromArray(4, 1, cv.CV_32FC2, [
|
|
59
|
+
0,
|
|
60
|
+
0,
|
|
61
|
+
outputWidth,
|
|
62
|
+
0,
|
|
63
|
+
outputWidth,
|
|
64
|
+
outputHeight,
|
|
65
|
+
0,
|
|
66
|
+
outputHeight,
|
|
67
|
+
]);
|
|
68
|
+
|
|
69
|
+
// Get perspective transform matrix
|
|
70
|
+
const transformMatrix = cv.getPerspectiveTransform(
|
|
71
|
+
srcPoints,
|
|
72
|
+
dstPoints
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
// Apply perspective transformation
|
|
76
|
+
const dst = new cv.Mat();
|
|
77
|
+
cv.warpPerspective(
|
|
78
|
+
src,
|
|
79
|
+
dst,
|
|
80
|
+
transformMatrix,
|
|
81
|
+
new cv.Size(outputWidth, outputHeight)
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
// Convert back to canvas and get base64
|
|
85
|
+
const outputCanvas = document.createElement("canvas");
|
|
86
|
+
cv.imshow(outputCanvas, dst);
|
|
87
|
+
const croppedBase64 = outputCanvas.toDataURL(
|
|
88
|
+
"image/jpeg",
|
|
89
|
+
options.imageQuality
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
// Cleanup OpenCV matrices
|
|
93
|
+
cleanupMatrices([src, dst, srcPoints, dstPoints, transformMatrix]);
|
|
94
|
+
|
|
95
|
+
resolve(croppedBase64);
|
|
96
|
+
} catch (error) {
|
|
97
|
+
reject(error);
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
img.onerror = () => reject(new Error("Failed to load image"));
|
|
101
|
+
img.src = imageBase64;
|
|
102
|
+
} catch (error) {
|
|
103
|
+
reject(error);
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function calculateOutputDimensions(
|
|
109
|
+
corners: DocumentCorners,
|
|
110
|
+
scaleX: number,
|
|
111
|
+
scaleY: number
|
|
112
|
+
): { outputWidth: number; outputHeight: number } {
|
|
113
|
+
const distance = (
|
|
114
|
+
p1: { x: number; y: number },
|
|
115
|
+
p2: { x: number; y: number }
|
|
116
|
+
) => Math.sqrt(((p2.x - p1.x) * scaleX) ** 2 + ((p2.y - p1.y) * scaleY) ** 2);
|
|
117
|
+
|
|
118
|
+
const topWidth = distance(corners.topLeftCorner, corners.topRightCorner);
|
|
119
|
+
const bottomWidth = distance(
|
|
120
|
+
corners.bottomLeftCorner,
|
|
121
|
+
corners.bottomRightCorner
|
|
122
|
+
);
|
|
123
|
+
const leftHeight = distance(corners.topLeftCorner, corners.bottomLeftCorner);
|
|
124
|
+
const rightHeight = distance(
|
|
125
|
+
corners.topRightCorner,
|
|
126
|
+
corners.bottomRightCorner
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
return {
|
|
130
|
+
outputWidth: Math.max(topWidth, bottomWidth),
|
|
131
|
+
outputHeight: Math.max(leftHeight, rightHeight),
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function cleanupMatrices(matrices: Mat[]): void {
|
|
136
|
+
matrices.forEach((matrix) => {
|
|
137
|
+
matrix.delete();
|
|
138
|
+
});
|
|
139
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DownloadIcon,
|
|
3
|
+
EyeIcon,
|
|
4
|
+
EyeOffIcon,
|
|
5
|
+
SearchIcon,
|
|
6
|
+
ZoomIn,
|
|
7
|
+
ZoomOut,
|
|
8
|
+
} from "lucide-react";
|
|
9
|
+
import Link from "next/link";
|
|
10
|
+
import { useEffect, useState } from "react";
|
|
11
|
+
import { Button } from "@repo/ayasofyazilim-ui/components/button";
|
|
12
|
+
import {
|
|
13
|
+
Popover,
|
|
14
|
+
PopoverContent,
|
|
15
|
+
PopoverTrigger,
|
|
16
|
+
} from "@repo/ayasofyazilim-ui/components/popover";
|
|
17
|
+
import { Input } from "@repo/ayasofyazilim-ui/components/input";
|
|
18
|
+
|
|
19
|
+
export function Controllers({
|
|
20
|
+
documentUri,
|
|
21
|
+
zoom,
|
|
22
|
+
setZoom,
|
|
23
|
+
showThumbnail,
|
|
24
|
+
setShowThumbnail,
|
|
25
|
+
searchValue,
|
|
26
|
+
setSearchValue,
|
|
27
|
+
}: {
|
|
28
|
+
documentUri: string;
|
|
29
|
+
zoom: number;
|
|
30
|
+
setZoom: (zoom: number) => void;
|
|
31
|
+
showThumbnail?: boolean;
|
|
32
|
+
setShowThumbnail?: (show: boolean) => void;
|
|
33
|
+
searchValue?: string;
|
|
34
|
+
setSearchValue?: (value: string) => void;
|
|
35
|
+
}) {
|
|
36
|
+
const [open, setOpen] = useState(false);
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
if (!open) {
|
|
39
|
+
if (setSearchValue) {
|
|
40
|
+
setSearchValue("");
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}, [open]);
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<div className="absolute top-4 right-6 flex gap-2 z-10 flex-col">
|
|
47
|
+
{setShowThumbnail && (
|
|
48
|
+
<Button
|
|
49
|
+
variant="outline"
|
|
50
|
+
size="icon"
|
|
51
|
+
onClick={() => setShowThumbnail(!showThumbnail)}
|
|
52
|
+
>
|
|
53
|
+
{showThumbnail ? (
|
|
54
|
+
<EyeIcon className="size-4" />
|
|
55
|
+
) : (
|
|
56
|
+
<EyeOffIcon className="size-4" />
|
|
57
|
+
)}
|
|
58
|
+
</Button>
|
|
59
|
+
)}
|
|
60
|
+
<Button variant="outline" size="icon" onClick={() => setZoom(zoom - 0.1)}>
|
|
61
|
+
<ZoomOut className="size-4" />
|
|
62
|
+
</Button>
|
|
63
|
+
<Button variant="outline" size="icon" onClick={() => setZoom(zoom + 0.1)}>
|
|
64
|
+
<ZoomIn className="size-4" />
|
|
65
|
+
</Button>
|
|
66
|
+
<Button asChild variant="outline" size="icon">
|
|
67
|
+
<Link href={documentUri} download target="_blank">
|
|
68
|
+
<DownloadIcon className="size-4" />
|
|
69
|
+
</Link>
|
|
70
|
+
</Button>
|
|
71
|
+
{setSearchValue && (
|
|
72
|
+
<Popover open={open} onOpenChange={setOpen}>
|
|
73
|
+
<PopoverTrigger asChild>
|
|
74
|
+
<Button
|
|
75
|
+
variant="outline"
|
|
76
|
+
size="icon"
|
|
77
|
+
onClick={() => setOpen(!open)}
|
|
78
|
+
>
|
|
79
|
+
<SearchIcon className="size-4" />
|
|
80
|
+
</Button>
|
|
81
|
+
</PopoverTrigger>
|
|
82
|
+
<PopoverContent className="w-80 p-0" side="left">
|
|
83
|
+
<div className="grid gap-4">
|
|
84
|
+
<Input
|
|
85
|
+
id="search"
|
|
86
|
+
defaultValue={searchValue}
|
|
87
|
+
onChange={(e) => {
|
|
88
|
+
setSearchValue(e.target.value);
|
|
89
|
+
}}
|
|
90
|
+
className="col-span-2 h-8"
|
|
91
|
+
/>
|
|
92
|
+
</div>
|
|
93
|
+
</PopoverContent>
|
|
94
|
+
</Popover>
|
|
95
|
+
)}
|
|
96
|
+
</div>
|
|
97
|
+
);
|
|
98
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { cn } from "@repo/ayasofyazilim-ui/lib/utils";
|
|
4
|
+
import DocViewer, { DocRenderer, DocViewerRenderers } from "react-doc-viewer";
|
|
5
|
+
import CustomImageRenderer from "./renderers/image";
|
|
6
|
+
import CustomPDFRenderer from "./renderers/pdf";
|
|
7
|
+
|
|
8
|
+
export * from "react-doc-viewer";
|
|
9
|
+
|
|
10
|
+
export type DocumentType = {
|
|
11
|
+
uri: string;
|
|
12
|
+
fileType?: string;
|
|
13
|
+
fileName?: string;
|
|
14
|
+
fileData?: string | ArrayBuffer;
|
|
15
|
+
};
|
|
16
|
+
export default function DocumentViewer({
|
|
17
|
+
document,
|
|
18
|
+
className,
|
|
19
|
+
renderers = [],
|
|
20
|
+
}: {
|
|
21
|
+
document: DocumentType;
|
|
22
|
+
className?: string;
|
|
23
|
+
renderers?: DocRenderer[];
|
|
24
|
+
}) {
|
|
25
|
+
return (
|
|
26
|
+
<DocViewer
|
|
27
|
+
config={{
|
|
28
|
+
header: {
|
|
29
|
+
disableHeader: true,
|
|
30
|
+
disableFileName: true,
|
|
31
|
+
},
|
|
32
|
+
}}
|
|
33
|
+
className={cn("h-full rounded-md border relative", className)}
|
|
34
|
+
pluginRenderers={[
|
|
35
|
+
...DocViewerRenderers,
|
|
36
|
+
CustomPDFRenderer,
|
|
37
|
+
CustomImageRenderer,
|
|
38
|
+
...renderers,
|
|
39
|
+
]}
|
|
40
|
+
documents={[document]}
|
|
41
|
+
/>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
import { DocRendererProps } from "react-doc-viewer";
|
|
3
|
+
import { Controllers } from "../controllers";
|
|
4
|
+
import ImageCanvas from "../../image-canvas";
|
|
5
|
+
|
|
6
|
+
const CustomImageRenderer = (props: DocRendererProps) => {
|
|
7
|
+
const { mainState } = props;
|
|
8
|
+
const { currentDocument } = mainState;
|
|
9
|
+
if (!currentDocument) return null;
|
|
10
|
+
const [zoom, setZoom] = useState(1);
|
|
11
|
+
return (
|
|
12
|
+
<div className="flex w-full items-center justify-center p-4">
|
|
13
|
+
<Controllers
|
|
14
|
+
documentUri={currentDocument.uri}
|
|
15
|
+
zoom={zoom}
|
|
16
|
+
setZoom={setZoom}
|
|
17
|
+
/>
|
|
18
|
+
<div className="relative size-full flex items-center justify-center">
|
|
19
|
+
<ImageCanvas
|
|
20
|
+
classNames={{
|
|
21
|
+
canvas: "border rounded-md",
|
|
22
|
+
}}
|
|
23
|
+
imageUrl={currentDocument.uri}
|
|
24
|
+
zoom={zoom}
|
|
25
|
+
minZoom={0.5}
|
|
26
|
+
maxZoom={2}
|
|
27
|
+
onZoomChange={setZoom}
|
|
28
|
+
/>
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
CustomImageRenderer.fileTypes = ["image/jpeg", "image/png", "image/gif"];
|
|
35
|
+
CustomImageRenderer.weight = 1;
|
|
36
|
+
|
|
37
|
+
export default CustomImageRenderer;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { useMemo, useState } from "react";
|
|
2
|
+
import { DocRenderer, DocRendererProps } from "react-doc-viewer";
|
|
3
|
+
import { Document, Page, pdfjs, Thumbnail } from "react-pdf";
|
|
4
|
+
import { cn } from "@repo/ayasofyazilim-ui/lib/utils";
|
|
5
|
+
import "react-pdf/dist/Page/AnnotationLayer.css";
|
|
6
|
+
import "react-pdf/dist/Page/TextLayer.css";
|
|
7
|
+
import { Controllers } from "../controllers";
|
|
8
|
+
|
|
9
|
+
pdfjs.GlobalWorkerOptions.workerSrc = `https://cdn.jsdelivr.net/npm/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.mjs`;
|
|
10
|
+
|
|
11
|
+
type CustomDocRendererProps = {} & DocRendererProps;
|
|
12
|
+
|
|
13
|
+
const CustomPDFRenderer = (props: CustomDocRendererProps) => {
|
|
14
|
+
const { mainState } = props;
|
|
15
|
+
const { currentDocument } = mainState;
|
|
16
|
+
const [zoom, setZoom] = useState(1);
|
|
17
|
+
const [showThumbnail, setShowThumbnail] = useState(false);
|
|
18
|
+
const [pageCount, setPageCount] = useState(0);
|
|
19
|
+
const [activePage, setActivePage] = useState(1);
|
|
20
|
+
const [searchValue, setSearchValue] = useState<string>();
|
|
21
|
+
|
|
22
|
+
if (!currentDocument) return null;
|
|
23
|
+
return (
|
|
24
|
+
<Document
|
|
25
|
+
className={cn("p-4 w-full flex")}
|
|
26
|
+
file={currentDocument.uri}
|
|
27
|
+
renderMode="canvas"
|
|
28
|
+
onLoadSuccess={({ numPages }) => {
|
|
29
|
+
setPageCount(numPages);
|
|
30
|
+
}}
|
|
31
|
+
>
|
|
32
|
+
<Controllers
|
|
33
|
+
documentUri={currentDocument.uri}
|
|
34
|
+
zoom={zoom}
|
|
35
|
+
setZoom={setZoom}
|
|
36
|
+
showThumbnail={showThumbnail}
|
|
37
|
+
setShowThumbnail={setShowThumbnail}
|
|
38
|
+
searchValue={searchValue}
|
|
39
|
+
setSearchValue={setSearchValue}
|
|
40
|
+
/>
|
|
41
|
+
|
|
42
|
+
<div className="flex gap-2 w-full justify-center">
|
|
43
|
+
{showThumbnail && (
|
|
44
|
+
<div className="flex flex-col gap-2 left-4 absolute top-4 z-10 w-full max-w-[110px]">
|
|
45
|
+
{Array.from(new Array(pageCount), (el, index) => (
|
|
46
|
+
<Thumbnail
|
|
47
|
+
key={"page_" + index}
|
|
48
|
+
onClick={() => {
|
|
49
|
+
setActivePage(index + 1);
|
|
50
|
+
}}
|
|
51
|
+
className={cn(
|
|
52
|
+
"rounded-md border bg-white p-1 flex justify-center",
|
|
53
|
+
activePage === index + 1 && "border-primary"
|
|
54
|
+
)}
|
|
55
|
+
pageNumber={index + 1}
|
|
56
|
+
width={100}
|
|
57
|
+
height={100}
|
|
58
|
+
/>
|
|
59
|
+
))}
|
|
60
|
+
</div>
|
|
61
|
+
)}
|
|
62
|
+
<div className={cn("flex flex-col", showThumbnail && "")}>
|
|
63
|
+
{Array.from(new Array(pageCount), (el, index) => (
|
|
64
|
+
<Page
|
|
65
|
+
customTextRenderer={({ str }) =>
|
|
66
|
+
searchValue
|
|
67
|
+
? str.replace(
|
|
68
|
+
new RegExp(searchValue, "gi"),
|
|
69
|
+
(value) => `<mark>${value}</mark>`
|
|
70
|
+
)
|
|
71
|
+
: str
|
|
72
|
+
}
|
|
73
|
+
className="border shadow-sm max-w-max overflow-hidden rounded-md mb-2"
|
|
74
|
+
key={`page_${index + 1}`}
|
|
75
|
+
pageNumber={index + 1}
|
|
76
|
+
scale={zoom}
|
|
77
|
+
/>
|
|
78
|
+
))}
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
81
|
+
</Document>
|
|
82
|
+
);
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
CustomPDFRenderer.fileTypes = ["pdf", "application/pdf"];
|
|
86
|
+
CustomPDFRenderer.weight = 1;
|
|
87
|
+
|
|
88
|
+
export default CustomPDFRenderer;
|
|
89
|
+
|
|
90
|
+
export const ExtendCustomPDFRenderer = ({
|
|
91
|
+
searchValue,
|
|
92
|
+
}: {
|
|
93
|
+
searchValue?: string;
|
|
94
|
+
}): DocRenderer => {
|
|
95
|
+
const Renderer = useMemo(() => {
|
|
96
|
+
function RendererComponent(props: DocRendererProps) {
|
|
97
|
+
return <CustomPDFRenderer {...props} />;
|
|
98
|
+
}
|
|
99
|
+
RendererComponent.fileTypes = ["pdf", "application/pdf"];
|
|
100
|
+
RendererComponent.weight = 1;
|
|
101
|
+
return RendererComponent;
|
|
102
|
+
}, [searchValue]);
|
|
103
|
+
|
|
104
|
+
return Renderer;
|
|
105
|
+
};
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
[
|
|
2
|
+
"gmail.com",
|
|
3
|
+
"outlook.com",
|
|
4
|
+
"hotmail.com",
|
|
5
|
+
"icloud.com",
|
|
6
|
+
"yahoo.com",
|
|
7
|
+
"aol.com",
|
|
8
|
+
"att.net",
|
|
9
|
+
"comcast.net",
|
|
10
|
+
"facebook.com",
|
|
11
|
+
"gmx.com",
|
|
12
|
+
"googlemail.com",
|
|
13
|
+
"google.com",
|
|
14
|
+
"hotmail.co.uk",
|
|
15
|
+
"mac.com",
|
|
16
|
+
"me.com",
|
|
17
|
+
"mail.com",
|
|
18
|
+
"msn.com",
|
|
19
|
+
"live.com",
|
|
20
|
+
"sbcglobal.net",
|
|
21
|
+
"verizon.net",
|
|
22
|
+
"yahoo.co.uk",
|
|
23
|
+
"email.com",
|
|
24
|
+
"fastmail.fm",
|
|
25
|
+
"games.com",
|
|
26
|
+
"gmx.net",
|
|
27
|
+
"hush.com",
|
|
28
|
+
"hushmail.com",
|
|
29
|
+
"iname.com",
|
|
30
|
+
"inbox.com",
|
|
31
|
+
"lavabit.com",
|
|
32
|
+
"love.com",
|
|
33
|
+
"pobox.com",
|
|
34
|
+
"protonmail.ch",
|
|
35
|
+
"protonmail.com",
|
|
36
|
+
"tutanota.de",
|
|
37
|
+
"tutanota.com",
|
|
38
|
+
"tutamail.com",
|
|
39
|
+
"tuta.io",
|
|
40
|
+
"keemail.me",
|
|
41
|
+
"rocketmail.com",
|
|
42
|
+
"safe-mail.net",
|
|
43
|
+
"wow.com",
|
|
44
|
+
"ygm.com",
|
|
45
|
+
"ymail.com",
|
|
46
|
+
"zoho.com",
|
|
47
|
+
"bellsouth.net",
|
|
48
|
+
"charter.net",
|
|
49
|
+
"cox.net",
|
|
50
|
+
"earthlink.net",
|
|
51
|
+
"juno.com",
|
|
52
|
+
"btinternet.com",
|
|
53
|
+
"virginmedia.com",
|
|
54
|
+
"blueyonder.co.uk",
|
|
55
|
+
"live.co.uk",
|
|
56
|
+
"ntlworld.com",
|
|
57
|
+
"orange.net",
|
|
58
|
+
"sky.com",
|
|
59
|
+
"talktalk.co.uk",
|
|
60
|
+
"tiscali.co.uk",
|
|
61
|
+
"virgin.net",
|
|
62
|
+
"bt.com",
|
|
63
|
+
"sina.com",
|
|
64
|
+
"sina.cn",
|
|
65
|
+
"qq.com",
|
|
66
|
+
"naver.com",
|
|
67
|
+
"hanmail.net",
|
|
68
|
+
"daum.net",
|
|
69
|
+
"nate.com",
|
|
70
|
+
"yahoo.co.jp",
|
|
71
|
+
"yahoo.co.kr",
|
|
72
|
+
"yahoo.co.id",
|
|
73
|
+
"yahoo.co.in",
|
|
74
|
+
"yahoo.com.sg",
|
|
75
|
+
"yahoo.com.ph",
|
|
76
|
+
"163.com",
|
|
77
|
+
"yeah.net",
|
|
78
|
+
"126.com",
|
|
79
|
+
"21cn.com",
|
|
80
|
+
"aliyun.com",
|
|
81
|
+
"foxmail.com",
|
|
82
|
+
"hotmail.fr",
|
|
83
|
+
"live.fr",
|
|
84
|
+
"laposte.net",
|
|
85
|
+
"yahoo.fr",
|
|
86
|
+
"wanadoo.fr",
|
|
87
|
+
"orange.fr",
|
|
88
|
+
"gmx.fr",
|
|
89
|
+
"sfr.fr",
|
|
90
|
+
"neuf.fr",
|
|
91
|
+
"free.fr",
|
|
92
|
+
"gmx.de",
|
|
93
|
+
"hotmail.de",
|
|
94
|
+
"live.de",
|
|
95
|
+
"online.de",
|
|
96
|
+
"t-online.de",
|
|
97
|
+
"web.de",
|
|
98
|
+
"yahoo.de",
|
|
99
|
+
"libero.it",
|
|
100
|
+
"virgilio.it",
|
|
101
|
+
"hotmail.it",
|
|
102
|
+
"aol.it",
|
|
103
|
+
"tiscali.it",
|
|
104
|
+
"alice.it",
|
|
105
|
+
"live.it",
|
|
106
|
+
"yahoo.it",
|
|
107
|
+
"email.it",
|
|
108
|
+
"tin.it",
|
|
109
|
+
"poste.it",
|
|
110
|
+
"teletu.it",
|
|
111
|
+
"bk.ru",
|
|
112
|
+
"inbox.ru",
|
|
113
|
+
"list.ru",
|
|
114
|
+
"mail.ru",
|
|
115
|
+
"rambler.ru",
|
|
116
|
+
"yandex.by",
|
|
117
|
+
"yandex.com",
|
|
118
|
+
"yandex.kz",
|
|
119
|
+
"yandex.ru",
|
|
120
|
+
"yandex.ua",
|
|
121
|
+
"ya.ru",
|
|
122
|
+
"hotmail.be",
|
|
123
|
+
"live.be",
|
|
124
|
+
"skynet.be",
|
|
125
|
+
"voo.be",
|
|
126
|
+
"tvcablenet.be",
|
|
127
|
+
"telenet.be",
|
|
128
|
+
"hotmail.com.ar",
|
|
129
|
+
"live.com.ar",
|
|
130
|
+
"yahoo.com.ar",
|
|
131
|
+
"fibertel.com.ar",
|
|
132
|
+
"speedy.com.ar",
|
|
133
|
+
"arnet.com.ar",
|
|
134
|
+
"yahoo.com.mx",
|
|
135
|
+
"live.com.mx",
|
|
136
|
+
"hotmail.es",
|
|
137
|
+
"hotmail.com.mx",
|
|
138
|
+
"prodigy.net.mx",
|
|
139
|
+
"yahoo.ca",
|
|
140
|
+
"hotmail.ca",
|
|
141
|
+
"bell.net",
|
|
142
|
+
"shaw.ca",
|
|
143
|
+
"sympatico.ca",
|
|
144
|
+
"rogers.com",
|
|
145
|
+
"yahoo.com.br",
|
|
146
|
+
"hotmail.com.br",
|
|
147
|
+
"outlook.com.br",
|
|
148
|
+
"uol.com.br",
|
|
149
|
+
"bol.com.br",
|
|
150
|
+
"terra.com.br",
|
|
151
|
+
"ig.com.br",
|
|
152
|
+
"r7.com",
|
|
153
|
+
"zipmail.com.br",
|
|
154
|
+
"globo.com",
|
|
155
|
+
"globomail.com",
|
|
156
|
+
"oi.com.br",
|
|
157
|
+
"unirefund.com",
|
|
158
|
+
"clomerce.com"
|
|
159
|
+
]
|