sanity-plugin-hotspot-array 0.1.0-v3-studio.2 → 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/.babelrc +3 -0
- package/.releaserc.json +4 -0
- package/.semantic-release/sanity-plugin-hotspot-array-0.1.0.tgz +0 -0
- package/CHANGELOG.md +16 -0
- package/LICENSE +1 -1
- package/README.md +55 -131
- package/lib/Feedback.js +19 -0
- package/lib/Feedback.js.map +1 -0
- package/lib/HotspotArray.js +150 -0
- package/lib/HotspotArray.js.map +1 -0
- package/lib/NestedFormBuilder.js +53 -0
- package/lib/NestedFormBuilder.js.map +1 -0
- package/lib/Spot.js +157 -0
- package/lib/Spot.js.map +1 -0
- package/lib/useUnsetInputComponent.js +24 -0
- package/lib/useUnsetInputComponent.js.map +1 -0
- package/package.json +57 -66
- package/sanity.json +5 -6
- package/src/Feedback.tsx +2 -2
- package/src/HotspotArray.tsx +178 -0
- package/src/NestedFormBuilder.tsx +44 -0
- package/src/Spot.tsx +19 -31
- package/src/useUnsetInputComponent.ts +17 -0
- package/lib/index.esm.js +0 -2
- package/lib/index.esm.js.map +0 -1
- package/lib/index.js +0 -2
- package/lib/index.js.map +0 -1
- package/lib/src/index.d.ts +0 -55
- package/src/ImageHotspotArray.tsx +0 -188
- package/src/index.ts +0 -4
- package/src/plugin.tsx +0 -39
- package/v2-incompatible.js +0 -11
package/.babelrc
ADDED
package/.releaserc.json
ADDED
|
Binary file
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<!-- markdownlint-disable --><!-- textlint-disable -->
|
|
2
|
+
|
|
3
|
+
# 📓 Changelog
|
|
4
|
+
|
|
5
|
+
All notable changes to this project will be documented in this file. See
|
|
6
|
+
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
7
|
+
|
|
8
|
+
## [0.1.0](https://github.com/sanity-io/sanity-plugin-hotspot-array/compare/v0.0.10...v0.1.0) (2022-11-22)
|
|
9
|
+
|
|
10
|
+
### Features
|
|
11
|
+
|
|
12
|
+
- make semantic-release happy (not really a feat) ([a70d25c](https://github.com/sanity-io/sanity-plugin-hotspot-array/commit/a70d25c0df2b03350ed8e94954e7a41c94aacb8f))
|
|
13
|
+
|
|
14
|
+
### Bug Fixes
|
|
15
|
+
|
|
16
|
+
- **ci:** publish using semantic-release ([4b67704](https://github.com/sanity-io/sanity-plugin-hotspot-array/commit/4b67704e5ce0216a0faaf1a3377d8052b2b866b1))
|
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
# sanity-plugin-hotspot-array
|
|
2
2
|
|
|
3
|
-
>
|
|
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?
|
|
3
|
+
> This is a **Sanity Studio v2** plugin.
|
|
4
|
+
> For the v3 version, please refer to the [v3-branch](https://github.com/sanity-io/sanity-plugin-hotspot-array).
|
|
10
5
|
|
|
11
6
|
A configurable Custom Input for Arrays that will add and update items by clicking on an Image
|
|
12
7
|
|
|
@@ -14,106 +9,85 @@ A configurable Custom Input for Arrays that will add and update items by clickin
|
|
|
14
9
|
|
|
15
10
|
## Installation
|
|
16
11
|
|
|
12
|
+
```sh
|
|
13
|
+
yarn add sanity-plugin-hotspot-array@studio-v2
|
|
17
14
|
```
|
|
18
|
-
npm install --save sanity-plugin-hotspot-array@studio-v3
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
or
|
|
22
15
|
|
|
16
|
+
Next, add `"hotspot-array"` to `sanity.json` plugins array:
|
|
17
|
+
```json
|
|
18
|
+
"plugins": [
|
|
19
|
+
"hotspot-array"
|
|
20
|
+
]
|
|
23
21
|
```
|
|
24
|
-
yarn add sanity-plugin-hotspot-array@studio-v3
|
|
25
|
-
```
|
|
26
|
-
|
|
27
22
|
|
|
28
|
-
##
|
|
23
|
+
## Setup
|
|
29
24
|
|
|
30
|
-
|
|
25
|
+
Import the `HotspotArray` component from this package, into your schema. And insert it as the `inputComponent` of an `array` field.
|
|
31
26
|
|
|
32
27
|
```js
|
|
33
|
-
import
|
|
34
|
-
|
|
35
|
-
export default defineConfig({
|
|
36
|
-
// ...
|
|
37
|
-
plugins: [
|
|
38
|
-
imageHotspotArray(),
|
|
39
|
-
]
|
|
40
|
-
})
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
Now you will have `imageHotspot` available as an options on `array` fields:
|
|
28
|
+
import HotspotArray from 'sanity-plugin-hotspot-array'
|
|
44
29
|
|
|
45
|
-
|
|
46
|
-
import {defineType, defineField} from 'sanity'
|
|
47
|
-
|
|
48
|
-
export const productSchema = defineType({
|
|
30
|
+
export default {
|
|
49
31
|
name: `product`,
|
|
50
32
|
title: `Product`,
|
|
51
33
|
type: `document`,
|
|
52
34
|
fields: [
|
|
53
|
-
|
|
35
|
+
{
|
|
54
36
|
name: `hotspots`,
|
|
55
37
|
type: `array`,
|
|
38
|
+
inputComponent: HotspotArray,
|
|
56
39
|
of: [
|
|
57
40
|
// see `Spot object` setup below
|
|
58
41
|
],
|
|
59
42
|
options: {
|
|
60
|
-
//
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
tooltip: undefined,
|
|
67
|
-
}
|
|
43
|
+
// see `Image and description paths` setup below
|
|
44
|
+
imageHotspotPathRoot: `document`,
|
|
45
|
+
hotspotImagePath: `featureImage`,
|
|
46
|
+
hotspotDescriptionPath: `details`,
|
|
47
|
+
// see `Custom tooltip` setup below
|
|
48
|
+
hotspotTooltip: undefined,
|
|
68
49
|
},
|
|
69
|
-
}
|
|
50
|
+
},
|
|
70
51
|
// ...all your other fields
|
|
71
|
-
// ...of which one should be featureImage in this example
|
|
72
52
|
],
|
|
73
|
-
}
|
|
53
|
+
}
|
|
74
54
|
```
|
|
75
|
-
There is no need to provide an explicit input component, as that is handled by the plugin.
|
|
76
55
|
|
|
77
56
|
The plugin makes a number of assumptions to add and update data in the array. Including:
|
|
78
57
|
|
|
79
|
-
- The `array` field is an array of objects
|
|
58
|
+
- The `array` field is an array of objects
|
|
80
59
|
- The object contains two number fields named `x` and `y`
|
|
81
60
|
- You'll want to save those values as % from the top left of the image
|
|
82
61
|
- The same document contains the image you want to add hotspots to
|
|
83
62
|
|
|
84
|
-
### Image
|
|
63
|
+
### Image and description paths
|
|
85
64
|
|
|
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.
|
|
65
|
+
The custom input has the current values of all fields in the document by default, and so can "pick" the image out of the document by its path.
|
|
87
66
|
|
|
88
|
-
For example, if you want to add hotspots to an image, and that image is uploaded to the field `featuredImage`, your fields `options` would look like:
|
|
67
|
+
For example, if you want to add hotspots to an image, and that image is uploaded to the document field of `featuredImage`, your fields `options` would look like:
|
|
89
68
|
|
|
90
69
|
```js
|
|
91
70
|
options: {
|
|
92
|
-
|
|
93
|
-
imagePath: `featureImage`
|
|
94
|
-
}
|
|
71
|
+
hotspotImagePath: `featureImage`
|
|
95
72
|
}
|
|
96
73
|
```
|
|
97
74
|
|
|
98
|
-
|
|
75
|
+
Alternatively, you may supply 'parent' to the `imageHotspotPathRoot` option to pick from the parent object instead. Using 'parent' as `imageHotspotPathRoot` in favor of the default 'document' may be required, e.g. if your schema of hotspots array is defined as a child of another array, and therefore you can not reference dynamically the correct field in a 'document' specified by `hotspotImagePath`.
|
|
76
|
+
|
|
77
|
+
In this case, if the image is uploaded to the parent object field of `featuredImage`, your fields `options` would look like:
|
|
78
|
+
|
|
99
79
|
```js
|
|
100
80
|
options: {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
}
|
|
81
|
+
imageHotspotPathRoot: `parent`,
|
|
82
|
+
hotspotImagePath: `featureImage`
|
|
104
83
|
}
|
|
105
84
|
```
|
|
106
85
|
|
|
107
|
-
|
|
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.
|
|
86
|
+
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.
|
|
111
87
|
|
|
112
88
|
```js
|
|
113
89
|
options: {
|
|
114
|
-
|
|
115
|
-
descriptionPath: `details`
|
|
116
|
-
}
|
|
90
|
+
hotspotDescriptionPath: `details`
|
|
117
91
|
}
|
|
118
92
|
```
|
|
119
93
|
|
|
@@ -122,7 +96,7 @@ options: {
|
|
|
122
96
|
Here's an example object schema complete with initial values, validation, fieldsets and a styled preview.
|
|
123
97
|
|
|
124
98
|
```js
|
|
125
|
-
|
|
99
|
+
{
|
|
126
100
|
name: 'spot',
|
|
127
101
|
type: 'object',
|
|
128
102
|
fieldsets: [{name: 'position', options: {columns: 2}}],
|
|
@@ -158,66 +132,28 @@ defineField({
|
|
|
158
132
|
}
|
|
159
133
|
},
|
|
160
134
|
},
|
|
161
|
-
}
|
|
135
|
+
}
|
|
162
136
|
```
|
|
163
137
|
|
|
164
138
|
## Custom tooltip
|
|
165
139
|
|
|
166
|
-
You can customise the Tooltip to display any Component,
|
|
167
|
-
`schemaType` (schemaType of the hotspot value), and `renderPreview` (callback for rendering Studio preview).
|
|
168
|
-
|
|
169
|
-
### Example 1 - use default hotspot preview
|
|
140
|
+
You can customise the Tooltip to display any Component, it will accept a single prop `spot` which contains the values of the object.
|
|
170
141
|
|
|
171
|
-
|
|
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
|
|
142
|
+
In this example our `spot` object has a `reference` field to the `product` schema type, and will show a Document Preview.
|
|
193
143
|
|
|
194
144
|
```js
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
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'
|
|
145
|
+
// Setup a custom tooltip component
|
|
146
|
+
import Preview from 'part:@sanity/base/preview'
|
|
147
|
+
import schema from 'part:@sanity/base/schema'
|
|
207
148
|
import {Box} from '@sanity/ui'
|
|
208
149
|
|
|
209
|
-
export function ProductPreview({
|
|
210
|
-
const productSchemaType = useSchema().get('product')
|
|
150
|
+
export default function ProductPreview({spot}) {
|
|
211
151
|
return (
|
|
212
152
|
<Box padding={2} style={{minWidth: 200}}>
|
|
213
|
-
{
|
|
214
|
-
|
|
215
|
-
value,
|
|
216
|
-
schemaType: productSchemaType,
|
|
217
|
-
layout: "default"
|
|
218
|
-
})
|
|
153
|
+
{spot?.product?._ref ? (
|
|
154
|
+
<Preview value={{_id: spot.product._ref}} type={schema.get(`product`)} />
|
|
219
155
|
) : (
|
|
220
|
-
`No
|
|
156
|
+
`No Reference Selected`
|
|
221
157
|
)}
|
|
222
158
|
</Box>
|
|
223
159
|
)
|
|
@@ -227,28 +163,16 @@ export function ProductPreview({value, renderPreview}) {
|
|
|
227
163
|
Then back in your schema definition
|
|
228
164
|
|
|
229
165
|
```js
|
|
166
|
+
import HotspotArray from 'sanity-plugin-hotspot-array'
|
|
167
|
+
import ProductPreview from '../../components/ProductPreview'
|
|
168
|
+
|
|
230
169
|
options: {
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
}
|
|
170
|
+
hotspotImagePath: `hotspotImage`,
|
|
171
|
+
hotspotTooltip: ProductPreview,
|
|
172
|
+
},
|
|
235
173
|
```
|
|
236
174
|
|
|
237
175
|
## License
|
|
238
176
|
|
|
239
|
-
MIT
|
|
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.
|
|
177
|
+
MIT ©
|
|
178
|
+
See LICENSE
|
package/lib/Feedback.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = Feedback;
|
|
7
|
+
var _react = _interopRequireDefault(require("react"));
|
|
8
|
+
var _ui = require("@sanity/ui");
|
|
9
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
10
|
+
function Feedback(_ref) {
|
|
11
|
+
var children = _ref.children;
|
|
12
|
+
return /*#__PURE__*/_react.default.createElement(_ui.Card, {
|
|
13
|
+
padding: 4,
|
|
14
|
+
radius: 2,
|
|
15
|
+
shadow: 1,
|
|
16
|
+
tone: "caution"
|
|
17
|
+
}, /*#__PURE__*/_react.default.createElement(_ui.Text, null, children));
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=Feedback.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Feedback.js","names":["Feedback","children"],"sources":["../src/Feedback.tsx"],"sourcesContent":["import React from 'react'\nimport {Card, Text} from '@sanity/ui'\n\nexport default function Feedback({children}) {\n return (\n <Card padding={4} radius={2} shadow={1} tone=\"caution\">\n <Text>{children}</Text>\n </Card>\n )\n}\n"],"mappings":";;;;;;AAAA;AACA;AAAqC;AAEtB,SAASA,QAAQ,OAAa;EAAA,IAAXC,QAAQ,QAARA,QAAQ;EACxC,oBACE,6BAAC,QAAI;IAAC,OAAO,EAAE,CAAE;IAAC,MAAM,EAAE,CAAE;IAAC,MAAM,EAAE,CAAE;IAAC,IAAI,EAAC;EAAS,gBACpD,6BAAC,QAAI,QAAEA,QAAQ,CAAQ,CAClB;AAEX"}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _client = _interopRequireDefault(require("part:@sanity/base/client"));
|
|
8
|
+
var _formBuilder = require("part:@sanity/form-builder");
|
|
9
|
+
var _assetUtils = require("@sanity/asset-utils");
|
|
10
|
+
var _PatchEvent = require("@sanity/form-builder/PatchEvent");
|
|
11
|
+
var _imageUrl = _interopRequireDefault(require("@sanity/image-url"));
|
|
12
|
+
var _ui = require("@sanity/ui");
|
|
13
|
+
var _content = require("@sanity/util/content");
|
|
14
|
+
var _get = _interopRequireDefault(require("lodash/get"));
|
|
15
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
16
|
+
var _web = require("@react-hookz/web");
|
|
17
|
+
var _Feedback = _interopRequireDefault(require("./Feedback"));
|
|
18
|
+
var _Spot = _interopRequireDefault(require("./Spot"));
|
|
19
|
+
var _useUnsetInputComponent = require("./useUnsetInputComponent");
|
|
20
|
+
var _NestedFormBuilder = require("./NestedFormBuilder");
|
|
21
|
+
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
22
|
+
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
23
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
24
|
+
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
|
25
|
+
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
|
|
26
|
+
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
27
|
+
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
28
|
+
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
|
|
29
|
+
function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
|
|
30
|
+
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
31
|
+
var imageStyle = {
|
|
32
|
+
width: "100%",
|
|
33
|
+
height: "auto"
|
|
34
|
+
};
|
|
35
|
+
var VALID_ROOT_PATHS = ['document', 'parent'];
|
|
36
|
+
var HotspotArray = /*#__PURE__*/_react.default.forwardRef((props, ref) => {
|
|
37
|
+
var _type$options, _type$options2, _type$options3;
|
|
38
|
+
console.log(props);
|
|
39
|
+
var type = props.type,
|
|
40
|
+
value = props.value,
|
|
41
|
+
onChange = props.onChange,
|
|
42
|
+
document = props.document;
|
|
43
|
+
var _ref = type !== null && type !== void 0 ? type : {},
|
|
44
|
+
options = _ref.options;
|
|
45
|
+
|
|
46
|
+
// Attempt prevention of infinite loop in <FormBuilderInput />
|
|
47
|
+
// Re-renders can still occur if this Component is used again in a nested field
|
|
48
|
+
var typeWithoutInputComponent = (0, _useUnsetInputComponent.useUnsetInputComponent)(type, type === null || type === void 0 ? void 0 : type.inputComponent);
|
|
49
|
+
var imageHotspotPathRoot = VALID_ROOT_PATHS.includes(options === null || options === void 0 ? void 0 : options.imageHotspotPathRoot) ? props[options.imageHotspotPathRoot] : document;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Finding the image from the imageHotspotPathRoot (defaults to document),
|
|
53
|
+
* using the path from the hotspot's `options` field
|
|
54
|
+
*
|
|
55
|
+
* when changes in imageHotspotPathRoot (e.g. document) occur,
|
|
56
|
+
* check if there are any changes to the hotspotImage and update the reference
|
|
57
|
+
*/
|
|
58
|
+
var hotspotImage = _react.default.useMemo(() => {
|
|
59
|
+
return (0, _get.default)(imageHotspotPathRoot, options === null || options === void 0 ? void 0 : options.hotspotImagePath);
|
|
60
|
+
}, [imageHotspotPathRoot]);
|
|
61
|
+
var displayImage = _react.default.useMemo(() => {
|
|
62
|
+
var _hotspotImage$asset;
|
|
63
|
+
var builder = (0, _imageUrl.default)(_client.default).dataset(_client.default.config().dataset);
|
|
64
|
+
var urlFor = source => builder.image(source);
|
|
65
|
+
if (hotspotImage !== null && hotspotImage !== void 0 && (_hotspotImage$asset = hotspotImage.asset) !== null && _hotspotImage$asset !== void 0 && _hotspotImage$asset._ref) {
|
|
66
|
+
var _getImageDimensions = (0, _assetUtils.getImageDimensions)(hotspotImage.asset._ref),
|
|
67
|
+
aspectRatio = _getImageDimensions.aspectRatio;
|
|
68
|
+
var width = 1200;
|
|
69
|
+
var height = Math.round(width / aspectRatio);
|
|
70
|
+
var url = urlFor(hotspotImage).width(width).url();
|
|
71
|
+
return {
|
|
72
|
+
width,
|
|
73
|
+
height,
|
|
74
|
+
url
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
return null;
|
|
78
|
+
}, [hotspotImage]);
|
|
79
|
+
var handleHotspotImageClick = _react.default.useCallback(event => {
|
|
80
|
+
var nativeEvent = event.nativeEvent;
|
|
81
|
+
|
|
82
|
+
// Calculate the x/y percentage of the click position
|
|
83
|
+
var x = Number((nativeEvent.offsetX * 100 / nativeEvent.srcElement.width).toFixed(2));
|
|
84
|
+
var y = Number((nativeEvent.offsetY * 100 / nativeEvent.srcElement.height).toFixed(2));
|
|
85
|
+
var description = "New Hotspot at ".concat(x, "% x ").concat(y, "%");
|
|
86
|
+
var newRow = {
|
|
87
|
+
_key: (0, _content.randomKey)(12),
|
|
88
|
+
_type: "spot",
|
|
89
|
+
x,
|
|
90
|
+
y
|
|
91
|
+
};
|
|
92
|
+
if (options !== null && options !== void 0 && options.hotspotDescriptionPath) {
|
|
93
|
+
newRow[options.hotspotDescriptionPath] = description;
|
|
94
|
+
}
|
|
95
|
+
onChange(_PatchEvent.PatchEvent.from((0, _PatchEvent.setIfMissing)([]), (0, _PatchEvent.insert)([newRow], 'after', [-1])));
|
|
96
|
+
}, []);
|
|
97
|
+
var handleHotspotMove = _react.default.useCallback((key, x, y) => {
|
|
98
|
+
onChange(_PatchEvent.PatchEvent.from(
|
|
99
|
+
// Set the `x` value of this array key item
|
|
100
|
+
(0, _PatchEvent.set)(x, [{
|
|
101
|
+
_key: key
|
|
102
|
+
}, 'x']),
|
|
103
|
+
// Set the `y` value of this array key item
|
|
104
|
+
(0, _PatchEvent.set)(y, [{
|
|
105
|
+
_key: key
|
|
106
|
+
}, 'y'])));
|
|
107
|
+
}, [value]);
|
|
108
|
+
var hotspotImageRef = _react.default.useRef(null);
|
|
109
|
+
var _useState = (0, _react.useState)(),
|
|
110
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
111
|
+
imageRect = _useState2[0],
|
|
112
|
+
setImageRect = _useState2[1];
|
|
113
|
+
var updateImageRectCallback = (0, _web.useDebouncedCallback)(e => setImageRect(e.contentRect), [setImageRect], 200);
|
|
114
|
+
(0, _web.useResizeObserver)(hotspotImageRef, updateImageRectCallback);
|
|
115
|
+
return /*#__PURE__*/_react.default.createElement(_ui.Stack, {
|
|
116
|
+
space: [2, 2, 3]
|
|
117
|
+
}, displayImage !== null && displayImage !== void 0 && displayImage.url ? /*#__PURE__*/_react.default.createElement("div", {
|
|
118
|
+
style: {
|
|
119
|
+
position: "relative"
|
|
120
|
+
}
|
|
121
|
+
}, imageRect && (value === null || value === void 0 ? void 0 : value.length) > 0 && value.map((spot, index) => /*#__PURE__*/_react.default.createElement(_Spot.default, {
|
|
122
|
+
index: index,
|
|
123
|
+
key: spot._key,
|
|
124
|
+
spot: spot,
|
|
125
|
+
bounds: imageRect,
|
|
126
|
+
update: handleHotspotMove,
|
|
127
|
+
hotspotDescriptionPath: options === null || options === void 0 ? void 0 : options.hotspotDescriptionPath,
|
|
128
|
+
tooltip: options === null || options === void 0 ? void 0 : options.hotspotTooltip
|
|
129
|
+
})), /*#__PURE__*/_react.default.createElement(_ui.Card, {
|
|
130
|
+
__unstable_checkered: true,
|
|
131
|
+
shadow: 1
|
|
132
|
+
}, /*#__PURE__*/_react.default.createElement(_ui.Flex, {
|
|
133
|
+
align: "center",
|
|
134
|
+
justify: "center"
|
|
135
|
+
}, /*#__PURE__*/_react.default.createElement("img", {
|
|
136
|
+
ref: hotspotImageRef,
|
|
137
|
+
src: displayImage.url,
|
|
138
|
+
width: displayImage.width,
|
|
139
|
+
height: displayImage.height,
|
|
140
|
+
alt: "",
|
|
141
|
+
style: imageStyle,
|
|
142
|
+
onClick: handleHotspotImageClick
|
|
143
|
+
})))) : /*#__PURE__*/_react.default.createElement(_Feedback.default, null, type !== null && type !== void 0 && (_type$options = type.options) !== null && _type$options !== void 0 && _type$options.hotspotImagePath ? /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, "No Hotspot image found at path ", /*#__PURE__*/_react.default.createElement("code", null, type === null || type === void 0 ? void 0 : (_type$options2 = type.options) === null || _type$options2 === void 0 ? void 0 : _type$options2.hotspotImagePath)) : /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, "Define a path in this field using to the image field in this document at", ' ', /*#__PURE__*/_react.default.createElement("code", null, "options.hotspotImagePath"))), (type === null || type === void 0 ? void 0 : (_type$options3 = type.options) === null || _type$options3 === void 0 ? void 0 : _type$options3.imageHotspotPathRoot) && !VALID_ROOT_PATHS.includes(type.options.imageHotspotPathRoot) && /*#__PURE__*/_react.default.createElement(_Feedback.default, null, "The supplied imageHotspotPathRoot \"", type.options.imageHotspotPathRoot, "\" is not valid, falling back to \"document\". Available values are \"", VALID_ROOT_PATHS.join(', '), "\"."), /*#__PURE__*/_react.default.createElement(_NestedFormBuilder.NestedFormBuilder, _extends({}, props, {
|
|
144
|
+
type: typeWithoutInputComponent,
|
|
145
|
+
ref: ref
|
|
146
|
+
})));
|
|
147
|
+
});
|
|
148
|
+
var _default = (0, _formBuilder.withParent)((0, _formBuilder.withDocument)(HotspotArray));
|
|
149
|
+
exports.default = _default;
|
|
150
|
+
//# sourceMappingURL=HotspotArray.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HotspotArray.js","names":["imageStyle","width","height","VALID_ROOT_PATHS","HotspotArray","React","forwardRef","props","ref","console","log","type","value","onChange","document","options","typeWithoutInputComponent","useUnsetInputComponent","inputComponent","imageHotspotPathRoot","includes","hotspotImage","useMemo","get","hotspotImagePath","displayImage","builder","imageUrlBuilder","sanityClient","dataset","config","urlFor","source","image","asset","_ref","getImageDimensions","aspectRatio","Math","round","url","handleHotspotImageClick","useCallback","event","nativeEvent","x","Number","offsetX","srcElement","toFixed","y","offsetY","description","newRow","_key","randomKey","_type","hotspotDescriptionPath","PatchEvent","from","setIfMissing","insert","handleHotspotMove","key","set","hotspotImageRef","useRef","useState","imageRect","setImageRect","updateImageRectCallback","useDebouncedCallback","e","contentRect","useResizeObserver","position","length","map","spot","index","hotspotTooltip","join","withParent","withDocument"],"sources":["../src/HotspotArray.tsx"],"sourcesContent":["/* eslint-disable react/display-name */\n\n// @ts-ignore\nimport sanityClient from 'part:@sanity/base/client'\n// @ts-ignore\nimport {withDocument, withParent} from 'part:@sanity/form-builder'\n\nimport {getImageDimensions} from '@sanity/asset-utils'\nimport {insert, PatchEvent, set, setIfMissing} from '@sanity/form-builder/PatchEvent'\nimport imageUrlBuilder from '@sanity/image-url'\nimport {Card, Flex, Stack} from '@sanity/ui'\nimport {randomKey} from '@sanity/util/content'\nimport get from 'lodash/get'\nimport React, {useState} from 'react'\n\nimport {IUseResizeObserverCallback, useDebouncedCallback, useResizeObserver} from '@react-hookz/web'\nimport Feedback from './Feedback'\nimport Spot from './Spot'\nimport {useUnsetInputComponent} from './useUnsetInputComponent'\nimport { NestedFormBuilder } from './NestedFormBuilder'\n\nconst imageStyle = {width: `100%`, height: `auto`}\n\nconst VALID_ROOT_PATHS = ['document', 'parent']\n\nexport type FnHotspotMove = (key: string, x: number, y: number) => void\n\nexport type TSpot = {\n _key: string\n _type: `spot`\n x: number\n y: number\n} & {[key: string]: unknown}\n\nconst HotspotArray = React.forwardRef((props: any, ref) => {\n console.log(props);\n const {type, value, onChange, document} = props\n const {options} = type ?? {}\n\n // Attempt prevention of infinite loop in <FormBuilderInput />\n // Re-renders can still occur if this Component is used again in a nested field\n const typeWithoutInputComponent = useUnsetInputComponent(type, type?.inputComponent)\n const imageHotspotPathRoot = VALID_ROOT_PATHS.includes(options?.imageHotspotPathRoot)\n ? props[options.imageHotspotPathRoot]\n : document\n\n /**\n * Finding the image from the imageHotspotPathRoot (defaults to document),\n * using the path from the hotspot's `options` field\n *\n * when changes in imageHotspotPathRoot (e.g. document) occur,\n * check if there are any changes to the hotspotImage and update the reference\n */\n const hotspotImage = React.useMemo(() => {\n return get(imageHotspotPathRoot, options?.hotspotImagePath)\n }, [imageHotspotPathRoot])\n\n const displayImage = React.useMemo(() => {\n const builder = imageUrlBuilder(sanityClient).dataset(sanityClient.config().dataset)\n const urlFor = (source) => builder.image(source)\n\n if (hotspotImage?.asset?._ref) {\n const {aspectRatio} = getImageDimensions(hotspotImage.asset._ref)\n const width = 1200\n const height = Math.round(width / aspectRatio)\n const url = urlFor(hotspotImage).width(width).url()\n\n return {width, height, url}\n }\n\n return null\n }, [hotspotImage])\n\n const handleHotspotImageClick = React.useCallback((event) => {\n const {nativeEvent} = event\n\n // Calculate the x/y percentage of the click position\n const x = Number(((nativeEvent.offsetX * 100) / nativeEvent.srcElement.width).toFixed(2))\n const y = Number(((nativeEvent.offsetY * 100) / nativeEvent.srcElement.height).toFixed(2))\n const description = `New Hotspot at ${x}% x ${y}%`\n\n const newRow: TSpot = {\n _key: randomKey(12),\n _type: `spot`,\n x,\n y,\n }\n\n if (options?.hotspotDescriptionPath) {\n newRow[options.hotspotDescriptionPath] = description\n }\n\n onChange(PatchEvent.from(setIfMissing([]), insert([newRow], 'after', [-1])))\n }, [])\n\n const handleHotspotMove: FnHotspotMove = React.useCallback(\n (key, x, y) => {\n onChange(\n PatchEvent.from(\n // Set the `x` value of this array key item\n set(x, [{_key: key}, 'x']),\n // Set the `y` value of this array key item\n set(y, [{_key: key}, 'y'])\n )\n )\n },\n [value]\n )\n\n const hotspotImageRef = React.useRef<HTMLImageElement | null>(null)\n\n const [imageRect, setImageRect] = useState<DOMRectReadOnly>()\n const updateImageRectCallback = useDebouncedCallback(\n ((e) => setImageRect(e.contentRect)) as IUseResizeObserverCallback,\n [setImageRect],\n 200\n )\n useResizeObserver(hotspotImageRef, updateImageRectCallback)\n\n return (\n <Stack space={[2, 2, 3]}>\n {displayImage?.url ? (\n <div style={{position: `relative`}}>\n {imageRect &&\n value?.length > 0 &&\n value.map((spot, index) => (\n <Spot\n index={index}\n key={spot._key}\n spot={spot}\n bounds={imageRect}\n update={handleHotspotMove}\n hotspotDescriptionPath={options?.hotspotDescriptionPath}\n tooltip={options?.hotspotTooltip}\n />\n ))}\n\n <Card __unstable_checkered shadow={1}>\n <Flex align=\"center\" justify=\"center\">\n <img\n ref={hotspotImageRef}\n src={displayImage.url}\n width={displayImage.width}\n height={displayImage.height}\n alt=\"\"\n style={imageStyle}\n onClick={handleHotspotImageClick}\n />\n </Flex>\n </Card>\n </div>\n ) : (\n <Feedback>\n {type?.options?.hotspotImagePath ? (\n <>\n No Hotspot image found at path <code>{type?.options?.hotspotImagePath}</code>\n </>\n ) : (\n <>\n Define a path in this field using to the image field in this document at{' '}\n <code>options.hotspotImagePath</code>\n </>\n )}\n </Feedback>\n )}\n {type?.options?.imageHotspotPathRoot &&\n !VALID_ROOT_PATHS.includes(type.options.imageHotspotPathRoot) && (\n <Feedback>\n The supplied imageHotspotPathRoot \"{type.options.imageHotspotPathRoot}\" is not valid,\n falling back to \"document\". Available values are \"{VALID_ROOT_PATHS.join(', ')}\".\n </Feedback>\n )}\n <NestedFormBuilder {...props} type={typeWithoutInputComponent} ref={ref} />\n </Stack>\n )\n})\n\nexport default withParent(withDocument(HotspotArray))\n"],"mappings":";;;;;;AAGA;AAEA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAAuD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEvD,IAAMA,UAAU,GAAG;EAACC,KAAK,QAAQ;EAAEC,MAAM;AAAQ,CAAC;AAElD,IAAMC,gBAAgB,GAAG,CAAC,UAAU,EAAE,QAAQ,CAAC;AAW/C,IAAMC,YAAY,gBAAGC,cAAK,CAACC,UAAU,CAAC,CAACC,KAAU,EAAEC,GAAG,KAAK;EAAA;EACzDC,OAAO,CAACC,GAAG,CAACH,KAAK,CAAC;EAClB,IAAOI,IAAI,GAA+BJ,KAAK,CAAxCI,IAAI;IAAEC,KAAK,GAAwBL,KAAK,CAAlCK,KAAK;IAAEC,QAAQ,GAAcN,KAAK,CAA3BM,QAAQ;IAAEC,QAAQ,GAAIP,KAAK,CAAjBO,QAAQ;EACtC,WAAkBH,IAAI,aAAJA,IAAI,cAAJA,IAAI,GAAI,CAAC,CAAC;IAArBI,OAAO,QAAPA,OAAO;;EAEd;EACA;EACA,IAAMC,yBAAyB,GAAG,IAAAC,8CAAsB,EAACN,IAAI,EAAEA,IAAI,aAAJA,IAAI,uBAAJA,IAAI,CAAEO,cAAc,CAAC;EACpF,IAAMC,oBAAoB,GAAGhB,gBAAgB,CAACiB,QAAQ,CAACL,OAAO,aAAPA,OAAO,uBAAPA,OAAO,CAAEI,oBAAoB,CAAC,GACjFZ,KAAK,CAACQ,OAAO,CAACI,oBAAoB,CAAC,GACnCL,QAAQ;;EAEZ;AACF;AACA;AACA;AACA;AACA;AACA;EACE,IAAMO,YAAY,GAAGhB,cAAK,CAACiB,OAAO,CAAC,MAAM;IACvC,OAAO,IAAAC,YAAG,EAACJ,oBAAoB,EAAEJ,OAAO,aAAPA,OAAO,uBAAPA,OAAO,CAAES,gBAAgB,CAAC;EAC7D,CAAC,EAAE,CAACL,oBAAoB,CAAC,CAAC;EAE1B,IAAMM,YAAY,GAAGpB,cAAK,CAACiB,OAAO,CAAC,MAAM;IAAA;IACvC,IAAMI,OAAO,GAAG,IAAAC,iBAAe,EAACC,eAAY,CAAC,CAACC,OAAO,CAACD,eAAY,CAACE,MAAM,EAAE,CAACD,OAAO,CAAC;IACpF,IAAME,MAAM,GAAIC,MAAM,IAAKN,OAAO,CAACO,KAAK,CAACD,MAAM,CAAC;IAEhD,IAAIX,YAAY,aAAZA,YAAY,sCAAZA,YAAY,CAAEa,KAAK,gDAAnB,oBAAqBC,IAAI,EAAE;MAC7B,0BAAsB,IAAAC,8BAAkB,EAACf,YAAY,CAACa,KAAK,CAACC,IAAI,CAAC;QAA1DE,WAAW,uBAAXA,WAAW;MAClB,IAAMpC,KAAK,GAAG,IAAI;MAClB,IAAMC,MAAM,GAAGoC,IAAI,CAACC,KAAK,CAACtC,KAAK,GAAGoC,WAAW,CAAC;MAC9C,IAAMG,GAAG,GAAGT,MAAM,CAACV,YAAY,CAAC,CAACpB,KAAK,CAACA,KAAK,CAAC,CAACuC,GAAG,EAAE;MAEnD,OAAO;QAACvC,KAAK;QAAEC,MAAM;QAAEsC;MAAG,CAAC;IAC7B;IAEA,OAAO,IAAI;EACb,CAAC,EAAE,CAACnB,YAAY,CAAC,CAAC;EAElB,IAAMoB,uBAAuB,GAAGpC,cAAK,CAACqC,WAAW,CAAEC,KAAK,IAAK;IAC3D,IAAOC,WAAW,GAAID,KAAK,CAApBC,WAAW;;IAElB;IACA,IAAMC,CAAC,GAAGC,MAAM,CAAC,CAAEF,WAAW,CAACG,OAAO,GAAG,GAAG,GAAIH,WAAW,CAACI,UAAU,CAAC/C,KAAK,EAAEgD,OAAO,CAAC,CAAC,CAAC,CAAC;IACzF,IAAMC,CAAC,GAAGJ,MAAM,CAAC,CAAEF,WAAW,CAACO,OAAO,GAAG,GAAG,GAAIP,WAAW,CAACI,UAAU,CAAC9C,MAAM,EAAE+C,OAAO,CAAC,CAAC,CAAC,CAAC;IAC1F,IAAMG,WAAW,4BAAqBP,CAAC,iBAAOK,CAAC,MAAG;IAElD,IAAMG,MAAa,GAAG;MACpBC,IAAI,EAAE,IAAAC,kBAAS,EAAC,EAAE,CAAC;MACnBC,KAAK,QAAQ;MACbX,CAAC;MACDK;IACF,CAAC;IAED,IAAInC,OAAO,aAAPA,OAAO,eAAPA,OAAO,CAAE0C,sBAAsB,EAAE;MACnCJ,MAAM,CAACtC,OAAO,CAAC0C,sBAAsB,CAAC,GAAGL,WAAW;IACtD;IAEAvC,QAAQ,CAAC6C,sBAAU,CAACC,IAAI,CAAC,IAAAC,wBAAY,EAAC,EAAE,CAAC,EAAE,IAAAC,kBAAM,EAAC,CAACR,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;EAC9E,CAAC,EAAE,EAAE,CAAC;EAEN,IAAMS,iBAAgC,GAAGzD,cAAK,CAACqC,WAAW,CACxD,CAACqB,GAAG,EAAElB,CAAC,EAAEK,CAAC,KAAK;IACbrC,QAAQ,CACN6C,sBAAU,CAACC,IAAI;IACb;IACA,IAAAK,eAAG,EAACnB,CAAC,EAAE,CAAC;MAACS,IAAI,EAAES;IAAG,CAAC,EAAE,GAAG,CAAC,CAAC;IAC1B;IACA,IAAAC,eAAG,EAACd,CAAC,EAAE,CAAC;MAACI,IAAI,EAAES;IAAG,CAAC,EAAE,GAAG,CAAC,CAAC,CAC3B,CACF;EACH,CAAC,EACD,CAACnD,KAAK,CAAC,CACR;EAED,IAAMqD,eAAe,GAAG5D,cAAK,CAAC6D,MAAM,CAA0B,IAAI,CAAC;EAEnE,gBAAkC,IAAAC,eAAQ,GAAmB;IAAA;IAAtDC,SAAS;IAAEC,YAAY;EAC9B,IAAMC,uBAAuB,GAAG,IAAAC,yBAAoB,EAChDC,CAAC,IAAKH,YAAY,CAACG,CAAC,CAACC,WAAW,CAAC,EACnC,CAACJ,YAAY,CAAC,EACd,GAAG,CACJ;EACD,IAAAK,sBAAiB,EAACT,eAAe,EAAEK,uBAAuB,CAAC;EAE3D,oBACE,6BAAC,SAAK;IAAC,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;EAAE,GACrB7C,YAAY,aAAZA,YAAY,eAAZA,YAAY,CAAEe,GAAG,gBAChB;IAAK,KAAK,EAAE;MAACmC,QAAQ;IAAY;EAAE,GAChCP,SAAS,IACR,CAAAxD,KAAK,aAALA,KAAK,uBAALA,KAAK,CAAEgE,MAAM,IAAG,CAAC,IACjBhE,KAAK,CAACiE,GAAG,CAAC,CAACC,IAAI,EAAEC,KAAK,kBACpB,6BAAC,aAAI;IACH,KAAK,EAAEA,KAAM;IACb,GAAG,EAAED,IAAI,CAACxB,IAAK;IACf,IAAI,EAAEwB,IAAK;IACX,MAAM,EAAEV,SAAU;IAClB,MAAM,EAAEN,iBAAkB;IAC1B,sBAAsB,EAAE/C,OAAO,aAAPA,OAAO,uBAAPA,OAAO,CAAE0C,sBAAuB;IACxD,OAAO,EAAE1C,OAAO,aAAPA,OAAO,uBAAPA,OAAO,CAAEiE;EAAe,EAEpC,CAAC,eAEJ,6BAAC,QAAI;IAAC,oBAAoB;IAAC,MAAM,EAAE;EAAE,gBACnC,6BAAC,QAAI;IAAC,KAAK,EAAC,QAAQ;IAAC,OAAO,EAAC;EAAQ,gBACnC;IACE,GAAG,EAAEf,eAAgB;IACrB,GAAG,EAAExC,YAAY,CAACe,GAAI;IACtB,KAAK,EAAEf,YAAY,CAACxB,KAAM;IAC1B,MAAM,EAAEwB,YAAY,CAACvB,MAAO;IAC5B,GAAG,EAAC,EAAE;IACN,KAAK,EAAEF,UAAW;IAClB,OAAO,EAAEyC;EAAwB,EACjC,CACG,CACF,CACH,gBAEN,6BAAC,iBAAQ,QACN9B,IAAI,aAAJA,IAAI,gCAAJA,IAAI,CAAEI,OAAO,0CAAb,cAAeS,gBAAgB,gBAC9B,4GACiC,2CAAOb,IAAI,aAAJA,IAAI,yCAAJA,IAAI,CAAEI,OAAO,mDAAb,eAAeS,gBAAgB,CAAQ,CAC5E,gBAEH,wIAC2E,GAAG,eAC5E,sEAAqC,CAExC,CAEJ,EACA,CAAAb,IAAI,aAAJA,IAAI,yCAAJA,IAAI,CAAEI,OAAO,mDAAb,eAAeI,oBAAoB,KAClC,CAAChB,gBAAgB,CAACiB,QAAQ,CAACT,IAAI,CAACI,OAAO,CAACI,oBAAoB,CAAC,iBAC3D,6BAAC,iBAAQ,gDAC6BR,IAAI,CAACI,OAAO,CAACI,oBAAoB,4EAClBhB,gBAAgB,CAAC8E,IAAI,CAAC,IAAI,CAAC,QAEjF,eACH,6BAAC,oCAAiB,eAAK1E,KAAK;IAAE,IAAI,EAAES,yBAA0B;IAAC,GAAG,EAAER;EAAI,GAAG,CACrE;AAEZ,CAAC,CAAC;AAAA,eAEa,IAAA0E,uBAAU,EAAC,IAAAC,yBAAY,EAAC/E,YAAY,CAAC,CAAC;AAAA"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.NestedFormBuilder = void 0;
|
|
7
|
+
var _react = _interopRequireDefault(require("react"));
|
|
8
|
+
var _FormBuilderInput = require("@sanity/form-builder/lib/FormBuilderInput");
|
|
9
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
10
|
+
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
|
11
|
+
/**
|
|
12
|
+
* Nesting FormBuilderInput components results in inconsistent focus & tab-index behaviour.
|
|
13
|
+
*
|
|
14
|
+
* FormBuilderInputs requests focus if props.focusPath matches the input.focusPath
|
|
15
|
+
* when mounted and when props change. If multiple components "handle" the same focus path,
|
|
16
|
+
* there is a race-condition on which component will receive the focus, often resulting
|
|
17
|
+
* in seemingly random scrollbehaviour.
|
|
18
|
+
*
|
|
19
|
+
* This is a workaround, reusing as much of FormBuilderInput as possible.
|
|
20
|
+
*
|
|
21
|
+
* Use FormBuilderInput when you need to render a field obtained from a SchemaType (type.fields or type.fieldset[].field).
|
|
22
|
+
*
|
|
23
|
+
* Use NestedFormBuilder for decorator components that are used as inputComponent or in input-resolver.ts.
|
|
24
|
+
*
|
|
25
|
+
* Decorator components are components that just want to modify a type, add some markup or so on,
|
|
26
|
+
* then delegate back to Sanity to obtain an actual input implementation.
|
|
27
|
+
*
|
|
28
|
+
* FormBuilderInput should only be used as the outermost component when resolving
|
|
29
|
+
* inputs recursively.
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
class NestedFormBuilder extends _FormBuilderInput.FormBuilderInput {
|
|
33
|
+
componentDidMount() {
|
|
34
|
+
// do nothing - prevent focus-bug when nesting FormBuilderInput
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// eslint-disable-next-line camelcase
|
|
38
|
+
UNSAFE_componentWillReceiveProps() {
|
|
39
|
+
// do nothing - prevent focus-bug when nesting FormBuilderInput
|
|
40
|
+
}
|
|
41
|
+
componentDidUpdate() {
|
|
42
|
+
// do nothing - prevent focus-bug when nesting FormBuilderInput
|
|
43
|
+
}
|
|
44
|
+
render() {
|
|
45
|
+
var type = this.props.type;
|
|
46
|
+
var InputComponent = this.resolveInputComponent(type);
|
|
47
|
+
return /*#__PURE__*/_react.default.createElement(InputComponent, _extends({}, this.props, {
|
|
48
|
+
ref: this.setInput
|
|
49
|
+
}));
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
exports.NestedFormBuilder = NestedFormBuilder;
|
|
53
|
+
//# sourceMappingURL=NestedFormBuilder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NestedFormBuilder.js","names":["NestedFormBuilder","FormBuilderInput","componentDidMount","UNSAFE_componentWillReceiveProps","componentDidUpdate","render","type","props","InputComponent","resolveInputComponent","setInput"],"sources":["../src/NestedFormBuilder.tsx"],"sourcesContent":["import React from 'react';\nimport { FormBuilderInput } from '@sanity/form-builder/lib/FormBuilderInput';\n\n/**\n * Nesting FormBuilderInput components results in inconsistent focus & tab-index behaviour.\n *\n * FormBuilderInputs requests focus if props.focusPath matches the input.focusPath\n * when mounted and when props change. If multiple components \"handle\" the same focus path,\n * there is a race-condition on which component will receive the focus, often resulting\n * in seemingly random scrollbehaviour.\n *\n * This is a workaround, reusing as much of FormBuilderInput as possible.\n *\n * Use FormBuilderInput when you need to render a field obtained from a SchemaType (type.fields or type.fieldset[].field).\n *\n * Use NestedFormBuilder for decorator components that are used as inputComponent or in input-resolver.ts.\n *\n * Decorator components are components that just want to modify a type, add some markup or so on,\n * then delegate back to Sanity to obtain an actual input implementation.\n *\n * FormBuilderInput should only be used as the outermost component when resolving\n * inputs recursively.\n */\n\nexport class NestedFormBuilder extends FormBuilderInput {\n componentDidMount() {\n // do nothing - prevent focus-bug when nesting FormBuilderInput\n }\n \n // eslint-disable-next-line camelcase\n UNSAFE_componentWillReceiveProps() {\n // do nothing - prevent focus-bug when nesting FormBuilderInput\n }\n \n componentDidUpdate() {\n // do nothing - prevent focus-bug when nesting FormBuilderInput\n }\n \n render(): JSX.Element {\n const { type } = this.props;\n const InputComponent = this.resolveInputComponent(type);\n return <InputComponent {...this.props} ref={this.setInput} />;\n }\n }"],"mappings":";;;;;;AAAA;AACA;AAA6E;AAAA;AAE7E;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEO,MAAMA,iBAAiB,SAASC,kCAAgB,CAAC;EACpDC,iBAAiB,GAAG;IAClB;EACF;;EAEA;EACAC,gCAAgC,GAAG;IACjC;EACF;EAEAC,kBAAkB,GAAG;IACnB;EACF;EAEAC,MAAM,GAAgB;IACpB,IAAQC,IAAI,GAAK,IAAI,CAACC,KAAK,CAAnBD,IAAI;IACZ,IAAME,cAAc,GAAG,IAAI,CAACC,qBAAqB,CAACH,IAAI,CAAC;IACvD,oBAAO,6BAAC,cAAc,eAAK,IAAI,CAACC,KAAK;MAAE,GAAG,EAAE,IAAI,CAACG;IAAS,GAAG;EAC/D;AACF;AAAC"}
|