sanity-plugin-hotspot-array 0.1.0 → 1.0.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/README.md +128 -55
- package/lib/index.esm.js +2 -0
- package/lib/index.esm.js.map +1 -0
- package/lib/index.js +2 -0
- package/lib/index.js.map +1 -0
- package/lib/src/index.d.ts +55 -0
- package/package.json +57 -46
- package/sanity.json +6 -5
- package/src/Feedback.tsx +2 -2
- package/src/ImageHotspotArray.tsx +188 -0
- package/src/Spot.tsx +31 -19
- package/src/index.ts +4 -0
- package/src/plugin.tsx +39 -0
- package/v2-incompatible.js +11 -0
- package/.babelrc +0 -3
- package/.releaserc.json +0 -4
- package/.semantic-release/sanity-plugin-hotspot-array-0.1.0.tgz +0 -0
- package/CHANGELOG.md +0 -16
- package/lib/Feedback.js +0 -19
- package/lib/Feedback.js.map +0 -1
- package/lib/HotspotArray.js +0 -150
- package/lib/HotspotArray.js.map +0 -1
- package/lib/NestedFormBuilder.js +0 -53
- package/lib/NestedFormBuilder.js.map +0 -1
- package/lib/Spot.js +0 -157
- package/lib/Spot.js.map +0 -1
- package/lib/useUnsetInputComponent.js +0 -24
- package/lib/useUnsetInputComponent.js.map +0 -1
- package/src/HotspotArray.tsx +0 -178
- package/src/NestedFormBuilder.tsx +0 -44
- package/src/useUnsetInputComponent.ts +0 -17
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/* eslint-disable react/display-name */
|
|
2
|
+
|
|
3
|
+
import {getImageDimensions} from '@sanity/asset-utils'
|
|
4
|
+
import {
|
|
5
|
+
ArrayOfObjectsInputProps,
|
|
6
|
+
ImageValue,
|
|
7
|
+
insert,
|
|
8
|
+
ObjectSchemaType,
|
|
9
|
+
PatchEvent,
|
|
10
|
+
set,
|
|
11
|
+
setIfMissing,
|
|
12
|
+
useClient,
|
|
13
|
+
useFormValue,
|
|
14
|
+
} from 'sanity'
|
|
15
|
+
import imageUrlBuilder from '@sanity/image-url'
|
|
16
|
+
import {Card, Flex, Stack} from '@sanity/ui'
|
|
17
|
+
import {randomKey} from '@sanity/util/content'
|
|
18
|
+
import get from 'lodash/get'
|
|
19
|
+
import React, {useCallback, useMemo, useRef, useState} from 'react'
|
|
20
|
+
|
|
21
|
+
import {IUseResizeObserverCallback, useDebouncedCallback, useResizeObserver} from '@react-hookz/web'
|
|
22
|
+
import Feedback from './Feedback'
|
|
23
|
+
import Spot from './Spot'
|
|
24
|
+
import {ImageHotspotOptions} from './plugin'
|
|
25
|
+
|
|
26
|
+
const imageStyle = {width: `100%`, height: `auto`}
|
|
27
|
+
|
|
28
|
+
const VALID_ROOT_PATHS = ['document', 'parent']
|
|
29
|
+
|
|
30
|
+
export type FnHotspotMove = (key: string, x: number, y: number) => void
|
|
31
|
+
|
|
32
|
+
export type HotspotItem<HotspotFields = {[key: string]: unknown}> = {
|
|
33
|
+
_key: string
|
|
34
|
+
_type: string
|
|
35
|
+
x: number
|
|
36
|
+
y: number
|
|
37
|
+
} & HotspotFields
|
|
38
|
+
|
|
39
|
+
export function ImageHotspotArray(
|
|
40
|
+
props: ArrayOfObjectsInputProps<HotspotItem> & {imageHotspotOptions: ImageHotspotOptions}
|
|
41
|
+
) {
|
|
42
|
+
const {value, onChange, imageHotspotOptions, schemaType, renderPreview} = props
|
|
43
|
+
|
|
44
|
+
const sanityClient = useClient({apiVersion: '2022-01-01'})
|
|
45
|
+
|
|
46
|
+
const imageHotspotPathRoot = useMemo(() => {
|
|
47
|
+
const pathRoot = VALID_ROOT_PATHS.includes(imageHotspotOptions.pathRoot ?? '')
|
|
48
|
+
? imageHotspotOptions.pathRoot
|
|
49
|
+
: 'document'
|
|
50
|
+
return pathRoot === 'document' ? [] : props.path.slice(0, -1)
|
|
51
|
+
}, [imageHotspotOptions.pathRoot, props.path])
|
|
52
|
+
|
|
53
|
+
const rootObject = useFormValue(imageHotspotPathRoot)
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Finding the image from the imageHotspotPathRoot (defaults to document),
|
|
57
|
+
* using the path from the hotspot's `options` field
|
|
58
|
+
*
|
|
59
|
+
* when changes in imageHotspotPathRoot (e.g. document) occur,
|
|
60
|
+
* check if there are any changes to the hotspotImage and update the reference
|
|
61
|
+
*/
|
|
62
|
+
const hotspotImage = useMemo(() => {
|
|
63
|
+
return get(rootObject, imageHotspotOptions.imagePath) as ImageValue | undefined
|
|
64
|
+
}, [rootObject, imageHotspotOptions.imagePath])
|
|
65
|
+
|
|
66
|
+
const displayImage = useMemo(() => {
|
|
67
|
+
const builder = imageUrlBuilder(sanityClient).dataset(sanityClient.config().dataset ?? '')
|
|
68
|
+
const urlFor = (source: ImageValue) => builder.image(source)
|
|
69
|
+
|
|
70
|
+
if (hotspotImage?.asset?._ref) {
|
|
71
|
+
const {aspectRatio} = getImageDimensions(hotspotImage.asset._ref)
|
|
72
|
+
const width = 1200
|
|
73
|
+
const height = Math.round(width / aspectRatio)
|
|
74
|
+
const url = urlFor(hotspotImage).width(width).url()
|
|
75
|
+
|
|
76
|
+
return {width, height, url}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return null
|
|
80
|
+
}, [hotspotImage, sanityClient])
|
|
81
|
+
|
|
82
|
+
const handleHotspotImageClick = useCallback(
|
|
83
|
+
(event: any) => {
|
|
84
|
+
const {nativeEvent} = event
|
|
85
|
+
|
|
86
|
+
// Calculate the x/y percentage of the click position
|
|
87
|
+
const x = Number(((nativeEvent.offsetX * 100) / nativeEvent.srcElement.width).toFixed(2))
|
|
88
|
+
const y = Number(((nativeEvent.offsetY * 100) / nativeEvent.srcElement.height).toFixed(2))
|
|
89
|
+
const description = `New Hotspot at ${x}% x ${y}%`
|
|
90
|
+
|
|
91
|
+
const newRow: HotspotItem = {
|
|
92
|
+
_key: randomKey(12),
|
|
93
|
+
_type: schemaType.of[0].name,
|
|
94
|
+
x,
|
|
95
|
+
y,
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (imageHotspotOptions?.descriptionPath) {
|
|
99
|
+
newRow[imageHotspotOptions.descriptionPath] = description
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
onChange(PatchEvent.from([setIfMissing([]), insert([newRow], 'after', [-1])]))
|
|
103
|
+
},
|
|
104
|
+
[imageHotspotOptions, onChange, schemaType]
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
const handleHotspotMove: FnHotspotMove = useCallback(
|
|
108
|
+
(key, x, y) => {
|
|
109
|
+
onChange(
|
|
110
|
+
PatchEvent.from([
|
|
111
|
+
// Set the `x` value of this array key item
|
|
112
|
+
set(x, [{_key: key}, 'x']),
|
|
113
|
+
// Set the `y` value of this array key item
|
|
114
|
+
set(y, [{_key: key}, 'y']),
|
|
115
|
+
])
|
|
116
|
+
)
|
|
117
|
+
},
|
|
118
|
+
[onChange]
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
const hotspotImageRef = useRef<HTMLImageElement | null>(null)
|
|
122
|
+
|
|
123
|
+
const [imageRect, setImageRect] = useState<DOMRectReadOnly>()
|
|
124
|
+
const updateImageRectCallback = useDebouncedCallback(
|
|
125
|
+
((e) => setImageRect(e.contentRect)) as IUseResizeObserverCallback,
|
|
126
|
+
[setImageRect],
|
|
127
|
+
200
|
|
128
|
+
)
|
|
129
|
+
useResizeObserver(hotspotImageRef, updateImageRectCallback)
|
|
130
|
+
|
|
131
|
+
return (
|
|
132
|
+
<Stack space={[2, 2, 3]}>
|
|
133
|
+
{displayImage?.url ? (
|
|
134
|
+
<div style={{position: `relative`}}>
|
|
135
|
+
{imageRect &&
|
|
136
|
+
(value?.length ?? 0) > 0 &&
|
|
137
|
+
value?.map((spot, index) => (
|
|
138
|
+
<Spot
|
|
139
|
+
index={index}
|
|
140
|
+
key={spot._key}
|
|
141
|
+
value={spot}
|
|
142
|
+
bounds={imageRect}
|
|
143
|
+
update={handleHotspotMove}
|
|
144
|
+
hotspotDescriptionPath={imageHotspotOptions?.descriptionPath}
|
|
145
|
+
tooltip={imageHotspotOptions?.tooltip}
|
|
146
|
+
renderPreview={renderPreview}
|
|
147
|
+
schemaType={schemaType.of[0] as ObjectSchemaType}
|
|
148
|
+
/>
|
|
149
|
+
))}
|
|
150
|
+
|
|
151
|
+
<Card __unstable_checkered shadow={1}>
|
|
152
|
+
<Flex align="center" justify="center">
|
|
153
|
+
<img
|
|
154
|
+
ref={hotspotImageRef}
|
|
155
|
+
src={displayImage.url}
|
|
156
|
+
width={displayImage.width}
|
|
157
|
+
height={displayImage.height}
|
|
158
|
+
alt=""
|
|
159
|
+
style={imageStyle}
|
|
160
|
+
onClick={handleHotspotImageClick}
|
|
161
|
+
/>
|
|
162
|
+
</Flex>
|
|
163
|
+
</Card>
|
|
164
|
+
</div>
|
|
165
|
+
) : (
|
|
166
|
+
<Feedback>
|
|
167
|
+
{imageHotspotOptions.imagePath ? (
|
|
168
|
+
<>
|
|
169
|
+
No Hotspot image found at path <code>{imageHotspotOptions.imagePath}</code>
|
|
170
|
+
</>
|
|
171
|
+
) : (
|
|
172
|
+
<>
|
|
173
|
+
Define a path in this field using to the image field in this document at{' '}
|
|
174
|
+
<code>options.hotspotImagePath</code>
|
|
175
|
+
</>
|
|
176
|
+
)}
|
|
177
|
+
</Feedback>
|
|
178
|
+
)}
|
|
179
|
+
{imageHotspotOptions.pathRoot && !VALID_ROOT_PATHS.includes(imageHotspotOptions.pathRoot) && (
|
|
180
|
+
<Feedback>
|
|
181
|
+
The supplied imageHotspotPathRoot "{imageHotspotOptions.pathRoot}" is not valid, falling
|
|
182
|
+
back to "document". Available values are "{VALID_ROOT_PATHS.join(', ')}".
|
|
183
|
+
</Feedback>
|
|
184
|
+
)}
|
|
185
|
+
{props.renderDefault(props as unknown as ArrayOfObjectsInputProps)}
|
|
186
|
+
</Stack>
|
|
187
|
+
)
|
|
188
|
+
}
|
package/src/Spot.tsx
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
1
2
|
import {Box, Text, Tooltip} from '@sanity/ui'
|
|
2
3
|
import {motion, useMotionValue} from 'framer-motion'
|
|
3
4
|
import get from 'lodash/get'
|
|
4
|
-
import React, {CSSProperties, ReactElement, useEffect} from 'react'
|
|
5
|
-
import {FnHotspotMove,
|
|
5
|
+
import React, {ComponentType, CSSProperties, ReactElement, useEffect} from 'react'
|
|
6
|
+
import {FnHotspotMove, HotspotItem} from './ImageHotspotArray'
|
|
7
|
+
import {ObjectSchemaType, RenderPreviewCallback} from 'sanity'
|
|
6
8
|
|
|
7
9
|
const dragStyle: CSSProperties = {
|
|
8
10
|
width: '1.4rem',
|
|
@@ -61,39 +63,49 @@ const labelStyleWhileActive: CSSProperties = {
|
|
|
61
63
|
visibility: 'hidden',
|
|
62
64
|
}
|
|
63
65
|
|
|
64
|
-
const round = (num) => Math.round(num * 100) / 100
|
|
66
|
+
const round = (num: number) => Math.round(num * 100) / 100
|
|
65
67
|
|
|
66
|
-
interface
|
|
67
|
-
|
|
68
|
+
export interface HotspotTooltipProps<HotspotFields = {[key: string]: unknown}> {
|
|
69
|
+
value: HotspotItem<HotspotFields>
|
|
70
|
+
schemaType: ObjectSchemaType
|
|
71
|
+
renderPreview: RenderPreviewCallback
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
interface HotspotProps<HotspotFields = {[key: string]: unknown}> {
|
|
75
|
+
value: HotspotItem
|
|
68
76
|
bounds: DOMRectReadOnly
|
|
69
77
|
update: FnHotspotMove
|
|
70
78
|
hotspotDescriptionPath?: string
|
|
71
|
-
tooltip?:
|
|
79
|
+
tooltip?: ComponentType<HotspotTooltipProps<HotspotFields>>
|
|
72
80
|
index: number
|
|
81
|
+
schemaType: ObjectSchemaType
|
|
82
|
+
renderPreview: RenderPreviewCallback
|
|
73
83
|
}
|
|
74
84
|
|
|
75
85
|
export default function Spot({
|
|
76
|
-
|
|
86
|
+
value,
|
|
77
87
|
bounds,
|
|
78
88
|
update,
|
|
79
89
|
hotspotDescriptionPath,
|
|
80
90
|
tooltip,
|
|
81
91
|
index,
|
|
82
|
-
|
|
92
|
+
schemaType,
|
|
93
|
+
renderPreview,
|
|
94
|
+
}: HotspotProps) {
|
|
83
95
|
const [isDragging, setIsDragging] = React.useState(false)
|
|
84
96
|
const [isHovering, setIsHovering] = React.useState(false)
|
|
85
97
|
|
|
86
98
|
// x/y are stored as % but need to be converted to px
|
|
87
|
-
const x = useMotionValue(round(bounds.width * (
|
|
88
|
-
const y = useMotionValue(round(bounds.height * (
|
|
99
|
+
const x = useMotionValue(round(bounds.width * (value.x / 100)))
|
|
100
|
+
const y = useMotionValue(round(bounds.height * (value.y / 100)))
|
|
89
101
|
|
|
90
102
|
/**
|
|
91
103
|
* update x/y if the bounds change when resizing the window
|
|
92
104
|
*/
|
|
93
105
|
useEffect(() => {
|
|
94
|
-
x.set(round(bounds.width * (
|
|
95
|
-
y.set(round(bounds.height * (
|
|
96
|
-
}, [bounds])
|
|
106
|
+
x.set(round(bounds.width * (value.x / 100)))
|
|
107
|
+
y.set(round(bounds.height * (value.y / 100)))
|
|
108
|
+
}, [x, y, value, bounds])
|
|
97
109
|
|
|
98
110
|
const handleDragEnd = React.useCallback(() => {
|
|
99
111
|
setIsDragging(false)
|
|
@@ -110,8 +122,8 @@ export default function Spot({
|
|
|
110
122
|
const safeX = Math.max(0, Math.min(100, newX))
|
|
111
123
|
const safeY = Math.max(0, Math.min(100, newY))
|
|
112
124
|
|
|
113
|
-
update(
|
|
114
|
-
}, [
|
|
125
|
+
update(value._key, safeX, safeY)
|
|
126
|
+
}, [x, y, value, update, bounds])
|
|
115
127
|
const handleDragStart = React.useCallback(() => setIsDragging(true), [])
|
|
116
128
|
|
|
117
129
|
const handleHoverStart = React.useCallback(() => setIsHovering(true), [])
|
|
@@ -123,18 +135,18 @@ export default function Spot({
|
|
|
123
135
|
|
|
124
136
|
return (
|
|
125
137
|
<Tooltip
|
|
126
|
-
key={
|
|
138
|
+
key={value._key}
|
|
127
139
|
disabled={isDragging}
|
|
128
140
|
portal
|
|
129
141
|
content={
|
|
130
142
|
tooltip && typeof tooltip === 'function' ? (
|
|
131
|
-
React.createElement(tooltip, {
|
|
143
|
+
React.createElement(tooltip, {value, renderPreview, schemaType})
|
|
132
144
|
) : (
|
|
133
145
|
<Box padding={2} style={{maxWidth: 200, pointerEvents: `none`}}>
|
|
134
146
|
<Text textOverflow="ellipsis">
|
|
135
147
|
{hotspotDescriptionPath
|
|
136
|
-
? (get(
|
|
137
|
-
: `${
|
|
148
|
+
? (get(value, hotspotDescriptionPath) as string)
|
|
149
|
+
: `${value.x}% x ${value.y}%`}
|
|
138
150
|
</Text>
|
|
139
151
|
</Box>
|
|
140
152
|
)
|
package/src/index.ts
ADDED
package/src/plugin.tsx
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import {ImageHotspotArray, type HotspotItem} from './ImageHotspotArray'
|
|
2
|
+
import React, {ComponentType} from 'react'
|
|
3
|
+
import {ArrayOfObjectsInputProps, definePlugin} from 'sanity'
|
|
4
|
+
import {type HotspotTooltipProps} from './Spot'
|
|
5
|
+
|
|
6
|
+
export interface ImageHotspotOptions<HotspotFields = {[key: string]: unknown}> {
|
|
7
|
+
pathRoot?: 'document' | 'parent'
|
|
8
|
+
imagePath: string
|
|
9
|
+
descriptionPath?: string
|
|
10
|
+
tooltip?: ComponentType<HotspotTooltipProps<HotspotFields>>
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
declare module '@sanity/types' {
|
|
14
|
+
export interface ArrayOptions {
|
|
15
|
+
imageHotspot?: ImageHotspotOptions
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const imageHotspotArrayPlugin = definePlugin({
|
|
20
|
+
name: 'image-hotspot-array',
|
|
21
|
+
form: {
|
|
22
|
+
components: {
|
|
23
|
+
input: (props) => {
|
|
24
|
+
if (props.schemaType.jsonType === 'array' && props.schemaType.options?.imageHotspot) {
|
|
25
|
+
const imageHotspotOptions = props.schemaType.options?.imageHotspot
|
|
26
|
+
if (imageHotspotOptions) {
|
|
27
|
+
return (
|
|
28
|
+
<ImageHotspotArray
|
|
29
|
+
{...(props as unknown as ArrayOfObjectsInputProps<HotspotItem>)}
|
|
30
|
+
imageHotspotOptions={imageHotspotOptions}
|
|
31
|
+
/>
|
|
32
|
+
)
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return props.renderDefault(props)
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
})
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const {showIncompatiblePluginDialog} = require('@sanity/incompatible-plugin')
|
|
2
|
+
const {name, version, sanityExchangeUrl} = require('./package.json')
|
|
3
|
+
|
|
4
|
+
export default showIncompatiblePluginDialog({
|
|
5
|
+
name: name,
|
|
6
|
+
versions: {
|
|
7
|
+
v3: version,
|
|
8
|
+
v2: '^0.0.10',
|
|
9
|
+
},
|
|
10
|
+
sanityExchangeUrl,
|
|
11
|
+
})
|
package/.babelrc
DELETED
package/.releaserc.json
DELETED
|
Binary file
|
package/CHANGELOG.md
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
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/lib/Feedback.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
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
|
package/lib/Feedback.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
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"}
|
package/lib/HotspotArray.js
DELETED
|
@@ -1,150 +0,0 @@
|
|
|
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
|
package/lib/HotspotArray.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
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":"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"}
|
package/lib/NestedFormBuilder.js
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
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
|
|
@@ -1 +0,0 @@
|
|
|
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"}
|