• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Yoast / wordpress-seo / 2d66c210b3cdb04e0cabd3a27852287fa31a581c

14 May 2024 08:05AM UTC coverage: 53.131% (+0.9%) from 52.242%
2d66c210b3cdb04e0cabd3a27852287fa31a581c

push

github

YoastBot
Bump version to 22.7 on free

7464 of 13622 branches covered (54.79%)

Branch coverage included in aggregate %.

28518 of 54101 relevant lines covered (52.71%)

41520.75 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/packages/replacement-variable-editor/src/ReplacementVariableEditor.js
1
/* eslint-disable react/jsx-no-bind */
2
import { applyFilters } from "@wordpress/hooks";
3
// External dependencies.
4
import React, { Fragment } from "react";
5
import PropTypes from "prop-types";
6
import uniqueId from "lodash/uniqueId";
7
import { __ } from "@wordpress/i18n";
8
import { Slot } from "@wordpress/components";
9

10
// Yoast dependencies.
11
import ReplacementVariableEditorStandalone from "./ReplacementVariableEditorStandalone";
12
import { withCaretStyles } from "@yoast/style-guide";
13
import {
14
        ButtonsContainer,
15
        DescriptionInputContainer,
16
        FormSection,
17
        TitleInputContainer,
18
        TriggerReplacementVariableSuggestionsButton,
19
} from "./shared";
20
import {
21
        replacementVariablesShape,
22
        recommendedReplacementVariablesShape,
23
} from "./constants";
24
import { NewBadge, SimulatedLabel, PremiumBadge } from "@yoast/components";
25

26
/**
27
 * The replacement variable editor.
28
 */
29
class ReplacementVariableEditor extends React.Component {
30
        /**
31
         * The constructor.
32
         *
33
         * @param {Object} props The component props.
34
         */
35
        constructor( props ) {
36
                super( props );
×
37

38
                this.uniqueId = uniqueId( "replacement-variable-editor-field-" );
×
39

40
                switch ( props.type ) {
×
41
                        case "description":
42
                                this.InputContainer = DescriptionInputContainer;
×
43
                                break;
×
44
                        case "title":
45
                                this.InputContainer = TitleInputContainer;
×
46
                                break;
×
47
                        default:
48
                                this.InputContainer = TitleInputContainer;
×
49
                }
50

51
                if ( props.withCaret ) {
×
52
                        this.InputContainer = withCaretStyles( this.InputContainer );
×
53
                }
54

55
                this.triggerReplacementVariableSuggestions = this.triggerReplacementVariableSuggestions.bind( this );
×
56
        }
57

58
        /**
59
         * Inserts a % into a ReplacementVariableEditor to trigger the replacement variable suggestions.
60
         *
61
         * @returns {void}
62
         */
63
        triggerReplacementVariableSuggestions() {
64
                this.ref.triggerReplacementVariableSuggestions();
×
65
        }
66

67
        /**
68
         * Renders the components.
69
         *
70
         * @returns {ReactElement} The rendered element.
71
         */
72
        render() {
73
                const {
74
                        label,
75
                        onChange,
76
                        content,
77
                        onFocus,
78
                        onBlur,
79
                        isActive,
80
                        isHovered,
81
                        onSearchChange,
82
                        replacementVariables,
83
                        recommendedReplacementVariables,
84
                        editorRef,
85
                        placeholder,
86
                        fieldId,
87
                        onMouseEnter,
88
                        onMouseLeave,
89
                        hasNewBadge,
90
                        isDisabled,
91
                        hasPremiumBadge,
92
                        type,
93
                } = this.props;
×
94

95
                const InputContainer = this.InputContainer;
×
96

97
                const buttons = applyFilters( "yoast.replacementVariableEditor.additionalButtons", [], { fieldId, type } );
×
98
                const mentions = applyFilters( "yoast.replacementVariableEditor.additionalMentions", [], { fieldId, type } );
×
99

100
                return (
×
101
                        <FormSection
102
                                className={ [ "yst-replacevar", isDisabled && "yst-replacevar--disabled" ].filter( Boolean ).join( " " ) }
×
103
                                onMouseEnter={ onMouseEnter }
104
                                onMouseLeave={ onMouseLeave }
105
                        >
106
                                <SimulatedLabel
107
                                        className="yst-replacevar__label"
108
                                        id={ this.uniqueId }
109
                                        onClick={ onFocus }
110
                                >
111
                                        { label }
112
                                </SimulatedLabel>
113

114
                                { hasPremiumBadge && <PremiumBadge inLabel={ true } /> }
×
115
                                { hasNewBadge && <NewBadge inLabel={ true } /> }
×
116

117
                                <ButtonsContainer className="yst-replacevar__buttons">
118
                                        <Slot name={ `yoast.replacementVariableEditor.additionalButtons.${ fieldId }` } />
119
                                        { buttons.map( ( button, index ) => (
120
                                                <Fragment key={ `additional-button-${ index }-${ fieldId }` }>
×
121
                                                        { button }
122
                                                </Fragment>
123
                                        ) ) }
124
                                        <Slot key={ `PluginComponent-${ fieldId }` } name={ `PluginComponent-${ fieldId }` } />
125
                                        <TriggerReplacementVariableSuggestionsButton
126
                                                className="yst-replacevar__button-insert"
127
                                                onClick={ this.triggerReplacementVariableSuggestions }
128
                                                disabled={ isDisabled }
129
                                        >
130
                                                { __( "Insert variable", "wordpress-seo" ) }
131
                                        </TriggerReplacementVariableSuggestionsButton>
132
                                </ButtonsContainer>
133

134
                                <InputContainer
135
                                        className={ `yst-replacevar__editor yst-replacevar__editor--${ type }` }
136
                                        onClick={ onFocus }
137
                                        isActive={ isActive && ! isDisabled }
×
138
                                        isHovered={ isHovered }
139
                                >
140
                                        <Slot name={ `yoast.replacementVariableEditor.additionalMentions.${ fieldId }` } />
141
                                        { mentions.map( ( mention, index ) => (
142
                                                <Fragment key={ `additional-mention-${ index }-${ fieldId }` }>
×
143
                                                        { mention }
144
                                                </Fragment>
145
                                        ) ) }
146
                                        <ReplacementVariableEditorStandalone
147
                                                fieldId={ fieldId }
148
                                                placeholder={ placeholder }
149
                                                content={ content }
150
                                                onChange={ onChange }
151
                                                onFocus={ onFocus }
152
                                                onBlur={ onBlur }
153
                                                onSearchChange={ onSearchChange }
154
                                                replacementVariables={ replacementVariables }
155
                                                recommendedReplacementVariables={ recommendedReplacementVariables }
156
                                                ref={ ref => {
157
                                                        this.ref = ref;
×
158
                                                        editorRef( ref );
×
159
                                                } }
160
                                                ariaLabelledBy={ this.uniqueId }
161
                                                isDisabled={ isDisabled }
162
                                                wrapperClassName={ `yst-replacevar__editor-wrapper--${ type }` }
163
                                        />
164
                                </InputContainer>
165
                        </FormSection>
166
                );
167
        }
168
}
169

