@elementor/editor-variables 0.18.0 → 3.32.0-21
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 +0 -28
- package/dist/index.d.mts +19 -1
- package/dist/index.d.ts +19 -1
- package/dist/index.js +1282 -1026
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1262 -990
- package/dist/index.mjs.map +1 -1
- package/package.json +16 -14
- package/src/api.ts +18 -2
- package/src/components/fields/color-field.tsx +3 -3
- package/src/components/fields/font-field.tsx +21 -10
- package/src/components/fields/label-field.tsx +31 -5
- package/src/components/ui/edit-confirmation-dialog.tsx +75 -0
- package/src/components/ui/missing-variable-alert.tsx +39 -0
- package/src/components/ui/no-variables.tsx +59 -26
- package/src/components/ui/tags/missing-tag.tsx +25 -0
- package/src/components/ui/variable/assigned-variable.tsx +11 -14
- package/src/components/ui/variable/deleted-variable.tsx +102 -50
- package/src/components/ui/variable/missing-variable.tsx +44 -0
- package/src/components/{color-variable-creation.tsx → variable-creation.tsx} +51 -22
- package/src/components/variable-edit.tsx +221 -0
- package/src/components/variable-restore.tsx +117 -0
- package/src/components/variable-selection-popover.tsx +91 -92
- package/src/components/variables-manager/variables-manager-panel.tsx +115 -0
- package/src/components/{font-variables-selection.tsx → variables-selection.tsx} +38 -17
- package/src/context/variable-selection-popover.context.tsx +19 -0
- package/src/context/variable-type-context.tsx +23 -0
- package/src/controls/variable-control.tsx +26 -0
- package/src/hooks/use-initial-value.ts +22 -0
- package/src/hooks/use-permissions.ts +15 -0
- package/src/hooks/use-prop-variable-action.tsx +53 -0
- package/src/hooks/use-prop-variables.ts +2 -2
- package/src/index.ts +1 -0
- package/src/init.ts +33 -4
- package/src/register-variable-types.tsx +29 -0
- package/src/repeater-injections.ts +5 -1
- package/src/service.ts +2 -19
- package/src/transformers/inheritance-transformer.tsx +30 -0
- package/src/transformers/utils/resolve-css-variable.ts +24 -0
- package/src/transformers/variable-transformer.ts +3 -16
- package/src/utils/tracking.ts +39 -0
- package/src/utils/validations.ts +40 -6
- package/src/variables-registry/create-variable-type-registry.ts +77 -0
- package/src/variables-registry/variable-type-registry.ts +3 -0
- package/src/components/color-variable-edit.tsx +0 -157
- package/src/components/color-variables-selection.tsx +0 -128
- package/src/components/font-variable-creation.tsx +0 -106
- package/src/components/font-variable-edit.tsx +0 -157
- package/src/components/variable-selection-popover.context.ts +0 -7
- package/src/controls/color-variable-control.tsx +0 -39
- package/src/controls/font-variable-control.tsx +0 -37
- package/src/hooks/use-prop-color-variable-action.tsx +0 -25
- package/src/hooks/use-prop-font-variable-action.tsx +0 -25
- package/src/init-color-variables.ts +0 -27
- package/src/init-font-variables.ts +0 -24
- package/src/utils.ts +0 -20
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elementor/editor-variables",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.32.0-21",
|
|
4
4
|
"private": false,
|
|
5
5
|
"author": "Elementor Team",
|
|
6
6
|
"homepage": "https://elementor.com/",
|
|
@@ -18,11 +18,11 @@
|
|
|
18
18
|
},
|
|
19
19
|
"repository": {
|
|
20
20
|
"type": "git",
|
|
21
|
-
"url": "git+https://github.com/elementor/elementor
|
|
21
|
+
"url": "git+https://github.com/elementor/elementor.git",
|
|
22
22
|
"directory": "packages/core/editor-variables"
|
|
23
23
|
},
|
|
24
24
|
"bugs": {
|
|
25
|
-
"url": "https://github.com/elementor/elementor
|
|
25
|
+
"url": "https://github.com/elementor/elementor/issues"
|
|
26
26
|
},
|
|
27
27
|
"publishConfig": {
|
|
28
28
|
"access": "public"
|
|
@@ -39,18 +39,20 @@
|
|
|
39
39
|
"dev": "tsup --config=../../tsup.dev.ts"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@elementor/editor": "0
|
|
43
|
-
"@elementor/editor-
|
|
44
|
-
"@elementor/editor-
|
|
45
|
-
"@elementor/editor-
|
|
46
|
-
"@elementor/
|
|
47
|
-
"@elementor/editor-
|
|
42
|
+
"@elementor/editor": "3.32.0-21",
|
|
43
|
+
"@elementor/editor-canvas": "3.32.0-21",
|
|
44
|
+
"@elementor/editor-controls": "3.32.0-21",
|
|
45
|
+
"@elementor/editor-current-user": "3.32.0-21",
|
|
46
|
+
"@elementor/editor-editing-panel": "3.32.0-21",
|
|
47
|
+
"@elementor/editor-panels": "3.32.0-21",
|
|
48
|
+
"@elementor/editor-props": "3.32.0-21",
|
|
49
|
+
"@elementor/editor-ui": "3.32.0-21",
|
|
50
|
+
"@elementor/editor-v1-adapters": "3.32.0-21",
|
|
51
|
+
"@elementor/http-client": "3.32.0-21",
|
|
48
52
|
"@elementor/icons": "1.46.0",
|
|
49
|
-
"@
|
|
50
|
-
"@elementor/ui": "1.36.
|
|
51
|
-
"@
|
|
52
|
-
"@elementor/http-client": "0.3.0",
|
|
53
|
-
"@elementor/editor-ui": "0.14.2"
|
|
53
|
+
"@elementor/schema": "3.32.0-21",
|
|
54
|
+
"@elementor/ui": "1.36.2",
|
|
55
|
+
"@wordpress/i18n": "^5.13.0"
|
|
54
56
|
},
|
|
55
57
|
"peerDependencies": {
|
|
56
58
|
"react": "^18.3.1",
|
package/src/api.ts
CHANGED
|
@@ -2,6 +2,12 @@ import { httpService } from '@elementor/http-client';
|
|
|
2
2
|
|
|
3
3
|
const BASE_PATH = 'elementor/v1/variables';
|
|
4
4
|
|
|
5
|
+
type RestoreVariablePayload = {
|
|
6
|
+
id: string;
|
|
7
|
+
label?: string;
|
|
8
|
+
value?: string;
|
|
9
|
+
};
|
|
10
|
+
|
|
5
11
|
export const apiClient = {
|
|
6
12
|
list: () => {
|
|
7
13
|
return httpService().get( BASE_PATH + '/list' );
|
|
@@ -27,7 +33,17 @@ export const apiClient = {
|
|
|
27
33
|
return httpService().post( BASE_PATH + '/delete', { id } );
|
|
28
34
|
},
|
|
29
35
|
|
|
30
|
-
restore: ( id: string ) => {
|
|
31
|
-
|
|
36
|
+
restore: ( id: string, label?: string, value?: string ) => {
|
|
37
|
+
const payload: RestoreVariablePayload = { id };
|
|
38
|
+
|
|
39
|
+
if ( label ) {
|
|
40
|
+
payload.label = label;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if ( value ) {
|
|
44
|
+
payload.value = value;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return httpService().post( BASE_PATH + '/restore', payload );
|
|
32
48
|
},
|
|
33
49
|
};
|
|
@@ -3,8 +3,8 @@ import { useRef, useState } from 'react';
|
|
|
3
3
|
import { FormHelperText, FormLabel, Grid, UnstableColorField } from '@elementor/ui';
|
|
4
4
|
import { __ } from '@wordpress/i18n';
|
|
5
5
|
|
|
6
|
+
import { usePopoverContentRef } from '../../context/variable-selection-popover.context';
|
|
6
7
|
import { validateValue } from '../../utils/validations';
|
|
7
|
-
import { usePopoverContentRef } from '../variable-selection-popover.context';
|
|
8
8
|
|
|
9
9
|
type ColorFieldProps = {
|
|
10
10
|
value: string;
|
|
@@ -16,7 +16,7 @@ export const ColorField = ( { value, onChange }: ColorFieldProps ) => {
|
|
|
16
16
|
const [ errorMessage, setErrorMessage ] = useState( '' );
|
|
17
17
|
|
|
18
18
|
const defaultRef = useRef< HTMLDivElement >( null );
|
|
19
|
-
const anchorRef = usePopoverContentRef() ?? defaultRef;
|
|
19
|
+
const anchorRef = usePopoverContentRef() ?? defaultRef.current;
|
|
20
20
|
|
|
21
21
|
const handleChange = ( newValue: string ) => {
|
|
22
22
|
setColor( newValue );
|
|
@@ -41,7 +41,7 @@ export const ColorField = ( { value, onChange }: ColorFieldProps ) => {
|
|
|
41
41
|
error={ errorMessage ?? undefined }
|
|
42
42
|
slotProps={ {
|
|
43
43
|
colorPicker: {
|
|
44
|
-
anchorEl: anchorRef
|
|
44
|
+
anchorEl: anchorRef,
|
|
45
45
|
anchorOrigin: { vertical: 'top', horizontal: 'right' },
|
|
46
46
|
transformOrigin: { vertical: 'top', horizontal: -10 },
|
|
47
47
|
},
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { useRef, useState } from 'react';
|
|
3
|
-
import {
|
|
3
|
+
import { enqueueFont, ItemSelector } from '@elementor/editor-controls';
|
|
4
4
|
import { useFontFamilies, useSectionWidth } from '@elementor/editor-editing-panel';
|
|
5
|
-
import { ChevronDownIcon } from '@elementor/icons';
|
|
5
|
+
import { ChevronDownIcon, TextIcon } from '@elementor/icons';
|
|
6
6
|
import {
|
|
7
7
|
bindPopover,
|
|
8
8
|
bindTrigger,
|
|
@@ -15,8 +15,8 @@ import {
|
|
|
15
15
|
} from '@elementor/ui';
|
|
16
16
|
import { __ } from '@wordpress/i18n';
|
|
17
17
|
|
|
18
|
+
import { usePopoverContentRef } from '../../context/variable-selection-popover.context';
|
|
18
19
|
import { validateValue } from '../../utils/validations';
|
|
19
|
-
import { usePopoverContentRef } from '../variable-selection-popover.context';
|
|
20
20
|
|
|
21
21
|
type FontFieldProps = {
|
|
22
22
|
value: string;
|
|
@@ -28,13 +28,20 @@ export const FontField = ( { value, onChange }: FontFieldProps ) => {
|
|
|
28
28
|
const [ errorMessage, setErrorMessage ] = useState( '' );
|
|
29
29
|
|
|
30
30
|
const defaultRef = useRef< HTMLDivElement >( null );
|
|
31
|
-
const anchorRef = usePopoverContentRef() ?? defaultRef;
|
|
31
|
+
const anchorRef = usePopoverContentRef() ?? defaultRef.current;
|
|
32
32
|
|
|
33
33
|
const fontPopoverState = usePopupState( { variant: 'popover' } );
|
|
34
34
|
|
|
35
35
|
const fontFamilies = useFontFamilies();
|
|
36
36
|
const sectionWidth = useSectionWidth();
|
|
37
37
|
|
|
38
|
+
const mapFontSubs = React.useMemo( () => {
|
|
39
|
+
return fontFamilies.map( ( { label, fonts } ) => ( {
|
|
40
|
+
label,
|
|
41
|
+
items: fonts,
|
|
42
|
+
} ) );
|
|
43
|
+
}, [ fontFamilies ] );
|
|
44
|
+
|
|
38
45
|
const handleChange = ( newValue: string ) => {
|
|
39
46
|
setFontFamily( newValue );
|
|
40
47
|
|
|
@@ -65,17 +72,21 @@ export const FontField = ( { value, onChange }: FontFieldProps ) => {
|
|
|
65
72
|
<Popover
|
|
66
73
|
disablePortal
|
|
67
74
|
disableScrollLock
|
|
68
|
-
anchorEl={ anchorRef
|
|
75
|
+
anchorEl={ anchorRef }
|
|
69
76
|
anchorOrigin={ { vertical: 'top', horizontal: 'right' } }
|
|
70
|
-
transformOrigin={ { vertical: 'top', horizontal: -
|
|
77
|
+
transformOrigin={ { vertical: 'top', horizontal: -28 } }
|
|
71
78
|
{ ...bindPopover( fontPopoverState ) }
|
|
72
79
|
>
|
|
73
|
-
<
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
80
|
+
<ItemSelector
|
|
81
|
+
itemsList={ mapFontSubs }
|
|
82
|
+
selectedItem={ fontFamily }
|
|
83
|
+
onItemChange={ handleFontFamilyChange }
|
|
77
84
|
onClose={ fontPopoverState.close }
|
|
78
85
|
sectionWidth={ sectionWidth }
|
|
86
|
+
title={ __( 'Font Family', 'elementor' ) }
|
|
87
|
+
itemStyle={ ( item ) => ( { fontFamily: item.value } ) }
|
|
88
|
+
onDebounce={ enqueueFont }
|
|
89
|
+
icon={ TextIcon as React.ElementType< { fontSize: string } > }
|
|
79
90
|
/>
|
|
80
91
|
</Popover>
|
|
81
92
|
{ errorMessage && <FormHelperText error>{ errorMessage }</FormHelperText> }
|
|
@@ -5,12 +5,31 @@ import { __ } from '@wordpress/i18n';
|
|
|
5
5
|
|
|
6
6
|
import { labelHint, validateLabel, VARIABLE_LABEL_MAX_LENGTH } from '../../utils/validations';
|
|
7
7
|
|
|
8
|
+
function isLabelEqual( a: string, b: string ) {
|
|
9
|
+
return a.trim().toLowerCase() === b.trim().toLowerCase();
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
type LabelErrorProps = {
|
|
13
|
+
value: string;
|
|
14
|
+
message: string;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export const useLabelError = ( initialError?: LabelErrorProps ) => {
|
|
18
|
+
const [ error, setError ] = useState< LabelErrorProps >( initialError ?? { value: '', message: '' } );
|
|
19
|
+
|
|
20
|
+
return {
|
|
21
|
+
labelFieldError: error,
|
|
22
|
+
setLabelFieldError: setError,
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
|
|
8
26
|
type LabelFieldProps = {
|
|
9
27
|
value: string;
|
|
28
|
+
error?: LabelErrorProps;
|
|
10
29
|
onChange: ( value: string ) => void;
|
|
11
30
|
};
|
|
12
31
|
|
|
13
|
-
export const LabelField = ( { value, onChange }: LabelFieldProps ) => {
|
|
32
|
+
export const LabelField = ( { value, error, onChange }: LabelFieldProps ) => {
|
|
14
33
|
const [ label, setLabel ] = useState( value );
|
|
15
34
|
const [ errorMessage, setErrorMessage ] = useState( '' );
|
|
16
35
|
const [ noticeMessage, setNoticeMessage ] = useState( () => labelHint( value ) );
|
|
@@ -24,11 +43,18 @@ export const LabelField = ( { value, onChange }: LabelFieldProps ) => {
|
|
|
24
43
|
setErrorMessage( errorMsg );
|
|
25
44
|
setNoticeMessage( errorMsg ? '' : hintMsg );
|
|
26
45
|
|
|
27
|
-
onChange( errorMsg ? '' : newValue );
|
|
46
|
+
onChange( isLabelEqual( newValue, error?.value ?? '' ) || errorMsg ? '' : newValue );
|
|
28
47
|
};
|
|
29
48
|
|
|
30
49
|
const id = useId();
|
|
31
50
|
|
|
51
|
+
let errorMsg = errorMessage;
|
|
52
|
+
if ( isLabelEqual( label, error?.value ?? '' ) && error?.message ) {
|
|
53
|
+
errorMsg = error.message;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const noticeMsg = errorMsg ? '' : noticeMessage;
|
|
57
|
+
|
|
32
58
|
return (
|
|
33
59
|
<Grid container gap={ 0.75 } alignItems="center">
|
|
34
60
|
<Grid item xs={ 12 }>
|
|
@@ -42,12 +68,12 @@ export const LabelField = ( { value, onChange }: LabelFieldProps ) => {
|
|
|
42
68
|
size="tiny"
|
|
43
69
|
fullWidth
|
|
44
70
|
value={ label }
|
|
45
|
-
error={ !!
|
|
71
|
+
error={ !! errorMsg }
|
|
46
72
|
onChange={ ( e: React.ChangeEvent< HTMLInputElement > ) => handleChange( e.target.value ) }
|
|
47
73
|
inputProps={ { maxLength: VARIABLE_LABEL_MAX_LENGTH } }
|
|
48
74
|
/>
|
|
49
|
-
{
|
|
50
|
-
{
|
|
75
|
+
{ errorMsg && <FormHelperText error>{ errorMsg }</FormHelperText> }
|
|
76
|
+
{ noticeMsg && <FormHelperText>{ noticeMsg }</FormHelperText> }
|
|
51
77
|
</Grid>
|
|
52
78
|
</Grid>
|
|
53
79
|
);
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { AlertTriangleFilledIcon } from '@elementor/icons';
|
|
4
|
+
import {
|
|
5
|
+
Button,
|
|
6
|
+
Checkbox,
|
|
7
|
+
Dialog,
|
|
8
|
+
DialogActions,
|
|
9
|
+
DialogContent,
|
|
10
|
+
DialogContentText,
|
|
11
|
+
DialogTitle,
|
|
12
|
+
FormControlLabel,
|
|
13
|
+
Typography,
|
|
14
|
+
} from '@elementor/ui';
|
|
15
|
+
import { __ } from '@wordpress/i18n';
|
|
16
|
+
|
|
17
|
+
export const EDIT_CONFIRMATION_DIALOG_ID = 'edit-confirmation-dialog';
|
|
18
|
+
|
|
19
|
+
export const EditConfirmationDialog = ( {
|
|
20
|
+
closeDialog,
|
|
21
|
+
onConfirm,
|
|
22
|
+
onSuppressMessage,
|
|
23
|
+
}: {
|
|
24
|
+
closeDialog: () => void;
|
|
25
|
+
onConfirm?: () => void;
|
|
26
|
+
onSuppressMessage?: () => void;
|
|
27
|
+
} ) => {
|
|
28
|
+
const [ dontShowAgain, setDontShowAgain ] = useState( false );
|
|
29
|
+
|
|
30
|
+
const handleSave = () => {
|
|
31
|
+
if ( dontShowAgain ) {
|
|
32
|
+
onSuppressMessage?.();
|
|
33
|
+
}
|
|
34
|
+
onConfirm?.();
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<Dialog open onClose={ closeDialog } maxWidth="xs">
|
|
39
|
+
<DialogTitle display="flex" alignItems="center" gap={ 1 }>
|
|
40
|
+
<AlertTriangleFilledIcon color="secondary" />
|
|
41
|
+
{ __( 'Changes to variables go live right away.', 'elementor' ) }
|
|
42
|
+
</DialogTitle>
|
|
43
|
+
<DialogContent>
|
|
44
|
+
<DialogContentText variant="body2" color="textPrimary">
|
|
45
|
+
{ __(
|
|
46
|
+
"Don't worry - all other changes you make will wait until you publish your site.",
|
|
47
|
+
'elementor'
|
|
48
|
+
) }
|
|
49
|
+
</DialogContentText>
|
|
50
|
+
</DialogContent>
|
|
51
|
+
<DialogActions sx={ { justifyContent: 'space-between', alignItems: 'center' } }>
|
|
52
|
+
<FormControlLabel
|
|
53
|
+
control={
|
|
54
|
+
<Checkbox
|
|
55
|
+
checked={ dontShowAgain }
|
|
56
|
+
onChange={ ( event: React.ChangeEvent< HTMLInputElement > ) =>
|
|
57
|
+
setDontShowAgain( event.target.checked )
|
|
58
|
+
}
|
|
59
|
+
size="small"
|
|
60
|
+
/>
|
|
61
|
+
}
|
|
62
|
+
label={ <Typography variant="body2">{ __( "Don't show me again", 'elementor' ) }</Typography> }
|
|
63
|
+
/>
|
|
64
|
+
<div>
|
|
65
|
+
<Button color="secondary" onClick={ closeDialog }>
|
|
66
|
+
{ __( 'Keep editing', 'elementor' ) }
|
|
67
|
+
</Button>
|
|
68
|
+
<Button variant="contained" color="secondary" onClick={ handleSave } sx={ { ml: 1 } }>
|
|
69
|
+
{ __( 'Save', 'elementor' ) }
|
|
70
|
+
</Button>
|
|
71
|
+
</div>
|
|
72
|
+
</DialogActions>
|
|
73
|
+
</Dialog>
|
|
74
|
+
);
|
|
75
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { useSectionWidth } from '@elementor/editor-editing-panel';
|
|
3
|
+
import { Alert, AlertAction, AlertTitle, ClickAwayListener } from '@elementor/ui';
|
|
4
|
+
import { __ } from '@wordpress/i18n';
|
|
5
|
+
|
|
6
|
+
type MissingVariableAlertProps = {
|
|
7
|
+
onClose: () => void;
|
|
8
|
+
onClear?: () => void;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export const MissingVariableAlert = ( { onClose, onClear }: MissingVariableAlertProps ) => {
|
|
12
|
+
const sectionWidth = useSectionWidth();
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<ClickAwayListener onClickAway={ onClose }>
|
|
16
|
+
<Alert
|
|
17
|
+
variant="standard"
|
|
18
|
+
severity="warning"
|
|
19
|
+
onClose={ onClose }
|
|
20
|
+
action={
|
|
21
|
+
<>
|
|
22
|
+
{ onClear && (
|
|
23
|
+
<AlertAction variant="contained" onClick={ onClear }>
|
|
24
|
+
{ __( 'Clear', 'elementor' ) }
|
|
25
|
+
</AlertAction>
|
|
26
|
+
) }
|
|
27
|
+
</>
|
|
28
|
+
}
|
|
29
|
+
sx={ { width: sectionWidth } }
|
|
30
|
+
>
|
|
31
|
+
<AlertTitle>{ __( 'This variable is missing', 'elementor' ) }</AlertTitle>
|
|
32
|
+
{ __(
|
|
33
|
+
'It may have been deleted. Try clearing this field and select a different value or variable.',
|
|
34
|
+
'elementor'
|
|
35
|
+
) }
|
|
36
|
+
</Alert>
|
|
37
|
+
</ClickAwayListener>
|
|
38
|
+
);
|
|
39
|
+
};
|
|
@@ -2,35 +2,68 @@ import * as React from 'react';
|
|
|
2
2
|
import { Button, Stack, Typography } from '@elementor/ui';
|
|
3
3
|
import { __ } from '@wordpress/i18n';
|
|
4
4
|
|
|
5
|
+
import { usePermissions } from '../../hooks/use-permissions';
|
|
6
|
+
|
|
5
7
|
type Props = {
|
|
6
8
|
icon?: React.ReactNode;
|
|
7
9
|
title?: string;
|
|
8
10
|
onAdd?: () => void;
|
|
9
11
|
};
|
|
10
12
|
|
|
11
|
-
export const NoVariables = ( { icon, title, onAdd }: Props ) =>
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
{
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
)
|
|
13
|
+
export const NoVariables = ( { icon, title, onAdd }: Props ) => {
|
|
14
|
+
const canAdd = usePermissions().canAdd();
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<Stack
|
|
18
|
+
gap={ 1 }
|
|
19
|
+
alignItems="center"
|
|
20
|
+
justifyContent="center"
|
|
21
|
+
height="100%"
|
|
22
|
+
color="text.secondary"
|
|
23
|
+
sx={ { p: 2.5, pb: 5.5 } }
|
|
24
|
+
>
|
|
25
|
+
{ icon }
|
|
26
|
+
|
|
27
|
+
{ canAdd ? (
|
|
28
|
+
<>
|
|
29
|
+
<NoVariablesContent
|
|
30
|
+
title={ title || __( 'Create your first variable', 'elementor' ) }
|
|
31
|
+
message={ __(
|
|
32
|
+
'Variables are saved attributes that you can apply anywhere on your site.',
|
|
33
|
+
'elementor'
|
|
34
|
+
) }
|
|
35
|
+
/>
|
|
36
|
+
{ onAdd && (
|
|
37
|
+
<Button variant="outlined" color="secondary" size="small" onClick={ onAdd }>
|
|
38
|
+
{ __( 'Create a variable', 'elementor' ) }
|
|
39
|
+
</Button>
|
|
40
|
+
) }
|
|
41
|
+
</>
|
|
42
|
+
) : (
|
|
43
|
+
<NoVariablesContent
|
|
44
|
+
title={ __( 'There are no variables', 'elementor' ) }
|
|
45
|
+
message={ __( 'With your current role, you can only connect and detach variables.', 'elementor' ) }
|
|
46
|
+
/>
|
|
47
|
+
) }
|
|
48
|
+
</Stack>
|
|
49
|
+
);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
type NoVariablesContentProps = {
|
|
53
|
+
title: string;
|
|
54
|
+
message: string;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
function NoVariablesContent( { title, message }: NoVariablesContentProps ) {
|
|
58
|
+
return (
|
|
59
|
+
<>
|
|
60
|
+
<Typography align="center" variant="subtitle2">
|
|
61
|
+
{ title }
|
|
62
|
+
</Typography>
|
|
63
|
+
|
|
64
|
+
<Typography align="center" variant="caption" maxWidth="180px">
|
|
65
|
+
{ message }
|
|
66
|
+
</Typography>
|
|
67
|
+
</>
|
|
68
|
+
);
|
|
69
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { AlertTriangleFilledIcon } from '@elementor/icons';
|
|
3
|
+
import { Chip, type ChipProps, type Theme } from '@elementor/ui';
|
|
4
|
+
|
|
5
|
+
export const MissingTag = React.forwardRef< HTMLDivElement, ChipProps >( ( { label, onClick, ...props }, ref ) => {
|
|
6
|
+
return (
|
|
7
|
+
<Chip
|
|
8
|
+
ref={ ref }
|
|
9
|
+
size="tiny"
|
|
10
|
+
color="warning"
|
|
11
|
+
shape="rounded"
|
|
12
|
+
variant="standard"
|
|
13
|
+
onClick={ onClick }
|
|
14
|
+
icon={ <AlertTriangleFilledIcon /> }
|
|
15
|
+
label={ label }
|
|
16
|
+
sx={ {
|
|
17
|
+
height: ( theme: Theme ) => theme.spacing( 3.5 ),
|
|
18
|
+
borderRadius: ( theme: Theme ) => theme.spacing( 1 ),
|
|
19
|
+
justifyContent: 'flex-start',
|
|
20
|
+
width: '100%',
|
|
21
|
+
} }
|
|
22
|
+
{ ...props }
|
|
23
|
+
/>
|
|
24
|
+
);
|
|
25
|
+
} );
|
|
@@ -1,27 +1,22 @@
|
|
|
1
1
|
import { useId, useRef } from 'react';
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import { useBoundProp } from '@elementor/editor-controls';
|
|
4
|
-
import { type
|
|
4
|
+
import { type PropTypeKey } from '@elementor/editor-props';
|
|
5
5
|
import { ColorFilterIcon } from '@elementor/icons';
|
|
6
6
|
import { bindPopover, bindTrigger, Box, Popover, usePopupState } from '@elementor/ui';
|
|
7
7
|
|
|
8
8
|
import { type Variable } from '../../../types';
|
|
9
|
+
import { getVariableType } from '../../../variables-registry/variable-type-registry';
|
|
9
10
|
import { VariableSelectionPopover } from '../../variable-selection-popover';
|
|
10
11
|
import { AssignedTag, SIZE } from '../tags/assigned-tag';
|
|
11
12
|
|
|
12
13
|
type Props = {
|
|
13
|
-
|
|
14
|
-
fallbackPropTypeUtil: PropTypeUtil< string, string | null > | PropTypeUtil< string, string >;
|
|
15
|
-
additionalStartIcon?: React.ReactNode;
|
|
14
|
+
propTypeKey: PropTypeKey;
|
|
16
15
|
variable: Variable;
|
|
17
16
|
};
|
|
18
17
|
|
|
19
|
-
export const AssignedVariable = ( {
|
|
20
|
-
|
|
21
|
-
variablePropTypeUtil,
|
|
22
|
-
fallbackPropTypeUtil,
|
|
23
|
-
additionalStartIcon,
|
|
24
|
-
}: Props ) => {
|
|
18
|
+
export const AssignedVariable = ( { variable, propTypeKey }: Props ) => {
|
|
19
|
+
const { fallbackPropTypeUtil, startIcon, propTypeUtil } = getVariableType( propTypeKey );
|
|
25
20
|
const { setValue } = useBoundProp();
|
|
26
21
|
const anchorRef = useRef< HTMLDivElement >( null );
|
|
27
22
|
|
|
@@ -32,9 +27,12 @@ export const AssignedVariable = ( {
|
|
|
32
27
|
} );
|
|
33
28
|
|
|
34
29
|
const unlinkVariable = () => {
|
|
35
|
-
|
|
30
|
+
const fallbackValue = fallbackPropTypeUtil.create( variable.value );
|
|
31
|
+
setValue( fallbackValue );
|
|
36
32
|
};
|
|
37
33
|
|
|
34
|
+
const StartIcon = startIcon || ( () => null );
|
|
35
|
+
|
|
38
36
|
return (
|
|
39
37
|
<Box ref={ anchorRef }>
|
|
40
38
|
<AssignedTag
|
|
@@ -42,8 +40,7 @@ export const AssignedVariable = ( {
|
|
|
42
40
|
startIcon={
|
|
43
41
|
<>
|
|
44
42
|
<ColorFilterIcon fontSize={ SIZE } />
|
|
45
|
-
|
|
46
|
-
{ additionalStartIcon }
|
|
43
|
+
<StartIcon value={ variable.value } />
|
|
47
44
|
</>
|
|
48
45
|
}
|
|
49
46
|
onUnlink={ unlinkVariable }
|
|
@@ -62,7 +59,7 @@ export const AssignedVariable = ( {
|
|
|
62
59
|
<VariableSelectionPopover
|
|
63
60
|
selectedVariable={ variable }
|
|
64
61
|
closePopover={ popupState.close }
|
|
65
|
-
propTypeKey={
|
|
62
|
+
propTypeKey={ propTypeUtil.key }
|
|
66
63
|
/>
|
|
67
64
|
</Popover>
|
|
68
65
|
</Box>
|