sanity-plugin-hotspot-array 0.0.7 → 0.1.0-v3-studio.1

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/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2021 Simeon Griggs
3
+ Copyright (c) 2022 Simeon Griggs
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # sanity-plugin-hotspot-array
2
2
 
3
+ > > **NOTE**
4
+ >
5
+ > This is the **Sanity Studio v3 version** of sanity-plugin-hotspot-array.
6
+ >
7
+ > For the v2 version, please refer to the [v2-branch](https://github.com/sanity-io/sanity-plugin-hotspot-array).
8
+
9
+ ## What is it?
10
+
3
11
  A configurable Custom Input for Arrays that will add and update items by clicking on an Image
4
12
 
5
13
  <img src="https://user-images.githubusercontent.com/209129/174171697-57319ebc-03a7-4d82-a73e-b6effcb0b3ba.gif" width="600" />
@@ -7,49 +15,73 @@ A configurable Custom Input for Arrays that will add and update items by clickin
7
15
  ## Installation
8
16
 
9
17
  ```
10
- sanity install hotspot-array
18
+ npm install --save sanity-plugin-hotspot-array@studio-v3
19
+ ```
20
+
21
+ or
22
+
23
+ ```
24
+ yarn add sanity-plugin-hotspot-array@studio-v3
11
25
  ```
12
26
 
13
- ## Setup
14
27
 
15
- Import the `HotspotArray` component from this package, into your schema. And insert it as the `inputComponent` of an `array` field.
28
+ ## Usage
29
+
30
+ Add it as a plugin in sanity.config.ts (or .js):
31
+
32
+ ```js
33
+ import { imageHotspotArray } from "sanity-plugin-hotspot-array";
34
+
35
+ export default createConfig({
36
+ // ...
37
+ plugins: [
38
+ imageHotspotArray(),
39
+ ]
40
+ })
41
+ ```
42
+
43
+ Now you will have `imageHotspot` available as an options on `array` fields:
16
44
 
17
45
  ```js
18
- import HotspotArray from 'sanity-plugin-hotspot-array'
46
+ import {defineType, defineField} from 'sanity'
19
47
 
20
- export default {
48
+ export const productSchema = defineType({
21
49
  name: `product`,
22
50
  title: `Product`,
23
51
  type: `document`,
24
52
  fields: [
25
- {
53
+ defineField({
26
54
  name: `hotspots`,
27
55
  type: `array`,
28
- inputComponent: HotspotArray,
29
56
  of: [
30
57
  // see `Spot object` setup below
31
58
  ],
32
59
  options: {
33
- // see `Image and description path` setup below
34
- hotspotImagePath: `featureImage`,
35
- hotspotDescriptionPath: `details`,
36
- // see `Custom tooltip` setup below
37
- hotspotTooltip: undefined,
60
+ // plugin adds support for this option
61
+ imageHotspot: {
62
+ // see `Image and description path` setup below
63
+ imagePath: `featureImage`,
64
+ descriptionPath: `details`,
65
+ // see `Custom tooltip` setup below
66
+ tooltip: undefined,
67
+ }
38
68
  },
39
- },
69
+ }),
40
70
  // ...all your other fields
71
+ // ...of which one should be featureImage in this example
41
72
  ],
42
- }
73
+ })
43
74
  ```
75
+ There is no need to provide an explicit input component, as that is handled by the plugin.
44
76
 
45
77
  The plugin makes a number of assumptions to add and update data in the array. Including:
46
78
 
47
- - The `array` field is an array of objects
79
+ - The `array` field is an array of objects, with a single object type
48
80
  - The object contains two number fields named `x` and `y`
49
81
  - You'll want to save those values as % from the top left of the image
50
82
  - The same document contains the image you want to add hotspots to
51
83
 
52
- ### Image and description paths
84
+ ### Image path
53
85
 
54
86
  The custom input has the current values of all fields in the document, and so can "pick" the image out of the document by its path.
55
87
 
@@ -57,15 +89,31 @@ For example, if you want to add hotspots to an image, and that image is uploaded
57
89
 
58
90
  ```js
59
91
  options: {
60
- hotspotImagePath: `featureImage`
92
+ imageHotspot: {
93
+ imagePath: `featureImage`
94
+ }
95
+ }
96
+ ```
97
+
98
+ To pick the image out of the hotspot-array parent object, use
99
+ ```js
100
+ options: {
101
+ imageHotspot: {
102
+ pathRoot: 'parent'
103
+ }
61
104
  }
62
105
  ```
63
106
 
64
- The custom input can also pre-fill a string or text field with a description of the position of the spot to make them easier to identify. Add a path **relative to the spot object** for this field.
107
+ ### Description path
108
+
109
+ The custom input can also pre-fill a string or text field with a description of the position of the spot to make them easier to identify.
110
+ Add a path **relative to the spot object** for this field.
65
111
 
66
112
  ```js
67
113
  options: {
68
- hotspotDescriptionPath: `details`
114
+ imageHotspot: {
115
+ descriptionPath: `details`
116
+ }
69
117
  }
70
118
  ```
71
119
 
@@ -74,7 +122,7 @@ options: {
74
122
  Here's an example object schema complete with initial values, validation, fieldsets and a styled preview.
75
123
 
76
124
  ```js
77
- {
125
+ defineField({
78
126
  name: 'spot',
79
127
  type: 'object',
80
128
  fieldsets: [{name: 'position', options: {columns: 2}}],
@@ -110,28 +158,66 @@ Here's an example object schema complete with initial values, validation, fields
110
158
  }
111
159
  },
112
160
  },
113
- }
161
+ })
114
162
  ```
115
163
 
116
164
  ## Custom tooltip
117
165
 
118
- You can customise the Tooltip to display any Component, it will accept a single prop `spot` which contains the values of the object.
166
+ You can customise the Tooltip to display any Component, which will receive `value` (the hotspot value with x and y),
167
+ `schemaType` (schemaType of the hotspot value), and `renderPreview` (callback for rendering Studio preview).
119
168
 
120
- In this example our `spot` object has a `reference` field to the `product` schema type, and will show a Document Preview.
169
+ ### Example 1 - use default hotspot preview
170
+
171
+ ```tsx
172
+ import { Box } from "@sanity/ui";
173
+ import { HotspotTooltipProps } from "sanity-plugin-hotspot-array";
174
+
175
+ export function HotspotPreview({
176
+ value,
177
+ schemaType,
178
+ renderPreview,
179
+ }: HotspotTooltipProps) {
180
+ return (
181
+ <Box padding={2} style={{ minWidth: 200 }}>
182
+ {renderPreview({
183
+ value,
184
+ schemaType,
185
+ layout: "default",
186
+ })}
187
+ </Box>
188
+ );
189
+ }
190
+ ```
191
+
192
+ Then back in your schema definition
121
193
 
122
194
  ```js
123
- // Setup a custom tooltip component
124
- import Preview from 'part:@sanity/base/preview'
125
- import schema from 'part:@sanity/base/schema'
195
+ options: {
196
+ imageHotspot: {
197
+ tooltip: HotspotPreview
198
+ }
199
+ }
200
+ ```
201
+
202
+ ### Example 2 - reference value in hotspot
203
+ In this example our `value` object has a `reference` field to the `product` schema type, and will show a document preview.
204
+
205
+ ```jsx
206
+ import {useSchema }from 'sanity'
126
207
  import {Box} from '@sanity/ui'
127
208
 
128
- export default function ProductPreview({spot}) {
209
+ export function ProductPreview({value, renderPreview}) {
210
+ const productSchemaType = useSchema().get('product')
129
211
  return (
130
212
  <Box padding={2} style={{minWidth: 200}}>
131
- {spot?.product?._ref ? (
132
- <Preview value={{_id: spot.product._ref}} type={schema.get(`product`)} />
213
+ {value?.product?._ref ? (
214
+ renderPreview({
215
+ value,
216
+ schemaType: productSchemaType,
217
+ layout: "default"
218
+ })
133
219
  ) : (
134
- `No Reference Selected`
220
+ `No reference selected`
135
221
  )}
136
222
  </Box>
137
223
  )
@@ -141,16 +227,28 @@ export default function ProductPreview({spot}) {
141
227
  Then back in your schema definition
142
228
 
143
229
  ```js
144
- import HotspotArray from 'sanity-plugin-hotspot-array'
145
- import ProductPreview from '../../components/ProductPreview'
146
-
147
230
  options: {
148
- hotspotImagePath: `hotspotImage`,
149
- hotspotTooltip: ProductPreview,
150
- },
231
+ imageHotspot: {
232
+ tooltip: ProductPreview
233
+ }
234
+ }
151
235
  ```
152
236
 
153
237
  ## License
154
238
 
155
- MIT © Simeon Griggs
156
- See LICENSE
239
+ MIT-licensed. See LICENSE.
240
+
241
+ ## Develop & test
242
+
243
+ This plugin uses [@sanity/plugin-kit](https://github.com/sanity-io/plugin-kit)
244
+ with default configuration for build & watch scripts.
245
+
246
+ See [Testing a plugin in Sanity Studio](https://github.com/sanity-io/plugin-kit#testing-a-plugin-in-sanity-studio)
247
+ on how to run this plugin with hotreload in the studio.
248
+
249
+ ### Release new version
250
+
251
+ Run ["CI & Release" workflow](https://github.com/sanity-io/sanity-plugin-hotspot-array/actions/workflows/main.yml).
252
+ Make sure to select the main branch and check "Release new version".
253
+
254
+ Semantic release will only release on configured branches, so it is safe to run release on any branch.
@@ -0,0 +1,403 @@
1
+ var $dyHF6$reactjsxruntime = require("react/jsx-runtime");
2
+ var $dyHF6$react = require("react");
3
+ var $dyHF6$sanity = require("sanity");
4
+ var $dyHF6$sanityassetutils = require("@sanity/asset-utils");
5
+ var $dyHF6$sanityimageurl = require("@sanity/image-url");
6
+ var $dyHF6$sanityui = require("@sanity/ui");
7
+ var $dyHF6$sanityutilcontent = require("@sanity/util/content");
8
+ var $dyHF6$lodashget = require("lodash/get");
9
+ var $dyHF6$reacthookzweb = require("@react-hookz/web");
10
+ var $dyHF6$framermotion = require("framer-motion");
11
+
12
+ function $parcel$export(e, n, v, s) {
13
+ Object.defineProperty(e, n, {get: v, set: s, enumerable: true, configurable: true});
14
+ }
15
+ function $parcel$interopDefault(a) {
16
+ return a && a.__esModule ? a.default : a;
17
+ }
18
+
19
+ $parcel$export(module.exports, "imageHotspotArrayPlugin", () => $329a1cedcedb1349$export$2e97a933fd61fb01);
20
+ $parcel$export(module.exports, "ImageHotspotArray", () => $4336b3bb99d0500f$export$aa9dd3c5642820fe);
21
+
22
+
23
+
24
+
25
+
26
+
27
+
28
+
29
+
30
+
31
+
32
+
33
+
34
+ function $8f6d54ef8e8d6bcf$export$2e2bcd8739ae039({ children: children }) {
35
+ return /*#__PURE__*/ (0, $dyHF6$reactjsxruntime.jsx)((0, $dyHF6$sanityui.Card), {
36
+ padding: 4,
37
+ radius: 2,
38
+ shadow: 1,
39
+ tone: "caution",
40
+ children: /*#__PURE__*/ (0, $dyHF6$reactjsxruntime.jsx)((0, $dyHF6$sanityui.Text), {
41
+ children: children
42
+ })
43
+ });
44
+ }
45
+
46
+
47
+
48
+
49
+
50
+
51
+
52
+ const $b9909e9b23fcefed$var$dragStyle = {
53
+ width: "1.4rem",
54
+ height: "1.4rem",
55
+ position: "absolute",
56
+ boxSizing: "border-box",
57
+ top: 0,
58
+ left: 0,
59
+ margin: "-0.7rem 0 0 -0.7rem",
60
+ cursor: "pointer",
61
+ display: "flex",
62
+ justifyContent: "center",
63
+ alignItems: "center",
64
+ borderRadius: "50%",
65
+ background: "#000",
66
+ color: "white"
67
+ };
68
+ const $b9909e9b23fcefed$var$dragStyleWhileDrag = {
69
+ background: "rgba(0, 0, 0, 0.1)",
70
+ border: "1px solid #fff",
71
+ cursor: "none"
72
+ };
73
+ const $b9909e9b23fcefed$var$dragStyleWhileHover = {
74
+ background: "rgba(0, 0, 0, 0.1)",
75
+ border: "1px solid #fff"
76
+ };
77
+ const $b9909e9b23fcefed$var$dotStyle = {
78
+ position: "absolute",
79
+ left: "50%",
80
+ top: "50%",
81
+ height: "0.2rem",
82
+ width: "0.2rem",
83
+ margin: "-0.1rem 0 0 -0.1rem",
84
+ background: "#fff",
85
+ visibility: "hidden",
86
+ borderRadius: "50%",
87
+ // make sure pointer events only run on the parent
88
+ pointerEvents: "none"
89
+ };
90
+ const $b9909e9b23fcefed$var$dotStyleWhileActive = {
91
+ visibility: "visible"
92
+ };
93
+ const $b9909e9b23fcefed$var$labelStyle = {
94
+ color: "white",
95
+ fontSize: "0.7rem",
96
+ fontWeight: 600,
97
+ lineHeight: "1"
98
+ };
99
+ const $b9909e9b23fcefed$var$labelStyleWhileActive = {
100
+ visibility: "hidden"
101
+ };
102
+ const $b9909e9b23fcefed$var$round = (num)=>Math.round(num * 100) / 100;
103
+ function $b9909e9b23fcefed$export$2e2bcd8739ae039({ value: value , bounds: bounds , update: update , hotspotDescriptionPath: hotspotDescriptionPath , tooltip: tooltip , index: index , schemaType: schemaType , renderPreview: renderPreview }) {
104
+ const [isDragging, setIsDragging] = (0, ($parcel$interopDefault($dyHF6$react))).useState(false);
105
+ const [isHovering, setIsHovering] = (0, ($parcel$interopDefault($dyHF6$react))).useState(false);
106
+ // x/y are stored as % but need to be converted to px
107
+ const x = (0, $dyHF6$framermotion.useMotionValue)($b9909e9b23fcefed$var$round(bounds.width * (value.x / 100)));
108
+ const y = (0, $dyHF6$framermotion.useMotionValue)($b9909e9b23fcefed$var$round(bounds.height * (value.y / 100)));
109
+ /**
110
+ * update x/y if the bounds change when resizing the window
111
+ */ (0, $dyHF6$react.useEffect)(()=>{
112
+ x.set($b9909e9b23fcefed$var$round(bounds.width * (value.x / 100)));
113
+ y.set($b9909e9b23fcefed$var$round(bounds.height * (value.y / 100)));
114
+ }, [
115
+ x,
116
+ y,
117
+ value,
118
+ bounds
119
+ ]);
120
+ const handleDragEnd = (0, ($parcel$interopDefault($dyHF6$react))).useCallback(()=>{
121
+ setIsDragging(false);
122
+ // get current values for x/y in px
123
+ const currentX = x.get();
124
+ const currentY = y.get();
125
+ // Which we need to convert back to `%` to patch the document
126
+ const newX = $b9909e9b23fcefed$var$round(currentX * 100 / bounds.width);
127
+ const newY = $b9909e9b23fcefed$var$round(currentY * 100 / bounds.height);
128
+ // Don't go below 0 or above 100
129
+ const safeX = Math.max(0, Math.min(100, newX));
130
+ const safeY = Math.max(0, Math.min(100, newY));
131
+ update(value._key, safeX, safeY);
132
+ }, [
133
+ x,
134
+ y,
135
+ value,
136
+ update,
137
+ bounds
138
+ ]);
139
+ const handleDragStart = (0, ($parcel$interopDefault($dyHF6$react))).useCallback(()=>setIsDragging(true), []);
140
+ const handleHoverStart = (0, ($parcel$interopDefault($dyHF6$react))).useCallback(()=>setIsHovering(true), []);
141
+ const handleHoverEnd = (0, ($parcel$interopDefault($dyHF6$react))).useCallback(()=>setIsHovering(false), []);
142
+ if (!x || !y) return null;
143
+ return /*#__PURE__*/ (0, $dyHF6$reactjsxruntime.jsx)((0, $dyHF6$sanityui.Tooltip), {
144
+ disabled: isDragging,
145
+ portal: true,
146
+ content: tooltip && typeof tooltip === "function" ? /*#__PURE__*/ (0, ($parcel$interopDefault($dyHF6$react))).createElement(tooltip, {
147
+ value: value,
148
+ renderPreview: renderPreview,
149
+ schemaType: schemaType
150
+ }) : /*#__PURE__*/ (0, $dyHF6$reactjsxruntime.jsx)((0, $dyHF6$sanityui.Box), {
151
+ padding: 2,
152
+ style: {
153
+ maxWidth: 200,
154
+ pointerEvents: `none`
155
+ },
156
+ children: /*#__PURE__*/ (0, $dyHF6$reactjsxruntime.jsx)((0, $dyHF6$sanityui.Text), {
157
+ textOverflow: "ellipsis",
158
+ children: hotspotDescriptionPath ? (0, ($parcel$interopDefault($dyHF6$lodashget)))(value, hotspotDescriptionPath) : `${value.x}% x ${value.y}%`
159
+ })
160
+ }),
161
+ children: /*#__PURE__*/ (0, $dyHF6$reactjsxruntime.jsxs)((0, $dyHF6$framermotion.motion).div, {
162
+ drag: true,
163
+ dragConstraints: bounds,
164
+ dragElastic: 0,
165
+ dragMomentum: false,
166
+ onDragEnd: handleDragEnd,
167
+ onDragStart: handleDragStart,
168
+ onHoverStart: handleHoverStart,
169
+ onHoverEnd: handleHoverEnd,
170
+ style: {
171
+ ...$b9909e9b23fcefed$var$dragStyle,
172
+ x: x,
173
+ y: y,
174
+ ...isDragging && {
175
+ ...$b9909e9b23fcefed$var$dragStyleWhileDrag
176
+ },
177
+ ...isHovering && {
178
+ ...$b9909e9b23fcefed$var$dragStyleWhileHover
179
+ }
180
+ },
181
+ children: [
182
+ /*#__PURE__*/ (0, $dyHF6$reactjsxruntime.jsx)((0, $dyHF6$sanityui.Box), {
183
+ style: {
184
+ ...$b9909e9b23fcefed$var$dotStyle,
185
+ ...(isDragging || isHovering) && {
186
+ ...$b9909e9b23fcefed$var$dotStyleWhileActive
187
+ }
188
+ }
189
+ }),
190
+ /*#__PURE__*/ (0, $dyHF6$reactjsxruntime.jsx)("div", {
191
+ style: {
192
+ ...$b9909e9b23fcefed$var$labelStyle,
193
+ ...(isDragging || isHovering) && {
194
+ ...$b9909e9b23fcefed$var$labelStyleWhileActive
195
+ }
196
+ },
197
+ children: index + 1
198
+ })
199
+ ]
200
+ })
201
+ }, value._key);
202
+ }
203
+
204
+
205
+ const $4336b3bb99d0500f$var$imageStyle = {
206
+ width: `100%`,
207
+ height: `auto`
208
+ };
209
+ const $4336b3bb99d0500f$var$VALID_ROOT_PATHS = [
210
+ "document",
211
+ "parent"
212
+ ];
213
+ function $4336b3bb99d0500f$export$aa9dd3c5642820fe(props) {
214
+ const { value: value , onChange: onChange , imageHotspotOptions: imageHotspotOptions , schemaType: schemaType , renderPreview: renderPreview } = props;
215
+ const sanityClient = (0, $dyHF6$sanity.useClient)({
216
+ apiVersion: "2022-01-01"
217
+ });
218
+ const imageHotspotPathRoot = (0, $dyHF6$react.useMemo)(()=>{
219
+ const pathRoot = $4336b3bb99d0500f$var$VALID_ROOT_PATHS.includes(imageHotspotOptions.pathRoot ?? "") ? imageHotspotOptions.pathRoot : "document";
220
+ return pathRoot === "document" ? [] : props.path.slice(0, -1);
221
+ }, [
222
+ imageHotspotOptions.pathRoot,
223
+ props.path
224
+ ]);
225
+ const rootObject = (0, $dyHF6$sanity.useFormValue)(imageHotspotPathRoot);
226
+ /**
227
+ * Finding the image from the imageHotspotPathRoot (defaults to document),
228
+ * using the path from the hotspot's `options` field
229
+ *
230
+ * when changes in imageHotspotPathRoot (e.g. document) occur,
231
+ * check if there are any changes to the hotspotImage and update the reference
232
+ */ const hotspotImage = (0, $dyHF6$react.useMemo)(()=>{
233
+ return (0, ($parcel$interopDefault($dyHF6$lodashget)))(rootObject, imageHotspotOptions.imagePath);
234
+ }, [
235
+ rootObject,
236
+ imageHotspotOptions.imagePath
237
+ ]);
238
+ const displayImage = (0, $dyHF6$react.useMemo)(()=>{
239
+ const builder = (0, ($parcel$interopDefault($dyHF6$sanityimageurl)))(sanityClient).dataset(sanityClient.config().dataset ?? "");
240
+ const urlFor = (source)=>builder.image(source);
241
+ if (hotspotImage?.asset?._ref) {
242
+ const { aspectRatio: aspectRatio } = (0, $dyHF6$sanityassetutils.getImageDimensions)(hotspotImage.asset._ref);
243
+ const width = 1200;
244
+ const height = Math.round(width / aspectRatio);
245
+ const url = urlFor(hotspotImage).width(width).url();
246
+ return {
247
+ width: width,
248
+ height: height,
249
+ url: url
250
+ };
251
+ }
252
+ return null;
253
+ }, [
254
+ hotspotImage,
255
+ sanityClient
256
+ ]);
257
+ const handleHotspotImageClick = (0, $dyHF6$react.useCallback)((event)=>{
258
+ const { nativeEvent: nativeEvent } = event;
259
+ // Calculate the x/y percentage of the click position
260
+ const x = Number((nativeEvent.offsetX * 100 / nativeEvent.srcElement.width).toFixed(2));
261
+ const y = Number((nativeEvent.offsetY * 100 / nativeEvent.srcElement.height).toFixed(2));
262
+ const description = `New Hotspot at ${x}% x ${y}%`;
263
+ const newRow = {
264
+ _key: (0, $dyHF6$sanityutilcontent.randomKey)(12),
265
+ _type: schemaType.of[0].name,
266
+ x: x,
267
+ y: y
268
+ };
269
+ if (imageHotspotOptions?.descriptionPath) newRow[imageHotspotOptions.descriptionPath] = description;
270
+ onChange((0, $dyHF6$sanity.PatchEvent).from([
271
+ (0, $dyHF6$sanity.setIfMissing)([]),
272
+ (0, $dyHF6$sanity.insert)([
273
+ newRow
274
+ ], "after", [
275
+ -1
276
+ ])
277
+ ]));
278
+ }, [
279
+ imageHotspotOptions,
280
+ onChange,
281
+ schemaType
282
+ ]);
283
+ const handleHotspotMove = (0, $dyHF6$react.useCallback)((key, x, y)=>{
284
+ onChange((0, $dyHF6$sanity.PatchEvent).from([
285
+ // Set the `x` value of this array key item
286
+ (0, $dyHF6$sanity.set)(x, [
287
+ {
288
+ _key: key
289
+ },
290
+ "x"
291
+ ]),
292
+ // Set the `y` value of this array key item
293
+ (0, $dyHF6$sanity.set)(y, [
294
+ {
295
+ _key: key
296
+ },
297
+ "y"
298
+ ]),
299
+ ]));
300
+ }, [
301
+ onChange
302
+ ]);
303
+ const hotspotImageRef = (0, $dyHF6$react.useRef)(null);
304
+ const [imageRect, setImageRect] = (0, $dyHF6$react.useState)();
305
+ const updateImageRectCallback = (0, $dyHF6$reacthookzweb.useDebouncedCallback)((e)=>setImageRect(e.contentRect), [
306
+ setImageRect
307
+ ], 200);
308
+ (0, $dyHF6$reacthookzweb.useResizeObserver)(hotspotImageRef, updateImageRectCallback);
309
+ return /*#__PURE__*/ (0, $dyHF6$reactjsxruntime.jsxs)((0, $dyHF6$sanityui.Stack), {
310
+ space: [
311
+ 2,
312
+ 2,
313
+ 3
314
+ ],
315
+ children: [
316
+ displayImage?.url ? /*#__PURE__*/ (0, $dyHF6$reactjsxruntime.jsxs)("div", {
317
+ style: {
318
+ position: `relative`
319
+ },
320
+ children: [
321
+ imageRect && (value?.length ?? 0) > 0 && value?.map((spot, index)=>/*#__PURE__*/ (0, $dyHF6$reactjsxruntime.jsx)((0, $b9909e9b23fcefed$export$2e2bcd8739ae039), {
322
+ index: index,
323
+ value: spot,
324
+ bounds: imageRect,
325
+ update: handleHotspotMove,
326
+ hotspotDescriptionPath: imageHotspotOptions?.descriptionPath,
327
+ tooltip: imageHotspotOptions?.tooltip,
328
+ renderPreview: renderPreview,
329
+ schemaType: schemaType.of[0]
330
+ }, spot._key)),
331
+ /*#__PURE__*/ (0, $dyHF6$reactjsxruntime.jsx)((0, $dyHF6$sanityui.Card), {
332
+ __unstable_checkered: true,
333
+ shadow: 1,
334
+ children: /*#__PURE__*/ (0, $dyHF6$reactjsxruntime.jsx)((0, $dyHF6$sanityui.Flex), {
335
+ align: "center",
336
+ justify: "center",
337
+ children: /*#__PURE__*/ (0, $dyHF6$reactjsxruntime.jsx)("img", {
338
+ ref: hotspotImageRef,
339
+ src: displayImage.url,
340
+ width: displayImage.width,
341
+ height: displayImage.height,
342
+ alt: "",
343
+ style: $4336b3bb99d0500f$var$imageStyle,
344
+ onClick: handleHotspotImageClick
345
+ })
346
+ })
347
+ })
348
+ ]
349
+ }) : /*#__PURE__*/ (0, $dyHF6$reactjsxruntime.jsx)((0, $8f6d54ef8e8d6bcf$export$2e2bcd8739ae039), {
350
+ children: imageHotspotOptions.imagePath ? /*#__PURE__*/ (0, $dyHF6$reactjsxruntime.jsxs)((0, $dyHF6$reactjsxruntime.Fragment), {
351
+ children: [
352
+ "No Hotspot image found at path ",
353
+ /*#__PURE__*/ (0, $dyHF6$reactjsxruntime.jsx)("code", {
354
+ children: imageHotspotOptions.imagePath
355
+ })
356
+ ]
357
+ }) : /*#__PURE__*/ (0, $dyHF6$reactjsxruntime.jsxs)((0, $dyHF6$reactjsxruntime.Fragment), {
358
+ children: [
359
+ "Define a path in this field using to the image field in this document at",
360
+ " ",
361
+ /*#__PURE__*/ (0, $dyHF6$reactjsxruntime.jsx)("code", {
362
+ children: "options.hotspotImagePath"
363
+ })
364
+ ]
365
+ })
366
+ }),
367
+ imageHotspotOptions.pathRoot && !$4336b3bb99d0500f$var$VALID_ROOT_PATHS.includes(imageHotspotOptions.pathRoot) && /*#__PURE__*/ (0, $dyHF6$reactjsxruntime.jsxs)((0, $8f6d54ef8e8d6bcf$export$2e2bcd8739ae039), {
368
+ children: [
369
+ 'The supplied imageHotspotPathRoot "',
370
+ imageHotspotOptions.pathRoot,
371
+ '" is not valid, falling back to "document". Available values are "',
372
+ $4336b3bb99d0500f$var$VALID_ROOT_PATHS.join(", "),
373
+ '".'
374
+ ]
375
+ }),
376
+ props.renderDefault(props)
377
+ ]
378
+ });
379
+ }
380
+
381
+
382
+
383
+
384
+ const $329a1cedcedb1349$export$2e97a933fd61fb01 = (0, $dyHF6$sanity.createPlugin)({
385
+ name: "image-hotspot-array",
386
+ form: {
387
+ components: {
388
+ input: (props)=>{
389
+ if (props.schemaType.jsonType === "array" && props.schemaType.options?.imageHotspot) {
390
+ const imageHotspotOptions = props.schemaType.options?.imageHotspot;
391
+ if (imageHotspotOptions) return /*#__PURE__*/ (0, $dyHF6$reactjsxruntime.jsx)((0, $4336b3bb99d0500f$export$aa9dd3c5642820fe), {
392
+ ...props,
393
+ imageHotspotOptions: imageHotspotOptions
394
+ });
395
+ }
396
+ return props.renderDefault(props);
397
+ }
398
+ }
399
+ }
400
+ });
401
+
402
+
403
+ //# sourceMappingURL=index.js.map