react-image-marker-viewer 0.1.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/README.md +102 -0
- package/dist/image-marker-viewer.css +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/react-image-marker.es.js +811 -0
- package/dist/react-image-marker.umd.js +22 -0
- package/dist/vite.svg +1 -0
- package/package.json +49 -0
package/README.md
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# React Image Marker Viewer
|
|
2
|
+
|
|
3
|
+
A powerful, responsive, and customizable image annotation library for React.
|
|
4
|
+
Add markers to images, edit details, upload photos, and manage state with ease.
|
|
5
|
+
|
|
6
|
+
## Features
|
|
7
|
+
|
|
8
|
+
- 🎯 **Responsive Markers**: Markers stay in position (percentage-based) regardless of image resizing.
|
|
9
|
+
- 🖼️ **Image Support**: Works with any image URL or base64 string.
|
|
10
|
+
- 📝 **Rich Details**: Add titles, notes, and colors to markers.
|
|
11
|
+
- 📸 **Photo Attachments**: Upload up to 3 photos per marker (stored as Base64).
|
|
12
|
+
- 🔍 **Lightbox**: Built-in full-screen lightbox with zoom and pan support.
|
|
13
|
+
- 🖱️ **Drag & Drop**: Drag markers to reposition them.
|
|
14
|
+
- 🗑️ **Long Press Delete**: Hold a marker for 500ms to delete it.
|
|
15
|
+
- 🌍 **Localization**: Auto-detects English (`en`), Turkish (`tr`), and Spanish (`es`).
|
|
16
|
+
- ✅ **Validation**: Enforces required fields (e.g., Title) and prevents empty saves.
|
|
17
|
+
- 🎨 **Customizable**: Built with Tailwind CSS logic (classes are scoped).
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install react-image-marker-viewer
|
|
23
|
+
# or
|
|
24
|
+
yarn add react-image-marker-viewer
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Basic Usage
|
|
28
|
+
|
|
29
|
+
```jsx
|
|
30
|
+
import { ImageArea, useMarkerState } from 'react-image-marker-viewer';
|
|
31
|
+
import 'react-image-marker-viewer/dist/style.css'; // Don't forget CSS!
|
|
32
|
+
|
|
33
|
+
function App() {
|
|
34
|
+
const { markers, addMarker, updateMarker, removeMarker } = useMarkerState();
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<ImageArea
|
|
38
|
+
src="https://example.com/image.jpg"
|
|
39
|
+
markers={markers}
|
|
40
|
+
onAddMarker={addMarker}
|
|
41
|
+
onUpdateMarker={updateMarker}
|
|
42
|
+
onDeleteMarker={removeMarker}
|
|
43
|
+
/>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Components
|
|
49
|
+
|
|
50
|
+
### `ImageArea`
|
|
51
|
+
|
|
52
|
+
The main component that renders the image and markers.
|
|
53
|
+
|
|
54
|
+
| Prop | Type | Description |
|
|
55
|
+
|------|------|-------------|
|
|
56
|
+
| `src` | `string` | URL or Base64 string of the image. |
|
|
57
|
+
| `markers` | `Marker[]` | Array of marker objects. |
|
|
58
|
+
| `onAddMarker` | `(marker: Marker) => void` | Callback when a new marker is saved. |
|
|
59
|
+
| `onUpdateMarker` | `(id: string, updates: Partial<Marker>) => void` | Callback when a marker is updated. |
|
|
60
|
+
| `onDeleteMarker` | `(id: string) => void` | Callback when a marker is deleted. |
|
|
61
|
+
|
|
62
|
+
### `useMarkerState` Hook
|
|
63
|
+
|
|
64
|
+
A helper hook to manage marker state easily.
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
const {
|
|
68
|
+
markers, // Current array of markers
|
|
69
|
+
addMarker, // Function to add a marker
|
|
70
|
+
updateMarker, // Function to update a marker
|
|
71
|
+
removeMarker, // Function to delete a marker
|
|
72
|
+
setAllMarkers // Function to replace all markers (e.g. loading from DB)
|
|
73
|
+
} = useMarkerState();
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Types
|
|
77
|
+
|
|
78
|
+
### `Marker`
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
interface Marker {
|
|
82
|
+
id: string;
|
|
83
|
+
x: number; // Percentage (0-100)
|
|
84
|
+
y: number; // Percentage (0-100)
|
|
85
|
+
color: number; // Integer color value
|
|
86
|
+
markerTitle: string;
|
|
87
|
+
note: string;
|
|
88
|
+
photos: string[]; // Base64 strings
|
|
89
|
+
photosName: string[]; // File names
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Localization
|
|
94
|
+
|
|
95
|
+
The library automatically detects the browser language. Currently supported:
|
|
96
|
+
- English (`en`) - Default
|
|
97
|
+
- Turkish (`tr`)
|
|
98
|
+
- Spanish (`es`)
|
|
99
|
+
|
|
100
|
+
## License
|
|
101
|
+
|
|
102
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.\!container{width:100%!important}.container{width:100%}@media(min-width:640px){.\!container{max-width:640px!important}.container{max-width:640px}}@media(min-width:768px){.\!container{max-width:768px!important}.container{max-width:768px}}@media(min-width:1024px){.\!container{max-width:1024px!important}.container{max-width:1024px}}@media(min-width:1280px){.\!container{max-width:1280px!important}.container{max-width:1280px}}@media(min-width:1536px){.\!container{max-width:1536px!important}.container{max-width:1536px}}.pointer-events-none{pointer-events:none}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{top:0;right:0;bottom:0;left:0}.-right-1{right:-.25rem}.-top-1{top:-.25rem}.bottom-4{bottom:1rem}.left-0{left:0}.left-4{left:1rem}.right-0{right:0}.right-4{right:1rem}.top-4{top:1rem}.z-40{z-index:40}.z-50{z-index:50}.z-\[60\]{z-index:60}.mx-auto{margin-left:auto;margin-right:auto}.mb-4{margin-bottom:1rem}.mb-8{margin-bottom:2rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-4{margin-top:1rem}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.hidden{display:none}.h-10{height:2.5rem}.h-16{height:4rem}.h-2{height:.5rem}.h-4{height:1rem}.h-6{height:1.5rem}.h-8{height:2rem}.h-auto{height:auto}.h-full{height:100%}.h-screen{height:100vh}.max-h-\[90vh\]{max-height:90vh}.min-h-screen{min-height:100vh}.w-10{width:2.5rem}.w-16{width:4rem}.w-2{width:.5rem}.w-4{width:1rem}.w-6{width:1.5rem}.w-72{width:18rem}.w-8{width:2rem}.w-full{width:100%}.max-w-5xl{max-width:64rem}.max-w-full{max-width:100%}.-translate-x-1\/2{--tw-translate-x: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-1\/2{--tw-translate-y: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.scale-125{--tw-scale-x: 1.25;--tw-scale-y: 1.25;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-crosshair{cursor:crosshair}.cursor-pointer{cursor:pointer}.touch-none{touch-action:none}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-2{gap:.5rem}.gap-4{gap:1rem}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(.5rem * var(--tw-space-x-reverse));margin-left:calc(.5rem * calc(1 - var(--tw-space-x-reverse)))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-xl{border-radius:.75rem}.border{border-width:1px}.border-2{border-width:2px}.border-dashed{border-style:dashed}.border-gray-100{--tw-border-opacity: 1;border-color:rgb(243 244 246 / var(--tw-border-opacity, 1))}.border-gray-200{--tw-border-opacity: 1;border-color:rgb(229 231 235 / var(--tw-border-opacity, 1))}.border-gray-300{--tw-border-opacity: 1;border-color:rgb(209 213 219 / var(--tw-border-opacity, 1))}.border-red-500{--tw-border-opacity: 1;border-color:rgb(239 68 68 / var(--tw-border-opacity, 1))}.border-white{--tw-border-opacity: 1;border-color:rgb(255 255 255 / var(--tw-border-opacity, 1))}.bg-black{--tw-bg-opacity: 1;background-color:rgb(0 0 0 / var(--tw-bg-opacity, 1))}.bg-black\/50{background-color:#00000080}.bg-blue-500{--tw-bg-opacity: 1;background-color:rgb(59 130 246 / var(--tw-bg-opacity, 1))}.bg-blue-600{--tw-bg-opacity: 1;background-color:rgb(37 99 235 / var(--tw-bg-opacity, 1))}.bg-gray-100{--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity, 1))}.bg-gray-900{--tw-bg-opacity: 1;background-color:rgb(17 24 39 / var(--tw-bg-opacity, 1))}.bg-red-500{--tw-bg-opacity: 1;background-color:rgb(239 68 68 / var(--tw-bg-opacity, 1))}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.bg-opacity-90{--tw-bg-opacity: .9}.object-contain{-o-object-fit:contain;object-fit:contain}.object-cover{-o-object-fit:cover;object-fit:cover}.p-0{padding:0}.p-0\.5{padding:.125rem}.p-2{padding:.5rem}.p-4{padding:1rem}.p-8{padding:2rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.text-center{text-align:center}.font-sans{font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji"}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.text-gray-400{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.text-gray-600{--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity, 1))}.text-gray-700{--tw-text-opacity: 1;color:rgb(55 65 81 / var(--tw-text-opacity, 1))}.text-gray-900{--tw-text-opacity: 1;color:rgb(17 24 39 / var(--tw-text-opacity, 1))}.text-red-500{--tw-text-opacity: 1;color:rgb(239 68 68 / var(--tw-text-opacity, 1))}.text-red-600{--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity, 1))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.opacity-0{opacity:0}.opacity-50{opacity:.5}.shadow-lg{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-md{--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.ring-2{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-blue-500{--tw-ring-opacity: 1;--tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity, 1))}.ring-offset-1{--tw-ring-offset-width: 1px}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.hover\:scale-110:hover{--tw-scale-x: 1.1;--tw-scale-y: 1.1;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\:border-blue-500:hover{--tw-border-opacity: 1;border-color:rgb(59 130 246 / var(--tw-border-opacity, 1))}.hover\:bg-blue-50:hover{--tw-bg-opacity: 1;background-color:rgb(239 246 255 / var(--tw-bg-opacity, 1))}.hover\:bg-blue-600:hover{--tw-bg-opacity: 1;background-color:rgb(37 99 235 / var(--tw-bg-opacity, 1))}.hover\:bg-blue-700:hover{--tw-bg-opacity: 1;background-color:rgb(29 78 216 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-50:hover{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity, 1))}.hover\:bg-red-50:hover{--tw-bg-opacity: 1;background-color:rgb(254 242 242 / var(--tw-bg-opacity, 1))}.hover\:bg-white\/10:hover{background-color:#ffffff1a}.hover\:text-gray-300:hover{--tw-text-opacity: 1;color:rgb(209 213 219 / var(--tw-text-opacity, 1))}.hover\:text-gray-600:hover{--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity, 1))}.focus\:border-blue-500:focus{--tw-border-opacity: 1;border-color:rgb(59 130 246 / var(--tw-border-opacity, 1))}.focus\:border-red-500:focus{--tw-border-opacity: 1;border-color:rgb(239 68 68 / var(--tw-border-opacity, 1))}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-1:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring-2:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring-blue-500:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity, 1))}.focus\:ring-red-500:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(239 68 68 / var(--tw-ring-opacity, 1))}.focus\:ring-offset-1:focus{--tw-ring-offset-width: 1px}.group:hover .group-hover\:opacity-100{opacity:1}@media(min-width:640px){.sm\:text-sm{font-size:.875rem;line-height:1.25rem}}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|
|
@@ -0,0 +1,811 @@
|
|
|
1
|
+
import de, { useMemo as fe, useState as N, useRef as T, useCallback as M, useEffect as q } from "react";
|
|
2
|
+
var Y = { exports: {} }, I = {};
|
|
3
|
+
/**
|
|
4
|
+
* @license React
|
|
5
|
+
* react-jsx-runtime.production.js
|
|
6
|
+
*
|
|
7
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
8
|
+
*
|
|
9
|
+
* This source code is licensed under the MIT license found in the
|
|
10
|
+
* LICENSE file in the root directory of this source tree.
|
|
11
|
+
*/
|
|
12
|
+
var ee;
|
|
13
|
+
function me() {
|
|
14
|
+
if (ee) return I;
|
|
15
|
+
ee = 1;
|
|
16
|
+
var t = Symbol.for("react.transitional.element"), u = Symbol.for("react.fragment");
|
|
17
|
+
function i(o, n, s) {
|
|
18
|
+
var x = null;
|
|
19
|
+
if (s !== void 0 && (x = "" + s), n.key !== void 0 && (x = "" + n.key), "key" in n) {
|
|
20
|
+
s = {};
|
|
21
|
+
for (var c in n)
|
|
22
|
+
c !== "key" && (s[c] = n[c]);
|
|
23
|
+
} else s = n;
|
|
24
|
+
return n = s.ref, {
|
|
25
|
+
$$typeof: t,
|
|
26
|
+
type: o,
|
|
27
|
+
key: x,
|
|
28
|
+
ref: n !== void 0 ? n : null,
|
|
29
|
+
props: s
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
return I.Fragment = u, I.jsx = i, I.jsxs = i, I;
|
|
33
|
+
}
|
|
34
|
+
var F = {};
|
|
35
|
+
/**
|
|
36
|
+
* @license React
|
|
37
|
+
* react-jsx-runtime.development.js
|
|
38
|
+
*
|
|
39
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
40
|
+
*
|
|
41
|
+
* This source code is licensed under the MIT license found in the
|
|
42
|
+
* LICENSE file in the root directory of this source tree.
|
|
43
|
+
*/
|
|
44
|
+
var te;
|
|
45
|
+
function he() {
|
|
46
|
+
return te || (te = 1, process.env.NODE_ENV !== "production" && (function() {
|
|
47
|
+
function t(e) {
|
|
48
|
+
if (e == null) return null;
|
|
49
|
+
if (typeof e == "function")
|
|
50
|
+
return e.$$typeof === ie ? null : e.displayName || e.name || null;
|
|
51
|
+
if (typeof e == "string") return e;
|
|
52
|
+
switch (e) {
|
|
53
|
+
case C:
|
|
54
|
+
return "Fragment";
|
|
55
|
+
case A:
|
|
56
|
+
return "Profiler";
|
|
57
|
+
case p:
|
|
58
|
+
return "StrictMode";
|
|
59
|
+
case w:
|
|
60
|
+
return "Suspense";
|
|
61
|
+
case P:
|
|
62
|
+
return "SuspenseList";
|
|
63
|
+
case le:
|
|
64
|
+
return "Activity";
|
|
65
|
+
}
|
|
66
|
+
if (typeof e == "object")
|
|
67
|
+
switch (typeof e.tag == "number" && console.error(
|
|
68
|
+
"Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."
|
|
69
|
+
), e.$$typeof) {
|
|
70
|
+
case E:
|
|
71
|
+
return "Portal";
|
|
72
|
+
case R:
|
|
73
|
+
return e.displayName || "Context";
|
|
74
|
+
case l:
|
|
75
|
+
return (e._context.displayName || "Context") + ".Consumer";
|
|
76
|
+
case _:
|
|
77
|
+
var a = e.render;
|
|
78
|
+
return e = e.displayName, e || (e = a.displayName || a.name || "", e = e !== "" ? "ForwardRef(" + e + ")" : "ForwardRef"), e;
|
|
79
|
+
case O:
|
|
80
|
+
return a = e.displayName || null, a !== null ? a : t(e.type) || "Memo";
|
|
81
|
+
case L:
|
|
82
|
+
a = e._payload, e = e._init;
|
|
83
|
+
try {
|
|
84
|
+
return t(e(a));
|
|
85
|
+
} catch {
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
function u(e) {
|
|
91
|
+
return "" + e;
|
|
92
|
+
}
|
|
93
|
+
function i(e) {
|
|
94
|
+
try {
|
|
95
|
+
u(e);
|
|
96
|
+
var a = !1;
|
|
97
|
+
} catch {
|
|
98
|
+
a = !0;
|
|
99
|
+
}
|
|
100
|
+
if (a) {
|
|
101
|
+
a = console;
|
|
102
|
+
var b = a.error, y = typeof Symbol == "function" && Symbol.toStringTag && e[Symbol.toStringTag] || e.constructor.name || "Object";
|
|
103
|
+
return b.call(
|
|
104
|
+
a,
|
|
105
|
+
"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",
|
|
106
|
+
y
|
|
107
|
+
), u(e);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
function o(e) {
|
|
111
|
+
if (e === C) return "<>";
|
|
112
|
+
if (typeof e == "object" && e !== null && e.$$typeof === L)
|
|
113
|
+
return "<...>";
|
|
114
|
+
try {
|
|
115
|
+
var a = t(e);
|
|
116
|
+
return a ? "<" + a + ">" : "<...>";
|
|
117
|
+
} catch {
|
|
118
|
+
return "<...>";
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
function n() {
|
|
122
|
+
var e = $.A;
|
|
123
|
+
return e === null ? null : e.getOwner();
|
|
124
|
+
}
|
|
125
|
+
function s() {
|
|
126
|
+
return Error("react-stack-top-frame");
|
|
127
|
+
}
|
|
128
|
+
function x(e) {
|
|
129
|
+
if (G.call(e, "key")) {
|
|
130
|
+
var a = Object.getOwnPropertyDescriptor(e, "key").get;
|
|
131
|
+
if (a && a.isReactWarning) return !1;
|
|
132
|
+
}
|
|
133
|
+
return e.key !== void 0;
|
|
134
|
+
}
|
|
135
|
+
function c(e, a) {
|
|
136
|
+
function b() {
|
|
137
|
+
J || (J = !0, console.error(
|
|
138
|
+
"%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",
|
|
139
|
+
a
|
|
140
|
+
));
|
|
141
|
+
}
|
|
142
|
+
b.isReactWarning = !0, Object.defineProperty(e, "key", {
|
|
143
|
+
get: b,
|
|
144
|
+
configurable: !0
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
function d() {
|
|
148
|
+
var e = t(this.type);
|
|
149
|
+
return H[e] || (H[e] = !0, console.error(
|
|
150
|
+
"Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release."
|
|
151
|
+
)), e = this.props.ref, e !== void 0 ? e : null;
|
|
152
|
+
}
|
|
153
|
+
function f(e, a, b, y, D, U) {
|
|
154
|
+
var k = b.ref;
|
|
155
|
+
return e = {
|
|
156
|
+
$$typeof: g,
|
|
157
|
+
type: e,
|
|
158
|
+
key: a,
|
|
159
|
+
props: b,
|
|
160
|
+
_owner: y
|
|
161
|
+
}, (k !== void 0 ? k : null) !== null ? Object.defineProperty(e, "ref", {
|
|
162
|
+
enumerable: !1,
|
|
163
|
+
get: d
|
|
164
|
+
}) : Object.defineProperty(e, "ref", { enumerable: !1, value: null }), e._store = {}, Object.defineProperty(e._store, "validated", {
|
|
165
|
+
configurable: !1,
|
|
166
|
+
enumerable: !1,
|
|
167
|
+
writable: !0,
|
|
168
|
+
value: 0
|
|
169
|
+
}), Object.defineProperty(e, "_debugInfo", {
|
|
170
|
+
configurable: !1,
|
|
171
|
+
enumerable: !1,
|
|
172
|
+
writable: !0,
|
|
173
|
+
value: null
|
|
174
|
+
}), Object.defineProperty(e, "_debugStack", {
|
|
175
|
+
configurable: !1,
|
|
176
|
+
enumerable: !1,
|
|
177
|
+
writable: !0,
|
|
178
|
+
value: D
|
|
179
|
+
}), Object.defineProperty(e, "_debugTask", {
|
|
180
|
+
configurable: !1,
|
|
181
|
+
enumerable: !1,
|
|
182
|
+
writable: !0,
|
|
183
|
+
value: U
|
|
184
|
+
}), Object.freeze && (Object.freeze(e.props), Object.freeze(e)), e;
|
|
185
|
+
}
|
|
186
|
+
function h(e, a, b, y, D, U) {
|
|
187
|
+
var k = a.children;
|
|
188
|
+
if (k !== void 0)
|
|
189
|
+
if (y)
|
|
190
|
+
if (ce(k)) {
|
|
191
|
+
for (y = 0; y < k.length; y++)
|
|
192
|
+
v(k[y]);
|
|
193
|
+
Object.freeze && Object.freeze(k);
|
|
194
|
+
} else
|
|
195
|
+
console.error(
|
|
196
|
+
"React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead."
|
|
197
|
+
);
|
|
198
|
+
else v(k);
|
|
199
|
+
if (G.call(a, "key")) {
|
|
200
|
+
k = t(e);
|
|
201
|
+
var S = Object.keys(a).filter(function(ue) {
|
|
202
|
+
return ue !== "key";
|
|
203
|
+
});
|
|
204
|
+
y = 0 < S.length ? "{key: someKey, " + S.join(": ..., ") + ": ...}" : "{key: someKey}", Q[k + y] || (S = 0 < S.length ? "{" + S.join(": ..., ") + ": ...}" : "{}", console.error(
|
|
205
|
+
`A props object containing a "key" prop is being spread into JSX:
|
|
206
|
+
let props = %s;
|
|
207
|
+
<%s {...props} />
|
|
208
|
+
React keys must be passed directly to JSX without using spread:
|
|
209
|
+
let props = %s;
|
|
210
|
+
<%s key={someKey} {...props} />`,
|
|
211
|
+
y,
|
|
212
|
+
k,
|
|
213
|
+
S,
|
|
214
|
+
k
|
|
215
|
+
), Q[k + y] = !0);
|
|
216
|
+
}
|
|
217
|
+
if (k = null, b !== void 0 && (i(b), k = "" + b), x(a) && (i(a.key), k = "" + a.key), "key" in a) {
|
|
218
|
+
b = {};
|
|
219
|
+
for (var z in a)
|
|
220
|
+
z !== "key" && (b[z] = a[z]);
|
|
221
|
+
} else b = a;
|
|
222
|
+
return k && c(
|
|
223
|
+
b,
|
|
224
|
+
typeof e == "function" ? e.displayName || e.name || "Unknown" : e
|
|
225
|
+
), f(
|
|
226
|
+
e,
|
|
227
|
+
k,
|
|
228
|
+
b,
|
|
229
|
+
n(),
|
|
230
|
+
D,
|
|
231
|
+
U
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
function v(e) {
|
|
235
|
+
j(e) ? e._store && (e._store.validated = 1) : typeof e == "object" && e !== null && e.$$typeof === L && (e._payload.status === "fulfilled" ? j(e._payload.value) && e._payload.value._store && (e._payload.value._store.validated = 1) : e._store && (e._store.validated = 1));
|
|
236
|
+
}
|
|
237
|
+
function j(e) {
|
|
238
|
+
return typeof e == "object" && e !== null && e.$$typeof === g;
|
|
239
|
+
}
|
|
240
|
+
var m = de, g = Symbol.for("react.transitional.element"), E = Symbol.for("react.portal"), C = Symbol.for("react.fragment"), p = Symbol.for("react.strict_mode"), A = Symbol.for("react.profiler"), l = Symbol.for("react.consumer"), R = Symbol.for("react.context"), _ = Symbol.for("react.forward_ref"), w = Symbol.for("react.suspense"), P = Symbol.for("react.suspense_list"), O = Symbol.for("react.memo"), L = Symbol.for("react.lazy"), le = Symbol.for("react.activity"), ie = Symbol.for("react.client.reference"), $ = m.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, G = Object.prototype.hasOwnProperty, ce = Array.isArray, B = console.createTask ? console.createTask : function() {
|
|
241
|
+
return null;
|
|
242
|
+
};
|
|
243
|
+
m = {
|
|
244
|
+
react_stack_bottom_frame: function(e) {
|
|
245
|
+
return e();
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
var J, H = {}, Z = m.react_stack_bottom_frame.bind(
|
|
249
|
+
m,
|
|
250
|
+
s
|
|
251
|
+
)(), K = B(o(s)), Q = {};
|
|
252
|
+
F.Fragment = C, F.jsx = function(e, a, b) {
|
|
253
|
+
var y = 1e4 > $.recentlyCreatedOwnerStacks++;
|
|
254
|
+
return h(
|
|
255
|
+
e,
|
|
256
|
+
a,
|
|
257
|
+
b,
|
|
258
|
+
!1,
|
|
259
|
+
y ? Error("react-stack-top-frame") : Z,
|
|
260
|
+
y ? B(o(e)) : K
|
|
261
|
+
);
|
|
262
|
+
}, F.jsxs = function(e, a, b) {
|
|
263
|
+
var y = 1e4 > $.recentlyCreatedOwnerStacks++;
|
|
264
|
+
return h(
|
|
265
|
+
e,
|
|
266
|
+
a,
|
|
267
|
+
b,
|
|
268
|
+
!0,
|
|
269
|
+
y ? Error("react-stack-top-frame") : Z,
|
|
270
|
+
y ? B(o(e)) : K
|
|
271
|
+
);
|
|
272
|
+
};
|
|
273
|
+
})()), F;
|
|
274
|
+
}
|
|
275
|
+
var re;
|
|
276
|
+
function xe() {
|
|
277
|
+
return re || (re = 1, process.env.NODE_ENV === "production" ? Y.exports = me() : Y.exports = he()), Y.exports;
|
|
278
|
+
}
|
|
279
|
+
var r = xe();
|
|
280
|
+
const ge = (t, u) => {
|
|
281
|
+
const i = u.getBoundingClientRect();
|
|
282
|
+
let o, n;
|
|
283
|
+
"touches" in t ? (o = t.touches[0].clientX, n = t.touches[0].clientY) : (o = t.clientX, n = t.clientY);
|
|
284
|
+
const s = (o - i.left) / i.width * 100, x = (n - i.top) / i.height * 100;
|
|
285
|
+
return {
|
|
286
|
+
x: Math.max(0, Math.min(100, s)),
|
|
287
|
+
y: Math.max(0, Math.min(100, x))
|
|
288
|
+
};
|
|
289
|
+
}, X = (t) => parseInt(t.replace(/^#/, ""), 16), ae = (t) => {
|
|
290
|
+
const u = t.toString(16).toUpperCase();
|
|
291
|
+
return `#${"0".repeat(6 - u.length)}${u}`;
|
|
292
|
+
}, W = {
|
|
293
|
+
en: {
|
|
294
|
+
editMarker: "Edit Marker",
|
|
295
|
+
title: "Title",
|
|
296
|
+
note: "Note",
|
|
297
|
+
photos: "Photos",
|
|
298
|
+
delete: "Delete",
|
|
299
|
+
cancel: "Cancel",
|
|
300
|
+
save: "Save",
|
|
301
|
+
newMarker: "New Marker",
|
|
302
|
+
uploadImage: "Upload Image",
|
|
303
|
+
deleteConfirmation: "Are you sure you want to delete this marker?",
|
|
304
|
+
confirmClear: "Clear existing markers for new image?",
|
|
305
|
+
titlePlaceholder: "Enter a title",
|
|
306
|
+
notePlaceholder: "Enter a note",
|
|
307
|
+
titleRequired: "Title is required"
|
|
308
|
+
},
|
|
309
|
+
tr: {
|
|
310
|
+
editMarker: "İşaretçiyi Düzenle",
|
|
311
|
+
title: "Başlık",
|
|
312
|
+
note: "Not",
|
|
313
|
+
photos: "Fotoğraflar",
|
|
314
|
+
delete: "Sil",
|
|
315
|
+
cancel: "İptal",
|
|
316
|
+
save: "Kaydet",
|
|
317
|
+
newMarker: "Yeni İşaretçi",
|
|
318
|
+
uploadImage: "Görsel Yükle",
|
|
319
|
+
deleteConfirmation: "Bu işaretçiyi silmek istediğinizden emin misiniz?",
|
|
320
|
+
confirmClear: "Yeni görsel için mevcut işaretçileri temizle?",
|
|
321
|
+
titlePlaceholder: "Bir başlık girin",
|
|
322
|
+
notePlaceholder: "Bir not girin",
|
|
323
|
+
titleRequired: "Başlık zorunludur"
|
|
324
|
+
},
|
|
325
|
+
es: {
|
|
326
|
+
editMarker: "Editar Marcador",
|
|
327
|
+
title: "Título",
|
|
328
|
+
note: "Nota",
|
|
329
|
+
photos: "Fotos",
|
|
330
|
+
delete: "Eliminar",
|
|
331
|
+
cancel: "Cancelar",
|
|
332
|
+
save: "Guardar",
|
|
333
|
+
newMarker: "Nuevo Marcador",
|
|
334
|
+
uploadImage: "Subir Imagen",
|
|
335
|
+
deleteConfirmation: "¿Estás seguro de que deseas eliminar este marcador?",
|
|
336
|
+
confirmClear: "¿Borrar marcadores existentes para la nueva imagen?",
|
|
337
|
+
titlePlaceholder: "Ingrese un título",
|
|
338
|
+
notePlaceholder: "Ingrese una nota",
|
|
339
|
+
titleRequired: "El título es obligatorio"
|
|
340
|
+
}
|
|
341
|
+
}, V = () => fe(() => {
|
|
342
|
+
const u = navigator.language.split("-")[0];
|
|
343
|
+
return u === "tr" ? W.tr : u === "es" ? W.es : W.en;
|
|
344
|
+
}, []), ne = ({ marker: t, onClick: u, onUpdate: i, onDelete: o }) => {
|
|
345
|
+
const n = ae(t.color), [s, x] = N(!1), c = T(null), d = V(), f = T(null), h = T(!1), v = T({ x: 0, y: 0 }), j = T(!1), m = (p) => {
|
|
346
|
+
p.stopPropagation(), p.preventDefault(), j.current = !1, h.current = !1, v.current = { x: p.clientX, y: p.clientY }, f.current = window.setTimeout(() => {
|
|
347
|
+
h.current = !0, window.confirm(d.deleteConfirmation) && o(t.id);
|
|
348
|
+
}, 500), x(!0), p.target.setPointerCapture(p.pointerId);
|
|
349
|
+
}, g = (p) => {
|
|
350
|
+
var R;
|
|
351
|
+
if (!s) return;
|
|
352
|
+
Math.sqrt(Math.pow(p.clientX - v.current.x, 2) + Math.pow(p.clientY - v.current.y, 2)) > 5 && (j.current = !0, f.current && (clearTimeout(f.current), f.current = null));
|
|
353
|
+
const l = (R = c.current) == null ? void 0 : R.parentElement;
|
|
354
|
+
if (l) {
|
|
355
|
+
const _ = l.getBoundingClientRect();
|
|
356
|
+
let w = (p.clientX - _.left) / _.width * 100, P = (p.clientY - _.top) / _.height * 100;
|
|
357
|
+
w = Math.max(0, Math.min(100, w)), P = Math.max(0, Math.min(100, P)), i(t.id, { x: w, y: P });
|
|
358
|
+
}
|
|
359
|
+
}, E = (p) => {
|
|
360
|
+
p.stopPropagation(), x(!1), p.target.releasePointerCapture(p.pointerId), f.current && (clearTimeout(f.current), f.current = null);
|
|
361
|
+
}, C = (p) => {
|
|
362
|
+
p.stopPropagation(), !j.current && !h.current && u(t);
|
|
363
|
+
};
|
|
364
|
+
return /* @__PURE__ */ r.jsx(
|
|
365
|
+
"div",
|
|
366
|
+
{
|
|
367
|
+
ref: c,
|
|
368
|
+
onPointerDown: m,
|
|
369
|
+
onPointerMove: g,
|
|
370
|
+
onPointerUp: E,
|
|
371
|
+
onClick: C,
|
|
372
|
+
style: {
|
|
373
|
+
left: `${t.x}%`,
|
|
374
|
+
top: `${t.y}%`,
|
|
375
|
+
backgroundColor: n,
|
|
376
|
+
touchAction: "none"
|
|
377
|
+
},
|
|
378
|
+
className: `absolute h-6 w-6 -translate-x-1/2 -translate-y-1/2 cursor-pointer rounded-full border-2 border-white shadow-md flex items-center justify-center transition-transform ${s ? "scale-125 z-50" : "hover:scale-110"}`,
|
|
379
|
+
children: /* @__PURE__ */ r.jsx("div", { className: "w-2 h-2 bg-white rounded-full opacity-50" })
|
|
380
|
+
}
|
|
381
|
+
);
|
|
382
|
+
}, se = [
|
|
383
|
+
{ name: "Red", hex: "#EF4444" },
|
|
384
|
+
{ name: "Orange", hex: "#F97316" },
|
|
385
|
+
{ name: "Amber", hex: "#F59E0B" },
|
|
386
|
+
{ name: "Yellow", hex: "#EAB308" },
|
|
387
|
+
{ name: "Lime", hex: "#84CC16" },
|
|
388
|
+
{ name: "Green", hex: "#22C55E" },
|
|
389
|
+
{ name: "Emerald", hex: "#10B981" },
|
|
390
|
+
{ name: "Teal", hex: "#14B8A6" },
|
|
391
|
+
{ name: "Cyan", hex: "#06B6D4" },
|
|
392
|
+
{ name: "Sky", hex: "#0EA5E9" },
|
|
393
|
+
{ name: "Blue", hex: "#3B82F6" },
|
|
394
|
+
{ name: "Indigo", hex: "#6366F1" },
|
|
395
|
+
{ name: "Violet", hex: "#8B5CF6" },
|
|
396
|
+
{ name: "Purple", hex: "#A855F7" },
|
|
397
|
+
{ name: "Fuchsia", hex: "#D946EF" },
|
|
398
|
+
{ name: "Pink", hex: "#EC4899" },
|
|
399
|
+
{ name: "Rose", hex: "#F43F5E" },
|
|
400
|
+
{ name: "Slate", hex: "#64748B" },
|
|
401
|
+
{ name: "Black", hex: "#000000" },
|
|
402
|
+
{ name: "White", hex: "#FFFFFF" }
|
|
403
|
+
];
|
|
404
|
+
X(se[0].hex);
|
|
405
|
+
const pe = ({ color: t, onChange: u }) => {
|
|
406
|
+
const i = ae(t);
|
|
407
|
+
return /* @__PURE__ */ r.jsxs("div", { className: "space-y-2", children: [
|
|
408
|
+
/* @__PURE__ */ r.jsx("label", { className: "block text-sm font-medium text-gray-700", children: "Color" }),
|
|
409
|
+
/* @__PURE__ */ r.jsxs("div", { className: "flex flex-wrap gap-2", children: [
|
|
410
|
+
se.map((o) => /* @__PURE__ */ r.jsx(
|
|
411
|
+
"button",
|
|
412
|
+
{
|
|
413
|
+
onClick: () => u(X(o.hex)),
|
|
414
|
+
className: `h-6 w-6 rounded-full border transition-transform hover:scale-110 focus:outline-none focus:ring-2 focus:ring-offset-1 ${i === o.hex ? "ring-2 ring-blue-500 ring-offset-1" : "border-gray-200"}`,
|
|
415
|
+
style: { backgroundColor: o.hex },
|
|
416
|
+
title: o.name
|
|
417
|
+
},
|
|
418
|
+
o.hex
|
|
419
|
+
)),
|
|
420
|
+
/* @__PURE__ */ r.jsx(
|
|
421
|
+
"input",
|
|
422
|
+
{
|
|
423
|
+
type: "color",
|
|
424
|
+
value: i,
|
|
425
|
+
onChange: (o) => u(X(o.target.value)),
|
|
426
|
+
className: "h-6 w-6 cursor-pointer rounded-full border border-gray-300 p-0 overflow-hidden",
|
|
427
|
+
title: "Custom Color"
|
|
428
|
+
}
|
|
429
|
+
)
|
|
430
|
+
] })
|
|
431
|
+
] });
|
|
432
|
+
}, be = (t) => new Promise((u, i) => {
|
|
433
|
+
const o = new FileReader();
|
|
434
|
+
o.readAsDataURL(t), o.onload = () => u(o.result), o.onerror = (n) => i(n);
|
|
435
|
+
}), ve = ({ photos: t, photosNames: u, onUpload: i, onRemove: o, onPhotoClick: n }) => {
|
|
436
|
+
const s = V(), x = async (c) => {
|
|
437
|
+
if (c.target.files) {
|
|
438
|
+
const d = Array.from(c.target.files), f = await Promise.all(d.map(be)), h = d.map((g) => g.name), v = 3 - t.length, j = f.slice(0, v), m = h.slice(0, v);
|
|
439
|
+
i([...t, ...j], [...u, ...m]);
|
|
440
|
+
}
|
|
441
|
+
};
|
|
442
|
+
return /* @__PURE__ */ r.jsxs("div", { className: "space-y-2", children: [
|
|
443
|
+
/* @__PURE__ */ r.jsx("div", { className: "flex items-center justify-between", children: /* @__PURE__ */ r.jsxs("label", { className: "text-sm font-medium text-gray-700", children: [
|
|
444
|
+
s.photos,
|
|
445
|
+
" (",
|
|
446
|
+
t.length,
|
|
447
|
+
"/3)"
|
|
448
|
+
] }) }),
|
|
449
|
+
/* @__PURE__ */ r.jsxs("div", { className: "flex flex-wrap gap-2", children: [
|
|
450
|
+
t.map((c, d) => /* @__PURE__ */ r.jsxs("div", { className: "relative h-16 w-16 group", children: [
|
|
451
|
+
/* @__PURE__ */ r.jsx(
|
|
452
|
+
"img",
|
|
453
|
+
{
|
|
454
|
+
src: c,
|
|
455
|
+
alt: `Upload ${d}`,
|
|
456
|
+
className: "h-full w-full object-cover rounded border cursor-pointer",
|
|
457
|
+
onClick: () => n && n(d)
|
|
458
|
+
}
|
|
459
|
+
),
|
|
460
|
+
/* @__PURE__ */ r.jsx(
|
|
461
|
+
"button",
|
|
462
|
+
{
|
|
463
|
+
onClick: () => o(d),
|
|
464
|
+
className: "absolute -top-1 -right-1 bg-red-500 text-white rounded-full p-0.5 w-4 h-4 flex items-center justify-center text-xs opacity-0 group-hover:opacity-100 transition-opacity",
|
|
465
|
+
children: "×"
|
|
466
|
+
}
|
|
467
|
+
)
|
|
468
|
+
] }, d)),
|
|
469
|
+
t.length < 3 && /* @__PURE__ */ r.jsxs("label", { className: "flex h-16 w-16 cursor-pointer items-center justify-center rounded border-2 border-dashed border-gray-300 hover:border-blue-500 hover:bg-blue-50 transition-colors", children: [
|
|
470
|
+
/* @__PURE__ */ r.jsx("span", { className: "text-xl text-gray-400", children: "+" }),
|
|
471
|
+
/* @__PURE__ */ r.jsx("input", { type: "file", accept: "image/*", multiple: !0, onChange: x, className: "hidden" })
|
|
472
|
+
] })
|
|
473
|
+
] })
|
|
474
|
+
] });
|
|
475
|
+
}, we = ({ photos: t, initialIndex: u, onClose: i }) => {
|
|
476
|
+
const [o, n] = N(u), [s, x] = N(1), [c, d] = N({ x: 0, y: 0 }), [f, h] = N(!1), v = T({ x: 0, y: 0 }), j = T(null), m = M(() => {
|
|
477
|
+
x(1), d({ x: 0, y: 0 });
|
|
478
|
+
}, []), g = M(() => {
|
|
479
|
+
n((l) => (l + 1) % t.length), m();
|
|
480
|
+
}, [t.length, m]), E = M(() => {
|
|
481
|
+
n((l) => (l - 1 + t.length) % t.length), m();
|
|
482
|
+
}, [t.length, m]);
|
|
483
|
+
q(() => {
|
|
484
|
+
const l = (R) => {
|
|
485
|
+
R.key === "Escape" && i(), R.key === "ArrowRight" && g(), R.key === "ArrowLeft" && E();
|
|
486
|
+
};
|
|
487
|
+
return window.addEventListener("keydown", l), () => window.removeEventListener("keydown", l);
|
|
488
|
+
}, [i, g, E]), q(() => {
|
|
489
|
+
const l = j.current;
|
|
490
|
+
if (!l) return;
|
|
491
|
+
const R = (_) => {
|
|
492
|
+
_.preventDefault();
|
|
493
|
+
const w = -_.deltaY * 0.01, P = Math.min(Math.max(1, s + w), 5);
|
|
494
|
+
x(P), P === 1 && d({ x: 0, y: 0 });
|
|
495
|
+
};
|
|
496
|
+
return l.addEventListener("wheel", R, { passive: !1 }), () => l.removeEventListener("wheel", R);
|
|
497
|
+
}, [s]);
|
|
498
|
+
const C = (l) => {
|
|
499
|
+
s > 1 && (l.preventDefault(), h(!0), v.current = { x: l.clientX - c.x, y: l.clientY - c.y }, l.target.setPointerCapture(l.pointerId));
|
|
500
|
+
}, p = (l) => {
|
|
501
|
+
f && s > 1 && (l.preventDefault(), d({
|
|
502
|
+
x: l.clientX - v.current.x,
|
|
503
|
+
y: l.clientY - v.current.y
|
|
504
|
+
}));
|
|
505
|
+
}, A = (l) => {
|
|
506
|
+
h(!1), l.target.releasePointerCapture(l.pointerId);
|
|
507
|
+
};
|
|
508
|
+
return t.length ? /* @__PURE__ */ r.jsxs(
|
|
509
|
+
"div",
|
|
510
|
+
{
|
|
511
|
+
className: "fixed inset-0 z-[60] flex items-center justify-center bg-black bg-opacity-90 overflow-hidden",
|
|
512
|
+
onClick: (l) => {
|
|
513
|
+
l.stopPropagation(), i();
|
|
514
|
+
},
|
|
515
|
+
children: [
|
|
516
|
+
/* @__PURE__ */ r.jsx(
|
|
517
|
+
"button",
|
|
518
|
+
{
|
|
519
|
+
onClick: i,
|
|
520
|
+
className: "absolute top-4 right-4 text-white hover:text-gray-300 z-50 p-2",
|
|
521
|
+
children: /* @__PURE__ */ r.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-8 w-8", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ r.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
|
|
522
|
+
}
|
|
523
|
+
),
|
|
524
|
+
/* @__PURE__ */ r.jsxs(
|
|
525
|
+
"div",
|
|
526
|
+
{
|
|
527
|
+
ref: j,
|
|
528
|
+
className: "relative flex items-center justify-center w-full h-full p-4",
|
|
529
|
+
onClick: (l) => l.stopPropagation(),
|
|
530
|
+
children: [
|
|
531
|
+
t.length > 1 && /* @__PURE__ */ r.jsx(
|
|
532
|
+
"button",
|
|
533
|
+
{
|
|
534
|
+
onClick: E,
|
|
535
|
+
className: "absolute left-4 z-40 p-2 text-white hover:bg-white/10 rounded-full transition-colors",
|
|
536
|
+
children: /* @__PURE__ */ r.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-10 w-10", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ r.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M15 19l-7-7 7-7" }) })
|
|
537
|
+
}
|
|
538
|
+
),
|
|
539
|
+
/* @__PURE__ */ r.jsx("div", { className: "relative overflow-hidden flex items-center justify-center w-full h-full", children: /* @__PURE__ */ r.jsx(
|
|
540
|
+
"img",
|
|
541
|
+
{
|
|
542
|
+
src: t[o],
|
|
543
|
+
alt: `View ${o + 1}`,
|
|
544
|
+
onPointerDown: C,
|
|
545
|
+
onPointerMove: p,
|
|
546
|
+
onPointerUp: A,
|
|
547
|
+
style: {
|
|
548
|
+
transform: `scale(${s}) translate(${c.x / s}px, ${c.y / s}px)`,
|
|
549
|
+
transition: f ? "none" : "transform 0.1s ease-out",
|
|
550
|
+
cursor: s > 1 ? f ? "grabbing" : "grab" : "default",
|
|
551
|
+
maxHeight: "100%",
|
|
552
|
+
maxWidth: "100%"
|
|
553
|
+
},
|
|
554
|
+
className: "object-contain select-none touch-none"
|
|
555
|
+
}
|
|
556
|
+
) }),
|
|
557
|
+
t.length > 1 && /* @__PURE__ */ r.jsx(
|
|
558
|
+
"button",
|
|
559
|
+
{
|
|
560
|
+
onClick: g,
|
|
561
|
+
className: "absolute right-4 z-40 p-2 text-white hover:bg-white/10 rounded-full transition-colors",
|
|
562
|
+
children: /* @__PURE__ */ r.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-10 w-10", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ r.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 5l7 7-7 7" }) })
|
|
563
|
+
}
|
|
564
|
+
),
|
|
565
|
+
/* @__PURE__ */ r.jsxs("div", { className: "absolute bottom-4 left-0 right-0 text-center text-white text-sm bg-black/50 py-1 pointer-events-none", children: [
|
|
566
|
+
o + 1,
|
|
567
|
+
" / ",
|
|
568
|
+
t.length,
|
|
569
|
+
" ",
|
|
570
|
+
s > 1 && `(${Math.round(s * 100)}%)`
|
|
571
|
+
] })
|
|
572
|
+
]
|
|
573
|
+
}
|
|
574
|
+
)
|
|
575
|
+
]
|
|
576
|
+
}
|
|
577
|
+
) : null;
|
|
578
|
+
}, oe = ({ marker: t, onSave: u, onDelete: i, onClose: o }) => {
|
|
579
|
+
const n = V(), [s, x] = N(t.markerTitle), [c, d] = N(t.note), [f, h] = N(t.color), [v, j] = N(t.photos), [m, g] = N(t.photosName || []), [E, C] = N(!1), [p, A] = N(0), [l, R] = N(!1);
|
|
580
|
+
q(() => {
|
|
581
|
+
x(t.markerTitle), d(t.note), h(t.color), j(t.photos), g(t.photosName || []), R(!1);
|
|
582
|
+
}, [t]);
|
|
583
|
+
const _ = () => {
|
|
584
|
+
if (!s.trim()) {
|
|
585
|
+
R(!0);
|
|
586
|
+
return;
|
|
587
|
+
}
|
|
588
|
+
u(t.id, { markerTitle: s, note: c, color: f, photos: v, photosName: m }), o();
|
|
589
|
+
};
|
|
590
|
+
return /* @__PURE__ */ r.jsxs(r.Fragment, { children: [
|
|
591
|
+
/* @__PURE__ */ r.jsx("div", { className: "fixed inset-0 z-40 flex items-center justify-center bg-black/50", onClick: (w) => w.stopPropagation(), children: /* @__PURE__ */ r.jsxs("div", { className: "w-72 max-h-[90vh] overflow-y-auto rounded-lg bg-white p-4 shadow-xl border border-gray-200 relative z-50", children: [
|
|
592
|
+
/* @__PURE__ */ r.jsxs("div", { className: "mb-4 flex items-center justify-between", children: [
|
|
593
|
+
/* @__PURE__ */ r.jsx("h3", { className: "text-lg font-semibold text-gray-900", children: n.editMarker }),
|
|
594
|
+
/* @__PURE__ */ r.jsx("button", { onClick: o, className: "text-gray-400 hover:text-gray-600", children: "✕" })
|
|
595
|
+
] }),
|
|
596
|
+
/* @__PURE__ */ r.jsxs("div", { className: "space-y-4", children: [
|
|
597
|
+
/* @__PURE__ */ r.jsxs("div", { children: [
|
|
598
|
+
/* @__PURE__ */ r.jsxs("label", { className: "block text-sm font-medium text-gray-700", children: [
|
|
599
|
+
n.title,
|
|
600
|
+
" ",
|
|
601
|
+
/* @__PURE__ */ r.jsx("span", { className: "text-red-500", children: "*" })
|
|
602
|
+
] }),
|
|
603
|
+
/* @__PURE__ */ r.jsx(
|
|
604
|
+
"input",
|
|
605
|
+
{
|
|
606
|
+
type: "text",
|
|
607
|
+
value: s,
|
|
608
|
+
placeholder: n.titlePlaceholder,
|
|
609
|
+
onChange: (w) => {
|
|
610
|
+
x(w.target.value), l && R(!1);
|
|
611
|
+
},
|
|
612
|
+
className: `mt-1 block w-full rounded-md border px-3 py-2 shadow-sm focus:outline-none focus:ring-1 sm:text-sm ${l ? "border-red-500 focus:border-red-500 focus:ring-red-500" : "border-gray-300 focus:border-blue-500 focus:ring-blue-500"}`
|
|
613
|
+
}
|
|
614
|
+
),
|
|
615
|
+
l && /* @__PURE__ */ r.jsx("p", { className: "mt-1 text-xs text-red-500", children: n.titleRequired })
|
|
616
|
+
] }),
|
|
617
|
+
/* @__PURE__ */ r.jsxs("div", { children: [
|
|
618
|
+
/* @__PURE__ */ r.jsx("label", { className: "block text-sm font-medium text-gray-700", children: n.note }),
|
|
619
|
+
/* @__PURE__ */ r.jsx(
|
|
620
|
+
"textarea",
|
|
621
|
+
{
|
|
622
|
+
value: c,
|
|
623
|
+
placeholder: n.notePlaceholder,
|
|
624
|
+
onChange: (w) => d(w.target.value),
|
|
625
|
+
rows: 3,
|
|
626
|
+
className: "mt-1 block w-full rounded-md border border-gray-300 px-3 py-2 shadow-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500 sm:text-sm"
|
|
627
|
+
}
|
|
628
|
+
)
|
|
629
|
+
] }),
|
|
630
|
+
/* @__PURE__ */ r.jsx(pe, { color: f, onChange: h }),
|
|
631
|
+
/* @__PURE__ */ r.jsx(
|
|
632
|
+
ve,
|
|
633
|
+
{
|
|
634
|
+
photos: v,
|
|
635
|
+
photosNames: m,
|
|
636
|
+
onUpload: (w, P) => {
|
|
637
|
+
j(w), g(P);
|
|
638
|
+
},
|
|
639
|
+
onRemove: (w) => {
|
|
640
|
+
j(v.filter((P, O) => O !== w)), g(m.filter((P, O) => O !== w));
|
|
641
|
+
},
|
|
642
|
+
onPhotoClick: (w) => {
|
|
643
|
+
A(w), C(!0);
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
),
|
|
647
|
+
/* @__PURE__ */ r.jsxs("div", { className: "mt-4 flex justify-between", children: [
|
|
648
|
+
/* @__PURE__ */ r.jsx(
|
|
649
|
+
"button",
|
|
650
|
+
{
|
|
651
|
+
onClick: () => i(t.id),
|
|
652
|
+
className: "rounded px-3 py-2 text-sm font-medium text-red-600 hover:bg-red-50",
|
|
653
|
+
children: n.delete
|
|
654
|
+
}
|
|
655
|
+
),
|
|
656
|
+
/* @__PURE__ */ r.jsxs("div", { className: "space-x-2", children: [
|
|
657
|
+
/* @__PURE__ */ r.jsx(
|
|
658
|
+
"button",
|
|
659
|
+
{
|
|
660
|
+
onClick: o,
|
|
661
|
+
className: "rounded border border-gray-300 px-3 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50",
|
|
662
|
+
children: n.cancel
|
|
663
|
+
}
|
|
664
|
+
),
|
|
665
|
+
/* @__PURE__ */ r.jsx(
|
|
666
|
+
"button",
|
|
667
|
+
{
|
|
668
|
+
onClick: _,
|
|
669
|
+
className: "rounded bg-blue-600 px-3 py-2 text-sm font-medium text-white hover:bg-blue-700",
|
|
670
|
+
children: n.save
|
|
671
|
+
}
|
|
672
|
+
)
|
|
673
|
+
] })
|
|
674
|
+
] })
|
|
675
|
+
] })
|
|
676
|
+
] }) }),
|
|
677
|
+
E && /* @__PURE__ */ r.jsx(
|
|
678
|
+
we,
|
|
679
|
+
{
|
|
680
|
+
photos: v,
|
|
681
|
+
initialIndex: p,
|
|
682
|
+
onClose: () => C(!1)
|
|
683
|
+
}
|
|
684
|
+
)
|
|
685
|
+
] });
|
|
686
|
+
}, ke = ({
|
|
687
|
+
src: t,
|
|
688
|
+
markers: u,
|
|
689
|
+
onAddMarker: i,
|
|
690
|
+
onUpdateMarker: o,
|
|
691
|
+
onDeleteMarker: n
|
|
692
|
+
}) => {
|
|
693
|
+
const s = T(null), x = T(null), [c, d] = N(null), [f, h] = N(null), v = (m) => {
|
|
694
|
+
if (!x.current) return;
|
|
695
|
+
if (c) {
|
|
696
|
+
d(null);
|
|
697
|
+
return;
|
|
698
|
+
}
|
|
699
|
+
if (f) {
|
|
700
|
+
h(null);
|
|
701
|
+
return;
|
|
702
|
+
}
|
|
703
|
+
const { x: g, y: E } = ge(m, x.current), C = {
|
|
704
|
+
id: crypto.randomUUID(),
|
|
705
|
+
x: g,
|
|
706
|
+
y: E,
|
|
707
|
+
color: 16711680,
|
|
708
|
+
// Default Red
|
|
709
|
+
markerTitle: "",
|
|
710
|
+
note: "",
|
|
711
|
+
photos: [],
|
|
712
|
+
photosName: []
|
|
713
|
+
};
|
|
714
|
+
h(C);
|
|
715
|
+
}, j = u.find((m) => m.id === c);
|
|
716
|
+
return /* @__PURE__ */ r.jsx("div", { className: "relative inline-block overflow-hidden rounded-lg shadow-lg group select-none", children: /* @__PURE__ */ r.jsxs(
|
|
717
|
+
"div",
|
|
718
|
+
{
|
|
719
|
+
ref: x,
|
|
720
|
+
onClick: v,
|
|
721
|
+
className: "relative cursor-crosshair",
|
|
722
|
+
children: [
|
|
723
|
+
/* @__PURE__ */ r.jsx(
|
|
724
|
+
"img",
|
|
725
|
+
{
|
|
726
|
+
ref: s,
|
|
727
|
+
src: t,
|
|
728
|
+
alt: "Marker Area",
|
|
729
|
+
className: "block max-w-full h-auto",
|
|
730
|
+
draggable: !1
|
|
731
|
+
}
|
|
732
|
+
),
|
|
733
|
+
u.map((m) => /* @__PURE__ */ r.jsx(
|
|
734
|
+
ne,
|
|
735
|
+
{
|
|
736
|
+
marker: m,
|
|
737
|
+
onClick: (g) => {
|
|
738
|
+
h(null), d(g.id);
|
|
739
|
+
},
|
|
740
|
+
onUpdate: (g, E) => o(g, E),
|
|
741
|
+
onDelete: n
|
|
742
|
+
},
|
|
743
|
+
m.id
|
|
744
|
+
)),
|
|
745
|
+
f && /* @__PURE__ */ r.jsx(
|
|
746
|
+
ne,
|
|
747
|
+
{
|
|
748
|
+
marker: f,
|
|
749
|
+
onClick: () => {
|
|
750
|
+
},
|
|
751
|
+
onUpdate: (m, g) => h((E) => E ? { ...E, ...g } : null),
|
|
752
|
+
onDelete: () => h(null)
|
|
753
|
+
},
|
|
754
|
+
"temp-marker"
|
|
755
|
+
),
|
|
756
|
+
j && /* @__PURE__ */ r.jsx(
|
|
757
|
+
oe,
|
|
758
|
+
{
|
|
759
|
+
marker: j,
|
|
760
|
+
onSave: o,
|
|
761
|
+
onDelete: (m) => {
|
|
762
|
+
n(m), d(null);
|
|
763
|
+
},
|
|
764
|
+
onClose: () => d(null)
|
|
765
|
+
}
|
|
766
|
+
),
|
|
767
|
+
f && /* @__PURE__ */ r.jsx(
|
|
768
|
+
oe,
|
|
769
|
+
{
|
|
770
|
+
marker: f,
|
|
771
|
+
onSave: (m, g) => {
|
|
772
|
+
i({ ...f, ...g }), h(null);
|
|
773
|
+
},
|
|
774
|
+
onDelete: () => h(null),
|
|
775
|
+
onClose: () => h(null)
|
|
776
|
+
}
|
|
777
|
+
)
|
|
778
|
+
]
|
|
779
|
+
}
|
|
780
|
+
) });
|
|
781
|
+
}, je = (t = []) => {
|
|
782
|
+
const [u, i] = N(t), o = M((c) => {
|
|
783
|
+
i((d) => [...d, c]);
|
|
784
|
+
}, []), n = M((c, d) => {
|
|
785
|
+
i(
|
|
786
|
+
(f) => f.map((h) => h.id === c ? { ...h, ...d } : h)
|
|
787
|
+
);
|
|
788
|
+
}, []), s = M((c) => {
|
|
789
|
+
i((d) => d.filter((f) => f.id !== c));
|
|
790
|
+
}, []), x = M((c) => {
|
|
791
|
+
i(c);
|
|
792
|
+
}, []);
|
|
793
|
+
return {
|
|
794
|
+
markers: u,
|
|
795
|
+
addMarker: o,
|
|
796
|
+
updateMarker: n,
|
|
797
|
+
removeMarker: s,
|
|
798
|
+
setAllMarkers: x
|
|
799
|
+
};
|
|
800
|
+
};
|
|
801
|
+
export {
|
|
802
|
+
pe as ColorPicker,
|
|
803
|
+
ke as ImageArea,
|
|
804
|
+
ke as ImageMarker,
|
|
805
|
+
we as Lightbox,
|
|
806
|
+
ne as MarkerItem,
|
|
807
|
+
oe as MarkerPopup,
|
|
808
|
+
ve as PhotoUploader,
|
|
809
|
+
V as useLocale,
|
|
810
|
+
je as useMarkerState
|
|
811
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
(function(N,n){typeof exports=="object"&&typeof module<"u"?n(exports,require("react")):typeof define=="function"&&define.amd?define(["exports","react"],n):(N=typeof globalThis<"u"?globalThis:N||self,n(N.ReactImageMarker={},N.React))})(this,(function(N,n){"use strict";var F={exports:{}},A={};/**
|
|
2
|
+
* @license React
|
|
3
|
+
* react-jsx-runtime.production.js
|
|
4
|
+
*
|
|
5
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
6
|
+
*
|
|
7
|
+
* This source code is licensed under the MIT license found in the
|
|
8
|
+
* LICENSE file in the root directory of this source tree.
|
|
9
|
+
*/var H;function ce(){if(H)return A;H=1;var t=Symbol.for("react.transitional.element"),d=Symbol.for("react.fragment");function c(a,o,l){var g=null;if(l!==void 0&&(g=""+l),o.key!==void 0&&(g=""+o.key),"key"in o){l={};for(var u in o)u!=="key"&&(l[u]=o[u])}else l=o;return o=l.ref,{$$typeof:t,type:a,key:g,ref:o!==void 0?o:null,props:l}}return A.Fragment=d,A.jsx=c,A.jsxs=c,A}var O={};/**
|
|
10
|
+
* @license React
|
|
11
|
+
* react-jsx-runtime.development.js
|
|
12
|
+
*
|
|
13
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
14
|
+
*
|
|
15
|
+
* This source code is licensed under the MIT license found in the
|
|
16
|
+
* LICENSE file in the root directory of this source tree.
|
|
17
|
+
*/var Z;function ue(){return Z||(Z=1,process.env.NODE_ENV!=="production"&&(function(){function t(e){if(e==null)return null;if(typeof e=="function")return e.$$typeof===ge?null:e.displayName||e.name||null;if(typeof e=="string")return e;switch(e){case P:return"Fragment";case S:return"Profiler";case b:return"StrictMode";case k:return"Suspense";case _:return"SuspenseList";case xe:return"Activity"}if(typeof e=="object")switch(typeof e.tag=="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),e.$$typeof){case R:return"Portal";case C:return e.displayName||"Context";case i:return(e._context.displayName||"Context")+".Consumer";case T:var s=e.render;return e=e.displayName,e||(e=s.displayName||s.name||"",e=e!==""?"ForwardRef("+e+")":"ForwardRef"),e;case I:return s=e.displayName||null,s!==null?s:t(e.type)||"Memo";case W:s=e._payload,e=e._init;try{return t(e(s))}catch{}}return null}function d(e){return""+e}function c(e){try{d(e);var s=!1}catch{s=!0}if(s){s=console;var v=s.error,y=typeof Symbol=="function"&&Symbol.toStringTag&&e[Symbol.toStringTag]||e.constructor.name||"Object";return v.call(s,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",y),d(e)}}function a(e){if(e===P)return"<>";if(typeof e=="object"&&e!==null&&e.$$typeof===W)return"<...>";try{var s=t(e);return s?"<"+s+">":"<...>"}catch{return"<...>"}}function o(){var e=X.A;return e===null?null:e.getOwner()}function l(){return Error("react-stack-top-frame")}function g(e){if(ne.call(e,"key")){var s=Object.getOwnPropertyDescriptor(e,"key").get;if(s&&s.isReactWarning)return!1}return e.key!==void 0}function u(e,s){function v(){oe||(oe=!0,console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",s))}v.isReactWarning=!0,Object.defineProperty(e,"key",{get:v,configurable:!0})}function f(){var e=t(this.type);return ae[e]||(ae[e]=!0,console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.")),e=this.props.ref,e!==void 0?e:null}function m(e,s,v,y,L,G){var j=v.ref;return e={$$typeof:p,type:e,key:s,props:v,_owner:y},(j!==void 0?j:null)!==null?Object.defineProperty(e,"ref",{enumerable:!1,get:f}):Object.defineProperty(e,"ref",{enumerable:!1,value:null}),e._store={},Object.defineProperty(e._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(e,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(e,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:L}),Object.defineProperty(e,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:G}),Object.freeze&&(Object.freeze(e.props),Object.freeze(e)),e}function x(e,s,v,y,L,G){var j=s.children;if(j!==void 0)if(y)if(pe(j)){for(y=0;y<j.length;y++)w(j[y]);Object.freeze&&Object.freeze(j)}else console.error("React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.");else w(j);if(ne.call(s,"key")){j=t(e);var M=Object.keys(s).filter(function(be){return be!=="key"});y=0<M.length?"{key: someKey, "+M.join(": ..., ")+": ...}":"{key: someKey}",ie[j+y]||(M=0<M.length?"{"+M.join(": ..., ")+": ...}":"{}",console.error(`A props object containing a "key" prop is being spread into JSX:
|
|
18
|
+
let props = %s;
|
|
19
|
+
<%s {...props} />
|
|
20
|
+
React keys must be passed directly to JSX without using spread:
|
|
21
|
+
let props = %s;
|
|
22
|
+
<%s key={someKey} {...props} />`,y,j,M,j),ie[j+y]=!0)}if(j=null,v!==void 0&&(c(v),j=""+v),g(s)&&(c(s.key),j=""+s.key),"key"in s){v={};for(var J in s)J!=="key"&&(v[J]=s[J])}else v=s;return j&&u(v,typeof e=="function"?e.displayName||e.name||"Unknown":e),m(e,j,v,o(),L,G)}function w(e){E(e)?e._store&&(e._store.validated=1):typeof e=="object"&&e!==null&&e.$$typeof===W&&(e._payload.status==="fulfilled"?E(e._payload.value)&&e._payload.value._store&&(e._payload.value._store.validated=1):e._store&&(e._store.validated=1))}function E(e){return typeof e=="object"&&e!==null&&e.$$typeof===p}var h=n,p=Symbol.for("react.transitional.element"),R=Symbol.for("react.portal"),P=Symbol.for("react.fragment"),b=Symbol.for("react.strict_mode"),S=Symbol.for("react.profiler"),i=Symbol.for("react.consumer"),C=Symbol.for("react.context"),T=Symbol.for("react.forward_ref"),k=Symbol.for("react.suspense"),_=Symbol.for("react.suspense_list"),I=Symbol.for("react.memo"),W=Symbol.for("react.lazy"),xe=Symbol.for("react.activity"),ge=Symbol.for("react.client.reference"),X=h.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,ne=Object.prototype.hasOwnProperty,pe=Array.isArray,V=console.createTask?console.createTask:function(){return null};h={react_stack_bottom_frame:function(e){return e()}};var oe,ae={},se=h.react_stack_bottom_frame.bind(h,l)(),le=V(a(l)),ie={};O.Fragment=P,O.jsx=function(e,s,v){var y=1e4>X.recentlyCreatedOwnerStacks++;return x(e,s,v,!1,y?Error("react-stack-top-frame"):se,y?V(a(e)):le)},O.jsxs=function(e,s,v){var y=1e4>X.recentlyCreatedOwnerStacks++;return x(e,s,v,!0,y?Error("react-stack-top-frame"):se,y?V(a(e)):le)}})()),O}var K;function de(){return K||(K=1,process.env.NODE_ENV==="production"?F.exports=ce():F.exports=ue()),F.exports}var r=de();const fe=(t,d)=>{const c=d.getBoundingClientRect();let a,o;"touches"in t?(a=t.touches[0].clientX,o=t.touches[0].clientY):(a=t.clientX,o=t.clientY);const l=(a-c.left)/c.width*100,g=(o-c.top)/c.height*100;return{x:Math.max(0,Math.min(100,l)),y:Math.max(0,Math.min(100,g))}},Y=t=>parseInt(t.replace(/^#/,""),16),Q=t=>{const d=t.toString(16).toUpperCase();return`#${"0".repeat(6-d.length)}${d}`},B={en:{editMarker:"Edit Marker",title:"Title",note:"Note",photos:"Photos",delete:"Delete",cancel:"Cancel",save:"Save",newMarker:"New Marker",uploadImage:"Upload Image",deleteConfirmation:"Are you sure you want to delete this marker?",confirmClear:"Clear existing markers for new image?",titlePlaceholder:"Enter a title",notePlaceholder:"Enter a note",titleRequired:"Title is required"},tr:{editMarker:"İşaretçiyi Düzenle",title:"Başlık",note:"Not",photos:"Fotoğraflar",delete:"Sil",cancel:"İptal",save:"Kaydet",newMarker:"Yeni İşaretçi",uploadImage:"Görsel Yükle",deleteConfirmation:"Bu işaretçiyi silmek istediğinizden emin misiniz?",confirmClear:"Yeni görsel için mevcut işaretçileri temizle?",titlePlaceholder:"Bir başlık girin",notePlaceholder:"Bir not girin",titleRequired:"Başlık zorunludur"},es:{editMarker:"Editar Marcador",title:"Título",note:"Nota",photos:"Fotos",delete:"Eliminar",cancel:"Cancelar",save:"Guardar",newMarker:"Nuevo Marcador",uploadImage:"Subir Imagen",deleteConfirmation:"¿Estás seguro de que deseas eliminar este marcador?",confirmClear:"¿Borrar marcadores existentes para la nueva imagen?",titlePlaceholder:"Ingrese un título",notePlaceholder:"Ingrese una nota",titleRequired:"El título es obligatorio"}},D=()=>n.useMemo(()=>{const d=navigator.language.split("-")[0];return d==="tr"?B.tr:d==="es"?B.es:B.en},[]),U=({marker:t,onClick:d,onUpdate:c,onDelete:a})=>{const o=Q(t.color),[l,g]=n.useState(!1),u=n.useRef(null),f=D(),m=n.useRef(null),x=n.useRef(!1),w=n.useRef({x:0,y:0}),E=n.useRef(!1),h=b=>{b.stopPropagation(),b.preventDefault(),E.current=!1,x.current=!1,w.current={x:b.clientX,y:b.clientY},m.current=window.setTimeout(()=>{x.current=!0,window.confirm(f.deleteConfirmation)&&a(t.id)},500),g(!0),b.target.setPointerCapture(b.pointerId)},p=b=>{var C;if(!l)return;Math.sqrt(Math.pow(b.clientX-w.current.x,2)+Math.pow(b.clientY-w.current.y,2))>5&&(E.current=!0,m.current&&(clearTimeout(m.current),m.current=null));const i=(C=u.current)==null?void 0:C.parentElement;if(i){const T=i.getBoundingClientRect();let k=(b.clientX-T.left)/T.width*100,_=(b.clientY-T.top)/T.height*100;k=Math.max(0,Math.min(100,k)),_=Math.max(0,Math.min(100,_)),c(t.id,{x:k,y:_})}},R=b=>{b.stopPropagation(),g(!1),b.target.releasePointerCapture(b.pointerId),m.current&&(clearTimeout(m.current),m.current=null)},P=b=>{b.stopPropagation(),!E.current&&!x.current&&d(t)};return r.jsx("div",{ref:u,onPointerDown:h,onPointerMove:p,onPointerUp:R,onClick:P,style:{left:`${t.x}%`,top:`${t.y}%`,backgroundColor:o,touchAction:"none"},className:`absolute h-6 w-6 -translate-x-1/2 -translate-y-1/2 cursor-pointer rounded-full border-2 border-white shadow-md flex items-center justify-center transition-transform ${l?"scale-125 z-50":"hover:scale-110"}`,children:r.jsx("div",{className:"w-2 h-2 bg-white rounded-full opacity-50"})})},q=[{name:"Red",hex:"#EF4444"},{name:"Orange",hex:"#F97316"},{name:"Amber",hex:"#F59E0B"},{name:"Yellow",hex:"#EAB308"},{name:"Lime",hex:"#84CC16"},{name:"Green",hex:"#22C55E"},{name:"Emerald",hex:"#10B981"},{name:"Teal",hex:"#14B8A6"},{name:"Cyan",hex:"#06B6D4"},{name:"Sky",hex:"#0EA5E9"},{name:"Blue",hex:"#3B82F6"},{name:"Indigo",hex:"#6366F1"},{name:"Violet",hex:"#8B5CF6"},{name:"Purple",hex:"#A855F7"},{name:"Fuchsia",hex:"#D946EF"},{name:"Pink",hex:"#EC4899"},{name:"Rose",hex:"#F43F5E"},{name:"Slate",hex:"#64748B"},{name:"Black",hex:"#000000"},{name:"White",hex:"#FFFFFF"}];Y(q[0].hex);const $=({color:t,onChange:d})=>{const c=Q(t);return r.jsxs("div",{className:"space-y-2",children:[r.jsx("label",{className:"block text-sm font-medium text-gray-700",children:"Color"}),r.jsxs("div",{className:"flex flex-wrap gap-2",children:[q.map(a=>r.jsx("button",{onClick:()=>d(Y(a.hex)),className:`h-6 w-6 rounded-full border transition-transform hover:scale-110 focus:outline-none focus:ring-2 focus:ring-offset-1 ${c===a.hex?"ring-2 ring-blue-500 ring-offset-1":"border-gray-200"}`,style:{backgroundColor:a.hex},title:a.name},a.hex)),r.jsx("input",{type:"color",value:c,onChange:a=>d(Y(a.target.value)),className:"h-6 w-6 cursor-pointer rounded-full border border-gray-300 p-0 overflow-hidden",title:"Custom Color"})]})]})},me=t=>new Promise((d,c)=>{const a=new FileReader;a.readAsDataURL(t),a.onload=()=>d(a.result),a.onerror=o=>c(o)}),ee=({photos:t,photosNames:d,onUpload:c,onRemove:a,onPhotoClick:o})=>{const l=D(),g=async u=>{if(u.target.files){const f=Array.from(u.target.files),m=await Promise.all(f.map(me)),x=f.map(p=>p.name),w=3-t.length,E=m.slice(0,w),h=x.slice(0,w);c([...t,...E],[...d,...h])}};return r.jsxs("div",{className:"space-y-2",children:[r.jsx("div",{className:"flex items-center justify-between",children:r.jsxs("label",{className:"text-sm font-medium text-gray-700",children:[l.photos," (",t.length,"/3)"]})}),r.jsxs("div",{className:"flex flex-wrap gap-2",children:[t.map((u,f)=>r.jsxs("div",{className:"relative h-16 w-16 group",children:[r.jsx("img",{src:u,alt:`Upload ${f}`,className:"h-full w-full object-cover rounded border cursor-pointer",onClick:()=>o&&o(f)}),r.jsx("button",{onClick:()=>a(f),className:"absolute -top-1 -right-1 bg-red-500 text-white rounded-full p-0.5 w-4 h-4 flex items-center justify-center text-xs opacity-0 group-hover:opacity-100 transition-opacity",children:"×"})]},f)),t.length<3&&r.jsxs("label",{className:"flex h-16 w-16 cursor-pointer items-center justify-center rounded border-2 border-dashed border-gray-300 hover:border-blue-500 hover:bg-blue-50 transition-colors",children:[r.jsx("span",{className:"text-xl text-gray-400",children:"+"}),r.jsx("input",{type:"file",accept:"image/*",multiple:!0,onChange:g,className:"hidden"})]})]})]})},te=({photos:t,initialIndex:d,onClose:c})=>{const[a,o]=n.useState(d),[l,g]=n.useState(1),[u,f]=n.useState({x:0,y:0}),[m,x]=n.useState(!1),w=n.useRef({x:0,y:0}),E=n.useRef(null),h=n.useCallback(()=>{g(1),f({x:0,y:0})},[]),p=n.useCallback(()=>{o(i=>(i+1)%t.length),h()},[t.length,h]),R=n.useCallback(()=>{o(i=>(i-1+t.length)%t.length),h()},[t.length,h]);n.useEffect(()=>{const i=C=>{C.key==="Escape"&&c(),C.key==="ArrowRight"&&p(),C.key==="ArrowLeft"&&R()};return window.addEventListener("keydown",i),()=>window.removeEventListener("keydown",i)},[c,p,R]),n.useEffect(()=>{const i=E.current;if(!i)return;const C=T=>{T.preventDefault();const k=-T.deltaY*.01,_=Math.min(Math.max(1,l+k),5);g(_),_===1&&f({x:0,y:0})};return i.addEventListener("wheel",C,{passive:!1}),()=>i.removeEventListener("wheel",C)},[l]);const P=i=>{l>1&&(i.preventDefault(),x(!0),w.current={x:i.clientX-u.x,y:i.clientY-u.y},i.target.setPointerCapture(i.pointerId))},b=i=>{m&&l>1&&(i.preventDefault(),f({x:i.clientX-w.current.x,y:i.clientY-w.current.y}))},S=i=>{x(!1),i.target.releasePointerCapture(i.pointerId)};return t.length?r.jsxs("div",{className:"fixed inset-0 z-[60] flex items-center justify-center bg-black bg-opacity-90 overflow-hidden",onClick:i=>{i.stopPropagation(),c()},children:[r.jsx("button",{onClick:c,className:"absolute top-4 right-4 text-white hover:text-gray-300 z-50 p-2",children:r.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-8 w-8",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:r.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M6 18L18 6M6 6l12 12"})})}),r.jsxs("div",{ref:E,className:"relative flex items-center justify-center w-full h-full p-4",onClick:i=>i.stopPropagation(),children:[t.length>1&&r.jsx("button",{onClick:R,className:"absolute left-4 z-40 p-2 text-white hover:bg-white/10 rounded-full transition-colors",children:r.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-10 w-10",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:r.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M15 19l-7-7 7-7"})})}),r.jsx("div",{className:"relative overflow-hidden flex items-center justify-center w-full h-full",children:r.jsx("img",{src:t[a],alt:`View ${a+1}`,onPointerDown:P,onPointerMove:b,onPointerUp:S,style:{transform:`scale(${l}) translate(${u.x/l}px, ${u.y/l}px)`,transition:m?"none":"transform 0.1s ease-out",cursor:l>1?m?"grabbing":"grab":"default",maxHeight:"100%",maxWidth:"100%"},className:"object-contain select-none touch-none"})}),t.length>1&&r.jsx("button",{onClick:p,className:"absolute right-4 z-40 p-2 text-white hover:bg-white/10 rounded-full transition-colors",children:r.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-10 w-10",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:r.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M9 5l7 7-7 7"})})}),r.jsxs("div",{className:"absolute bottom-4 left-0 right-0 text-center text-white text-sm bg-black/50 py-1 pointer-events-none",children:[a+1," / ",t.length," ",l>1&&`(${Math.round(l*100)}%)`]})]})]}):null},z=({marker:t,onSave:d,onDelete:c,onClose:a})=>{const o=D(),[l,g]=n.useState(t.markerTitle),[u,f]=n.useState(t.note),[m,x]=n.useState(t.color),[w,E]=n.useState(t.photos),[h,p]=n.useState(t.photosName||[]),[R,P]=n.useState(!1),[b,S]=n.useState(0),[i,C]=n.useState(!1);n.useEffect(()=>{g(t.markerTitle),f(t.note),x(t.color),E(t.photos),p(t.photosName||[]),C(!1)},[t]);const T=()=>{if(!l.trim()){C(!0);return}d(t.id,{markerTitle:l,note:u,color:m,photos:w,photosName:h}),a()};return r.jsxs(r.Fragment,{children:[r.jsx("div",{className:"fixed inset-0 z-40 flex items-center justify-center bg-black/50",onClick:k=>k.stopPropagation(),children:r.jsxs("div",{className:"w-72 max-h-[90vh] overflow-y-auto rounded-lg bg-white p-4 shadow-xl border border-gray-200 relative z-50",children:[r.jsxs("div",{className:"mb-4 flex items-center justify-between",children:[r.jsx("h3",{className:"text-lg font-semibold text-gray-900",children:o.editMarker}),r.jsx("button",{onClick:a,className:"text-gray-400 hover:text-gray-600",children:"✕"})]}),r.jsxs("div",{className:"space-y-4",children:[r.jsxs("div",{children:[r.jsxs("label",{className:"block text-sm font-medium text-gray-700",children:[o.title," ",r.jsx("span",{className:"text-red-500",children:"*"})]}),r.jsx("input",{type:"text",value:l,placeholder:o.titlePlaceholder,onChange:k=>{g(k.target.value),i&&C(!1)},className:`mt-1 block w-full rounded-md border px-3 py-2 shadow-sm focus:outline-none focus:ring-1 sm:text-sm ${i?"border-red-500 focus:border-red-500 focus:ring-red-500":"border-gray-300 focus:border-blue-500 focus:ring-blue-500"}`}),i&&r.jsx("p",{className:"mt-1 text-xs text-red-500",children:o.titleRequired})]}),r.jsxs("div",{children:[r.jsx("label",{className:"block text-sm font-medium text-gray-700",children:o.note}),r.jsx("textarea",{value:u,placeholder:o.notePlaceholder,onChange:k=>f(k.target.value),rows:3,className:"mt-1 block w-full rounded-md border border-gray-300 px-3 py-2 shadow-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500 sm:text-sm"})]}),r.jsx($,{color:m,onChange:x}),r.jsx(ee,{photos:w,photosNames:h,onUpload:(k,_)=>{E(k),p(_)},onRemove:k=>{E(w.filter((_,I)=>I!==k)),p(h.filter((_,I)=>I!==k))},onPhotoClick:k=>{S(k),P(!0)}}),r.jsxs("div",{className:"mt-4 flex justify-between",children:[r.jsx("button",{onClick:()=>c(t.id),className:"rounded px-3 py-2 text-sm font-medium text-red-600 hover:bg-red-50",children:o.delete}),r.jsxs("div",{className:"space-x-2",children:[r.jsx("button",{onClick:a,className:"rounded border border-gray-300 px-3 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50",children:o.cancel}),r.jsx("button",{onClick:T,className:"rounded bg-blue-600 px-3 py-2 text-sm font-medium text-white hover:bg-blue-700",children:o.save})]})]})]})]})}),R&&r.jsx(te,{photos:w,initialIndex:b,onClose:()=>P(!1)})]})},re=({src:t,markers:d,onAddMarker:c,onUpdateMarker:a,onDeleteMarker:o})=>{const l=n.useRef(null),g=n.useRef(null),[u,f]=n.useState(null),[m,x]=n.useState(null),w=h=>{if(!g.current)return;if(u){f(null);return}if(m){x(null);return}const{x:p,y:R}=fe(h,g.current),P={id:crypto.randomUUID(),x:p,y:R,color:16711680,markerTitle:"",note:"",photos:[],photosName:[]};x(P)},E=d.find(h=>h.id===u);return r.jsx("div",{className:"relative inline-block overflow-hidden rounded-lg shadow-lg group select-none",children:r.jsxs("div",{ref:g,onClick:w,className:"relative cursor-crosshair",children:[r.jsx("img",{ref:l,src:t,alt:"Marker Area",className:"block max-w-full h-auto",draggable:!1}),d.map(h=>r.jsx(U,{marker:h,onClick:p=>{x(null),f(p.id)},onUpdate:(p,R)=>a(p,R),onDelete:o},h.id)),m&&r.jsx(U,{marker:m,onClick:()=>{},onUpdate:(h,p)=>x(R=>R?{...R,...p}:null),onDelete:()=>x(null)},"temp-marker"),E&&r.jsx(z,{marker:E,onSave:a,onDelete:h=>{o(h),f(null)},onClose:()=>f(null)}),m&&r.jsx(z,{marker:m,onSave:(h,p)=>{c({...m,...p}),x(null)},onDelete:()=>x(null),onClose:()=>x(null)})]})})},he=(t=[])=>{const[d,c]=n.useState(t),a=n.useCallback(u=>{c(f=>[...f,u])},[]),o=n.useCallback((u,f)=>{c(m=>m.map(x=>x.id===u?{...x,...f}:x))},[]),l=n.useCallback(u=>{c(f=>f.filter(m=>m.id!==u))},[]),g=n.useCallback(u=>{c(u)},[]);return{markers:d,addMarker:a,updateMarker:o,removeMarker:l,setAllMarkers:g}};N.ColorPicker=$,N.ImageArea=re,N.ImageMarker=re,N.Lightbox=te,N.MarkerItem=U,N.MarkerPopup=z,N.PhotoUploader=ee,N.useLocale=D,N.useMarkerState=he,Object.defineProperty(N,Symbol.toStringTag,{value:"Module"})}));
|
package/dist/vite.svg
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "react-image-marker-viewer",
|
|
3
|
+
"private": false,
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/react-image-marker.umd.js",
|
|
7
|
+
"module": "./dist/react-image-marker.es.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"files": [
|
|
10
|
+
"dist"
|
|
11
|
+
],
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"import": "./dist/react-image-marker.es.js",
|
|
16
|
+
"require": "./dist/react-image-marker.umd.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"scripts": {
|
|
20
|
+
"dev": "vite",
|
|
21
|
+
"build": "tsc -b && vite build",
|
|
22
|
+
"lint": "eslint .",
|
|
23
|
+
"preview": "vite preview"
|
|
24
|
+
},
|
|
25
|
+
"peerDependencies": {
|
|
26
|
+
"react": ">=16.8.0",
|
|
27
|
+
"react-dom": ">=16.8.0"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"@eslint/js": "^9.39.1",
|
|
31
|
+
"@types/node": "^24.10.1",
|
|
32
|
+
"@types/react": "^19.2.7",
|
|
33
|
+
"@types/react-dom": "^19.2.3",
|
|
34
|
+
"@vitejs/plugin-react": "^5.1.1",
|
|
35
|
+
"autoprefixer": "^10.4.24",
|
|
36
|
+
"eslint": "^9.39.1",
|
|
37
|
+
"eslint-plugin-react-hooks": "^7.0.1",
|
|
38
|
+
"eslint-plugin-react-refresh": "^0.4.24",
|
|
39
|
+
"globals": "^16.5.0",
|
|
40
|
+
"postcss": "^8.5.6",
|
|
41
|
+
"tailwindcss": "^3.4.17",
|
|
42
|
+
"typescript": "~5.9.3",
|
|
43
|
+
"typescript-eslint": "^8.48.0",
|
|
44
|
+
"vite": "^6.0.7",
|
|
45
|
+
"vite-plugin-dts": "^4.5.4",
|
|
46
|
+
"react": "^19.2.7",
|
|
47
|
+
"react-dom": "^19.2.7"
|
|
48
|
+
}
|
|
49
|
+
}
|