<template> <div class="form-row form-group" :key="$attrs.key"> <vue-tribute class="tribute-container" :options="tributeOptions"> <textarea @tribute-no-match="noMatchFound" @tribute-replaced="textReplaced" :ref="localFormElement.key" class="form-control" @focus="clearErrors" @blur="validate" @change="validate" :placeholder="localFormElement.placeholder" :id="localFormElement.key" :name="localFormElement.key" v-model="textValue" cols="1" rows="1" > </textarea> <div class="dropdown-container"> <div class="dropdown six-dot-btn"> <button class="btn" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" > <div> <div data-block-id="ab81c411-c572-47f3-8f30-4051d9050c47" class="notion-selectable notion-text-block" > <div role="button" tabindex="-1" aria-label="Drag" class="svg-container" > <svg role="graphics-symbol" viewBox="0 0 10 10" class="dragHandle" style=" width: 14px; height: 14px; display: block; fill: inherit; flex-shrink: 0; " > <path d="M3,2 C2.44771525,2 2,1.55228475 2,1 C2,0.44771525 2.44771525,0 3,0 C3.55228475,0 4,0.44771525 4,1 C4,1.55228475 3.55228475,2 3,2 Z M3,6 C2.44771525,6 2,5.55228475 2,5 C2,4.44771525 2.44771525,4 3,4 C3.55228475,4 4,4.44771525 4,5 C4,5.55228475 3.55228475,6 3,6 Z M3,10 C2.44771525,10 2,9.55228475 2,9 C2,8.44771525 2.44771525,8 3,8 C3.55228475,8 4,8.44771525 4,9 C4,9.55228475 3.55228475,10 3,10 Z M7,2 C6.44771525,2 6,1.55228475 6,1 C6,0.44771525 6.44771525,0 7,0 C7.55228475,0 8,0.44771525 8,1 C8,1.55228475 7.55228475,2 7,2 Z M7,6 C6.44771525,6 6,5.55228475 6,5 C6,4.44771525 6.44771525,4 7,4 C7.55228475,4 8,4.44771525 8,5 C8,5.55228475 7.55228475,6 7,6 Z M7,10 C6.44771525,10 6,9.55228475 6,9 C6,8.44771525 6.44771525,8 7,8 C7.55228475,8 8,8.44771525 8,9 C8,9.55228475 7.55228475,10 7,10 Z" ></path> </svg> </div> </div> </div> </button> <div class="dropdown-menu" aria-labelledby="dropdownMenu1"> <notion-six-dot-component></notion-six-dot-component> </div> </div> <div class="dropdown plus-btn"> <button class="btn" type="button" id="dropdownMenu2" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" > <div role="button" tabindex="-1" aria-label="Click to add below. Alt-click to add a block above" > <svg role="graphics-symbol" viewBox="0 0 16 16" class="plus" style=" width: 16px; height: 100%; display: block; fill: inherit; flex-shrink: 0; " > <path d="M7.977 14.963c.407 0 .747-.324.747-.723V8.72h5.362c.399 0 .74-.34.74-.747a.746.746 0 00-.74-.738H8.724V1.706c0-.398-.34-.722-.747-.722a.732.732 0 00-.739.722v5.529h-5.37a.746.746 0 00-.74.738c0 .407.341.747.74.747h5.37v5.52c0 .399.332.723.739.723z" ></path> </svg> </div> </button> <div class="dropdown-menu" aria-labelledby="dropdownMenu2"> <notion-plus-component></notion-plus-component> </div> </div> </div> </vue-tribute> </div> </template> <script> import formBuilderMixin from "~/extensions/formBuilderExtension"; import VueTribute from "vue-tribute"; import apis from "~/apis/borhanApi.js"; export default { props: { enableSuggestion: { default: false, }, contextMenu: { default() { return []; }, }, }, extends: formBuilderMixin, data() { return { types: [ { id: "1", title: "javascript", }, { id: "2", title: "PHP", }, { id: "3", title: "SpareQL", }, { id: "4", title: "Paython", }, { id: "5", title: "BASIC", }, ], tributeOptions: { // symbol or string that starts the lookup trigger: "", // element to target for @mentions iframe: null, // class added in the flyout menu for active item selectClass: "highlight", // class added to the menu container containerClass: "tribute-container", // class added to each list item itemClass: "my-tribute-class", // function called on select that returns the content to insert selectTemplate: function (item) { return item.original.value; // return "@" + item.original.value; }, // template for displaying item in menu menuItemTemplate: function (item) { return item.string; }, // template for when no match is found (optional), // If no template is provided, menu is hidden. noMatchTemplate: '<span class="no-result">مورد مشابهی ثبت نشده است.</span>', // specify an alternative parent container for the menu // container must be a positioned element for the menu to appear correctly ie. `position: relative;` // default container is the body menuContainer: document.body, // column to search against in the object (accepts function or string) lookup: "key", // column that contains the content to insert by default fillAttr: "value", // REQUIRED: array of objects to match or a function that returns data (see 'Loading remote data' for an example) values: [ { key: "سلام", value: "سلام", }, { key: "باسلام", value: "باسلام", }, { key: "علیک سلام", value: "علیک سلام", }, { key: "بی سلام", value: "بی سلام", }, { key: "صدتا سلام", value: "صدتا سلام", }, ], // values: ["سلام", "باسلام", "علیک سلام", "بی سلام", "صدتا سلام"], // values: (text, cb) => { // this.remoteSearch(text, (items) => cb(items)); // }, // When your values function is async, an optional loading template to show loadingItemTemplate: null, // specify whether a space is required before the trigger string requireLeadingSpace: true, // specify whether a space is allowed in the middle of mentions allowSpaces: true, // optionally specify a custom suffix for the replace text // (defaults to empty space if undefined) // replaceTextSuffix: "", // specify whether the menu should be positioned. Set to false and use in conjuction with menuContainer to create an inline menu // (defaults to true) positionMenu: true, // when the spacebar is hit, select the current match spaceSelectsMatch: false, // turn tribute into an autocomplete autocompleteMode: true, // Customize the elements used to wrap matched strings within the results list // defaults to <span></span> if undefined searchOpts: { pre: "<span>", post: "</span>", skip: false, // true will skip local search, useful if doing server-side search }, // Limits the number of items in the menu menuItemLimit: 25, // specify the minimum number of characters that must be typed before menu appears menuShowMinLength: 0, }, httpService: undefined, }; }, mounted() { this.httpService = new HttpService(import.meta.env.VITE_BASE_URL); }, methods: { limitText(count) { return `و ${count} کاربر دیگر`; }, noMatchFound(args) { }, textReplaced(args) { }, methodName(action, index = 0) { try { this[action](index); } catch (err) { this.$emit(action, index); } }, remoteSearch(input, callback) { return this.httpService .getRequest(apis.concept.annotations.read + "?ontology_id=" + input) .then((res) => { callback(res.data); }) .catch((e) => { callback([]); }) .finally(() => { this.fetchingData = false; }); }, }, }; </script> <!-- #region tribute --> <style> .tribute-container { flex: 1 1 auto; position: relative; /* width: 100%; */ /* max-width: 100%; */ /* margin-top: 4px; */ /* margin-bottom: 4px; */ /* background-color: #fff; */ ul { margin: 0; margin-top: 2px; padding: 0; list-style: none; /* background: #efefef; */ li { padding: 0.5em 1em; cursor: pointer; &.highlight { /* background: #ddd; */ } &.no-match { cursor: default; } span { font-weight: bold; } } } .menu-highlighted { font-weight: bold; } } .form-group { &:hover { .ta-header, .ta-options { opacity: 1; visibility: visible; transition: opacity 300ms ease-in 0s; } } &.active, &:active { .ta-header, .ta-options { opacity: 1; visibility: visible; transition: opacity 300ms ease-in 0s; } } } </style> <!-- #endregion tribute --> <style lang="scss" scoped> .dropdown-container { // user-select: none; transition: background 20ms ease-in 0s; // cursor: -webkit-grab; display: flex; align-items: center; justify-content: center; fill: rgba(55, 53, 47, 0.35); position: absolute; top: 3px; width: 24px; height: 24px; border-radius: 4px; // pointer-events: auto; right: -2.5em; top: 1em; .dropdown { .dropdown-menu { padding: 0; border: none; border-radius: 0.25rem; text-align: inherit; } &.show { .notion-text-block { .svg-container { // user-select: none; // transition: background 20ms ease-in 0s; // cursor: grab; // display: flex; // align-items: center; // justify-content: center; // width: 18px; // height: 24px; // border-radius: 4px; fill: rgba(55, 53, 47, 0.35); background: rgba(55, 53, 47, 0.08); } } } .notion-text-block { .svg-container { // user-select: none; // transition: background 20ms ease-in 0s; // cursor: grab; display: flex; align-items: center; justify-content: center; width: 18px; height: 24px; border-radius: 4px; // fill: rgba(55, 53, 47, 0.35); // background: rgba(55, 53, 47, 0.08); } } &.plus-btn { // right: -44px; .btn { padding: 0; } } &.six-dot-btn { // right: -22px; .btn { padding: 0; } } } } .form-control { // flex-grow: 1; // flex-shrink: 1; // tab-size: 2; padding: 1em; min-height: 1em; color: rgb(55, 53, 47); white-space: pre; border-radius: 4px; // position: relative; background: #fff; min-width: 0px; width: 100%; resize: none; border-color: transparent; } .main-page__content .form-builder div input { border-color: transparent !important; } </style>