1- import { defineField , PortableTextBlock , Role , Rule , set , StringInputProps , useCurrentUser } from 'sanity'
2- import { configureBlockContent } from '../../editors'
1+ import { Card , Flex , Radio , Text } from '@sanity/ui'
2+ import { useCallback } from 'react'
3+ import { HiOutlineInformationCircle } from 'react-icons/hi2'
4+ import { type PortableTextBlock , type Role , type Rule , type StringInputProps , set , useCurrentUser } from 'sanity'
35import CompactBlockEditor from '../../components/CompactBlockEditor'
4- import { useCallback , useState } from 'react '
5- import { Badge , Card , Flex , Grid , Radio , Stack , Text } from '@sanity/ui '
6+ import { configureBlockContent } from '../../editors '
7+ import { backgroundPosition } from '../commonFields/commonFields '
68
79const titleContentType = configureBlockContent ( {
810 h2 : false ,
@@ -27,66 +29,45 @@ type ImageVariantInputProps = {
2729export const ImageVariantInput = ( props : ImageVariantInputProps ) => {
2830 const { onChange, schemaType, value = '' } = props
2931
30- const user = useCurrentUser ( )
31- const [ error , setError ] = useState ( false )
32+ //get the role of the current user
33+ //@ts -ignore CurrentUser has roles in types...
34+ const { roles } = useCurrentUser ( )
35+
36+ const options = schemaType ?. options ?. list ?. filter ( ( option : any ) => {
37+ return option . value === 'backgroundImage'
38+ ? roles . some ( ( userRole : Role ) => userRole . name === 'designer' || userRole . name === 'developer' )
39+ : true
40+ } )
3241
3342 const handleChange = useCallback (
3443 ( event : any ) => {
3544 const nextValue = event . currentTarget . value
36- if ( nextValue === 'backgroundImage' ) {
37- const isDesigner = user && user . roles . some ( ( userRole : Role ) => userRole . name === 'designer' )
38- if ( isDesigner ) {
39- onChange ( set ( nextValue ) )
40- } else {
41- setError ( true )
42- }
43- } else if ( nextValue === 'sideImage' ) {
44- if ( error ) {
45- setError ( false )
46- }
47- onChange ( set ( nextValue ) )
48- }
45+ onChange ( set ( nextValue ) )
4946 } ,
50- [ onChange , user , error ] ,
47+ [ onChange ] ,
5148 )
5249
5350 return (
54- < Stack space = { 3 } >
55- < Grid columns = { schemaType ?. options ?. list ?. length } rows = { 1 } gap = { 2 } >
56- { schemaType ?. options ?. list ?. map ( ( option : any ) => {
57- return (
58- < Card key = { option . value } paddingY = { 2 } paddingX = { 3 } radius = { 2 } shadow = { 1 } >
59- < Flex direction = "row" align = "flex-start" gap = { 2 } >
60- < Radio
61- checked = { value === option . value }
62- name = { option . value }
63- id = { option . value }
64- onChange = { handleChange }
65- value = { option . value }
66- />
67- < Flex direction = "column" align = { 'flex-start' } gap = { 2 } >
68- < Text as = "label" htmlFor = { option . value } >
69- { option . title }
70- </ Text >
71- { option ?. description && (
72- < Badge tone = "primary" fontSize = { 1 } >
73- { option ?. description }
74- </ Badge >
75- ) }
76- </ Flex >
77- </ Flex >
78- </ Card >
79- )
80- } ) }
81- </ Grid >
82- { error && (
83- < Card padding = { [ 2 ] } radius = { 2 } shadow = { 1 } tone = "caution" >
84- < Text align = "center" size = { [ 1 ] } >
85- Cannot perform change, missing designer role!
86- </ Text >
87- </ Card >
88- ) }
89- </ Stack >
51+ < Flex gap = { 2 } >
52+ { options ?. map ( ( option : any ) => {
53+ return (
54+ < Card key = { option . value } paddingY = { 2 } paddingX = { 3 } radius = { 2 } >
55+ < Flex direction = "row" align = "center" gap = { 2 } >
56+ < Radio
57+ checked = { value === option . value }
58+ name = { option . value }
59+ id = { option . value }
60+ onChange = { handleChange }
61+ value = { option . value }
62+ />
63+ < Text as = "label" htmlFor = { option . value } >
64+ { option . title }
65+ </ Text >
66+ </ Flex >
67+ </ Card >
68+ )
69+ } ) }
70+ </ Flex >
9071 )
9172}
9273
@@ -95,32 +76,36 @@ export default {
9576 type : 'object' ,
9677 name : 'tabsInfoPanel' ,
9778 fields : [
98- defineField ( {
99- name : 'image' ,
100- title : 'image' ,
101- type : 'image' ,
102- options : {
103- hotspot : true ,
104- } ,
105- } ) ,
106- defineField ( {
79+ {
10780 name : 'imageVariant' ,
10881 title : 'Select image variant' ,
109- description : 'Use same image variant for all information panels.' ,
11082 type : 'string' ,
11183 options : {
11284 list : [
113- { title : 'Background image' , description : 'Designer only' , value : 'backgroundImage' } ,
85+ {
86+ title : 'Background image' ,
87+ value : 'backgroundImage' ,
88+ } ,
11489 { title : 'Side image' , value : 'sideImage' } ,
90+ { title : 'Banner image' , value : 'bannerImage' } ,
11591 ] ,
11692 layout : 'radio' ,
11793 } ,
11894 initialValue : 'sideImage' ,
11995 components : {
12096 input : ImageVariantInput ,
12197 } ,
122- } ) ,
123- defineField ( {
98+ } ,
99+ {
100+ name : 'image' ,
101+ title : 'Image' ,
102+ type : 'image' ,
103+ options : {
104+ hotspot : true ,
105+ } ,
106+ } ,
107+ backgroundPosition ( ) ,
108+ {
124109 name : 'title' ,
125110 type : 'array' ,
126111 components : {
@@ -129,14 +114,14 @@ export default {
129114 of : [ titleContentType ] ,
130115 validation : ( Rule : Rule ) =>
131116 Rule . custom ( ( value : PortableTextBlock [ ] ) => ( ! value ? 'A title is recommended' : true ) ) . warning ( ) ,
132- } ) ,
133- defineField ( {
117+ } ,
118+ {
134119 name : 'text' ,
135- title : 'Text content ' ,
120+ title : 'Content ' ,
136121 type : 'array' ,
137122 of : [ blockContentType ] ,
138- } ) ,
139- defineField ( {
123+ } ,
124+ {
140125 name : 'action' ,
141126 type : 'array' ,
142127 title : 'CTA' ,
@@ -145,8 +130,16 @@ export default {
145130 { type : 'downloadableImage' , title : 'Call to action: Download image' } ,
146131 { type : 'downloadableFile' , title : 'Call to action: Download file' } ,
147132 ] ,
148- } ) ,
149- defineField ( {
133+ validation : ( Rule : Rule ) => Rule . max ( 1 ) . error ( 'Only 1' ) ,
134+ } ,
135+ {
136+ name : 'keyInfoTitle' ,
137+ title : 'Key figures title' ,
138+ description :
139+ 'Used for context for screen readers.Not visible and optional, but if empty then textsnippet for Key figures will be used' ,
140+ type : 'string' ,
141+ } ,
142+ {
150143 type : 'array' ,
151144 name : 'keyInfo' ,
152145 description : 'Up to 4 key information bits' ,
@@ -164,7 +157,7 @@ export default {
164157 } ,
165158 {
166159 name : 'keyFigure' ,
167- title : 'Key figure highlighted ' ,
160+ title : 'Key figure' ,
168161 type : 'string' ,
169162 } ,
170163 {
@@ -173,9 +166,24 @@ export default {
173166 type : 'text' ,
174167 } ,
175168 ] ,
169+ preview : {
170+ select : {
171+ title : 'title' ,
172+ keyFigure : 'keyFigure' ,
173+ explanation : 'explanation' ,
174+ } ,
175+ prepare ( selection : Record < string , string | number > ) {
176+ const { title, keyFigure, explanation } = selection
177+ return {
178+ title : `${ title ?? '' } ${ keyFigure ?? '' } ` ,
179+ subtitle : `${ explanation ?? '' } ` ,
180+ media : HiOutlineInformationCircle ,
181+ }
182+ } ,
183+ } ,
176184 } ,
177185 ] . filter ( ( e ) => e ) ,
178186 validation : ( Rule : Rule ) => Rule . max ( 4 ) ,
179- } ) ,
187+ } ,
180188 ] ,
181189}
0 commit comments