Added "Create snippet" toolbar icon when cards are selected

no issue

- show the toolbar icon for any `<KoenigCard>` instance that has the `saveAsSnippet` action passed to it
  - currently that's all cards except the HR card because that's a primitive element rather than containing any user-defined content
- add `koenigUi.inputHasFocus` so that card toolbars can be hidden when the snippet input is displayed
This commit is contained in:
Kevin Ansfield 2020-10-21 12:16:04 +01:00
parent 28d95002b5
commit e5ae72cbff
14 changed files with 65 additions and 17 deletions

View File

@ -6,6 +6,7 @@
@deselectCard={{action this.deselectCard}}
@onDeselect={{action "onDeselect"}}
@editCard={{action this.editCard}}
@saveAsSnippet={{this.saveAsSnippet}}
@toolbar={{this.toolbar}}
@hasEditMode={{false}}
@showSelectedOutline={{this.payload.metadata}}

View File

@ -1,5 +1,5 @@
<KoenigCard
@class={{concat "ba b--white relative kg-card-hover miw-100 relative" (if this.isEditing " bw2 pt1 pb1 pl2 nl6 pr6 nr6")}}
@class={{concat "ba b--white relative kg-card-hover miw-100" (if this.isEditing " bw2 pt1 pb1 pl2 nl6 pr6 nr6")}}
@style={{this.cardStyle}}
@headerOffset={{this.headerOffset}}
@toolbar={{this.toolbar}}
@ -10,6 +10,7 @@
@deselectCard={{action this.deselectCard}}
@editCard={{action this.editCard}}
@saveCard={{action this.saveCard}}
@saveAsSnippet={{this.saveAsSnippet}}
@onEnterEdit={{action "enterEditMode"}}
@onLeaveEdit={{action "leaveEditMode"}}
@addParagraphAfterCard={{this.addParagraphAfterCard}}

View File

@ -11,6 +11,7 @@
@deselectCard={{action this.deselectCard}}
@editCard={{action this.editCard}}
@saveCard={{action this.saveCard}}
@saveAsSnippet={{this.saveAsSnippet}}
@onLeaveEdit={{action "leaveEditMode"}}
@addParagraphAfterCard={{this.addParagraphAfterCard}}
@moveCursorToPrevSection={{this.moveCursorToPrevSection}}

View File

@ -6,6 +6,7 @@
@deselectCard={{action this.deselectCard}}
@onDeselect={{action "onDeselect"}}
@editCard={{action this.editCard}}
@saveAsSnippet={{this.saveAsSnippet}}
@toolbar={{this.toolbar}}
@hasEditMode={{false}}
@showSelectedOutline={{this.payload.html}}

View File

@ -6,6 +6,7 @@
@selectCard={{action this.selectCard}}
@deselectCard={{action this.deselectCard}}
@editCard={{action this.editCard}}
@saveAsSnippet={{this.saveAsSnippet}}
@toolbar={{this.toolbar}}
@hasEditMode={{false}}
@addParagraphAfterCard={{this.addParagraphAfterCard}}

View File

@ -10,6 +10,7 @@
@deselectCard={{action this.deselectCard}}
@editCard={{action this.editCard}}
@saveCard={{action this.saveCard}}
@saveAsSnippet={{this.saveAsSnippet}}
@onLeaveEdit={{action "leaveEditMode"}}
@editor={{this.editor}}
>

View File

@ -6,6 +6,7 @@
@selectCard={{action this.selectCard}}
@deselectCard={{action this.deselectCard}}
@editCard={{action this.editCard}}
@saveAsSnippet={{this.saveAsSnippet}}
@toolbar={{this.toolbar}}
@hasEditMode={{false}}
@addParagraphAfterCard={{this.addParagraphAfterCard}}

View File

