@elementor/editor-variables 0.14.0 → 0.16.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/CHANGELOG.md +76 -0
- package/dist/index.js +743 -500
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +720 -528
- package/dist/index.mjs.map +1 -1
- package/package.json +10 -10
- package/src/components/color-variable-creation.tsx +18 -57
- package/src/components/color-variable-edit.tsx +100 -79
- package/src/components/color-variables-selection.tsx +33 -20
- package/src/components/fields/color-field.tsx +54 -0
- package/src/components/fields/font-field.tsx +85 -0
- package/src/components/fields/label-field.tsx +54 -0
- package/src/components/font-variable-creation.tsx +19 -76
- package/src/components/font-variable-edit.tsx +98 -106
- package/src/components/font-variables-selection.tsx +33 -20
- package/src/components/ui/color-indicator.tsx +1 -0
- package/src/components/ui/delete-confirmation-dialog.tsx +55 -0
- package/src/components/ui/menu-item-content.tsx +29 -23
- package/src/components/ui/no-search-results.tsx +6 -8
- package/src/components/ui/no-variables.tsx +3 -2
- package/src/components/ui/tags/assigned-tag.tsx +43 -0
- package/src/components/ui/tags/deleted-tag.tsx +26 -0
- package/src/components/ui/variable/assigned-variable.tsx +70 -0
- package/src/components/ui/variable/deleted-variable.tsx +20 -0
- package/src/components/variable-selection-popover.context.ts +7 -0
- package/src/components/variable-selection-popover.tsx +17 -8
- package/src/controls/color-variable-control.tsx +15 -72
- package/src/controls/font-variable-control.tsx +14 -71
- package/src/hooks/use-prop-variables.ts +12 -18
- package/src/init-color-variables.ts +3 -48
- package/src/repeater-injections.ts +35 -0
- package/src/utils/validations.ts +42 -0
|
@@ -1,23 +1,16 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import { useBoundProp } from '@elementor/editor-controls';
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { PopoverContent, useBoundProp } from '@elementor/editor-controls';
|
|
4
|
+
import { PopoverScrollableContent } from '@elementor/editor-editing-panel';
|
|
4
5
|
import { PopoverHeader } from '@elementor/editor-ui';
|
|
5
6
|
import { ArrowLeftIcon, BrushIcon } from '@elementor/icons';
|
|
6
|
-
import {
|
|
7
|
-
Button,
|
|
8
|
-
CardActions,
|
|
9
|
-
Divider,
|
|
10
|
-
FormLabel,
|
|
11
|
-
Grid,
|
|
12
|
-
IconButton,
|
|
13
|
-
Stack,
|
|
14
|
-
TextField,
|
|
15
|
-
UnstableColorField,
|
|
16
|
-
} from '@elementor/ui';
|
|
7
|
+
import { Button, CardActions, Divider, IconButton } from '@elementor/ui';
|
|
17
8
|
import { __ } from '@wordpress/i18n';
|
|
18
9
|
|
|
19
10
|
import { createVariable } from '../hooks/use-prop-variables';
|
|
20
11
|
import { colorVariablePropTypeUtil } from '../prop-types/color-variable-prop-type';
|
|
12
|
+
import { ColorField } from './fields/color-field';
|
|
13
|
+
import { LabelField } from './fields/label-field';
|
|
21
14
|
|
|
22
15
|
const SIZE = 'tiny';
|
|
23
16
|
|
|
@@ -32,8 +25,6 @@ export const ColorVariableCreation = ( { onGoBack, onClose }: Props ) => {
|
|
|
32
25
|
const [ color, setColor ] = useState( '' );
|
|
33
26
|
const [ label, setLabel ] = useState( '' );
|
|
34
27
|
|
|
35
|
-
const anchorRef = useRef< HTMLDivElement >( null );
|
|
36
|
-
|
|
37
28
|
const resetFields = () => {
|
|
38
29
|
setColor( '' );
|
|
39
30
|
setLabel( '' );
|
|
@@ -55,12 +46,14 @@ export const ColorVariableCreation = ( { onGoBack, onClose }: Props ) => {
|
|
|
55
46
|
} );
|
|
56
47
|
};
|
|
57
48
|
|
|
58
|
-
const
|
|
59
|
-
return
|
|
49
|
+
const hasEmptyValue = () => {
|
|
50
|
+
return '' === color.trim() || '' === label.trim();
|
|
60
51
|
};
|
|
61
52
|
|
|
53
|
+
const isSubmitDisabled = hasEmptyValue();
|
|
54
|
+
|
|
62
55
|
return (
|
|
63
|
-
|
|
56
|
+
<PopoverScrollableContent height="auto">
|
|
64
57
|
<PopoverHeader
|
|
65
58
|
icon={
|
|
66
59
|
<>
|
|
@@ -78,48 +71,16 @@ export const ColorVariableCreation = ( { onGoBack, onClose }: Props ) => {
|
|
|
78
71
|
|
|
79
72
|
<Divider />
|
|
80
73
|
|
|
81
|
-
<
|
|
82
|
-
<
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
</Grid>
|
|
86
|
-
<Grid item xs={ 12 }>
|
|
87
|
-
<TextField
|
|
88
|
-
size="tiny"
|
|
89
|
-
fullWidth
|
|
90
|
-
value={ label }
|
|
91
|
-
onChange={ ( e: React.ChangeEvent< HTMLInputElement > ) => setLabel( e.target.value ) }
|
|
92
|
-
/>
|
|
93
|
-
</Grid>
|
|
94
|
-
</Grid>
|
|
95
|
-
|
|
96
|
-
<Grid container gap={ 0.75 } alignItems="center">
|
|
97
|
-
<Grid item xs={ 12 }>
|
|
98
|
-
<FormLabel size="small">{ __( 'Value', 'elementor' ) }</FormLabel>
|
|
99
|
-
</Grid>
|
|
100
|
-
<Grid item xs={ 12 }>
|
|
101
|
-
<UnstableColorField
|
|
102
|
-
size="tiny"
|
|
103
|
-
fullWidth
|
|
104
|
-
value={ color }
|
|
105
|
-
onChange={ setColor }
|
|
106
|
-
slotProps={ {
|
|
107
|
-
colorPicker: {
|
|
108
|
-
anchorEl: anchorRef.current,
|
|
109
|
-
anchorOrigin: { vertical: 'top', horizontal: 'right' },
|
|
110
|
-
transformOrigin: { vertical: 'top', horizontal: -10 },
|
|
111
|
-
},
|
|
112
|
-
} }
|
|
113
|
-
/>
|
|
114
|
-
</Grid>
|
|
115
|
-
</Grid>
|
|
116
|
-
</Stack>
|
|
74
|
+
<PopoverContent p={ 2 }>
|
|
75
|
+
<LabelField value={ label } onChange={ setLabel } />
|
|
76
|
+
<ColorField value={ color } onChange={ setColor } />
|
|
77
|
+
</PopoverContent>
|
|
117
78
|
|
|
118
|
-
<CardActions>
|
|
119
|
-
<Button size="small" variant="contained" disabled={
|
|
79
|
+
<CardActions sx={ { pt: 0.5, pb: 1 } }>
|
|
80
|
+
<Button size="small" variant="contained" disabled={ isSubmitDisabled } onClick={ handleCreate }>
|
|
120
81
|
{ __( 'Create', 'elementor' ) }
|
|
121
82
|
</Button>
|
|
122
83
|
</CardActions>
|
|
123
|
-
|
|
84
|
+
</PopoverScrollableContent>
|
|
124
85
|
);
|
|
125
86
|
};
|
|
@@ -1,21 +1,17 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { PopoverContent, useBoundProp } from '@elementor/editor-controls';
|
|
4
|
+
import { PopoverScrollableContent } from '@elementor/editor-editing-panel';
|
|
3
5
|
import { PopoverHeader } from '@elementor/editor-ui';
|
|
4
|
-
import { ArrowLeftIcon, BrushIcon } from '@elementor/icons';
|
|
5
|
-
import {
|
|
6
|
-
Button,
|
|
7
|
-
CardActions,
|
|
8
|
-
Divider,
|
|
9
|
-
FormLabel,
|
|
10
|
-
Grid,
|
|
11
|
-
IconButton,
|
|
12
|
-
Stack,
|
|
13
|
-
TextField,
|
|
14
|
-
UnstableColorField,
|
|
15
|
-
} from '@elementor/ui';
|
|
6
|
+
import { ArrowLeftIcon, BrushIcon, TrashIcon } from '@elementor/icons';
|
|
7
|
+
import { Button, CardActions, Divider, IconButton } from '@elementor/ui';
|
|
16
8
|
import { __ } from '@wordpress/i18n';
|
|
17
9
|
|
|
18
|
-
import { updateVariable, useVariable } from '../hooks/use-prop-variables';
|
|
10
|
+
import { deleteVariable, updateVariable, useVariable } from '../hooks/use-prop-variables';
|
|
11
|
+
import { colorVariablePropTypeUtil } from '../prop-types/color-variable-prop-type';
|
|
12
|
+
import { ColorField } from './fields/color-field';
|
|
13
|
+
import { LabelField } from './fields/label-field';
|
|
14
|
+
import { DeleteConfirmationDialog } from './ui/delete-confirmation-dialog';
|
|
19
15
|
|
|
20
16
|
const SIZE = 'tiny';
|
|
21
17
|
|
|
@@ -27,14 +23,14 @@ type Props = {
|
|
|
27
23
|
};
|
|
28
24
|
|
|
29
25
|
export const ColorVariableEdit = ( { onClose, onGoBack, onSubmit, editId }: Props ) => {
|
|
30
|
-
const
|
|
26
|
+
const { setValue: notifyBoundPropChange, value: assignedValue } = useBoundProp( colorVariablePropTypeUtil );
|
|
27
|
+
const [ deleteConfirmation, setDeleteConfirmation ] = useState( false );
|
|
31
28
|
|
|
29
|
+
const variable = useVariable( editId );
|
|
32
30
|
if ( ! variable ) {
|
|
33
31
|
throw new Error( `Global color variable not found` );
|
|
34
32
|
}
|
|
35
33
|
|
|
36
|
-
const anchorRef = useRef< HTMLDivElement >( null );
|
|
37
|
-
|
|
38
34
|
const [ color, setColor ] = useState( variable.value );
|
|
39
35
|
const [ label, setLabel ] = useState( variable.label );
|
|
40
36
|
|
|
@@ -43,75 +39,100 @@ export const ColorVariableEdit = ( { onClose, onGoBack, onSubmit, editId }: Prop
|
|
|
43
39
|
value: color,
|
|
44
40
|
label,
|
|
45
41
|
} ).then( () => {
|
|
42
|
+
maybeTriggerBoundPropChange();
|
|
43
|
+
onSubmit?.();
|
|
44
|
+
} );
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const handleDelete = () => {
|
|
48
|
+
deleteVariable( editId ).then( () => {
|
|
49
|
+
maybeTriggerBoundPropChange();
|
|
46
50
|
onSubmit?.();
|
|
47
51
|
} );
|
|
48
52
|
};
|
|
49
53
|
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
54
|
+
const maybeTriggerBoundPropChange = () => {
|
|
55
|
+
if ( editId === assignedValue ) {
|
|
56
|
+
notifyBoundPropChange( editId );
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const handleDeleteConfirmation = () => {
|
|
61
|
+
setDeleteConfirmation( true );
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const closeDeleteDialog = () => () => {
|
|
65
|
+
setDeleteConfirmation( false );
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const actions = [];
|
|
69
|
+
|
|
70
|
+
actions.push(
|
|
71
|
+
<IconButton
|
|
72
|
+
key="delete"
|
|
73
|
+
size={ SIZE }
|
|
74
|
+
aria-label={ __( 'Delete', 'elementor' ) }
|
|
75
|
+
onClick={ handleDeleteConfirmation }
|
|
76
|
+
>
|
|
77
|
+
<TrashIcon fontSize={ SIZE } />
|
|
78
|
+
</IconButton>
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
const hasEmptyValues = () => {
|
|
82
|
+
return ! color.trim() || ! label.trim();
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const noValueChanged = () => {
|
|
86
|
+
return color === variable.value && label === variable.label;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const isSubmitDisabled = noValueChanged() || hasEmptyValues();
|
|
53
90
|
|
|
54
91
|
return (
|
|
55
92
|
<>
|
|
56
|
-
<
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
<
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
colorPicker: {
|
|
100
|
-
anchorEl: anchorRef.current,
|
|
101
|
-
anchorOrigin: { vertical: 'top', horizontal: 'right' },
|
|
102
|
-
transformOrigin: { vertical: 'top', horizontal: -10 },
|
|
103
|
-
},
|
|
104
|
-
} }
|
|
105
|
-
/>
|
|
106
|
-
</Grid>
|
|
107
|
-
</Grid>
|
|
108
|
-
</Stack>
|
|
109
|
-
|
|
110
|
-
<CardActions>
|
|
111
|
-
<Button size="small" variant="contained" disabled={ isSaveDisabled() } onClick={ handleUpdate }>
|
|
112
|
-
{ __( 'Save', 'elementor' ) }
|
|
113
|
-
</Button>
|
|
114
|
-
</CardActions>
|
|
93
|
+
<PopoverScrollableContent height="auto">
|
|
94
|
+
<PopoverHeader
|
|
95
|
+
title={ __( 'Edit variable', 'elementor' ) }
|
|
96
|
+
onClose={ onClose }
|
|
97
|
+
icon={
|
|
98
|
+
<>
|
|
99
|
+
{ onGoBack && (
|
|
100
|
+
<IconButton
|
|
101
|
+
size={ SIZE }
|
|
102
|
+
aria-label={ __( 'Go Back', 'elementor' ) }
|
|
103
|
+
onClick={ onGoBack }
|
|
104
|
+
>
|
|
105
|
+
<ArrowLeftIcon fontSize={ SIZE } />
|
|
106
|
+
</IconButton>
|
|
107
|
+
) }
|
|
108
|
+
<BrushIcon fontSize={ SIZE } />
|
|
109
|
+
</>
|
|
110
|
+
}
|
|
111
|
+
actions={ actions }
|
|
112
|
+
/>
|
|
113
|
+
|
|
114
|
+
<Divider />
|
|
115
|
+
|
|
116
|
+
<PopoverContent p={ 2 }>
|
|
117
|
+
<LabelField value={ label } onChange={ setLabel } />
|
|
118
|
+
<ColorField value={ color } onChange={ setColor } />
|
|
119
|
+
</PopoverContent>
|
|
120
|
+
|
|
121
|
+
<CardActions sx={ { pt: 0.5, pb: 1 } }>
|
|
122
|
+
<Button size="small" variant="contained" disabled={ isSubmitDisabled } onClick={ handleUpdate }>
|
|
123
|
+
{ __( 'Save', 'elementor' ) }
|
|
124
|
+
</Button>
|
|
125
|
+
</CardActions>
|
|
126
|
+
</PopoverScrollableContent>
|
|
127
|
+
|
|
128
|
+
{ deleteConfirmation && (
|
|
129
|
+
<DeleteConfirmationDialog
|
|
130
|
+
open
|
|
131
|
+
label={ label }
|
|
132
|
+
onConfirm={ handleDelete }
|
|
133
|
+
closeDialog={ closeDeleteDialog() }
|
|
134
|
+
/>
|
|
135
|
+
) }
|
|
115
136
|
</>
|
|
116
137
|
);
|
|
117
138
|
};
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { useState } from 'react';
|
|
3
3
|
import { useBoundProp } from '@elementor/editor-controls';
|
|
4
|
+
import { PopoverScrollableContent } from '@elementor/editor-editing-panel';
|
|
4
5
|
import { PopoverHeader, PopoverMenuList, PopoverSearch, type VirtualizedItem } from '@elementor/editor-ui';
|
|
5
|
-
import { ColorFilterIcon, PlusIcon, SettingsIcon } from '@elementor/icons';
|
|
6
|
+
import { BrushIcon, ColorFilterIcon, PlusIcon, SettingsIcon } from '@elementor/icons';
|
|
6
7
|
import { Divider, IconButton } from '@elementor/ui';
|
|
7
8
|
import { __ } from '@wordpress/i18n';
|
|
8
9
|
|
|
@@ -93,25 +94,37 @@ export const ColorVariablesSelection = ( { closePopover, onAdd, onEdit, onSettin
|
|
|
93
94
|
|
|
94
95
|
<Divider />
|
|
95
96
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
97
|
+
<PopoverScrollableContent>
|
|
98
|
+
{ hasVariables && hasSearchResults && (
|
|
99
|
+
<PopoverMenuList
|
|
100
|
+
items={ items }
|
|
101
|
+
onSelect={ handleSetColorVariable }
|
|
102
|
+
onClose={ () => {} }
|
|
103
|
+
selectedValue={ variable }
|
|
104
|
+
data-testid="color-variables-list"
|
|
105
|
+
menuListTemplate={ VariablesStyledMenuList }
|
|
106
|
+
menuItemContentTemplate={ ( item: VirtualizedItem< 'item', string > ) => (
|
|
107
|
+
<MenuItemContent item={ item } />
|
|
108
|
+
) }
|
|
109
|
+
/>
|
|
110
|
+
) }
|
|
111
|
+
|
|
112
|
+
{ ! hasSearchResults && hasVariables && (
|
|
113
|
+
<NoSearchResults
|
|
114
|
+
searchValue={ searchValue }
|
|
115
|
+
onClear={ handleClearSearch }
|
|
116
|
+
icon={ <BrushIcon fontSize="large" /> }
|
|
117
|
+
/>
|
|
118
|
+
) }
|
|
119
|
+
|
|
120
|
+
{ ! hasVariables && (
|
|
121
|
+
<NoVariables
|
|
122
|
+
title={ __( 'Create your first color variable', 'elementor' ) }
|
|
123
|
+
icon={ <BrushIcon fontSize="large" /> }
|
|
124
|
+
onAdd={ onAdd }
|
|
125
|
+
/>
|
|
126
|
+
) }
|
|
127
|
+
</PopoverScrollableContent>
|
|
115
128
|
</>
|
|
116
129
|
);
|
|
117
130
|
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { useRef, useState } from 'react';
|
|
3
|
+
import { FormHelperText, FormLabel, Grid, UnstableColorField } from '@elementor/ui';
|
|
4
|
+
import { __ } from '@wordpress/i18n';
|
|
5
|
+
|
|
6
|
+
import { validateValue } from '../../utils/validations';
|
|
7
|
+
import { usePopoverContentRef } from '../variable-selection-popover.context';
|
|
8
|
+
|
|
9
|
+
type ColorFieldProps = {
|
|
10
|
+
value: string;
|
|
11
|
+
onChange: ( value: string ) => void;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export const ColorField = ( { value, onChange }: ColorFieldProps ) => {
|
|
15
|
+
const [ color, setColor ] = useState( value );
|
|
16
|
+
const [ errorMessage, setErrorMessage ] = useState( '' );
|
|
17
|
+
|
|
18
|
+
const defaultRef = useRef< HTMLDivElement >( null );
|
|
19
|
+
const anchorRef = usePopoverContentRef() ?? defaultRef;
|
|
20
|
+
|
|
21
|
+
const handleChange = ( newValue: string ) => {
|
|
22
|
+
setColor( newValue );
|
|
23
|
+
|
|
24
|
+
const errorMsg = validateValue( newValue );
|
|
25
|
+
setErrorMessage( errorMsg );
|
|
26
|
+
|
|
27
|
+
onChange( errorMsg ? '' : newValue );
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<Grid container gap={ 0.75 } alignItems="center">
|
|
32
|
+
<Grid item xs={ 12 }>
|
|
33
|
+
<FormLabel size="tiny">{ __( 'Value', 'elementor' ) }</FormLabel>
|
|
34
|
+
</Grid>
|
|
35
|
+
<Grid item xs={ 12 }>
|
|
36
|
+
<UnstableColorField
|
|
37
|
+
size="tiny"
|
|
38
|
+
fullWidth
|
|
39
|
+
value={ color }
|
|
40
|
+
onChange={ handleChange }
|
|
41
|
+
error={ errorMessage ?? undefined }
|
|
42
|
+
slotProps={ {
|
|
43
|
+
colorPicker: {
|
|
44
|
+
anchorEl: anchorRef.current,
|
|
45
|
+
anchorOrigin: { vertical: 'top', horizontal: 'right' },
|
|
46
|
+
transformOrigin: { vertical: 'top', horizontal: -10 },
|
|
47
|
+
},
|
|
48
|
+
} }
|
|
49
|
+
/>
|
|
50
|
+
{ errorMessage && <FormHelperText error>{ errorMessage }</FormHelperText> }
|
|
51
|
+
</Grid>
|
|
52
|
+
</Grid>
|
|
53
|
+
);
|
|
54
|
+
};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { useRef, useState } from 'react';
|
|
3
|
+
import { FontFamilySelector } from '@elementor/editor-controls';
|
|
4
|
+
import { useFontFamilies, useSectionWidth } from '@elementor/editor-editing-panel';
|
|
5
|
+
import { ChevronDownIcon } from '@elementor/icons';
|
|
6
|
+
import {
|
|
7
|
+
bindPopover,
|
|
8
|
+
bindTrigger,
|
|
9
|
+
FormHelperText,
|
|
10
|
+
FormLabel,
|
|
11
|
+
Grid,
|
|
12
|
+
Popover,
|
|
13
|
+
UnstableTag,
|
|
14
|
+
usePopupState,
|
|
15
|
+
} from '@elementor/ui';
|
|
16
|
+
import { __ } from '@wordpress/i18n';
|
|
17
|
+
|
|
18
|
+
import { validateValue } from '../../utils/validations';
|
|
19
|
+
import { usePopoverContentRef } from '../variable-selection-popover.context';
|
|
20
|
+
|
|
21
|
+
type FontFieldProps = {
|
|
22
|
+
value: string;
|
|
23
|
+
onChange: ( value: string ) => void;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export const FontField = ( { value, onChange }: FontFieldProps ) => {
|
|
27
|
+
const [ fontFamily, setFontFamily ] = useState( value );
|
|
28
|
+
const [ errorMessage, setErrorMessage ] = useState( '' );
|
|
29
|
+
|
|
30
|
+
const defaultRef = useRef< HTMLDivElement >( null );
|
|
31
|
+
const anchorRef = usePopoverContentRef() ?? defaultRef;
|
|
32
|
+
|
|
33
|
+
const fontPopoverState = usePopupState( { variant: 'popover' } );
|
|
34
|
+
|
|
35
|
+
const fontFamilies = useFontFamilies();
|
|
36
|
+
const sectionWidth = useSectionWidth();
|
|
37
|
+
|
|
38
|
+
const handleChange = ( newValue: string ) => {
|
|
39
|
+
setFontFamily( newValue );
|
|
40
|
+
|
|
41
|
+
const errorMsg = validateValue( newValue );
|
|
42
|
+
setErrorMessage( errorMsg );
|
|
43
|
+
|
|
44
|
+
onChange( errorMsg ? '' : newValue );
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const handleFontFamilyChange = ( newFontFamily: string ) => {
|
|
48
|
+
handleChange( newFontFamily );
|
|
49
|
+
fontPopoverState.close();
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<Grid container gap={ 0.75 } alignItems="center">
|
|
54
|
+
<Grid item xs={ 12 }>
|
|
55
|
+
<FormLabel size="tiny">{ __( 'Value', 'elementor' ) }</FormLabel>
|
|
56
|
+
</Grid>
|
|
57
|
+
<Grid item xs={ 12 }>
|
|
58
|
+
<UnstableTag
|
|
59
|
+
variant="outlined"
|
|
60
|
+
label={ fontFamily }
|
|
61
|
+
endIcon={ <ChevronDownIcon fontSize="tiny" /> }
|
|
62
|
+
{ ...bindTrigger( fontPopoverState ) }
|
|
63
|
+
fullWidth
|
|
64
|
+
/>
|
|
65
|
+
<Popover
|
|
66
|
+
disablePortal
|
|
67
|
+
disableScrollLock
|
|
68
|
+
anchorEl={ anchorRef.current }
|
|
69
|
+
anchorOrigin={ { vertical: 'top', horizontal: 'right' } }
|
|
70
|
+
transformOrigin={ { vertical: 'top', horizontal: -20 } }
|
|
71
|
+
{ ...bindPopover( fontPopoverState ) }
|
|
72
|
+
>
|
|
73
|
+
<FontFamilySelector
|
|
74
|
+
fontFamilies={ fontFamilies }
|
|
75
|
+
fontFamily={ fontFamily }
|
|
76
|
+
onFontFamilyChange={ handleFontFamilyChange }
|
|
77
|
+
onClose={ fontPopoverState.close }
|
|
78
|
+
sectionWidth={ sectionWidth }
|
|
79
|
+
/>
|
|
80
|
+
</Popover>
|
|
81
|
+
{ errorMessage && <FormHelperText error>{ errorMessage }</FormHelperText> }
|
|
82
|
+
</Grid>
|
|
83
|
+
</Grid>
|
|
84
|
+
);
|
|
85
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { useId, useState } from 'react';
|
|
3
|
+
import { FormHelperText, FormLabel, Grid, TextField } from '@elementor/ui';
|
|
4
|
+
import { __ } from '@wordpress/i18n';
|
|
5
|
+
|
|
6
|
+
import { labelHint, validateLabel, VARIABLE_LABEL_MAX_LENGTH } from '../../utils/validations';
|
|
7
|
+
|
|
8
|
+
type LabelFieldProps = {
|
|
9
|
+
value: string;
|
|
10
|
+
onChange: ( value: string ) => void;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const LabelField = ( { value, onChange }: LabelFieldProps ) => {
|
|
14
|
+
const [ label, setLabel ] = useState( value );
|
|
15
|
+
const [ errorMessage, setErrorMessage ] = useState( '' );
|
|
16
|
+
const [ noticeMessage, setNoticeMessage ] = useState( () => labelHint( value ) );
|
|
17
|
+
|
|
18
|
+
const handleChange = ( newValue: string ) => {
|
|
19
|
+
setLabel( newValue );
|
|
20
|
+
|
|
21
|
+
const errorMsg = validateLabel( newValue );
|
|
22
|
+
const hintMsg = labelHint( newValue );
|
|
23
|
+
|
|
24
|
+
setErrorMessage( errorMsg );
|
|
25
|
+
setNoticeMessage( errorMsg ? '' : hintMsg );
|
|
26
|
+
|
|
27
|
+
onChange( errorMsg ? '' : newValue );
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const id = useId();
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<Grid container gap={ 0.75 } alignItems="center">
|
|
34
|
+
<Grid item xs={ 12 }>
|
|
35
|
+
<FormLabel htmlFor={ id } size="tiny">
|
|
36
|
+
{ __( 'Name', 'elementor' ) }
|
|
37
|
+
</FormLabel>
|
|
38
|
+
</Grid>
|
|
39
|
+
<Grid item xs={ 12 }>
|
|
40
|
+
<TextField
|
|
41
|
+
id={ id }
|
|
42
|
+
size="tiny"
|
|
43
|
+
fullWidth
|
|
44
|
+
value={ label }
|
|
45
|
+
error={ !! errorMessage }
|
|
46
|
+
onChange={ ( e: React.ChangeEvent< HTMLInputElement > ) => handleChange( e.target.value ) }
|
|
47
|
+
inputProps={ { maxLength: VARIABLE_LABEL_MAX_LENGTH } }
|
|
48
|
+
/>
|
|
49
|
+
{ errorMessage && <FormHelperText error>{ errorMessage }</FormHelperText> }
|
|
50
|
+
{ noticeMessage && <FormHelperText>{ noticeMessage }</FormHelperText> }
|
|
51
|
+
</Grid>
|
|
52
|
+
</Grid>
|
|
53
|
+
);
|
|
54
|
+
};
|