170
ReplacementVariableEditor.propTypes = {
×
171
        editorRef: PropTypes.func,
172
        content: PropTypes.string.isRequired,
173
        onChange: PropTypes.func.isRequired,
174
        onBlur: PropTypes.func,
175
        onSearchChange: PropTypes.func,
176
        replacementVariables: replacementVariablesShape,
177
        recommendedReplacementVariables: recommendedReplacementVariablesShape,
178
        isActive: PropTypes.bool,
179
        isHovered: PropTypes.bool,
180
        withCaret: PropTypes.bool,
181
        onFocus: PropTypes.func,
182
        label: PropTypes.string,
183
        placeholder: PropTypes.string,
184
        type: PropTypes.oneOf( [ "title", "description" ] ).isRequired,
185
        fieldId: PropTypes.string,
186
        onMouseEnter: PropTypes.func,
187
        onMouseLeave: PropTypes.func,
188
        hasNewBadge: PropTypes.bool,
189
        isDisabled: PropTypes.bool,
190
        hasPremiumBadge: PropTypes.bool,
191
};
192

193
ReplacementVariableEditor.defaultProps = {
×
194
        onFocus: () => {},
195
        onBlur: () => {},
196
        onSearchChange: null,
197
        replacementVariables: [],
198
        recommendedReplacementVariables: [],
199
        fieldId: "",
200
        placeholder: "",
201
        label: "",
202
        withCaret: false,
203
        isHovered: false,
204
        isActive: false,
205
        editorRef: () => {},
206
        onMouseEnter: () => {},
207
        onMouseLeave: () => {},
208
        hasNewBadge: false,
209
        isDisabled: false,
210
        hasPremiumBadge: false,
211
};
212

213
export default ReplacementVariableEditor;
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc