/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ import { html, LitElement } from "chrome://global/content/vendor/lit.all.mjs"; import "chrome://browser/content/multilineeditor/multiline-editor.mjs"; import "chrome://global/content/elements/moz-badge.mjs"; import "chrome://global/content/elements/panel-list.js"; import { createMentionsPlugin } from "chrome://browser/content/multilineeditor/plugins/MentionsPlugin.mjs"; export default { title: "UI Widgets/Multiline Editor", component: "moz-multiline-editor", argTypes: { action: { options: [null, "chat", "search", "navigate"], control: { type: "select" }, }, }, parameters: { status: "in-development", }, }; const Template = ({ placeholder }) => html` `; export const Default = Template.bind({}); Default.args = { placeholder: "Placeholder text", }; /** * Demo editor with mentions. */ class MultilineEditorWithMentions extends LitElement { static properties = { placeholder: { type: String }, toDOM: { type: Function }, }; range = null; suggestions = [ { id: "1", label: "One" }, { id: "2", label: "Two" }, { id: "3", label: "Three" }, ]; mentionsPlugin = createMentionsPlugin({ triggerChar: "@", toDOM: node => this.toDOM?.(node) ?? ["mark", {}, node.attrs.label], onEnter: ({ range, view }) => { this.range = range; const panelList = this.shadowRoot.querySelector("panel-list"); panelList.show(null, this.#createVirtualAnchor(view, range)); }, onChange: ({ range }) => { this.range = range; }, onExit: () => { this.shadowRoot.querySelector("panel-list").hide(); }, }); constructor() { super(); this.placeholder = ""; } // Creates a virtual anchor to pass to `panel-list`. #createVirtualAnchor(view, range) { const coordsFrom = view.coordsAtPos(range.from); const coordsTo = view.coordsAtPos(range.to); return { getBoundingClientRect: () => ({ height: coordsTo.bottom - coordsFrom.top, width: coordsTo.right - coordsFrom.left, top: coordsFrom.top, right: coordsTo.right, bottom: coordsTo.bottom, left: coordsFrom.left, x: coordsFrom.left, y: coordsFrom.top, }), setAttribute: () => {}, getAttribute: () => null, hasAttribute: () => false, }; } handlePanelClick(e) { const panelItem = e.target.closest("panel-item"); this.mentionsPlugin.mentions.insert( { type: "default", id: panelItem.dataset.id, label: panelItem.textContent, }, this.range.from, this.range.to ); } render() { return html` ${this.suggestions.map( item => html` ${item.label} ` )} `; } } customElements.define( "multiline-editor-with-mentions", MultilineEditorWithMentions ); const MentionsTemplate = ({ placeholder, toDOM }) => html` `; export const WithMentions = MentionsTemplate.bind({}); WithMentions.args = { placeholder: "Type @ to see suggestions", }; export const WithMentionsCustomElement = MentionsTemplate.bind({}); WithMentionsCustomElement.args = { placeholder: "Type @ to see suggestions", toDOM: node => [ "moz-badge", { label: node.attrs.label, }, node.attrs.label, ], };