diff --git a/app/assets/javascripts/discourse/app/components/d-modal.gjs b/app/assets/javascripts/discourse/app/components/d-modal.gjs index 6bb6b5edabe..7ca44e041a7 100644 --- a/app/assets/javascripts/discourse/app/components/d-modal.gjs +++ b/app/assets/javascripts/discourse/app/components/d-modal.gjs @@ -1,6 +1,5 @@ import Component from "@glimmer/component"; import { cached, tracked } from "@glimmer/tracking"; -import ClassicComponent from "@ember/component"; import { concat } from "@ember/helper"; import { on } from "@ember/modifier"; 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 DButton from "discourse/components/d-button"; import concatClass from "discourse/helpers/concat-class"; +import element from "discourse/helpers/element"; import { disableBodyScroll, enableBodyScroll, @@ -39,24 +39,24 @@ export default class DModal extends Component { @tracked wrapperElement; @tracked animating = false; - registerModalContainer = modifierFn((element) => { - this.modalContainer = element; + registerModalContainer = modifierFn((el) => { + this.modalContainer = el; }); - setupModalBody = modifierFn((element) => { + setupModalBody = modifierFn((el) => { if (!this.site.mobileView) { return; } - disableBodyScroll(element); + disableBodyScroll(el); return () => { - enableBodyScroll(element); + enableBodyScroll(el); }; }); @action - async setupModal(element) { + async setupModal(el) { document.documentElement.addEventListener( "keydown", this.handleDocumentKeydown @@ -70,7 +70,7 @@ export default class DModal extends Component { if (this.site.mobileView) { this.animating = true; - await element.animate( + await el.animate( [{ transform: "translateY(100%)" }, { transform: "translateY(0)" }], { duration: getMaxAnimationTimeMs(), @@ -82,7 +82,7 @@ export default class DModal extends Component { this.animating = false; } - this.wrapperElement = element; + this.wrapperElement = el; } @action @@ -226,9 +226,7 @@ export default class DModal extends Component { throw `@tagName must be form or div`; } - return class WrapperComponent extends ClassicComponent { - tagName = tagName; - }; + return element(tagName); } @bind diff --git a/app/assets/javascripts/discourse/app/helpers/element.gjs b/app/assets/javascripts/discourse/app/helpers/element.gjs new file mode 100644 index 00000000000..af6142db0df --- /dev/null +++ b/app/assets/javascripts/discourse/app/helpers/element.gjs @@ -0,0 +1,65 @@ +import ClassicComponent from "@ember/component"; + +const empty = ; +const shortcuts = { + div: , + span: , + form: , + a: , + button: , +}; + +/** + * 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|}} + * + * Content + * + * {{/let}} + * ``` + * + * Or in js: + * + * ```gjs + * class MyComponent { + * get wrapper(){ + * return element(this.args.tagName); + * } + * + * + * } + * ``` + */ +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 ; + } +}