ui: Replace dom-buffering components with ember-stargate Portals (#8273)

* ui: Replace dom-buffering components with ember-stargate Portals
This commit is contained in:
John Cowen 2020-07-09 14:30:17 +01:00 committed by GitHub
parent 77886f6d69
commit b27efcd0ac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 46 additions and 188 deletions

View File

@ -1 +0,0 @@
{{yield}}

View File

@ -1,20 +0,0 @@
import { inject as service } from '@ember/service';
import Component from '@ember/component';
const append = function(content) {
this.element.appendChild(content);
};
export default Component.extend({
buffer: service('dom-buffer'),
init: function() {
this._super(...arguments);
this.append = append.bind(this);
},
didInsertElement: function() {
this._super(...arguments);
this.buffer.on('add', this.append);
},
didDestroyElement: function() {
this._super(...arguments);
this.buffer.off('add', this.append);
},
});

View File

@ -1 +0,0 @@
{{yield}}

View File

@ -1,19 +0,0 @@
import { inject as service } from '@ember/service';
import Component from '@ember/component';
export default Component.extend({
buffer: service('dom-buffer'),
getBufferName: function() {
// TODO: Right now we are only using this for the modal layer
// moving forwards you'll be able to name your buffers
return 'modal';
},
didInsertElement: function() {
this._super(...arguments);
this._element = this.buffer.add(this.getBufferName(), this.element);
},
didDestroyElement: function() {
this._super(...arguments);
this.buffer.remove(this.getBufferName(), this._element);
this._element = null;
},
});

View File

@ -1,32 +1,36 @@
{{on-window 'resize' (action "resize") }} {{on-window 'resize' (action "resize") }}
{{yield}} <Portal @target="modal">
<input id={{name}} type="radio" name="modal" data-checked="{{checked}}" checked={{checked}} onchange={{action 'change'}} /> {{yield}}
<div role="dialog" aria-modal="true"> <div {{ref this 'modal'}} ...attributes>
<label for="modal_close"></label> <input id={{name}} type="radio" name="modal" data-checked="{{checked}}" checked={{checked}} onchange={{action 'change'}} />
<div> <div role="dialog" aria-modal="true">
<div> <label for="modal_close"></label>
<header>
<label for="modal_close">Close</label>
<YieldSlot @name="header">
{{yield (hash
close=(action "close")
)}}
</YieldSlot>
</header>
<div> <div>
<YieldSlot @name="body"> <div>
{{yield (hash <header>
close=(action "close") <label for="modal_close">Close</label>
)}} <YieldSlot @name="header">
</YieldSlot> {{yield (hash
close=(action "close")
)}}
</YieldSlot>
</header>
<div>
<YieldSlot @name="body">
{{yield (hash
close=(action "close")
)}}
</YieldSlot>
</div>
<footer>
<YieldSlot @name="actions" @params={{block-params (action "close")}}>
{{yield (hash
close=(action "close")
)}}
</YieldSlot>
</footer>
</div>
</div> </div>
<footer>
<YieldSlot @name="actions" @params={{block-params (action "close")}}>
{{yield (hash
close=(action "close")
)}}
</YieldSlot>
</footer>
</div> </div>
</div> </div>
</div> </Portal>

View File

@ -1,10 +1,12 @@
import Component from '@ember/component';
import { get, set } from '@ember/object'; import { get, set } from '@ember/object';
import { inject as service } from '@ember/service'; import { inject as service } from '@ember/service';
import DomBufferComponent from 'consul-ui/components/dom-buffer';
import Slotted from 'block-slots'; import Slotted from 'block-slots';
import templatize from 'consul-ui/utils/templatize'; import templatize from 'consul-ui/utils/templatize';
export default DomBufferComponent.extend(Slotted, {
export default Component.extend(Slotted, {
tagName: '',
dom: service('dom'), dom: service('dom'),
checked: true, checked: true,
height: null, height: null,
@ -17,7 +19,7 @@ export default DomBufferComponent.extend(Slotted, {
set(this, 'checked', true); set(this, 'checked', true);
if (this.height === null) { if (this.height === null) {
if (this.element) { if (this.element) {
const dialogPanel = this.dom.element('[role="dialog"] > div > div', this.element); const dialogPanel = this.dom.element('[role="dialog"] > div > div', this.modal);
const rect = dialogPanel.getBoundingClientRect(); const rect = dialogPanel.getBoundingClientRect();
set(this, 'dialog', dialogPanel); set(this, 'dialog', dialogPanel);
set(this, 'height', rect.height); set(this, 'height', rect.height);
@ -110,7 +112,7 @@ export default DomBufferComponent.extend(Slotted, {
close: function() { close: function() {
const $close = this.dom.element('#modal_close'); const $close = this.dom.element('#modal_close');
$close.checked = true; $close.checked = true;
const $input = this.dom.element('input[name="modal"]', this.element); const $input = this.dom.element('input[name="modal"]', this.modal);
$input.onchange({ target: $input }); $input.onchange({ target: $input });
}, },
}, },

View File

@ -1 +1,4 @@
<span><input id="modal_close" type="radio" name="modal" onchange={{action 'change'}} /></span> <div>
<span><input id="modal_close" type="radio" name="modal" onchange={{action 'change'}} /></span>
<PortalTarget @name="modal" @multiple={{true}} />
</div>

View File

@ -1,8 +1,9 @@
import DomBufferFlushComponent from 'consul-ui/components/dom-buffer-flush'; import Component from '@ember/component';
import { inject as service } from '@ember/service'; import { inject as service } from '@ember/service';
export default DomBufferFlushComponent.extend({ export default Component.extend({
dom: service('dom'), dom: service('dom'),
tagName: '',
actions: { actions: {
change: function(e) { change: function(e) {
[...this.dom.elements('[name="modal"]')] [...this.dom.elements('[name="modal"]')]

View File

@ -1,46 +0,0 @@
import Service from '@ember/service';
import Evented from '@ember/object/evented';
let buffers;
// TODO: This all should be replaced with {{#in-element}} if possible
export default Service.extend(Evented, {
init: function() {
this._super(...arguments);
buffers = {};
},
willDestroy: function() {
Object.entries(buffers).forEach(function([key, items]) {
items.forEach(function(item) {
item.remove();
});
});
buffers = null;
},
// TODO: Consider renaming this and/or
// `delete`ing the buffer (but not the DOM element)
// flush should flush, but maybe being able to re-flush
// after you've flushed could be handy
flush: function(name) {
return buffers[name];
},
add: function(name, dom) {
this.trigger('add', dom);
if (typeof buffers[name] === 'undefined') {
buffers[name] = [];
}
buffers[name].push(dom);
return dom;
},
remove: function(name, dom) {
if (typeof buffers[name] !== 'undefined') {
const buffer = buffers[name];
const i = buffer.findIndex(item => item === dom);
if (i !== -1) {
const item = buffer.splice(i, 1)[0];
item.remove();
}
if (buffer.length === 0) {
delete buffers[name];
}
}
},
});

View File

@ -1,26 +0,0 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';
module('Integration | Component | dom buffer flush', function(hooks) {
setupRenderingTest(hooks);
test('it renders', async function(assert) {
// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.on('myAction', function(val) { ... });
await render(hbs`{{dom-buffer-flush}}`);
assert.dom('*').hasText('');
// Template block usage:
await render(hbs`
{{#dom-buffer-flush}}
template block text
{{/dom-buffer-flush}}
`);
assert.dom('*').hasText('template block text');
});
});

View File

@ -1,26 +0,0 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';
module('Integration | Component | dom buffer', function(hooks) {
setupRenderingTest(hooks);
test('it renders', async function(assert) {
// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.on('myAction', function(val) { ... });
await render(hbs`{{dom-buffer}}`);
assert.dom('*').hasText('');
// Template block usage:
await render(hbs`
{{#dom-buffer}}
template block text
{{/dom-buffer}}
`);
assert.dom('*').hasText('template block text');
});
});

View File

@ -10,7 +10,7 @@ module('Integration | Component | modal dialog', function(hooks) {
// Set any properties with this.set('myProperty', 'value'); // Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.on('myAction', function(val) { ... }); // Handle any actions with this.on('myAction', function(val) { ... });
await render(hbs`{{modal-dialog}}`); await render(hbs`<ModalLayer /><ModalDialog />`);
assert.ok( assert.ok(
find('*') find('*')
@ -20,8 +20,7 @@ module('Integration | Component | modal dialog', function(hooks) {
// Template block usage: // Template block usage:
await render(hbs` await render(hbs`
{{#modal-dialog}} <ModalLayer /><ModalDialog></ModalDialog>
{{/modal-dialog}}
`); `);
assert.ok( assert.ok(

View File

@ -1,12 +0,0 @@
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
module('Unit | Service | dom buffer', function(hooks) {
setupTest(hooks);
// Replace this with your real tests.
test('it exists', function(assert) {
let service = this.owner.lookup('service:dom-buffer');
assert.ok(service);
});
});