@ -12,6 +12,7 @@
@deselectCard={{action this.deselectCard}}
@editCard={{action this.editCard}}
@saveCard={{action this.saveCard}}
@saveAsSnippet={{this.saveAsSnippet}}
@editor={{this.editor}}
>
{{#if this.isEditing}}

View File

@ -19,8 +19,8 @@
)
)}}
{{#if this.toolbar}}
<KgActionBar @class="absolute" @style={{this.toolbarStyle}} @isVisible={{this.shouldShowToolbar}}>
{{#if (or this.toolbar this.saveAsSnippet)}}
<KgActionBar @class="absolute" @style={{this.toolbarStyle}} @isVisible={{this.shouldShowToolbar}} @instantClose={{this.koenigUi.inputHasFocus}}>
{{#each this.toolbar.items as |item|}}
{{#if item.divider}}
<li class="ma0 kg-action-bar-divider bg-darkgrey-d2 h5" role="separator"></li>
@ -37,5 +37,21 @@
</li>
{{/if}}
{{/each}}
{{#if (and this.saveAsSnippet (enable-developer-experiments))}}
{{#if this.toolbar.items}}
<li class="ma0 lh-solid kg-action-bar-divider bg-darkgrey-l2 h5" role="separator"></li>
{{/if}}
<li class="ma0 lh-solid">
<button
type="button"
title="Create snippet"
class="dib dim-lite link h9 w9 nudge-top--1"
{{on "click" this.saveAsSnippet}}
>
{{svg-jar "koenig/kg-snippet" class="w4 h4"}}
</button>
</li>
{{/if}}
</KgActionBar>
{{/if}}

View File

@ -42,8 +42,11 @@ export default Component.extend({
onEnterEdit() {},
onLeaveEdit() {},
shouldShowToolbar: computed('showToolbar', 'koenigUi.{captionHasFocus,isDragging}', function () {
return this.showToolbar && !this.koenigUi.captionHasFocus && !this.koenigUi.isDragging;
shouldShowToolbar: computed('showToolbar', 'koenigUi.{captionHasFocus,isDragging,inputHasFocus}', function () {
return this.showToolbar
&& !this.koenigUi.captionHasFocus
&& !this.koenigUi.inputHasFocus
&& !this.koenigUi.isDragging;
}),
toolbarStyle: computed('shouldShowToolbar', 'toolbarWidth', 'toolbarHeight', function () {
@ -241,7 +244,7 @@ export default Component.extend({
},
_setToolbarProperties() {
if (this.toolbar) {
if (this.toolbar || this.saveAsSnippet) {
// select the last toolbar in the element because card contents/captions
// may have their own toolbar elements
let toolbar = this.element.querySelector(':scope > [data-kg-toolbar="true"]');
@ -256,7 +259,7 @@ export default Component.extend({
_showToolbar() {
// only show a toolbar if we have one
if (this.toolbar) {
if (this.toolbar || this.saveAsSnippet) {
this._setToolbarProperties();
if (!this.showToolbar && !this._onMousemoveHandler) {

View File

@ -40,6 +40,7 @@
<KoenigSnippetInput
@editor={{this.editor}}
@snippetRange={{this.snippetRange}}
@snippetRect={{this.snippetRect}}
@save={{@saveSnippet}}
@cancel={{this.cancelAddSnippet}}
/>
@ -83,6 +84,7 @@
deselectCard=(action "deselectCard" card)
editCard=(action "editCard" card)
deleteCard=(action "deleteCard" card)
saveAsSnippet=(action "saveCardAsSnippet" card)
moveCursorToPrevSection=(action "moveCursorToPrevSection" card)
moveCursorToNextSection=(action "moveCursorToNextSection" card)
addParagraphAfterCard=(action "addParagraphAfterCard" card)

View File

@ -618,6 +618,12 @@ export default Component.extend({
this.deleteCard(card, cursorMovement);
},
saveCardAsSnippet(card) {
let section = this.getSectionFromCard(card);
this.set('snippetRect', card.component.element.getBoundingClientRect());
this.set('snippetRange', section.toRange());
},
moveCursorToPrevSection(card) {
let section = this.getSectionFromCard(card);
@ -671,11 +677,13 @@ export default Component.extend({
return;
}
this.set('snippetRect', null);
this.set('snippetRange', selectedRange);
}),
cancelAddSnippet: action(function () {
this.set('snippetRange', null);
this.set('snippetRect', null);
}),
/* public interface ----------------------------------------------------- */

View File

@ -4,6 +4,7 @@ import {TOOLBAR_MARGIN} from './koenig-toolbar';
import {action} from '@ember/object';
import {guidFor} from '@ember/object/internals';
import {run} from '@ember/runloop';
import {inject as service} from '@ember/service';
import {tracked} from '@glimmer/tracking';
// pixels that should be added to the `left` property of the tick adjustment styles
@ -11,12 +12,17 @@ import {tracked} from '@glimmer/tracking';
const TICK_ADJUSTMENT = 8;
export default class KoenigSnippetInputComponent extends Component {
@service koenigUi;
@tracked name = '';
@tracked style = ''.htmlSafe();
constructor() {
super(...arguments);
// hide any other toolbars
this.koenigUi.inputHasFocus = true;
// record the range now because the property is bound and will update
// when the selection changes
this._snippetRange = this.args.snippetRange;
@ -46,6 +52,7 @@ export default class KoenigSnippetInputComponent extends Component {
}
willDestroy() {
this.koenigUi.inputHasFocus = false;
window.removeEventListener('mousedown', this._onMousedownHandler);
window.removeEventListener('keydown', this._onKeydownHandler);
this._removeStyleElement();

View File

@ -1,18 +1,22 @@
import Service from '@ember/service';
import {tracked} from '@glimmer/tracking';
export default Service.extend({
captionHasFocus: false,
isDragging: false,
export default class KoenigUiService extends Service {
@tracked captionHasFocus = false;
@tracked inputHasFocus = false;
@tracked isDragging = false;
#focusedCaption = null;
captionGainedFocus(caption) {
this._focusedCaption = caption;
this.set('captionHasFocus', true);
},
this.captionHasFocus = true;
this.#focusedCaption = caption;
}
captionLostFocus(caption) {
if (this._focusedCaption === caption) {
this._focusedCaption = null;
this.set('captionHasFocus', false);
if (this.#focusedCaption === caption) {
this.captionHasFocus = false;
this.#focusedCaption = null;
}
}
});
}