@elementor/editor-controls 0.13.0 → 0.15.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.
@@ -1,117 +1,169 @@
1
1
  import * as React from 'react';
2
2
  import { dimensionsPropTypeUtil, type PropKey, sizePropTypeUtil } from '@elementor/editor-props';
3
3
  import { DetachIcon, LinkIcon, SideBottomIcon, SideLeftIcon, SideRightIcon, SideTopIcon } from '@elementor/icons';
4
- import { Grid, Stack, ToggleButton } from '@elementor/ui';
4
+ import { Grid, Stack, ToggleButton, Tooltip } from '@elementor/ui';
5
5
  import { __ } from '@wordpress/i18n';
6
6
 
7
7
  import { PropKeyProvider, PropProvider, useBoundProp } from '../bound-prop-context';
8
8
  import { ControlLabel } from '../components/control-label';
9
9
  import { createControl } from '../create-control';
10
- import { SizeControl } from './size-control';
10
+ import { type ExtendedValue, SizeControl } from './size-control';
11
11
 
12
- export const LinkedDimensionsControl = createControl( ( { label }: { label: string } ) => {
13
- const { value: dimensionsValue, setValue: setDimensionsValue, propType } = useBoundProp( dimensionsPropTypeUtil );
14
- const { value: sizeValue, setValue: setSizeValue } = useBoundProp( sizePropTypeUtil );
12
+ export const LinkedDimensionsControl = createControl(
13
+ ( {
14
+ label,
15
+ isSiteRtl = false,
16
+ extendedValues,
17
+ }: {
18
+ label: string;
19
+ isSiteRtl?: boolean;
20
+ extendedValues?: ExtendedValue[];
21
+ } ) => {
22
+ const {
23
+ value: dimensionsValue,
24
+ setValue: setDimensionsValue,
25
+ propType,
26
+ } = useBoundProp( dimensionsPropTypeUtil );
27
+ const { value: sizeValue, setValue: setSizeValue } = useBoundProp( sizePropTypeUtil );
15
28
 
16
- const isLinked = ! dimensionsValue && ! sizeValue ? true : !! sizeValue;
29
+ const isLinked = ! dimensionsValue && ! sizeValue ? true : !! sizeValue;
17
30
 
18
- const onLinkToggle = () => {
19
- if ( ! isLinked ) {
20
- setSizeValue( dimensionsValue?.top?.value );
21
- return;
22
- }
31
+ const onLinkToggle = () => {
32
+ if ( ! isLinked ) {
33
+ setSizeValue( dimensionsValue[ 'block-start' ]?.value );
34
+ return;
35
+ }
23
36
 
24
- const value = sizeValue ? sizePropTypeUtil.create( sizeValue ) : null;
37
+ const value = sizeValue ? sizePropTypeUtil.create( sizeValue ) : null;
25
38
 
26
- setDimensionsValue( {
27
- top: value,
28
- right: value,
29
- bottom: value,
30
- left: value,
31
- } );
32
- };
39
+ setDimensionsValue( {
40
+ 'block-start': value,
41
+ 'block-end': value,
42
+ 'inline-start': value,
43
+ 'inline-end': value,
44
+ } );
45
+ };
33
46
 
34
- const LinkedIcon = isLinked ? LinkIcon : DetachIcon;
47
+ const tooltipLabel = label.toLowerCase();
35
48
 
36
- return (
37
- <PropProvider propType={ propType } value={ dimensionsValue } setValue={ setDimensionsValue }>
38
- <Stack direction="row" gap={ 2 } flexWrap="nowrap">
39
- <ControlLabel>{ label }</ControlLabel>
40
- <ToggleButton
41
- aria-label={ __( 'Link inputs', 'elementor' ) }
42
- size={ 'tiny' }
43
- value={ 'check' }
44
- selected={ isLinked }
45
- sx={ { marginLeft: 'auto' } }
46
- onChange={ onLinkToggle }
47
- >
48
- <LinkedIcon fontSize={ 'tiny' } />
49
- </ToggleButton>
50
- </Stack>
51
- <Stack direction="row" gap={ 2 } flexWrap="nowrap">
52
- <Grid container gap={ 1 } alignItems="center">
53
- <Grid item xs={ 12 }>
54
- <ControlLabel>{ __( 'Top', 'elementor' ) }</ControlLabel>
55
- </Grid>
56
- <Grid item xs={ 12 }>
57
- <Control
58
- bind={ 'top' }
59
- startIcon={ <SideTopIcon fontSize={ 'tiny' } /> }
60
- isLinked={ isLinked }
61
- />
62
- </Grid>
63
- </Grid>
64
- <Grid container gap={ 1 } alignItems="center">
65
- <Grid item xs={ 12 }>
66
- <ControlLabel>{ __( 'Right', 'elementor' ) }</ControlLabel>
67
- </Grid>
68
- <Grid item xs={ 12 }>
69
- <Control
70
- bind={ 'right' }
71
- startIcon={ <SideRightIcon fontSize={ 'tiny' } /> }
72
- isLinked={ isLinked }
73
- />
74
- </Grid>
75
- </Grid>
76
- </Stack>
77
- <Stack direction="row" gap={ 2 } flexWrap="nowrap">
78
- <Grid container gap={ 1 } alignItems="center">
79
- <Grid item xs={ 12 }>
80
- <ControlLabel>{ __( 'Bottom', 'elementor' ) }</ControlLabel>
49
+ const LinkedIcon = isLinked ? LinkIcon : DetachIcon;
50
+ // translators: %s: Tooltip title.
51
+ const linkedLabel = __( 'Link %s', 'elementor' ).replace( '%s', tooltipLabel );
52
+ // translators: %s: Tooltip title.
53
+ const unlinkedLabel = __( 'Unlink %s', 'elementor' ).replace( '%s', tooltipLabel );
54
+
55
+ return (
56
+ <PropProvider propType={ propType } value={ dimensionsValue } setValue={ setDimensionsValue }>
57
+ <Stack direction="row" gap={ 2 } flexWrap="nowrap">
58
+ <ControlLabel>{ label }</ControlLabel>
59
+ <Tooltip title={ isLinked ? unlinkedLabel : linkedLabel } placement="top">
60
+ <ToggleButton
61
+ aria-label={ isLinked ? unlinkedLabel : linkedLabel }
62
+ size={ 'tiny' }
63
+ value={ 'check' }
64
+ selected={ isLinked }
65
+ sx={ { marginLeft: 'auto' } }
66
+ onChange={ onLinkToggle }
67
+ >
68
+ <LinkedIcon fontSize={ 'tiny' } />
69
+ </ToggleButton>
70
+ </Tooltip>
71
+ </Stack>
72
+ <Stack direction="row" gap={ 2 } flexWrap="nowrap">
73
+ <Grid container gap={ 1 } alignItems="center">
74
+ <Grid item xs={ 12 }>
75
+ <ControlLabel>{ __( 'Top', 'elementor' ) }</ControlLabel>
76
+ </Grid>
77
+ <Grid item xs={ 12 }>
78
+ <Control
79
+ bind={ 'block-start' }
80
+ startIcon={ <SideTopIcon fontSize={ 'tiny' } /> }
81
+ isLinked={ isLinked }
82
+ extendedValues={ extendedValues }
83
+ />
84
+ </Grid>
81
85
  </Grid>
82
- <Grid item xs={ 12 }>
83
- <Control
84
- bind={ 'bottom' }
85
- startIcon={ <SideBottomIcon fontSize={ 'tiny' } /> }
86
- isLinked={ isLinked }
87
- />
86
+ <Grid container gap={ 1 } alignItems="center">
87
+ <Grid item xs={ 12 }>
88
+ <ControlLabel>
89
+ { isSiteRtl ? __( 'Left', 'elementor' ) : __( 'Right', 'elementor' ) }
90
+ </ControlLabel>
91
+ </Grid>
92
+ <Grid item xs={ 12 }>
93
+ <Control
94
+ bind={ 'inline-end' }
95
+ startIcon={
96
+ isSiteRtl ? (
97
+ <SideLeftIcon fontSize={ 'tiny' } />
98
+ ) : (
99
+ <SideRightIcon fontSize={ 'tiny' } />
100
+ )
101
+ }
102
+ isLinked={ isLinked }
103
+ extendedValues={ extendedValues }
104
+ />
105
+ </Grid>
88
106
  </Grid>
89
- </Grid>
90
- <Grid container gap={ 1 } alignItems="center">
91
- <Grid item xs={ 12 }>
92
- <ControlLabel>{ __( 'Left', 'elementor' ) }</ControlLabel>
107
+ </Stack>
108
+ <Stack direction="row" gap={ 2 } flexWrap="nowrap">
109
+ <Grid container gap={ 1 } alignItems="center">
110
+ <Grid item xs={ 12 }>
111
+ <ControlLabel>{ __( 'Bottom', 'elementor' ) }</ControlLabel>
112
+ </Grid>
113
+ <Grid item xs={ 12 }>
114
+ <Control
115
+ bind={ 'block-end' }
116
+ startIcon={ <SideBottomIcon fontSize={ 'tiny' } /> }
117
+ isLinked={ isLinked }
118
+ extendedValues={ extendedValues }
119
+ />
120
+ </Grid>
93
121
  </Grid>
94
- <Grid item xs={ 12 }>
95
- <Control
96
- bind={ 'left' }
97
- startIcon={ <SideLeftIcon fontSize={ 'tiny' } /> }
98
- isLinked={ isLinked }
99
- />
122
+ <Grid container gap={ 1 } alignItems="center">
123
+ <Grid item xs={ 12 }>
124
+ <ControlLabel>
125
+ { isSiteRtl ? __( 'Right', 'elementor' ) : __( 'Left', 'elementor' ) }
126
+ </ControlLabel>
127
+ </Grid>
128
+ <Grid item xs={ 12 }>
129
+ <Control
130
+ bind={ 'inline-start' }
131
+ startIcon={
132
+ isSiteRtl ? (
133
+ <SideRightIcon fontSize={ 'tiny' } />
134
+ ) : (
135
+ <SideLeftIcon fontSize={ 'tiny' } />
136
+ )
137
+ }
138
+ isLinked={ isLinked }
139
+ extendedValues={ extendedValues }
140
+ />
141
+ </Grid>
100
142
  </Grid>
101
- </Grid>
102
- </Stack>
103
- </PropProvider>
104
- );
105
- } );
143
+ </Stack>
144
+ </PropProvider>
145
+ );
146
+ }
147
+ );
106
148
 
