mirror of
https://github.com/discourse/discourse.git
synced 2025-01-18 17:02:45 +08:00
DEV: Introduce element
helper (#27086)
Returns a wrapper component with the given tagname, or an empty wrapper for an empty string. Similar to the reference implementation of RFC389, with higher-performance shortcuts for common elements.
This commit is contained in:
parent
23b02a3824
commit
fb9a43c282
|
@ -1,6 +1,5 @@
|
||||||
import Component from "@glimmer/component";
|
import Component from "@glimmer/component";
|
||||||
import { cached, tracked } from "@glimmer/tracking";
|
import { cached, tracked } from "@glimmer/tracking";
|
||||||
import ClassicComponent from "@ember/component";
|
|
||||||
import { concat } from "@ember/helper";
|
import { concat } from "@ember/helper";
|
||||||
import { on } from "@ember/modifier";
|
import { on } from "@ember/modifier";
|
||||||
import { action } from "@ember/object";
|
import { action } from "@ember/object";
|
||||||
|
@ -12,6 +11,7 @@ import { and, not, or } from "truth-helpers";
|
||||||
import ConditionalInElement from "discourse/components/conditional-in-element";
|
import ConditionalInElement from "discourse/components/conditional-in-element";
|
||||||
import DButton from "discourse/components/d-button";
|
import DButton from "discourse/components/d-button";
|
||||||
import concatClass from "discourse/helpers/concat-class";
|
import concatClass from "discourse/helpers/concat-class";
|
||||||
|
import element from "discourse/helpers/element";
|
||||||
import {
|
import {
|
||||||
disableBodyScroll,
|
disableBodyScroll,
|
||||||
enableBodyScroll,
|
enableBodyScroll,
|
||||||
|
@ -39,24 +39,24 @@ export default class DModal extends Component {
|
||||||
@tracked wrapperElement;
|
@tracked wrapperElement;
|
||||||
@tracked animating = false;
|
@tracked animating = false;
|
||||||
|
|
||||||
registerModalContainer = modifierFn((element) => {
|
registerModalContainer = modifierFn((el) => {
|
||||||
this.modalContainer = element;
|
this.modalContainer = el;
|
||||||
});
|
});
|
||||||
|
|
||||||
setupModalBody = modifierFn((element) => {
|
setupModalBody = modifierFn((el) => {
|
||||||
if (!this.site.mobileView) {
|
if (!this.site.mobileView) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
disableBodyScroll(element);
|
disableBodyScroll(el);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
enableBodyScroll(element);
|
enableBodyScroll(el);
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@action
|
@action
|
||||||
async setupModal(element) {
|
async setupModal(el) {
|
||||||
document.documentElement.addEventListener(
|
document.documentElement.addEventListener(
|
||||||
"keydown",
|
"keydown",
|
||||||
this.handleDocumentKeydown
|
this.handleDocumentKeydown
|
||||||
|
@ -70,7 +70,7 @@ export default class DModal extends Component {
|
||||||
if (this.site.mobileView) {
|
if (this.site.mobileView) {
|
||||||
this.animating = true;
|
this.animating = true;
|
||||||
|
|
||||||
await element.animate(
|
await el.animate(
|
||||||
[{ transform: "translateY(100%)" }, { transform: "translateY(0)" }],
|
[{ transform: "translateY(100%)" }, { transform: "translateY(0)" }],
|
||||||
{
|
{
|
||||||
duration: getMaxAnimationTimeMs(),
|
duration: getMaxAnimationTimeMs(),
|
||||||
|
@ -82,7 +82,7 @@ export default class DModal extends Component {
|
||||||
this.animating = false;
|
this.animating = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.wrapperElement = element;
|
this.wrapperElement = el;
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
|
@ -226,9 +226,7 @@ export default class DModal extends Component {
|
||||||
throw `@tagName must be form or div`;
|
throw `@tagName must be form or div`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return class WrapperComponent extends ClassicComponent {
|
return element(tagName);
|
||||||
tagName = tagName;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@bind
|
@bind
|
||||||
|
|
65
app/assets/javascripts/discourse/app/helpers/element.gjs
Normal file
65
app/assets/javascripts/discourse/app/helpers/element.gjs
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
import ClassicComponent from "@ember/component";
|
||||||
|
|
||||||
|
const empty = <template>
|
||||||
|
{{! template-lint-disable no-yield-only}}{{yield}}
|
||||||
|
</template>;
|
||||||
|
const shortcuts = {
|
||||||
|
div: <template><div ...attributes>{{yield}}</div></template>,
|
||||||
|
span: <template><span ...attributes>{{yield}}</span></template>,
|
||||||
|
form: <template><form ...attributes>{{yield}}</form></template>,
|
||||||
|
a: <template><a ...attributes>{{yield}}</a></template>,
|
||||||
|
button: <template><button ...attributes>{{yield}}</button></template>,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a wrapper component with the given tagname, or an empty wrapper for an empty string.
|
||||||
|
* Similar to the reference implementation of RFC389, with higher-performance shortcuts for common elements.
|
||||||
|
*
|
||||||
|
* Can be used directly in a template:
|
||||||
|
*
|
||||||
|
* ```hbs
|
||||||
|
* {{#let (element @tagName) as |Wrapper|}}
|
||||||
|
* <Wrapper class="pt-10 pb-10 ps-20 box-shadow" ...attributes>
|
||||||
|
* Content
|
||||||
|
* </Wrapper>
|
||||||
|
* {{/let}}
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Or in js:
|
||||||
|
*
|
||||||
|
* ```gjs
|
||||||
|
* class MyComponent {
|
||||||
|
* get wrapper(){
|
||||||
|
* return element(this.args.tagName);
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* <template>
|
||||||
|
* <this.wrapper>
|
||||||
|
* Content
|
||||||
|
* </this.wrapper>
|
||||||
|
* </template>
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
export default function element(tagName) {
|
||||||
|
if (typeof tagName !== "string") {
|
||||||
|
throw new Error(
|
||||||
|
`element helper only accepts string literals, you passed ${tagName}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tagName === null || tagName === undefined) {
|
||||||
|
return null;
|
||||||
|
} else if (tagName === "") {
|
||||||
|
return empty;
|
||||||
|
} else if (shortcuts[tagName]) {
|
||||||
|
return shortcuts[tagName];
|
||||||
|
} else {
|
||||||
|
return <template>
|
||||||
|
<ClassicComponent
|
||||||
|
@tagName={{tagName}}
|
||||||
|
...attributes
|
||||||
|
>{{yield}}</ClassicComponent>
|
||||||
|
</template>;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user