mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-10 23:36:14 -05:00
Added TK support to feature image caption editor (#19285)
closes https://github.com/TryGhost/Product/issues/4227 - added `@onTKCountChange` to `<KoenigLexicalEditorInput>` - when present the `isTKEnabled` flag will be turned on and the `<TKCountPlugin>` registered - added `@registerAPI` support to `<KoenigLexicalEditorInput>` so we can focus the caption editor when its TK indicator is clicked - added manual display of TK indicator for the caption input - default editor indicator positioning doesn't work for this input because its container is not full editor width - hid it by adding `overflow: hidden` to the inner caption container - added custom indicator button shown when we have a non-zero count
This commit is contained in:
parent
e5c6b0a23f
commit
309aaf98aa
7 changed files with 57 additions and 5 deletions
|
@ -50,7 +50,7 @@
|
|||
{{svg-jar "koenig/kg-trash"}}
|
||||
</button>
|
||||
</div>
|
||||
<div class="flex justify-between align-center">
|
||||
<div class="relative flex justify-between align-center">
|
||||
{{#if this.isEditingAlt}}
|
||||
<input
|
||||
type="text"
|
||||
|
@ -70,6 +70,8 @@
|
|||
@placeholderText={{if this.captionInputFocused "" "Add a caption to the feature image"}}
|
||||
@onFocus={{fn (mut this.captionInputFocused) true}}
|
||||
@onBlur={{this.handleCaptionBlur}}
|
||||
@onTKCountChange={{this.onTKCountChange}}
|
||||
@registerAPI={{this.registerEditorAPI}}
|
||||
/>
|
||||
{{/if}}
|
||||
<button
|
||||
|
@ -78,6 +80,12 @@
|
|||
>
|
||||
Alt
|
||||
</button>
|
||||
|
||||
{{#if (and this.tkCount (not this.isEditingAlt))}}
|
||||
<div class="tk-indicator" data-testid="feature-image-tk-indicator" role="button" {{on "click" this.focusCaptionEditor}}>
|
||||
TK
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{else}}
|
||||
{{!-- no-image state --}}
|
||||
|
|
|
@ -18,6 +18,7 @@ export default class GhEditorFeatureImageComponent extends Component {
|
|||
@tracked captionInputFocused = false;
|
||||
@tracked showUnsplashSelector = false;
|
||||
@tracked canDrop = false;
|
||||
@tracked tkCount = 0;
|
||||
|
||||
get caption() {
|
||||
const content = this.args.caption;
|
||||
|
@ -34,6 +35,18 @@ export default class GhEditorFeatureImageComponent extends Component {
|
|||
this.args.updateCaption(cleanedHtml);
|
||||
}
|
||||
|
||||
@action
|
||||
registerEditorAPI(API) {
|
||||
this.editorAPI = API;
|
||||
}
|
||||
|
||||
@action
|
||||
focusCaptionEditor() {
|
||||
if (this.editorAPI) {
|
||||
this.editorAPI.focusEditor({position: 'bottom'});
|
||||
}
|
||||
}
|
||||
|
||||
@action
|
||||
handleCaptionBlur() {
|
||||
this.captionInputFocused = false;
|
||||
|
@ -116,4 +129,12 @@ export default class GhEditorFeatureImageComponent extends Component {
|
|||
this.canDrop = false;
|
||||
setFiles([imageFile]);
|
||||
}
|
||||
|
||||
@action
|
||||
onTKCountChange(count) {
|
||||
if (this.args.onTKCountChange) {
|
||||
this.tkCount = count;
|
||||
this.args.onTKCountChange(count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
@handleCaptionBlur={{@handleFeatureImageCaptionBlur}}
|
||||
@forceButtonDisplay={{or (not @title) (eq @title "(Untitled)") this.titleIsHovered this.titleIsFocused}}
|
||||
@isHidden={{or (not @cardOptions.post.showTitleAndFeatureImage) false}}
|
||||
@onTKCountChange={{@updateFeatureImageTkCount}}
|
||||
/>
|
||||
|
||||
<div class="gh-editor-title-container page-improvements">
|
||||
|
|
|
@ -57,6 +57,11 @@ const EmojiPickerPlugin = ({editorResource, ...props}) => {
|
|||
return <_EmojiPickerPlugin {...props} />;
|
||||
};
|
||||
|
||||
const TKCountPlugin = ({editorResource, ...props}) => {
|
||||
const {TKCountPlugin: _TKCountPlugin} = editorResource.read();
|
||||
return <_TKCountPlugin {...props} />;
|
||||
};
|
||||
|
||||
export default class KoenigLexicalEditorInput extends Component {
|
||||
@service ajax;
|
||||
@service feature;
|
||||
|
@ -100,6 +105,7 @@ export default class KoenigLexicalEditorInput extends Component {
|
|||
editorResource={this.editorResource}
|
||||
initialEditorState={this.args.lexical}
|
||||
onError={this.onError}
|
||||
isTKEnabled={this.args.onTKCountChange ? true : false}
|
||||
>
|
||||
<KoenigComposableEditor
|
||||
editorResource={this.editorResource}
|
||||
|
@ -112,9 +118,11 @@ export default class KoenigLexicalEditorInput extends Component {
|
|||
className={`koenig-lexical-editor-input ${this.feature.nightShift ? 'dark' : ''}`}
|
||||
placeholderText={props.placeholderText}
|
||||
placeholderClassName="koenig-lexical-editor-input-placeholder"
|
||||
registerAPI={this.args.registerAPI}
|
||||
>
|
||||
<HtmlOutputPlugin editorResource={this.editorResource} html={props.html} setHtml={props.onChangeHtml} />
|
||||
{this.emojiPicker ? <EmojiPickerPlugin editorResource={this.editorResource} /> : null}
|
||||
{this.args.onTKCountChange ? <TKCountPlugin editorResource={this.editorResource} onChange={this.args.onTKCountChange} /> : null}
|
||||
</KoenigComposableEditor>
|
||||
</KoenigComposer>
|
||||
</Suspense>
|
||||
|
|
|
@ -131,6 +131,7 @@ export default class LexicalEditorController extends Controller {
|
|||
// koenig related properties
|
||||
wordCount = 0;
|
||||
postTkCount = 0;
|
||||
featureImageTkCount = 0;
|
||||
|
||||
/* private properties ----------------------------------------------------*/
|
||||
|
||||
|
@ -262,9 +263,9 @@ export default class LexicalEditorController extends Controller {
|
|||
return true;
|
||||
}
|
||||
|
||||
@computed('titleHasTk', 'postTkCount')
|
||||
@computed('titleHasTk', 'postTkCount', 'featureImageTkCount')
|
||||
get tkCount() {
|
||||
return (this.titleHasTk ? 1 : 0) + this.postTkCount;
|
||||
return (this.titleHasTk ? 1 : 0) + this.postTkCount + this.featureImageTkCount;
|
||||
}
|
||||
|
||||
@action
|
||||
|
@ -368,6 +369,11 @@ export default class LexicalEditorController extends Controller {
|
|||
this.set('postTkCount', count);
|
||||
}
|
||||
|
||||
@action
|
||||
updateFeatureImageTkCount(count) {
|
||||
this.set('featureImageTkCount', count);
|
||||
}
|
||||
|
||||
@action
|
||||
setFeatureImage(url) {
|
||||
this.post.set('featureImage', url);
|
||||
|
@ -1135,6 +1141,7 @@ export default class LexicalEditorController extends Controller {
|
|||
this.set('showSettingsMenu', false);
|
||||
this.set('wordCount', 0);
|
||||
this.set('postTkCount', 0);
|
||||
this.set('featureImageTkCount', 0);
|
||||
|
||||
// remove the onbeforeunload handler as it's only relevant whilst on
|
||||
// the editor route
|
||||
|
|
|
@ -635,6 +635,7 @@ body[data-user-is-dragging] .gh-editor-feature-image-dropzone {
|
|||
background-color: transparent !important;
|
||||
transition: border-color .15s linear;
|
||||
-webkit-appearance: none;
|
||||
overflow: hidden; /* Hides any indicators such as TK */
|
||||
}
|
||||
|
||||
.gh-editor-feature-image-alttext::placeholder,
|
||||
|
@ -683,7 +684,7 @@ body[data-user-is-dragging] .gh-editor-feature-image-dropzone {
|
|||
opacity: .5;
|
||||
}
|
||||
|
||||
.gh-editor-title-container .tk-indicator {
|
||||
.gh-editor .tk-indicator {
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
right: -5.6rem;
|
||||
|
@ -691,7 +692,12 @@ body[data-user-is-dragging] .gh-editor-feature-image-dropzone {
|
|||
color: #95A1AD;
|
||||
font-size: 1.2rem;
|
||||
font-weight: 500;
|
||||
cursor: default;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.gh-editor-feature-image-container .tk-indicator {
|
||||
top: 0;
|
||||
padding: 0 .4rem;
|
||||
}
|
||||
|
||||
.gh-editor-back-button {
|
||||
|
|
|
@ -79,6 +79,7 @@
|
|||
@onEditorCreated={{this.setKoenigEditor}}
|
||||
@updateWordCount={{this.updateWordCount}}
|
||||
@updatePostTkCount={{this.updatePostTkCount}}
|
||||
@updateFeatureImageTkCount={{if (feature "tkReminders") this.updateFeatureImageTkCount}}
|
||||
@featureImage={{this.post.featureImage}}
|
||||
@featureImageAlt={{this.post.featureImageAlt}}
|
||||
@featureImageCaption={{this.post.featureImageCaption}}
|
||||
|
|
Loading…
Add table
Reference in a new issue