107
- const Control = ( { bind, startIcon, isLinked }: { bind: PropKey; startIcon: React.ReactNode; isLinked: boolean } ) => {
149
+ const Control = ( {
150
+ bind,
151
+ startIcon,
152
+ isLinked,
153
+ extendedValues,
154
+ }: {
155
+ bind: PropKey;
156
+ startIcon: React.ReactNode;
157
+ isLinked: boolean;
158
+ extendedValues?: ExtendedValue[];
159
+ } ) => {
108
160
  if ( isLinked ) {
109
- return <SizeControl startIcon={ startIcon } />;
161
+ return <SizeControl startIcon={ startIcon } extendedValues={ extendedValues } />;
110
162
  }
111
163
 
112
164
  return (
113
165
  <PropKeyProvider bind={ bind }>
114
- <SizeControl startIcon={ startIcon } />
166
+ <SizeControl startIcon={ startIcon } extendedValues={ extendedValues } />
115
167
  </PropKeyProvider>
116
168
  );
117
169
  };
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { sizePropTypeUtil } from '@elementor/editor-props';
2
+ import { sizePropTypeUtil, stringPropTypeUtil } from '@elementor/editor-props';
3
3
  import { InputAdornment } from '@elementor/ui';
4
4
 
5
5
  import { useBoundProp } from '../bound-prop-context';
@@ -8,6 +8,7 @@ import ControlActions from '../control-actions/control-actions';
8
8
  import { createControl } from '../create-control';
9
9
  import { useSyncExternalState } from '../hooks/use-sync-external-state';
10
10
 
11
+ export type ExtendedValue = 'auto';
11
12
  export type Unit = 'px' | '%' | 'em' | 'rem' | 'vw' | 'vh';
12
13
 
13
14
  const defaultUnits: Unit[] = [ 'px', '%', 'em', 'rem', 'vw', 'vh' ];
@@ -19,34 +20,98 @@ type SizeControlProps = {
19
20
  placeholder?: string;
20
21
  startIcon?: React.ReactNode;
21
22
  units?: Unit[];
23
+ extendedValues?: ExtendedValue[];
22
24
  };
23
25
 
24
- export const SizeControl = createControl( ( { units = defaultUnits, placeholder, startIcon }: SizeControlProps ) => {
25
- const { value, setValue } = useBoundProp( sizePropTypeUtil );
26
-
27
- const [ state, setState ] = useSyncExternalState( {
28
- external: value,
29
- setExternal: setValue,
30
- persistWhen: ( controlValue ) => !! controlValue?.size || controlValue?.size === 0,
31
- fallback: ( controlValue ) => ( { unit: controlValue?.unit || defaultUnit, size: defaultSize } ),
32
- } );
33
-
34
- const handleUnitChange = ( unit: Unit ) => {
35
- setState( ( prev ) => ( {
36
- size: prev?.size ?? defaultSize,
37
- unit,
38
- } ) );
39
- };
26
+ export const SizeControl = createControl(
27
+ ( { units = defaultUnits, extendedValues = [], placeholder, startIcon }: SizeControlProps ) => {
28
+ const { value: sizeValue, setValue: setSizeValue } = useBoundProp( sizePropTypeUtil );
29
+
30
+ const [ state, setState ] = useSyncExternalState( {
31
+ external: sizeValue,
32
+ setExternal: setSizeValue,
33
+ persistWhen: ( controlValue ) => !! controlValue?.size || controlValue?.size === 0,
34
+ fallback: ( controlValue ) => ( { unit: controlValue?.unit || defaultUnit, size: defaultSize } ),
35
+ } );
36
+
37
+ const handleUnitChange = ( unit: Unit ) => {
38
+ setState( ( prev ) => ( {
39
+ size: prev?.size ?? defaultSize,
40
+ unit,
41
+ } ) );
42
+ };
43
+
44
+ const handleSizeChange = ( event: React.ChangeEvent< HTMLInputElement > ) => {
45
+ const { value: size } = event.target;
46
+
47
+ setState( ( prev ) => ( {
48
+ ...prev,
49
+ size: size || size === '0' ? parseFloat( size ) : defaultSize,
50
+ } ) );
51
+ };
40
52
 
41
- const handleSizeChange = ( event: React.ChangeEvent< HTMLInputElement > ) => {
42
- const { value: size } = event.target;
53
+ const inputProps = {
54
+ size: state.size,
55
+ unit: state.unit,
56
+ placeholder,
57
+ startIcon,
58
+ units,
59
+ extendedValues,
60
+ handleSizeChange,
61
+ handleUnitChange,
62
+ };
43
63
 
44
- setState( ( prev ) => ( {
45
- ...prev,
46
- size: size || size === '0' ? parseFloat( size ) : defaultSize,
47
- } ) );
64
+ if ( extendedValues?.length ) {
65
+ return <ExtendedSizeInput { ...inputProps } />;
66
+ }
67
+ return <SizeInput { ...inputProps } />;
68
+ }
69
+ );
70
+
71
+ const ExtendedSizeInput = ( props: SizeInputProps ) => {
72
+ const { value: stringValue, setValue: setStringValue } = useBoundProp( stringPropTypeUtil );
73
+ const { extendedValues = [] } = props;
74
+
75
+ const unit = ( stringValue ?? props.unit ) as Unit;
76
+
77
+ const handleUnitChange = ( newUnit: Unit ) => {
78
+ if ( extendedValues.includes( newUnit as ExtendedValue ) ) {
79
+ setStringValue( newUnit );
80
+ } else {
81
+ props.handleUnitChange( newUnit );
82
+ }
48
83
  };
49
84
 
85
+ return (
86
+ <SizeInput
87
+ { ...props }
88
+ units={ [ ...props.units, ...( extendedValues as unknown as Unit[] ) ] }
89
+ handleUnitChange={ handleUnitChange }
90
+ unit={ unit }
91
+ />
92
+ );
93
+ };
94
+
95
+ type SizeInputProps = {
96
+ unit: Unit;
97
+ size: number;
98
+ placeholder?: string;
99
+ startIcon?: React.ReactNode;
100
+ units: Unit[];
101
+ extendedValues?: ExtendedValue[];
102
+ handleUnitChange: ( unit: Unit ) => void;
103
+ handleSizeChange: ( event: React.ChangeEvent< HTMLInputElement > ) => void;
104
+ };
105
+
106
+ const SizeInput = ( {
107
+ units,
108
+ handleUnitChange,
109
+ handleSizeChange,
110
+ placeholder,
111
+ startIcon,
112
+ size,
113
+ unit,
114
+ }: SizeInputProps ) => {
50
115
  return (
51
116
  <ControlActions>
52
117
  <TextFieldInnerSelection
@@ -54,7 +119,7 @@ export const SizeControl = createControl( ( { units = defaultUnits, placeholder,
54
119
  <SelectionEndAdornment
55
120
  options={ units }
56
121
  onClick={ handleUnitChange }
57
- value={ state?.unit ?? defaultUnit }
122
+ value={ unit ?? defaultUnit }
58
123
  />
59
124
  }
60
125
  placeholder={ placeholder }
@@ -62,9 +127,9 @@ export const SizeControl = createControl( ( { units = defaultUnits, placeholder,
62
127
  startIcon ? <InputAdornment position="start">{ startIcon }</InputAdornment> : undefined
63
128
  }
64
129
  type="number"
65
- value={ Number.isNaN( state?.size ) ? '' : state?.size }
130
+ value={ Number.isNaN( size ) ? '' : size }
66
131
  onChange={ handleSizeChange }
67
132
  />
68
133
  </ControlActions>
69
134
  );
70
- } );
135
+ };
@@ -2,13 +2,14 @@ import * as React from 'react';
2
2
  import { imageSrcPropTypeUtil } from '@elementor/editor-props';
3
3
  import { UploadIcon } from '@elementor/icons';
4
4
  import { Button, Card, CardMedia, CardOverlay, CircularProgress, Stack, styled } from '@elementor/ui';
5
- import { useWpMediaAttachment, useWpMediaFrame } from '@elementor/wp-media';
5
+ import { type OpenOptions, useWpMediaAttachment, useWpMediaFrame } from '@elementor/wp-media';
6
6
  import { __ } from '@wordpress/i18n';
7
7
 
8
8
  import { useBoundProp } from '../bound-prop-context';
9
9
  import { ControlLabel } from '../components/control-label';
10
10
  import ControlActions from '../control-actions/control-actions';
11
11
  import { createControl } from '../create-control';
12
+ import { useUnfilteredFilesUpload } from '../hooks/use-unfiltered-files-upload';
12
13
 
13
14
  const TILE_SIZE = 8;
14
15
  const TILE_WHITE = 'transparent';
@@ -40,9 +41,10 @@ export const SvgMediaControl = createControl( () => {
40
41
  const { id, url } = value ?? {};
41
42
  const { data: attachment, isFetching } = useWpMediaAttachment( id?.value || null );
42
43
  const src = attachment?.url ?? url?.value ?? null;
44
+ const { data: allowSvgUpload } = useUnfilteredFilesUpload();
45
+
43
46
  const { open } = useWpMediaFrame( {
44
- types: [ 'image/svg+xml' ],
45
- allowedExtensions: [ 'svg' ],
47
+ mediaTypes: [ 'svg' ],
46
48
  multiple: false,
47
49
  selected: id?.value || null,
48
50
  onSelect: ( selectedAttachment ) => {
@@ -56,9 +58,17 @@ export const SvgMediaControl = createControl( () => {
56
58
  },
57
59
  } );
58
60
 
61
+ const handleClick = ( openOptions?: OpenOptions ) => {
62
+ if ( allowSvgUpload ) {
63
+ open( openOptions );
64
+ } else {
65
+ // TODO open upload SVG confirmation modal
66
+ }
67
+ };
68
+
59
69
  return (
60
70
  <Stack gap={ 1 }>
61
- <ControlLabel> { __( 'Choose SVG', 'elementor' ) } </ControlLabel>
71
+ <ControlLabel> { __( 'SVG', 'elementor' ) } </ControlLabel>
62
72
  <ControlActions>
63
73
  <StyledCard variant="outlined">
64
74
  <StyledCardMediaContainer>
@@ -85,7 +95,7 @@ export const SvgMediaControl = createControl( () => {
85
95
  size="tiny"
86
96
  color="inherit"
87
97
  variant="outlined"
88
- onClick={ () => open( { mode: 'browse' } ) }
98
+ onClick={ () => handleClick( { mode: 'browse' } ) }
89
99
  >
90
100
  { __( 'Select SVG', 'elementor' ) }
91
101
  </Button>
@@ -94,9 +104,9 @@ export const SvgMediaControl = createControl( () => {
94
104
  variant="text"
95
105
  color="inherit"
96
106
  startIcon={ <UploadIcon /> }
97
- onClick={ () => open( { mode: 'upload' } ) }
107
+ onClick={ () => handleClick( { mode: 'upload' } ) }
98
108
  >
99
- { __( 'Upload SVG', 'elementor' ) }
109
+ { __( 'Upload', 'elementor' ) }
100
110
  </Button>
101
111
  </Stack>
102
112
  </CardOverlay>
@@ -1,37 +1,24 @@
1
- import { __ } from '@wordpress/i18n';
2
-
3
- export type SupportedFonts = 'system' | 'googlefonts' | 'customfonts';
4
-
5
- const supportedCategories: Record< SupportedFonts, string > = {
6
- system: __( 'System', 'elementor' ),
7
- googlefonts: __( 'Google Fonts', 'elementor' ),
8
- customfonts: __( 'Custom Fonts', 'elementor' ),
1
+ export type FontListItem = {
2
+ type: 'font' | 'category';
3
+ value: string;
9
4
  };
10
5
 
11
- export const useFilteredFontFamilies = ( fontFamilies: Record< string, SupportedFonts >, searchValue: string ) => {
12
- const filteredFontFamilies = Object.entries( fontFamilies ).reduce< Map< string, string[] > >(
13
- ( acc, [ font, category ] ) => {
14
- const isMatch = font.toLowerCase().includes( searchValue.trim().toLowerCase() );
15
-
16
- if ( ! isMatch ) {
17
- return acc;
18
- }
19
-
20
- const categoryLabel = supportedCategories[ category as SupportedFonts ];
6
+ export const useFilteredFontFamilies = ( fontFamilies: Record< string, string[] >, searchValue: string ) => {
7
+ const filteredFontFamilies = Object.entries( fontFamilies ).reduce< FontListItem[] >(
8
+ ( acc, [ category, fonts ] ) => {
9
+ const filteredFonts = fonts.filter( ( font ) => font.toLowerCase().includes( searchValue.toLowerCase() ) );
21
10
 
22
- if ( categoryLabel ) {
23
- const existingCategory = acc.get( categoryLabel );
11
+ if ( filteredFonts.length ) {
12
+ acc.push( { type: 'category', value: category } );
24
13
 
25
- if ( existingCategory ) {
26
- existingCategory.push( font );
27
- } else {
28
- acc.set( categoryLabel, [ font ] );
29
- }
14
+ filteredFonts.forEach( ( font ) => {
15
+ acc.push( { type: 'font', value: font } );
16
+ } );
30
17
  }
31
18
 
32
19
  return acc;
33
20
  },
34
- new Map()
21
+ []
35
22
  );
36
23
 
37
24
  return [ ...filteredFontFamilies ];
@@ -0,0 +1,40 @@
1
+ import { useMutation, useQuery, useQueryClient } from '@elementor/query';
2
+
3
+ import { apiClient } from '../api';
4
+
5
+ export const UNFILTERED_FILES_UPLOAD_KEY = 'elementor_unfiltered_files_upload';
6
+
7
+ const unfilteredFilesQueryKey = {
8
+ queryKey: [ UNFILTERED_FILES_UPLOAD_KEY ],
9
+ };
10
+
11
+ type Value = '0' | '1';
12
+
13
+ export const useUnfilteredFilesUpload = () =>
14
+ useQuery( {
15
+ ...unfilteredFilesQueryKey,
16
+ queryFn: (): Promise< boolean > =>
17
+ apiClient.getElementorSetting< Value >( UNFILTERED_FILES_UPLOAD_KEY ).then( ( res ) => {
18
+ return formatResponse( res );
19
+ } ),
20
+ staleTime: Infinity,
21
+ } );
22
+
23
+ export function useUpdateUnfilteredFilesUpload() {
24
+ const queryClient = useQueryClient();
25
+
26
+ const mutate = useMutation( {
27
+ mutationFn: ( { allowUnfilteredFilesUpload }: { allowUnfilteredFilesUpload: boolean } ) =>
28
+ apiClient.updateElementorSetting< Value >(
29
+ UNFILTERED_FILES_UPLOAD_KEY,
30
+ allowUnfilteredFilesUpload ? '1' : '0'
31
+ ),
32
+ onSuccess: () => queryClient.invalidateQueries( unfilteredFilesQueryKey ),
33
+ } );
34
+
35
+ return mutate;
36
+ }
37
+
38
+ const formatResponse = ( response: Value ): boolean => {
39
+ return Boolean( response === '1' );
40
+ };
package/src/index.ts CHANGED
@@ -11,7 +11,7 @@ export { ToggleControl } from './controls/toggle-control';
11
11
  export { NumberControl } from './controls/number-control';
12
12
  export { EqualUnequalSizesControl } from './controls/equal-unequal-sizes-control';
13
13
  export { LinkedDimensionsControl } from './controls/linked-dimensions-control';
14
- export { FontFamilyControl } from './controls/font-family-control';
14
+ export { FontFamilyControl } from './controls/font-family-control/font-family-control';
15
15
  export { UrlControl } from './controls/url-control';
16
16
  export { LinkControl } from './controls/link-control';
17
17
  export { GapControl } from './controls/gap-control';
@@ -29,6 +29,7 @@ export type { EqualUnequalItems } from './controls/equal-unequal-sizes-control';
29
29
  export type { ControlActionsItems } from './control-actions/control-actions-context';
30
30
  export type { PropProviderProps } from './bound-prop-context';
31
31
  export type { SetValue } from './bound-prop-context/prop-context';
32
+ export type { ExtendedValue } from './controls/size-control';
32
33
 
33
34
  // providers
34
35
  export { createControlReplacement, ControlReplacementProvider } from './create-control-replacement';