@ckeditor/ckeditor5-mention 36.0.0 → 37.0.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/mention.js CHANGED
@@ -1,4 +1,4 @@
1
1
  /*!
2
2
  * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md.
4
- */(()=>{var e={677:(e,t,n)=>{"use strict";n.d(t,{Z:()=>r});var i=n(609),o=n.n(i)()((function(e){return e[1]}));o.push([e.id,":root{--ck-color-mention-background:rgba(153,0,48,.1);--ck-color-mention-text:#990030}.ck-content .mention{background:var(--ck-color-mention-background);color:var(--ck-color-mention-text)}",""]);const r=o},216:(e,t,n)=>{"use strict";n.d(t,{Z:()=>r});var i=n(609),o=n.n(i)()((function(e){return e[1]}));o.push([e.id,":root{--ck-mention-list-max-height:300px}.ck.ck-mentions{max-height:var(--ck-mention-list-max-height);overflow-x:hidden;overflow-y:auto;overscroll-behavior:contain}.ck.ck-mentions>.ck-list__item{flex-shrink:0;overflow:hidden}",""]);const r=o},609:e=>{"use strict";e.exports=function(e){var t=[];return t.toString=function(){return this.map((function(t){var n=e(t);return t[2]?"@media ".concat(t[2]," {").concat(n,"}"):n})).join("")},t.i=function(e,n,i){"string"==typeof e&&(e=[[null,e,""]]);var o={};if(i)for(var r=0;r<this.length;r++){var s=this[r][0];null!=s&&(o[s]=!0)}for(var a=0;a<e.length;a++){var c=[].concat(e[a]);i&&o[c[0]]||(n&&(c[2]?c[2]="".concat(n," and ").concat(c[2]):c[2]=n),t.push(c))}},t}},62:(e,t,n)=>{"use strict";var i,o=function(){return void 0===i&&(i=Boolean(window&&document&&document.all&&!window.atob)),i},r=function(){var e={};return function(t){if(void 0===e[t]){var n=document.querySelector(t);if(window.HTMLIFrameElement&&n instanceof window.HTMLIFrameElement)try{n=n.contentDocument.head}catch(e){n=null}e[t]=n}return e[t]}}(),s=[];function a(e){for(var t=-1,n=0;n<s.length;n++)if(s[n].identifier===e){t=n;break}return t}function c(e,t){for(var n={},i=[],o=0;o<e.length;o++){var r=e[o],c=t.base?r[0]+t.base:r[0],d=n[c]||0,l="".concat(c," ").concat(d);n[c]=d+1;var u=a(l),m={css:r[1],media:r[2],sourceMap:r[3]};-1!==u?(s[u].references++,s[u].updater(m)):s.push({identifier:l,updater:p(m,t),references:1}),i.push(l)}return i}function d(e){var t=document.createElement("style"),i=e.attributes||{};if(void 0===i.nonce){var o=n.nc;o&&(i.nonce=o)}if(Object.keys(i).forEach((function(e){t.setAttribute(e,i[e])})),"function"==typeof e.insert)e.insert(t);else{var s=r(e.insert||"head");if(!s)throw new Error("Couldn't find a style target. This probably means that the value for the 'insert' parameter is invalid.");s.appendChild(t)}return t}var l,u=(l=[],function(e,t){return l[e]=t,l.filter(Boolean).join("\n")});function m(e,t,n,i){var o=n?"":i.media?"@media ".concat(i.media," {").concat(i.css,"}"):i.css;if(e.styleSheet)e.styleSheet.cssText=u(t,o);else{var r=document.createTextNode(o),s=e.childNodes;s[t]&&e.removeChild(s[t]),s.length?e.insertBefore(r,s[t]):e.appendChild(r)}}function h(e,t,n){var i=n.css,o=n.media,r=n.sourceMap;if(o?e.setAttribute("media",o):e.removeAttribute("media"),r&&"undefined"!=typeof btoa&&(i+="\n/*# sourceMappingURL=data:application/json;base64,".concat(btoa(unescape(encodeURIComponent(JSON.stringify(r))))," */")),e.styleSheet)e.styleSheet.cssText=i;else{for(;e.firstChild;)e.removeChild(e.firstChild);e.appendChild(document.createTextNode(i))}}var f=null,g=0;function p(e,t){var n,i,o;if(t.singleton){var r=g++;n=f||(f=d(t)),i=m.bind(null,n,r,!1),o=m.bind(null,n,r,!0)}else n=d(t),i=h.bind(null,n,t),o=function(){!function(e){if(null===e.parentNode)return!1;e.parentNode.removeChild(e)}(n)};return i(e),function(t){if(t){if(t.css===e.css&&t.media===e.media&&t.sourceMap===e.sourceMap)return;i(e=t)}else o()}}e.exports=function(e,t){(t=t||{}).singleton||"boolean"==typeof t.singleton||(t.singleton=o());var n=c(e=e||[],t);return function(e){if(e=e||[],"[object Array]"===Object.prototype.toString.call(e)){for(var i=0;i<n.length;i++){var o=a(n[i]);s[o].references--}for(var r=c(e,t),d=0;d<n.length;d++){var l=a(n[d]);0===s[l].references&&(s[l].updater(),s.splice(l,1))}n=r}}}},704:(e,t,n)=>{e.exports=n(79)("./src/core.js")},181:(e,t,n)=>{e.exports=n(79)("./src/typing.js")},273:(e,t,n)=>{e.exports=n(79)("./src/ui.js")},209:(e,t,n)=>{e.exports=n(79)("./src/utils.js")},79:e=>{"use strict";e.exports=CKEditor5.dll}},t={};function n(i){var o=t[i];if(void 0!==o)return o.exports;var r=t[i]={id:i,exports:{}};return e[i](r,r.exports,n),r.exports}n.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return n.d(t,{a:t}),t},n.d=(e,t)=>{for(var i in t)n.o(t,i)&&!n.o(e,i)&&Object.defineProperty(e,i,{enumerable:!0,get:t[i]})},n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),n.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.nc=void 0;var i={};(()=>{"use strict";n.r(i),n.d(i,{Mention:()=>ae,MentionEditing:()=>r,MentionUI:()=>X});var e=n(704),t=n(209);class o extends e.Command{refresh(){const e=this.editor.model,t=e.document;this.isEnabled=e.schema.checkAttributeInSelection(t.selection,"mention")}execute(e){const n=this.editor.model,i=n.document.selection,o="string"==typeof e.mention?{id:e.mention}:e.mention,r=o.id,a=e.range||i.getFirstRange(),c=e.text||r,d=s({_text:c,id:r},o);if(1!=e.marker.length)throw new t.CKEditorError("mentioncommand-incorrect-marker",this);if(r.charAt(0)!=e.marker)throw new t.CKEditorError("mentioncommand-incorrect-id",this);n.change((e=>{const o=(0,t.toMap)(i.getAttributes()),r=new Map(o.entries());r.set("mention",d),n.insertContent(e.createText(c,r),a),n.insertContent(e.createText(" ",o),a.start.getShiftedBy(c.length))}))}}class r extends e.Plugin{static get pluginName(){return"MentionEditing"}init(){const e=this.editor,t=e.model,n=t.document;t.schema.extend("$text",{allowAttributes:"mention"}),e.conversion.for("upcast").elementToAttribute({view:{name:"span",key:"data-mention",classes:"mention"},model:{key:"mention",value:e=>a(e)}}),e.conversion.for("downcast").attributeToElement({model:"mention",view:d}),e.conversion.for("downcast").add(c),n.registerPostFixer((e=>function(e,t,n){const i=t.differ.getChanges();let o=!1;for(const t of i){if("attribute"==t.type)continue;const i=t.position;if("$text"==t.name){const t=i.textNode&&i.textNode.nextSibling;o=u(i.textNode,e)||o,o=u(t,e)||o,o=u(i.nodeBefore,e)||o,o=u(i.nodeAfter,e)||o}if("$text"!=t.name&&"insert"==t.type){const t=i.nodeAfter;for(const n of e.createRangeIn(t).getItems())o=u(n,e)||o}if("insert"==t.type&&n.isInline(t.name)){const t=i.nodeAfter&&i.nodeAfter.nextSibling;o=u(i.nodeBefore,e)||o,o=u(t,e)||o}}return o}(e,n,t.schema))),n.registerPostFixer((e=>function(e,t){const n=t.differ.getChanges();let i=!1;for(const t of n)if("attribute"===t.type&&"mention"!=t.attributeKey){const n=t.range.start.nodeBefore,o=t.range.end.nodeAfter;for(const r of[n,o])l(r)&&r.getAttribute(t.attributeKey)!=t.attributeNewValue&&(e.setAttribute(t.attributeKey,t.attributeNewValue,r),i=!0)}return i}(e,n))),n.registerPostFixer((e=>function(e,t){const n=t.selection,i=n.focus;if(n.isCollapsed&&n.hasAttribute("mention")&&function(e){const t=e.isAtStart;return e.nodeBefore&&e.nodeBefore.is("$text")||t}(i))return e.removeSelectionAttribute("mention"),!0;return!1}(e,n))),e.commands.add("mention",new o(e))}}function s(e,n){return Object.assign({uid:(0,t.uid)()},e,n||{})}function a(e,t){const n=e.getAttribute("data-mention"),i=e.getChild(0);if(!i)return;return s({id:n,_text:i.data},t)}function c(e){e.on("attribute:mention",((e,t,n)=>{const i=t.attributeNewValue;if(!t.item.is("$textProxy")||!i)return;const o=t.range.start;(o.textNode||o.nodeAfter).data!=i._text&&n.consumable.consume(t.item,e.name)}),{priority:"highest"})}function d(e,{writer:t}){if(!e)return;const n={class:"mention","data-mention":e.id},i={id:e.uid,priority:20};return t.createAttributeElement("span",n,i)}function l(e){if(!e||!e.is("$text")&&!e.is("$textProxy")||!e.hasAttribute("mention"))return!1;return e.data!=e.getAttribute("mention")._text}function u(e,t){return!!l(e)&&(t.removeAttribute("mention",e),!0)}var m=n(273),h=n(181);const f=function(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)};const g="object"==typeof global&&global&&global.Object===Object&&global;var p="object"==typeof self&&self&&self.Object===Object&&self;const v=g||p||Function("return this")();const b=function(){return v.Date.now()};var w=/\s/;const x=function(e){for(var t=e.length;t--&&w.test(e.charAt(t)););return t};var y=/^\s+/;const k=function(e){return e?e.slice(0,x(e)+1).replace(y,""):e};const _=v.Symbol;var C=Object.prototype,A=C.hasOwnProperty,T=C.toString,I=_?_.toStringTag:void 0;const M=function(e){var t=A.call(e,I),n=e[I];try{e[I]=void 0;var i=!0}catch(e){}var o=T.call(e);return i&&(t?e[I]=n:delete e[I]),o};var R=Object.prototype.toString;const S=function(e){return R.call(e)};var V=_?_.toStringTag:void 0;const E=function(e){return null==e?void 0===e?"[object Undefined]":"[object Null]":V&&V in Object(e)?M(e):S(e)};const j=function(e){return null!=e&&"object"==typeof e};const O=function(e){return"symbol"==typeof e||j(e)&&"[object Symbol]"==E(e)};var P=/^[-+]0x[0-9a-f]+$/i,N=/^0b[01]+$/i,U=/^0o[0-7]+$/i,F=parseInt;const B=function(e){if("number"==typeof e)return e;if(O(e))return NaN;if(f(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=f(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=k(e);var n=N.test(e);return n||U.test(e)?F(e.slice(2),n?2:8):P.test(e)?NaN:+e};var $=Math.max,q=Math.min;const L=function(e,t,n){var i,o,r,s,a,c,d=0,l=!1,u=!1,m=!0;if("function"!=typeof e)throw new TypeError("Expected a function");function h(t){var n=i,r=o;return i=o=void 0,d=t,s=e.apply(r,n)}function g(e){return d=e,a=setTimeout(v,t),l?h(e):s}function p(e){var n=e-c;return void 0===c||n>=t||n<0||u&&e-d>=r}function v(){var e=b();if(p(e))return w(e);a=setTimeout(v,function(e){var n=t-(e-c);return u?q(n,r-(e-d)):n}(e))}function w(e){return a=void 0,m&&i?h(e):(i=o=void 0,s)}function x(){var e=b(),n=p(e);if(i=arguments,o=this,c=e,n){if(void 0===a)return g(c);if(u)return clearTimeout(a),a=setTimeout(v,t),h(c)}return void 0===a&&(a=setTimeout(v,t)),s}return t=B(t)||0,f(n)&&(l=!!n.leading,r=(u="maxWait"in n)?$(B(n.maxWait)||0,t):r,m="trailing"in n?!!n.trailing:m),x.cancel=function(){void 0!==a&&clearTimeout(a),d=0,i=c=o=a=void 0},x.flush=function(){return void 0===a?s:w(b())},x};var D=n(62),K=n.n(D),W=n(216),Z={injectType:"singletonStyleTag",attributes:{"data-cke":!0},insert:"head",singleton:!0};K()(W.Z,Z);W.Z.locals;class H extends m.ListView{constructor(e){super(e),this.extendTemplate({attributes:{class:["ck-mentions"],tabindex:"-1"}})}selectFirst(){this.select(0)}selectNext(){const e=this.selected,t=this.items.getIndex(e);this.select(t+1)}selectPrevious(){const e=this.selected,t=this.items.getIndex(e);this.select(t-1)}select(e){let t=0;e>0&&e<this.items.length?t=e:e<0&&(t=this.items.length-1);const n=this.items.get(t);this.selected!==n&&(this.selected&&this.selected.removeHighlight(),n.highlight(),this.selected=n,this._isItemVisibleInScrolledArea(n)||(this.element.scrollTop=n.element.offsetTop))}executeSelected(){this.selected.fire("execute")}_isItemVisibleInScrolledArea(e){return new t.Rect(this.element).contains(new t.Rect(e.element))}}class J extends m.View{constructor(e,t){super(e),this.template=!1,this.domElement=t,this.domElement.classList.add("ck-button"),this.set("isOn",!1),this.on("change:isOn",((e,t,n)=>{n?(this.domElement.classList.add("ck-on"),this.domElement.classList.remove("ck-off")):(this.domElement.classList.add("ck-off"),this.domElement.classList.remove("ck-on"))})),this.listenTo(this.domElement,"click",(()=>{this.fire("execute")}))}render(){super.render(),this.element=this.domElement}}class z extends m.ListItemView{highlight(){this.children.first.isOn=!0}removeHighlight(){this.children.first.isOn=!1}}const G=[t.keyCodes.arrowup,t.keyCodes.arrowdown,t.keyCodes.esc],Q=[t.keyCodes.enter,t.keyCodes.tab];class X extends e.Plugin{static get pluginName(){return"MentionUI"}static get requires(){return[m.ContextualBalloon]}constructor(e){super(e),this._items=new t.Collection,this._mentionsView=this._createMentionView(),this._mentionsConfigurations=new Map,this._requestFeedDebounced=L(this._requestFeed,100),e.config.define("mention",{feeds:[]})}init(){const e=this.editor,n=e.config.get("mention.commitKeys")||Q,i=G.concat(n);this._balloon=e.plugins.get(m.ContextualBalloon),e.editing.view.document.on("keydown",((e,o)=>{var r;r=o.keyCode,i.includes(r)&&this._isUIVisible&&(o.preventDefault(),e.stop(),o.keyCode==t.keyCodes.arrowdown&&this._mentionsView.selectNext(),o.keyCode==t.keyCodes.arrowup&&this._mentionsView.selectPrevious(),n.includes(o.keyCode)&&this._mentionsView.executeSelected(),o.keyCode==t.keyCodes.esc&&this._hideUIAndRemoveMarker())}),{priority:"highest"}),(0,m.clickOutsideHandler)({emitter:this._mentionsView,activator:()=>this._isUIVisible,contextElements:()=>[this._balloon.view.element],callback:()=>this._hideUIAndRemoveMarker()});const o=e.config.get("mention.feeds");for(const e of o){const n=e.feed,i=e.marker;if(!ie(i))throw new t.CKEditorError("mentionconfig-incorrect-marker",null,{marker:i});const o={marker:i,feedCallback:"function"==typeof n?n.bind(this.editor):ne(n),itemRenderer:e.itemRenderer};this._mentionsConfigurations.set(i,o)}this._setupTextWatcher(o),this.listenTo(e,"change:isReadOnly",(()=>{this._hideUIAndRemoveMarker()})),this.on("requestFeed:response",((e,t)=>this._handleFeedResponse(t))),this.on("requestFeed:error",(()=>this._hideUIAndRemoveMarker()))}destroy(){super.destroy(),this._mentionsView.destroy()}get _isUIVisible(){return this._balloon.visibleView===this._mentionsView}_createMentionView(){const e=this.editor.locale,t=new H(e);return t.items.bindTo(this._items).using((n=>{const{item:i,marker:o}=n,r=this.editor.config.get("mention.dropdownLimit")||10;if(t.items.length>=r)return null;const s=new z(e),a=this._renderItem(i,o);return a.delegate("execute").to(s),s.children.add(a),s.item=i,s.marker=o,s.on("execute",(()=>{t.fire("execute",{item:i,marker:o})})),s})),t.on("execute",((e,t)=>{const n=this.editor,i=n.model,o=t.item,r=t.marker,s=n.model.markers.get("mention"),a=i.createPositionAt(i.document.selection.focus),c=i.createPositionAt(s.getStart()),d=i.createRange(c,a);this._hideUIAndRemoveMarker(),n.execute("mention",{mention:o,text:o.text,marker:r,range:d}),n.editing.view.focus()})),t}_getItemRenderer(e){const{itemRenderer:t}=this._mentionsConfigurations.get(e);return t}_requestFeed(e,n){this._lastRequested=n;const{feedCallback:i}=this._mentionsConfigurations.get(e),o=i(n);o instanceof Promise?o.then((t=>{this._lastRequested==n?this.fire("requestFeed:response",{feed:t,marker:e,feedText:n}):this.fire("requestFeed:discarded",{feed:t,marker:e,feedText:n})})).catch((n=>{this.fire("requestFeed:error",{error:n}),(0,t.logWarning)("mention-feed-callback-error",{marker:e})})):this.fire("requestFeed:response",{feed:o,marker:e,feedText:n})}_setupTextWatcher(e){const t=this.editor,n=e.map((e=>({...e,pattern:te(e.marker,e.minimumCharacters||0)}))),i=new h.TextWatcher(t.model,function(e){const t=t=>{const n=ee(e,t);if(!n)return!1;let i=0;0!==n.position&&(i=n.position-1);const o=t.substring(i);return n.pattern.test(o)};return t}(n));i.on("matched",((e,i)=>{const o=ee(n,i.text),r=t.model.document.selection.focus,s=t.model.createPositionAt(r.parent,o.position);if(function(e){const t=e.textNode&&e.textNode.hasAttribute("mention"),n=e.nodeBefore;return t||n&&n.is("$text")&&n.hasAttribute("mention")}(r)||function(e){const t=e.nodeAfter;return t&&t.is("$text")&&t.hasAttribute("mention")}(s))return void this._hideUIAndRemoveMarker();const a=function(e,t){let n=0;0!==e.position&&(n=e.position-1);const i=te(e.marker,0),o=t.substring(n);return o.match(i)[2]}(o,i.text),c=o.marker.length+a.length,d=r.getShiftedBy(-c),l=r.getShiftedBy(-a.length),u=t.model.createRange(d,l);if(oe(t)){const e=t.model.markers.get("mention");t.model.change((t=>{t.updateMarker(e,{range:u})}))}else t.model.change((e=>{e.addMarker("mention",{range:u,usingOperation:!1,affectsData:!1})}));this._requestFeedDebounced(o.marker,a)})),i.on("unmatched",(()=>{this._hideUIAndRemoveMarker()}));const o=t.commands.get("mention");return i.bind("isEnabled").to(o),i}_handleFeedResponse(e){const{feed:t,marker:n}=e;if(!oe(this.editor))return;this._items.clear();for(const e of t){const t="object"!=typeof e?{id:e,text:e}:e;this._items.add({item:t,marker:n})}const i=this.editor.model.markers.get("mention");this._items.length?this._showOrUpdateUI(i):this._hideUIAndRemoveMarker()}_showOrUpdateUI(e){this._isUIVisible?this._balloon.updatePosition(this._getBalloonPanelPositionData(e,this._mentionsView.position)):this._balloon.add({view:this._mentionsView,position:this._getBalloonPanelPositionData(e,this._mentionsView.position),singleViewMode:!0}),this._mentionsView.position=this._balloon.view.position,this._mentionsView.selectFirst()}_hideUIAndRemoveMarker(){this._balloon.hasView(this._mentionsView)&&this._balloon.remove(this._mentionsView),oe(this.editor)&&this.editor.model.change((e=>e.removeMarker("mention"))),this._mentionsView.position=void 0}_renderItem(e,t){const n=this.editor;let i,o=e.id;const r=this._getItemRenderer(t);if(r){const t=r(e);"string"!=typeof t?i=new J(n.locale,t):o=t}if(!i){const e=new m.ButtonView(n.locale);e.label=o,e.withText=!0,i=e}return i}_getBalloonPanelPositionData(e,n){const i=this.editor,o=i.editing,r=o.view.domConverter,s=o.mapper;return{target:()=>{let n=e.getRange();"$graveyard"==n.start.root.rootName&&(n=i.model.document.selection.getFirstRange());const o=s.toViewRange(n);return t.Rect.getDomRangeRects(r.viewRangeToDom(o)).pop()},limiter:()=>{const e=this.editor.editing.view,t=e.document.selection.editableElement;return t?e.domConverter.mapViewToDom(t.root):null},positions:Y(n)}}}function Y(e){const t={caret_se:e=>({top:e.bottom+3,left:e.right,name:"caret_se",config:{withArrow:!1}}),caret_ne:(e,t)=>({top:e.top-t.height-3,left:e.right,name:"caret_ne",config:{withArrow:!1}}),caret_sw:(e,t)=>({top:e.bottom+3,left:e.right-t.width,name:"caret_sw",config:{withArrow:!1}}),caret_nw:(e,t)=>({top:e.top-t.height-3,left:e.right-t.width,name:"caret_nw",config:{withArrow:!1}})};return Object.prototype.hasOwnProperty.call(t,e)?[t[e]]:[t.caret_se,t.caret_sw,t.caret_ne,t.caret_nw]}function ee(e,t){let n;for(const i of e){const e=t.lastIndexOf(i.marker);e>0&&!t.substring(e-1).match(i.pattern)||(!n||e>=n.position)&&(n={marker:i.marker,position:e,minimumCharacters:i.minimumCharacters,pattern:i.pattern})}return n}function te(e,n){const i=0==n?"*":`{${n},}`,o=t.env.features.isRegExpUnicodePropertySupported?"\\p{Ps}\\p{Pi}\"'":"\\(\\[{\"'";return new RegExp(`(?:^|[ ${o}])([${e}])(.${i})$`,"u")}function ne(e){return t=>e.filter((e=>("string"==typeof e?e:String(e.id)).toLowerCase().includes(t.toLowerCase())))}function ie(e){return e&&1==e.length}function oe(e){return e.model.markers.has("mention")}var re=n(677),se={injectType:"singletonStyleTag",attributes:{"data-cke":!0},insert:"head",singleton:!0};K()(re.Z,se);re.Z.locals;class ae extends e.Plugin{toMentionAttribute(e,t){return a(e,t)}static get pluginName(){return"Mention"}static get requires(){return[r,X]}}})(),(window.CKEditor5=window.CKEditor5||{}).mention=i})();
4
+ */(()=>{var e={677:(e,t,n)=>{"use strict";n.d(t,{Z:()=>r});var i=n(609),o=n.n(i)()((function(e){return e[1]}));o.push([e.id,":root{--ck-color-mention-background:rgba(153,0,48,.1);--ck-color-mention-text:#990030}.ck-content .mention{background:var(--ck-color-mention-background);color:var(--ck-color-mention-text)}",""]);const r=o},216:(e,t,n)=>{"use strict";n.d(t,{Z:()=>r});var i=n(609),o=n.n(i)()((function(e){return e[1]}));o.push([e.id,":root{--ck-mention-list-max-height:300px}.ck.ck-mentions{max-height:var(--ck-mention-list-max-height);overflow-x:hidden;overflow-y:auto;overscroll-behavior:contain}.ck.ck-mentions>.ck-list__item{flex-shrink:0;overflow:hidden}",""]);const r=o},609:e=>{"use strict";e.exports=function(e){var t=[];return t.toString=function(){return this.map((function(t){var n=e(t);return t[2]?"@media ".concat(t[2]," {").concat(n,"}"):n})).join("")},t.i=function(e,n,i){"string"==typeof e&&(e=[[null,e,""]]);var o={};if(i)for(var r=0;r<this.length;r++){var s=this[r][0];null!=s&&(o[s]=!0)}for(var a=0;a<e.length;a++){var c=[].concat(e[a]);i&&o[c[0]]||(n&&(c[2]?c[2]="".concat(n," and ").concat(c[2]):c[2]=n),t.push(c))}},t}},62:(e,t,n)=>{"use strict";var i,o=function(){return void 0===i&&(i=Boolean(window&&document&&document.all&&!window.atob)),i},r=function(){var e={};return function(t){if(void 0===e[t]){var n=document.querySelector(t);if(window.HTMLIFrameElement&&n instanceof window.HTMLIFrameElement)try{n=n.contentDocument.head}catch(e){n=null}e[t]=n}return e[t]}}(),s=[];function a(e){for(var t=-1,n=0;n<s.length;n++)if(s[n].identifier===e){t=n;break}return t}function c(e,t){for(var n={},i=[],o=0;o<e.length;o++){var r=e[o],c=t.base?r[0]+t.base:r[0],d=n[c]||0,l="".concat(c," ").concat(d);n[c]=d+1;var u=a(l),m={css:r[1],media:r[2],sourceMap:r[3]};-1!==u?(s[u].references++,s[u].updater(m)):s.push({identifier:l,updater:p(m,t),references:1}),i.push(l)}return i}function d(e){var t=document.createElement("style"),i=e.attributes||{};if(void 0===i.nonce){var o=n.nc;o&&(i.nonce=o)}if(Object.keys(i).forEach((function(e){t.setAttribute(e,i[e])})),"function"==typeof e.insert)e.insert(t);else{var s=r(e.insert||"head");if(!s)throw new Error("Couldn't find a style target. This probably means that the value for the 'insert' parameter is invalid.");s.appendChild(t)}return t}var l,u=(l=[],function(e,t){return l[e]=t,l.filter(Boolean).join("\n")});function m(e,t,n,i){var o=n?"":i.media?"@media ".concat(i.media," {").concat(i.css,"}"):i.css;if(e.styleSheet)e.styleSheet.cssText=u(t,o);else{var r=document.createTextNode(o),s=e.childNodes;s[t]&&e.removeChild(s[t]),s.length?e.insertBefore(r,s[t]):e.appendChild(r)}}function h(e,t,n){var i=n.css,o=n.media,r=n.sourceMap;if(o?e.setAttribute("media",o):e.removeAttribute("media"),r&&"undefined"!=typeof btoa&&(i+="\n/*# sourceMappingURL=data:application/json;base64,".concat(btoa(unescape(encodeURIComponent(JSON.stringify(r))))," */")),e.styleSheet)e.styleSheet.cssText=i;else{for(;e.firstChild;)e.removeChild(e.firstChild);e.appendChild(document.createTextNode(i))}}var f=null,g=0;function p(e,t){var n,i,o;if(t.singleton){var r=g++;n=f||(f=d(t)),i=m.bind(null,n,r,!1),o=m.bind(null,n,r,!0)}else n=d(t),i=h.bind(null,n,t),o=function(){!function(e){if(null===e.parentNode)return!1;e.parentNode.removeChild(e)}(n)};return i(e),function(t){if(t){if(t.css===e.css&&t.media===e.media&&t.sourceMap===e.sourceMap)return;i(e=t)}else o()}}e.exports=function(e,t){(t=t||{}).singleton||"boolean"==typeof t.singleton||(t.singleton=o());var n=c(e=e||[],t);return function(e){if(e=e||[],"[object Array]"===Object.prototype.toString.call(e)){for(var i=0;i<n.length;i++){var o=a(n[i]);s[o].references--}for(var r=c(e,t),d=0;d<n.length;d++){var l=a(n[d]);0===s[l].references&&(s[l].updater(),s.splice(l,1))}n=r}}}},704:(e,t,n)=>{e.exports=n(79)("./src/core.js")},181:(e,t,n)=>{e.exports=n(79)("./src/typing.js")},273:(e,t,n)=>{e.exports=n(79)("./src/ui.js")},209:(e,t,n)=>{e.exports=n(79)("./src/utils.js")},79:e=>{"use strict";e.exports=CKEditor5.dll}},t={};function n(i){var o=t[i];if(void 0!==o)return o.exports;var r=t[i]={id:i,exports:{}};return e[i](r,r.exports,n),r.exports}n.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return n.d(t,{a:t}),t},n.d=(e,t)=>{for(var i in t)n.o(t,i)&&!n.o(e,i)&&Object.defineProperty(e,i,{enumerable:!0,get:t[i]})},n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),n.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.nc=void 0;var i={};(()=>{"use strict";n.r(i),n.d(i,{Mention:()=>he,MentionEditing:()=>r,MentionUI:()=>oe});var e=n(704),t=n(209);class o extends e.Command{refresh(){const e=this.editor.model,t=e.document;this.isEnabled=e.schema.checkAttributeInSelection(t.selection,"mention")}execute(e){const n=this.editor.model,i=n.document.selection,o="string"==typeof e.mention?{id:e.mention}:e.mention,r=o.id,a=e.range||i.getFirstRange(),c=e.text||r,d=s({_text:c,id:r},o);if(1!=e.marker.length)throw new t.CKEditorError("mentioncommand-incorrect-marker",this);if(r.charAt(0)!=e.marker)throw new t.CKEditorError("mentioncommand-incorrect-id",this);n.change((e=>{const o=(0,t.toMap)(i.getAttributes()),r=new Map(o.entries());r.set("mention",d),n.insertContent(e.createText(c,r),a),n.insertContent(e.createText(" ",o),a.start.getShiftedBy(c.length))}))}}class r extends e.Plugin{static get pluginName(){return"MentionEditing"}init(){const e=this.editor,t=e.model,n=t.document;t.schema.extend("$text",{allowAttributes:"mention"}),e.conversion.for("upcast").elementToAttribute({view:{name:"span",key:"data-mention",classes:"mention"},model:{key:"mention",value:e=>a(e)}}),e.conversion.for("downcast").attributeToElement({model:"mention",view:d}),e.conversion.for("downcast").add(c),n.registerPostFixer((e=>function(e,t,n){const i=t.differ.getChanges();let o=!1;for(const t of i){if("attribute"==t.type)continue;const i=t.position;if("$text"==t.name){const t=i.textNode&&i.textNode.nextSibling;o=u(i.textNode,e)||o,o=u(t,e)||o,o=u(i.nodeBefore,e)||o,o=u(i.nodeAfter,e)||o}if("$text"!=t.name&&"insert"==t.type){const t=i.nodeAfter;for(const n of e.createRangeIn(t).getItems())o=u(n,e)||o}if("insert"==t.type&&n.isInline(t.name)){const t=i.nodeAfter&&i.nodeAfter.nextSibling;o=u(i.nodeBefore,e)||o,o=u(t,e)||o}}return o}(e,n,t.schema))),n.registerPostFixer((e=>function(e,t){const n=t.differ.getChanges();let i=!1;for(const t of n)if("attribute"===t.type&&"mention"!=t.attributeKey){const n=t.range.start.nodeBefore,o=t.range.end.nodeAfter;for(const r of[n,o])l(r)&&r.getAttribute(t.attributeKey)!=t.attributeNewValue&&(e.setAttribute(t.attributeKey,t.attributeNewValue,r),i=!0)}return i}(e,n))),n.registerPostFixer((e=>function(e,t){const n=t.selection,i=n.focus;if(n.isCollapsed&&n.hasAttribute("mention")&&function(e){const t=e.isAtStart;return e.nodeBefore&&e.nodeBefore.is("$text")||t}(i))return e.removeSelectionAttribute("mention"),!0;return!1}(e,n))),e.commands.add("mention",new o(e))}}function s(e,n){return Object.assign({uid:(0,t.uid)()},e,n||{})}function a(e,t){const n=e.getAttribute("data-mention"),i=e.getChild(0);if(!i)return;return s({id:n,_text:i.data},t)}function c(e){e.on("attribute:mention",((e,t,n)=>{const i=t.attributeNewValue;if(!t.item.is("$textProxy")||!i)return;const o=t.range.start;(o.textNode||o.nodeAfter).data!=i._text&&n.consumable.consume(t.item,e.name)}),{priority:"highest"})}function d(e,{writer:t}){if(!e)return;const n={class:"mention","data-mention":e.id},i={id:e.uid,priority:20};return t.createAttributeElement("span",n,i)}function l(e){if(!e||!e.is("$text")&&!e.is("$textProxy")||!e.hasAttribute("mention"))return!1;return e.data!=e.getAttribute("mention")._text}function u(e,t){return!!l(e)&&(t.removeAttribute("mention",e),!0)}var m=n(273),h=n(181);const f=function(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)};const g="object"==typeof global&&global&&global.Object===Object&&global;var p="object"==typeof self&&self&&self.Object===Object&&self;const v=g||p||Function("return this")();const b=function(){return v.Date.now()};var w=/\s/;const x=function(e){for(var t=e.length;t--&&w.test(e.charAt(t)););return t};var y=/^\s+/;const _=function(e){return e?e.slice(0,x(e)+1).replace(y,""):e};const k=v.Symbol;var C=Object.prototype,A=C.hasOwnProperty,T=C.toString,I=k?k.toStringTag:void 0;const M=function(e){var t=A.call(e,I),n=e[I];try{e[I]=void 0;var i=!0}catch(e){}var o=T.call(e);return i&&(t?e[I]=n:delete e[I]),o};var R=Object.prototype.toString;const S=function(e){return R.call(e)};var V="[object Null]",E="[object Undefined]",j=k?k.toStringTag:void 0;const O=function(e){return null==e?void 0===e?E:V:j&&j in Object(e)?M(e):S(e)};const P=function(e){return null!=e&&"object"==typeof e};var N="[object Symbol]";const U=function(e){return"symbol"==typeof e||P(e)&&O(e)==N};var F=NaN,B=/^[-+]0x[0-9a-f]+$/i,$=/^0b[01]+$/i,L=/^0o[0-7]+$/i,q=parseInt;const D=function(e){if("number"==typeof e)return e;if(U(e))return F;if(f(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=f(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=_(e);var n=$.test(e);return n||L.test(e)?q(e.slice(2),n?2:8):B.test(e)?F:+e};var K="Expected a function",W=Math.max,Z=Math.min;const H=function(e,t,n){var i,o,r,s,a,c,d=0,l=!1,u=!1,m=!0;if("function"!=typeof e)throw new TypeError(K);function h(t){var n=i,r=o;return i=o=void 0,d=t,s=e.apply(r,n)}function g(e){var n=e-c;return void 0===c||n>=t||n<0||u&&e-d>=r}function p(){var e=b();if(g(e))return v(e);a=setTimeout(p,function(e){var n=t-(e-c);return u?Z(n,r-(e-d)):n}(e))}function v(e){return a=void 0,m&&i?h(e):(i=o=void 0,s)}function w(){var e=b(),n=g(e);if(i=arguments,o=this,c=e,n){if(void 0===a)return function(e){return d=e,a=setTimeout(p,t),l?h(e):s}(c);if(u)return clearTimeout(a),a=setTimeout(p,t),h(c)}return void 0===a&&(a=setTimeout(p,t)),s}return t=D(t)||0,f(n)&&(l=!!n.leading,r=(u="maxWait"in n)?W(D(n.maxWait)||0,t):r,m="trailing"in n?!!n.trailing:m),w.cancel=function(){void 0!==a&&clearTimeout(a),d=0,i=c=o=a=void 0},w.flush=function(){return void 0===a?s:v(b())},w};var J=n(62),z=n.n(J),G=n(216),Q={injectType:"singletonStyleTag",attributes:{"data-cke":!0},insert:"head",singleton:!0};z()(G.Z,Q);G.Z.locals;class X extends m.ListView{constructor(e){super(e),this.extendTemplate({attributes:{class:["ck-mentions"],tabindex:"-1"}})}selectFirst(){this.select(0)}selectNext(){const e=this.selected,t=this.items.getIndex(e);this.select(t+1)}selectPrevious(){const e=this.selected,t=this.items.getIndex(e);this.select(t-1)}select(e){let t=0;e>0&&e<this.items.length?t=e:e<0&&(t=this.items.length-1);const n=this.items.get(t);this.selected!==n&&(this.selected&&this.selected.removeHighlight(),n.highlight(),this.selected=n,this._isItemVisibleInScrolledArea(n)||(this.element.scrollTop=n.element.offsetTop))}executeSelected(){this.selected.fire("execute")}_isItemVisibleInScrolledArea(e){return new t.Rect(this.element).contains(new t.Rect(e.element))}}class Y extends m.View{constructor(e,t){super(e),this.template=void 0,this.domElement=t,this.domElement.classList.add("ck-button"),this.set("isOn",!1),this.on("change:isOn",((e,t,n)=>{n?(this.domElement.classList.add("ck-on"),this.domElement.classList.remove("ck-off")):(this.domElement.classList.add("ck-off"),this.domElement.classList.remove("ck-on"))})),this.listenTo(this.domElement,"click",(()=>{this.fire("execute")}))}render(){super.render(),this.element=this.domElement}}class ee extends m.ListItemView{highlight(){this.children.first.isOn=!0}removeHighlight(){this.children.first.isOn=!1}}const te=3,ne=[t.keyCodes.arrowup,t.keyCodes.arrowdown,t.keyCodes.esc],ie=[t.keyCodes.enter,t.keyCodes.tab];class oe extends e.Plugin{static get pluginName(){return"MentionUI"}static get requires(){return[m.ContextualBalloon]}constructor(e){super(e),this._items=new t.Collection,this._mentionsView=this._createMentionView(),this._mentionsConfigurations=new Map,this._requestFeedDebounced=H(this._requestFeed,100),e.config.define("mention",{feeds:[]})}init(){const e=this.editor,n=e.config.get("mention.commitKeys")||ie,i=ne.concat(n);this._balloon=e.plugins.get(m.ContextualBalloon),e.editing.view.document.on("keydown",((e,o)=>{var r;r=o.keyCode,i.includes(r)&&this._isUIVisible&&(o.preventDefault(),e.stop(),o.keyCode==t.keyCodes.arrowdown&&this._mentionsView.selectNext(),o.keyCode==t.keyCodes.arrowup&&this._mentionsView.selectPrevious(),n.includes(o.keyCode)&&this._mentionsView.executeSelected(),o.keyCode==t.keyCodes.esc&&this._hideUIAndRemoveMarker())}),{priority:"highest"}),(0,m.clickOutsideHandler)({emitter:this._mentionsView,activator:()=>this._isUIVisible,contextElements:()=>[this._balloon.view.element],callback:()=>this._hideUIAndRemoveMarker()});const o=e.config.get("mention.feeds");for(const e of o){const{feed:n,marker:i,dropdownLimit:o}=e;if(!de(i))throw new t.CKEditorError("mentionconfig-incorrect-marker",null,{marker:i});const r={marker:i,feedCallback:"function"==typeof n?n.bind(this.editor):ce(n),itemRenderer:e.itemRenderer,dropdownLimit:o};this._mentionsConfigurations.set(i,r)}this._setupTextWatcher(o),this.listenTo(e,"change:isReadOnly",(()=>{this._hideUIAndRemoveMarker()})),this.on("requestFeed:response",((e,t)=>this._handleFeedResponse(t))),this.on("requestFeed:error",(()=>this._hideUIAndRemoveMarker()))}destroy(){super.destroy(),this._mentionsView.destroy()}get _isUIVisible(){return this._balloon.visibleView===this._mentionsView}_createMentionView(){const e=this.editor.locale,t=new X(e);return t.items.bindTo(this._items).using((n=>{const{item:i,marker:o}=n,{dropdownLimit:r}=this._mentionsConfigurations.get(o),s=r||this.editor.config.get("mention.dropdownLimit")||10;if(t.items.length>=s)return null;const a=new ee(e),c=this._renderItem(i,o);return c.delegate("execute").to(a),a.children.add(c),a.item=i,a.marker=o,a.on("execute",(()=>{t.fire("execute",{item:i,marker:o})})),a})),t.on("execute",((e,t)=>{const n=this.editor,i=n.model,o=t.item,r=t.marker,s=n.model.markers.get("mention"),a=i.createPositionAt(i.document.selection.focus),c=i.createPositionAt(s.getStart()),d=i.createRange(c,a);this._hideUIAndRemoveMarker(),n.execute("mention",{mention:o,text:o.text,marker:r,range:d}),n.editing.view.focus()})),t}_getItemRenderer(e){const{itemRenderer:t}=this._mentionsConfigurations.get(e);return t}_requestFeed(e,n){this._lastRequested=n;const{feedCallback:i}=this._mentionsConfigurations.get(e),o=i(n);o instanceof Promise?o.then((t=>{this._lastRequested==n?this.fire("requestFeed:response",{feed:t,marker:e,feedText:n}):this.fire("requestFeed:discarded",{feed:t,marker:e,feedText:n})})).catch((n=>{this.fire("requestFeed:error",{error:n}),(0,t.logWarning)("mention-feed-callback-error",{marker:e})})):this.fire("requestFeed:response",{feed:o,marker:e,feedText:n})}_setupTextWatcher(e){const t=this.editor,n=e.map((e=>({...e,pattern:ae(e.marker,e.minimumCharacters||0)}))),i=new h.TextWatcher(t.model,function(e){const t=t=>{const n=se(e,t);if(!n)return!1;let i=0;0!==n.position&&(i=n.position-1);const o=t.substring(i);return n.pattern.test(o)};return t}(n));i.on("matched",((e,i)=>{const o=se(n,i.text),r=t.model.document.selection.focus,s=t.model.createPositionAt(r.parent,o.position);if(function(e){const t=e.textNode&&e.textNode.hasAttribute("mention"),n=e.nodeBefore;return t||n&&n.is("$text")&&n.hasAttribute("mention")}(r)||function(e){const t=e.nodeAfter;return t&&t.is("$text")&&t.hasAttribute("mention")}(s))return void this._hideUIAndRemoveMarker();const a=function(e,t){let n=0;0!==e.position&&(n=e.position-1);const i=ae(e.marker,0),o=t.substring(n);return o.match(i)[2]}(o,i.text),c=o.marker.length+a.length,d=r.getShiftedBy(-c),l=r.getShiftedBy(-a.length),u=t.model.createRange(d,l);if(le(t)){const e=t.model.markers.get("mention");t.model.change((t=>{t.updateMarker(e,{range:u})}))}else t.model.change((e=>{e.addMarker("mention",{range:u,usingOperation:!1,affectsData:!1})}));this._requestFeedDebounced(o.marker,a)})),i.on("unmatched",(()=>{this._hideUIAndRemoveMarker()}));const o=t.commands.get("mention");return i.bind("isEnabled").to(o),i}_handleFeedResponse(e){const{feed:t,marker:n}=e;if(!le(this.editor))return;this._items.clear();for(const e of t){const t="object"!=typeof e?{id:e,text:e}:e;this._items.add({item:t,marker:n})}const i=this.editor.model.markers.get("mention");this._items.length?this._showOrUpdateUI(i):this._hideUIAndRemoveMarker()}_showOrUpdateUI(e){this._isUIVisible?this._balloon.updatePosition(this._getBalloonPanelPositionData(e,this._mentionsView.position)):this._balloon.add({view:this._mentionsView,position:this._getBalloonPanelPositionData(e,this._mentionsView.position),singleViewMode:!0}),this._mentionsView.position=this._balloon.view.position,this._mentionsView.selectFirst()}_hideUIAndRemoveMarker(){this._balloon.hasView(this._mentionsView)&&this._balloon.remove(this._mentionsView),le(this.editor)&&this.editor.model.change((e=>e.removeMarker("mention"))),this._mentionsView.position=void 0}_renderItem(e,t){const n=this.editor;let i,o=e.id;const r=this._getItemRenderer(t);if(r){const t=r(e);"string"!=typeof t?i=new Y(n.locale,t):o=t}if(!i){const e=new m.ButtonView(n.locale);e.label=o,e.withText=!0,i=e}return i}_getBalloonPanelPositionData(e,n){const i=this.editor,o=i.editing,r=o.view.domConverter,s=o.mapper;return{target:()=>{let n=e.getRange();"$graveyard"==n.start.root.rootName&&(n=i.model.document.selection.getFirstRange());const o=s.toViewRange(n);return t.Rect.getDomRangeRects(r.viewRangeToDom(o)).pop()},limiter:()=>{const e=this.editor.editing.view,t=e.document.selection.editableElement;return t?e.domConverter.mapViewToDom(t.root):null},positions:re(n,i.locale.uiLanguageDirection)}}}function re(e,t){const n={caret_se:e=>({top:e.bottom+te,left:e.right,name:"caret_se",config:{withArrow:!1}}),caret_ne:(e,t)=>({top:e.top-t.height-te,left:e.right,name:"caret_ne",config:{withArrow:!1}}),caret_sw:(e,t)=>({top:e.bottom+te,left:e.right-t.width,name:"caret_sw",config:{withArrow:!1}}),caret_nw:(e,t)=>({top:e.top-t.height-te,left:e.right-t.width,name:"caret_nw",config:{withArrow:!1}})};return Object.prototype.hasOwnProperty.call(n,e)?[n[e]]:"rtl"!==t?[n.caret_se,n.caret_sw,n.caret_ne,n.caret_nw]:[n.caret_sw,n.caret_se,n.caret_nw,n.caret_ne]}function se(e,t){let n;for(const i of e){const e=t.lastIndexOf(i.marker);e>0&&!t.substring(e-1).match(i.pattern)||(!n||e>=n.position)&&(n={marker:i.marker,position:e,minimumCharacters:i.minimumCharacters,pattern:i.pattern})}return n}function ae(e,n){const i=0==n?"*":`{${n},}`,o=t.env.features.isRegExpUnicodePropertySupported?"\\p{Ps}\\p{Pi}\"'":"\\(\\[{\"'";return new RegExp(`(?:^|[ ${o}])([${e}])(.${i})$`,"u")}function ce(e){return t=>e.filter((e=>("string"==typeof e?e:String(e.id)).toLowerCase().includes(t.toLowerCase())))}function de(e){return e&&1==e.length}function le(e){return e.model.markers.has("mention")}var ue=n(677),me={injectType:"singletonStyleTag",attributes:{"data-cke":!0},insert:"head",singleton:!0};z()(ue.Z,me);ue.Z.locals;class he extends e.Plugin{toMentionAttribute(e,t){return a(e,t)}static get pluginName(){return"Mention"}static get requires(){return[r,oe]}}})(),(window.CKEditor5=window.CKEditor5||{}).mention=i})();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ckeditor/ckeditor5-mention",
3
- "version": "36.0.0",
3
+ "version": "37.0.0-alpha.0",
4
4
  "description": "Mention feature for CKEditor 5.",
5
5
  "keywords": [
6
6
  "ckeditor",
@@ -12,28 +12,28 @@
12
12
  ],
13
13
  "main": "src/index.js",
14
14
  "dependencies": {
15
- "ckeditor5": "^36.0.0",
15
+ "ckeditor5": "^37.0.0-alpha.0",
16
16
  "lodash-es": "^4.17.15"
17
17
  },
18
18
  "devDependencies": {
19
- "@ckeditor/ckeditor5-basic-styles": "^36.0.0",
20
- "@ckeditor/ckeditor5-block-quote": "^36.0.0",
21
- "@ckeditor/ckeditor5-clipboard": "^36.0.0",
22
- "@ckeditor/ckeditor5-cloud-services": "^36.0.0",
23
- "@ckeditor/ckeditor5-core": "^36.0.0",
24
- "@ckeditor/ckeditor5-dev-utils": "^32.0.0",
25
- "@ckeditor/ckeditor5-editor-classic": "^36.0.0",
26
- "@ckeditor/ckeditor5-engine": "^36.0.0",
27
- "@ckeditor/ckeditor5-font": "^36.0.0",
28
- "@ckeditor/ckeditor5-link": "^36.0.0",
29
- "@ckeditor/ckeditor5-paragraph": "^36.0.0",
30
- "@ckeditor/ckeditor5-table": "^36.0.0",
31
- "@ckeditor/ckeditor5-theme-lark": "^36.0.0",
32
- "@ckeditor/ckeditor5-typing": "^36.0.0",
33
- "@ckeditor/ckeditor5-ui": "^36.0.0",
34
- "@ckeditor/ckeditor5-undo": "^36.0.0",
35
- "@ckeditor/ckeditor5-utils": "^36.0.0",
36
- "@ckeditor/ckeditor5-widget": "^36.0.0",
19
+ "@ckeditor/ckeditor5-basic-styles": "^37.0.0-alpha.0",
20
+ "@ckeditor/ckeditor5-block-quote": "^37.0.0-alpha.0",
21
+ "@ckeditor/ckeditor5-clipboard": "^37.0.0-alpha.0",
22
+ "@ckeditor/ckeditor5-cloud-services": "^37.0.0-alpha.0",
23
+ "@ckeditor/ckeditor5-core": "^37.0.0-alpha.0",
24
+ "@ckeditor/ckeditor5-dev-utils": "^34.0.0",
25
+ "@ckeditor/ckeditor5-editor-classic": "^37.0.0-alpha.0",
26
+ "@ckeditor/ckeditor5-engine": "^37.0.0-alpha.0",
27
+ "@ckeditor/ckeditor5-font": "^37.0.0-alpha.0",
28
+ "@ckeditor/ckeditor5-link": "^37.0.0-alpha.0",
29
+ "@ckeditor/ckeditor5-paragraph": "^37.0.0-alpha.0",
30
+ "@ckeditor/ckeditor5-table": "^37.0.0-alpha.0",
31
+ "@ckeditor/ckeditor5-theme-lark": "^37.0.0-alpha.0",
32
+ "@ckeditor/ckeditor5-typing": "^37.0.0-alpha.0",
33
+ "@ckeditor/ckeditor5-ui": "^37.0.0-alpha.0",
34
+ "@ckeditor/ckeditor5-undo": "^37.0.0-alpha.0",
35
+ "@ckeditor/ckeditor5-utils": "^37.0.0-alpha.0",
36
+ "@ckeditor/ckeditor5-widget": "^37.0.0-alpha.0",
37
37
  "lodash": "^4.17.15",
38
38
  "typescript": "^4.8.4",
39
39
  "webpack": "^5.58.1",
@@ -65,5 +65,6 @@
65
65
  "dll:build": "webpack",
66
66
  "build": "tsc -p ./tsconfig.release.json",
67
67
  "postversion": "npm run build"
68
- }
68
+ },
69
+ "types": "src/index.d.ts"
69
70
  }
package/src/index.d.ts ADDED
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * @module mention
7
+ */
8
+ export { default as Mention } from './mention';
9
+ export { default as MentionEditing } from './mentionediting';
10
+ export { default as MentionUI } from './mentionui';
@@ -0,0 +1,69 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * @module mention/mention
7
+ */
8
+ import { Plugin, type PluginDependencies } from 'ckeditor5/src/core';
9
+ import type { Element } from 'ckeditor5/src/engine';
10
+ import '../theme/mention.css';
11
+ /**
12
+ * The mention plugin.
13
+ *
14
+ * For a detailed overview, check the {@glink features/mentions Mention feature} guide.
15
+ */
16
+ export default class Mention extends Plugin {
17
+ /**
18
+ * Creates a mention attribute value from the provided view element and optional data.
19
+ *
20
+ * ```ts
21
+ * editor.plugins.get( 'Mention' ).toMentionAttribute( viewElement, { userId: '1234' } );
22
+ *
23
+ * // For a view element: <span data-mention="@joe">@John Doe</span>
24
+ * // it will return:
25
+ * // { id: '@joe', userId: '1234', uid: '7a7bc7...', _text: '@John Doe' }
26
+ * ```
27
+ *
28
+ * @param viewElement
29
+ * @param data Additional data to be stored in the mention attribute.
30
+ */
31
+ toMentionAttribute(viewElement: Element, data?: MentionAttribute): MentionAttribute | undefined;
32
+ /**
33
+ * @inheritDoc
34
+ */
35
+ static get pluginName(): 'Mention';
36
+ /**
37
+ * @inheritDoc
38
+ */
39
+ static get requires(): PluginDependencies;
40
+ }
41
+ /**
42
+ * Represents a mention in the model.
43
+ *
44
+ * See {@link module:mention/mention~Mention#toMentionAttribute `Mention#toMentionAttribute()`}.
45
+ */
46
+ export type MentionAttribute = {
47
+ /**
48
+ * The ID of a mention. It identifies the mention item in the mention feed. There can be multiple mentions
49
+ * in the document with the same ID (e.g. the same hashtag being mentioned).
50
+ */
51
+ id: string;
52
+ /**
53
+ * A unique ID of this mention instance. Should be passed as an `option.id` when using
54
+ * {@link module:engine/view/downcastwriter~DowncastWriter#createAttributeElement writer.createAttributeElement()}.
55
+ */
56
+ uid?: string;
57
+ /**
58
+ * Helper property that stores the text of the inserted mention. Used for detecting a broken mention
59
+ * in the editing area.
60
+ *
61
+ * @internal
62
+ */
63
+ _text?: string;
64
+ };
65
+ declare module '@ckeditor/ckeditor5-core' {
66
+ interface PluginsMap {
67
+ [Mention.pluginName]: Mention;
68
+ }
69
+ }
package/src/mention.js CHANGED
@@ -12,7 +12,7 @@ import '../theme/mention.css';
12
12
  /**
13
13
  * The mention plugin.
14
14
  *
15
- * For a detailed overview, check the {@glink features/mentions Mention feature documentation}.
15
+ * For a detailed overview, check the {@glink features/mentions Mention feature} guide.
16
16
  */
17
17
  export default class Mention extends Plugin {
18
18
  /**
@@ -0,0 +1,76 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * @module mention/mentioncommand
7
+ */
8
+ import { Command } from 'ckeditor5/src/core';
9
+ import type { Range } from 'ckeditor5/src/engine';
10
+ import type { MentionAttribute } from './mention';
11
+ /**
12
+ * The mention command.
13
+ *
14
+ * The command is registered by {@link module:mention/mentionediting~MentionEditing} as `'mention'`.
15
+ *
16
+ * To insert a mention into a range, execute the command and specify a mention object with a range to replace:
17
+ *
18
+ * ```ts
19
+ * const focus = editor.model.document.selection.focus;
20
+ *
21
+ * // It will replace one character before the selection focus with the '#1234' text
22
+ * // with the mention attribute filled with passed attributes.
23
+ * editor.execute( 'mention', {
24
+ * marker: '#',
25
+ * mention: {
26
+ * id: '#1234',
27
+ * name: 'Foo',
28
+ * title: 'Big Foo'
29
+ * },
30
+ * range: editor.model.createRange( focus.getShiftedBy( -1 ), focus )
31
+ * } );
32
+ *
33
+ * // It will replace one character before the selection focus with the 'The "Big Foo"' text
34
+ * // with the mention attribute filled with passed attributes.
35
+ * editor.execute( 'mention', {
36
+ * marker: '#',
37
+ * mention: {
38
+ * id: '#1234',
39
+ * name: 'Foo',
40
+ * title: 'Big Foo'
41
+ * },
42
+ * text: 'The "Big Foo"',
43
+ * range: editor.model.createRange( focus.getShiftedBy( -1 ), focus )
44
+ * } );
45
+ * ```
46
+ */
47
+ export default class MentionCommand extends Command {
48
+ /**
49
+ * @inheritDoc
50
+ */
51
+ refresh(): void;
52
+ /**
53
+ * Executes the command.
54
+ *
55
+ * @param options Options for the executed command.
56
+ * @param options.mention The mention object to insert. When a string is passed, it will be used to create a plain
57
+ * object with the name attribute that equals the passed string.
58
+ * @param options.marker The marker character (e.g. `'@'`).
59
+ * @param options.text The text of the inserted mention. Defaults to the full mention string composed from `marker` and
60
+ * `mention` string or `mention.id` if an object is passed.
61
+ * @param options.range The range to replace.
62
+ * Note that the replaced range might be shorter than the inserted text with the mention attribute.
63
+ * @fires execute
64
+ */
65
+ execute(options: {
66
+ mention: string | MentionAttribute;
67
+ marker: string;
68
+ text?: string;
69
+ range?: Range;
70
+ }): void;
71
+ }
72
+ declare module '@ckeditor/ckeditor5-core' {
73
+ interface CommandsMap {
74
+ mention: MentionCommand;
75
+ }
76
+ }
@@ -13,7 +13,7 @@ import { _addMentionAttributes } from './mentionediting';
13
13
  *
14
14
  * The command is registered by {@link module:mention/mentionediting~MentionEditing} as `'mention'`.
15
15
  *
16
- * To insert a mention onto a range, execute the command and specify a mention object with a range to replace:
16
+ * To insert a mention into a range, execute the command and specify a mention object with a range to replace:
17
17
  *
18
18
  * ```ts
19
19
  * const focus = editor.model.document.selection.focus;
@@ -83,7 +83,7 @@ export default class MentionCommand extends Command {
83
83
  *
84
84
  * Incorrect markers: `'@@'`, `'[@'`.
85
85
  *
86
- * See {@link module:mention/mention~MentionConfig}.
86
+ * See {@link module:mention/mentionconfig~MentionConfig}.
87
87
  *
88
88
  * @error mentioncommand-incorrect-marker
89
89
  */
@@ -115,7 +115,7 @@ export default class MentionCommand extends Command {
115
115
  * ]
116
116
  * ```
117
117
  *
118
- * See {@link module:mention/mention~MentionConfig}.
118
+ * See {@link module:mention/mentionconfig~MentionConfig}.
119
119
  *
120
120
  * @error mentioncommand-incorrect-id
121
121
  */
@@ -0,0 +1,275 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * @module mention/mentionconfig
7
+ */
8
+ /**
9
+ * The configuration of the mention feature.
10
+ *
11
+ * Read more about {@glink features/mentions#configuration configuring the mention feature}.
12
+ *
13
+ * ```ts
14
+ * ClassicEditor
15
+ * .create( editorElement, {
16
+ * mention: ... // Mention feature options.
17
+ * } )
18
+ * .then( ... )
19
+ * .catch( ... );
20
+ * ```
21
+ *
22
+ * See {@link module:core/editor/editorconfig~EditorConfig all editor options}.
23
+ */
24
+ export interface MentionConfig {
25
+ /**
26
+ * The list of mention feeds supported by the editor.
27
+ *
28
+ * ```ts
29
+ * ClassicEditor
30
+ * .create( editorElement, {
31
+ * plugins: [ Mention, ... ],
32
+ * mention: {
33
+ * feeds: [
34
+ * {
35
+ * marker: '@',
36
+ * feed: [ '@Barney', '@Lily', '@Marshall', '@Robin', '@Ted' ]
37
+ * },
38
+ * ...
39
+ * ]
40
+ * }
41
+ * } )
42
+ * .then( ... )
43
+ * .catch( ... );
44
+ * ```
45
+ *
46
+ * You can provide many mention feeds but they must use different `marker`s.
47
+ * For example, you can use `'@'` to autocomplete people and `'#'` to autocomplete tags.
48
+ */
49
+ feeds: Array<MentionFeed>;
50
+ /**
51
+ * The configuration of the custom commit keys supported by the editor.
52
+ *
53
+ * ```ts
54
+ * ClassicEditor
55
+ * .create( editorElement, {
56
+ * plugins: [ Mention, ... ],
57
+ * mention: {
58
+ * // [ Enter, Space ]
59
+ * commitKeys: [ 13, 32 ]
60
+ * feeds: [
61
+ * { ... }
62
+ * ...
63
+ * ]
64
+ * }
65
+ * } )
66
+ * .then( ... )
67
+ * .catch( ... );
68
+ * ```
69
+ *
70
+ * Custom commit keys configuration allows you to customize how users will confirm the selection of mentions from the dropdown list.
71
+ * You can add as many mention commit keys as you need. For instance, in the snippet above new mentions will be committed by pressing
72
+ * either <kbd>Enter</kbd> or <kbd>Space</kbd> (13 and 32 key codes respectively).
73
+ *
74
+ * @default [ 13, 9 ] // [ Enter, Tab ]
75
+ */
76
+ commitKeys?: Array<number>;
77
+ /**
78
+ * The configuration of the custom number of visible mentions.
79
+ *
80
+ * Customizing the number of visible mentions allows you to specify how many available elements will the users be able to see
81
+ * in the dropdown list. You can specify any number you see fit. For example, in the snippets below you will find the
82
+ * dropdownLimit set to `20` and `Infinity` (the latter will result in showing all available mentions).
83
+ *
84
+ * ```ts
85
+ * ClassicEditor
86
+ * .create( editorElement, {
87
+ * plugins: [ Mention, ... ],
88
+ * mention: {
89
+ * dropdownLimit: 20,
90
+ * feeds: [
91
+ * { ... }
92
+ * ...
93
+ * ]
94
+ * }
95
+ * } )
96
+ * .then( ... )
97
+ * .catch( ... );
98
+ *
99
+ * ClassicEditor
100
+ * .create( editorElement, {
101
+ * plugins: [ Mention, ... ],
102
+ * mention: {
103
+ * dropdownLimit: Infinity,
104
+ * feeds: [
105
+ * { ... }
106
+ * ...
107
+ * ]
108
+ * }
109
+ * } )
110
+ * .then( ... )
111
+ * .catch( ... );
112
+ * ```
113
+ *
114
+ * @default 10
115
+ */
116
+ dropdownLimit?: number;
117
+ }
118
+ /**
119
+ * The mention feed descriptor. Used in {@link module:mention/mentionconfig~MentionConfig `config.mention`}.
120
+ *
121
+ * See {@link module:mention/mentionconfig~MentionConfig} to learn more.
122
+ *
123
+ * ```ts
124
+ * // Static configuration.
125
+ * const mentionFeedPeople = {
126
+ * marker: '@',
127
+ * feed: [ '@Alice', '@Bob', ... ],
128
+ * minimumCharacters: 2
129
+ * };
130
+ *
131
+ * // Simple synchronous callback.
132
+ * const mentionFeedTags = {
133
+ * marker: '#',
134
+ * feed: ( searchString: string ) => {
135
+ * return tags
136
+ * // Filter the tags list.
137
+ * .filter( tag => {
138
+ * return tag.toLowerCase().includes( queryText.toLowerCase() );
139
+ * } )
140
+ * }
141
+ * };
142
+ *
143
+ * const tags = [ 'wysiwyg', 'rte', 'rich-text-edior', 'collaboration', 'real-time', ... ];
144
+ *
145
+ * // Asynchronous callback.
146
+ * const mentionFeedPlaceholders = {
147
+ * marker: '$',
148
+ * feed: ( searchString: string ) => {
149
+ * return getMatchingPlaceholders( searchString );
150
+ * }
151
+ * };
152
+ *
153
+ * function getMatchingPlaceholders( searchString: string ) {
154
+ * return new Promise<Array<MentionFeedItem>>( resolve => {
155
+ * doSomeXHRQuery( result => {
156
+ * // console.log( result );
157
+ * // -> [ '$name', '$surname', '$postal', ... ]
158
+ *
159
+ * resolve( result );
160
+ * } );
161
+ * } );
162
+ * }
163
+ * ```
164
+ */
165
+ export interface MentionFeed {
166
+ /**
167
+ * The character which triggers autocompletion for mention. It must be a single character.
168
+ */
169
+ marker: string;
170
+ /**
171
+ * Autocomplete items. Provide an array for
172
+ * a static configuration (the mention feature will show matching items automatically) or a function which returns an array of
173
+ * matching items (directly, or via a promise). If a function is passed, it is executed in the context of the editor instance.
174
+ */
175
+ feed: Array<MentionFeedItem> | FeedCallback;
176
+ /**
177
+ * Specifies after how many characters the autocomplete panel should be shown.
178
+ *
179
+ * @default 0
180
+ */
181
+ minimumCharacters?: number;
182
+ /**
183
+ * A function that renders a {@link module:mention/mentionconfig~MentionFeedItem}
184
+ * to the autocomplete panel.
185
+ */
186
+ itemRenderer?: ItemRenderer;
187
+ /**
188
+ * Specify how many available elements per feeds will the users be able to see in the dropdown list.
189
+ * If it not set, limit is inherited from {@link module:mention/mentionconfig~MentionConfig#dropdownLimit MentionConfig}.
190
+ */
191
+ dropdownLimit?: number;
192
+ }
193
+ /**
194
+ * Function that renders an array of {@link module:mention/mentionconfig~MentionFeedItem} based on string input.
195
+ */
196
+ export type FeedCallback = (searchString: string) => Array<MentionFeedItem> | Promise<Array<MentionFeedItem>>;
197
+ /**
198
+ * Function that takes renders a {@link module:mention/mentionconfig~MentionFeedItem} as HTMLElement.
199
+ */
200
+ export type ItemRenderer = (item: MentionFeedItem) => HTMLElement;
201
+ /**
202
+ * The mention feed item. It may be defined as a string or a plain object.
203
+ *
204
+ * When defining a feed item as a plain object, the `id` property is obligatory. Additional properties
205
+ * can be used when customizing the mention feature bahavior
206
+ * (see {@glink features/mentions#customizing-the-autocomplete-list "Customizing the autocomplete list"}
207
+ * and {@glink features/mentions#customizing-the-output "Customizing the output"} sections).
208
+ *
209
+ * ```ts
210
+ * ClassicEditor
211
+ * .create( editorElement, {
212
+ * plugins: [ Mention, ... ],
213
+ * mention: {
214
+ * feeds: [
215
+ * // Feed items as objects.
216
+ * {
217
+ * marker: '@',
218
+ * feed: [
219
+ * {
220
+ * id: '@Barney',
221
+ * fullName: 'Barney Bloom'
222
+ * },
223
+ * {
224
+ * id: '@Lily',
225
+ * fullName: 'Lily Smith'
226
+ * },
227
+ * {
228
+ * id: '@Marshall',
229
+ * fullName: 'Marshall McDonald'
230
+ * },
231
+ * {
232
+ * id: '@Robin',
233
+ * fullName: 'Robin Hood'
234
+ * },
235
+ * {
236
+ * id: '@Ted',
237
+ * fullName: 'Ted Cruze'
238
+ * },
239
+ * // ...
240
+ * ]
241
+ * },
242
+ *
243
+ * // Feed items as plain strings.
244
+ * {
245
+ * marker: '#',
246
+ * feed: [ 'wysiwyg', 'rte', 'rich-text-edior', 'collaboration', 'real-time', ... ]
247
+ * },
248
+ * ]
249
+ * }
250
+ * } )
251
+ * .then( ... )
252
+ * .catch( ... );
253
+ * ```
254
+ */
255
+ export type MentionFeedItem = string | MentionFeedObjectItem;
256
+ export type MentionFeedObjectItem = {
257
+ /**
258
+ * A unique ID of the mention. It must start with the marker character.
259
+ */
260
+ id: string;
261
+ /**
262
+ * Text inserted into the editor when creating a mention.
263
+ */
264
+ text: string;
265
+ };
266
+ declare module '@ckeditor/ckeditor5-core' {
267
+ interface EditorConfig {
268
+ /**
269
+ * The configuration of the {@link module:mention/mention~Mention} feature.
270
+ *
271
+ * Read more in {@link module:mention/mentionconfig~MentionConfig}.
272
+ */
273
+ mention?: MentionConfig;
274
+ }
275
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ export {};
@@ -0,0 +1,45 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * @module mention/mentionediting
7
+ */
8
+ import { Plugin } from 'ckeditor5/src/core';
9
+ import type { Element } from 'ckeditor5/src/engine';
10
+ import type { MentionAttribute } from './mention';
11
+ /**
12
+ * The mention editing feature.
13
+ *
14
+ * It introduces the {@link module:mention/mentioncommand~MentionCommand command} and the `mention`
15
+ * attribute in the {@link module:engine/model/model~Model model} which renders in the {@link module:engine/view/view view}
16
+ * as a `<span class="mention" data-mention="@mention">`.
17
+ */
18
+ export default class MentionEditing extends Plugin {
19
+ /**
20
+ * @inheritDoc
21
+ */
22
+ static get pluginName(): 'MentionEditing';
23
+ /**
24
+ * @inheritDoc
25
+ */
26
+ init(): void;
27
+ }
28
+ /**
29
+ * @internal
30
+ */
31
+ export declare function _addMentionAttributes(baseMentionData: MentionAttribute, data?: MentionAttribute): MentionAttribute;
32
+ /**
33
+ * Creates a mention attribute value from the provided view element and optional data.
34
+ *
35
+ * This function is exposed as
36
+ * {@link module:mention/mention~Mention#toMentionAttribute `editor.plugins.get( 'Mention' ).toMentionAttribute()`}.
37
+ *
38
+ * @internal
39
+ */
40
+ export declare function _toMentionAttribute(viewElementOrMention: Element, data?: MentionAttribute): MentionAttribute | undefined;
41
+ declare module '@ckeditor/ckeditor5-core' {
42
+ interface PluginsMap {
43
+ [MentionEditing.pluginName]: MentionEditing;
44
+ }
45
+ }
@@ -0,0 +1,110 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * @module mention/mentionui
7
+ */
8
+ import { Plugin, type Editor, type PluginDependencies } from 'ckeditor5/src/core';
9
+ /**
10
+ * The mention UI feature.
11
+ */
12
+ export default class MentionUI extends Plugin {
13
+ /**
14
+ * The mention view.
15
+ */
16
+ private readonly _mentionsView;
17
+ /**
18
+ * Stores mention feeds configurations.
19
+ */
20
+ private _mentionsConfigurations;
21
+ /**
22
+ * The contextual balloon plugin instance.
23
+ */
24
+ private _balloon;
25
+ private _items;
26
+ private _lastRequested?;
27
+ /**
28
+ * Debounced feed requester. It uses `lodash#debounce` method to delay function call.
29
+ */
30
+ private _requestFeedDebounced;
31
+ /**
32
+ * @inheritDoc
33
+ */
34
+ static get pluginName(): 'MentionUI';
35
+ /**
36
+ * @inheritDoc
37
+ */
38
+ static get requires(): PluginDependencies;
39
+ /**
40
+ * @inheritDoc
41
+ */
42
+ constructor(editor: Editor);
43
+ /**
44
+ * @inheritDoc
45
+ */
46
+ init(): void;
47
+ /**
48
+ * @inheritDoc
49
+ */
50
+ destroy(): void;
51
+ /**
52
+ * Returns true when {@link #_mentionsView} is in the {@link module:ui/panel/balloon/contextualballoon~ContextualBalloon} and it is
53
+ * currently visible.
54
+ */
55
+ private get _isUIVisible();
56
+ /**
57
+ * Creates the {@link #_mentionsView}.
58
+ */
59
+ private _createMentionView;
60
+ /**
61
+ * Returns item renderer for the marker.
62
+ */
63
+ private _getItemRenderer;
64
+ /**
65
+ * Requests a feed from a configured callbacks.
66
+ *
67
+ * @fires response
68
+ * @fires discarded
69
+ * @fires error
70
+ */
71
+ private _requestFeed;
72
+ /**
73
+ * Registers a text watcher for the marker.
74
+ */
75
+ private _setupTextWatcher;
76
+ /**
77
+ * Handles the feed response event data.
78
+ */
79
+ private _handleFeedResponse;
80
+ /**
81
+ * Shows the mentions balloon. If the panel is already visible, it will reposition it.
82
+ */
83
+ private _showOrUpdateUI;
84
+ /**
85
+ * Hides the mentions balloon and removes the 'mention' marker from the markers collection.
86
+ */
87
+ private _hideUIAndRemoveMarker;
88
+ /**
89
+ * Renders a single item in the autocomplete list.
90
+ */
91
+ private _renderItem;
92
+ /**
93
+ * Creates a position options object used to position the balloon panel.
94
+ *
95
+ * @param mentionMarker
96
+ * @param preferredPosition The name of the last matched position name.
97
+ */
98
+ private _getBalloonPanelPositionData;
99
+ }
100
+ /**
101
+ * Creates a RegExp pattern for the marker.
102
+ *
103
+ * Function has to be exported to achieve 100% code coverage.
104
+ */
105
+ export declare function createRegExp(marker: string, minimumCharacters: number): RegExp;
106
+ declare module '@ckeditor/ckeditor5-core' {
107
+ interface PluginsMap {
108
+ [MentionUI.pluginName]: MentionUI;
109
+ }
110
+ }
package/src/mentionui.js CHANGED
@@ -88,8 +88,7 @@ export default class MentionUI extends Plugin {
88
88
  });
89
89
  const feeds = editor.config.get('mention.feeds');
90
90
  for (const mentionDescription of feeds) {
91
- const feed = mentionDescription.feed;
92
- const marker = mentionDescription.marker;
91
+ const { feed, marker, dropdownLimit } = mentionDescription;
93
92
  if (!isValidMentionMarker(marker)) {
94
93
  /**
95
94
  * The marker must be a single character.
@@ -98,7 +97,7 @@ export default class MentionUI extends Plugin {
98
97
  *
99
98
  * Incorrect markers: `'$$'`, `'[@'`.
100
99
  *
101
- * See {@link module:mention/mention~MentionConfig}.
100
+ * See {@link module:mention/mentionconfig~MentionConfig}.
102
101
  *
103
102
  * @error mentionconfig-incorrect-marker
104
103
  * @param marker Configured marker
@@ -107,7 +106,7 @@ export default class MentionUI extends Plugin {
107
106
  }
108
107
  const feedCallback = typeof feed == 'function' ? feed.bind(this.editor) : createFeedCallback(feed);
109
108
  const itemRenderer = mentionDescription.itemRenderer;
110
- const definition = { marker, feedCallback, itemRenderer };
109
+ const definition = { marker, feedCallback, itemRenderer, dropdownLimit };
111
110
  this._mentionsConfigurations.set(marker, definition);
112
111
  }
113
112
  this._setupTextWatcher(feeds);
@@ -146,8 +145,9 @@ export default class MentionUI extends Plugin {
146
145
  const mentionsView = new MentionsView(locale);
147
146
  mentionsView.items.bindTo(this._items).using(data => {
148
147
  const { item, marker } = data;
148
+ const { dropdownLimit: markerDropdownLimit } = this._mentionsConfigurations.get(marker);
149
149
  // Set to 10 by default for backwards compatibility. See: #10479
150
- const dropdownLimit = this.editor.config.get('mention.dropdownLimit') || 10;
150
+ const dropdownLimit = markerDropdownLimit || this.editor.config.get('mention.dropdownLimit') || 10;
151
151
  if (mentionsView.items.length >= dropdownLimit) {
152
152
  return null;
153
153
  }
@@ -281,7 +281,7 @@ export default class MentionUI extends Plugin {
281
281
  });
282
282
  }
283
283
  this._requestFeedDebounced(markerDefinition.marker, feedText);
284
- // @if CK_DEBUG_MENTION // console.groupEnd( '[TextWatcher] matched' );
284
+ // @if CK_DEBUG_MENTION // console.groupEnd();
285
285
  });
286
286
  watcher.on('unmatched', () => {
287
287
  this._hideUIAndRemoveMarker();
@@ -389,6 +389,7 @@ export default class MentionUI extends Plugin {
389
389
  const editing = editor.editing;
390
390
  const domConverter = editing.view.domConverter;
391
391
  const mapper = editing.mapper;
392
+ const uiLanguageDirection = editor.locale.uiLanguageDirection;
392
393
  return {
393
394
  target: () => {
394
395
  let modelRange = mentionMarker.getRange();
@@ -410,14 +411,14 @@ export default class MentionUI extends Plugin {
410
411
  }
411
412
  return null;
412
413
  },
413
- positions: getBalloonPanelPositions(preferredPosition)
414
+ positions: getBalloonPanelPositions(preferredPosition, uiLanguageDirection)
414
415
  };
415
416
  }
416
417
  }
417
418
  /**
418
419
  * Returns the balloon positions data callbacks.
419
420
  */
420
- function getBalloonPanelPositions(preferredPosition) {
421
+ function getBalloonPanelPositions(preferredPosition, uiLanguageDirection) {
421
422
  const positions = {
422
423
  // Positions the panel to the southeast of the caret rectangle.
423
424
  'caret_se': (targetRect) => {
@@ -470,12 +471,17 @@ function getBalloonPanelPositions(preferredPosition) {
470
471
  positions[preferredPosition]
471
472
  ];
472
473
  }
473
- // By default return all position callbacks.
474
- return [
474
+ // By default, return all position callbacks ordered depending on the UI language direction.
475
+ return uiLanguageDirection !== 'rtl' ? [
475
476
  positions.caret_se,
476
477
  positions.caret_sw,
477
478
  positions.caret_ne,
478
479
  positions.caret_nw
480
+ ] : [
481
+ positions.caret_sw,
482
+ positions.caret_se,
483
+ positions.caret_nw,
484
+ positions.caret_ne
479
485
  ];
480
486
  }
481
487
  /**
@@ -0,0 +1,37 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * @module mention/ui/domwrapperview
7
+ */
8
+ import { View } from 'ckeditor5/src/ui';
9
+ import type { Locale } from 'ckeditor5/src/utils';
10
+ /**
11
+ * This class wraps DOM element as a CKEditor5 UI View.
12
+ *
13
+ * It allows to render any DOM element and use it in mentions list.
14
+ */
15
+ export default class DomWrapperView extends View {
16
+ /**
17
+ * The DOM element for which wrapper was created.
18
+ */
19
+ domElement: HTMLElement;
20
+ /**
21
+ * Controls whether the dom wrapper view is "on". This is in line with {@link module:ui/button/button~Button#isOn} property.
22
+ *
23
+ * @observable
24
+ * @default true
25
+ */
26
+ isOn: boolean;
27
+ /**
28
+ * Creates an instance of {@link module:mention/ui/domwrapperview~DomWrapperView} class.
29
+ *
30
+ * Also see {@link #render}.
31
+ */
32
+ constructor(locale: Locale, domElement: HTMLElement);
33
+ /**
34
+ * @inheritDoc
35
+ */
36
+ render(): void;
37
+ }
@@ -20,7 +20,7 @@ export default class DomWrapperView extends View {
20
20
  constructor(locale, domElement) {
21
21
  super(locale);
22
22
  // Disable template rendering on this view.
23
- this.template = false;
23
+ this.template = undefined;
24
24
  this.domElement = domElement;
25
25
  // Render dom wrapper as a button.
26
26
  this.domElement.classList.add('ck-button');
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * @module mention/ui/mentionlistitemview
7
+ */
8
+ import { ListItemView } from 'ckeditor5/src/ui';
9
+ import type { MentionFeedItem } from '../mentionconfig';
10
+ export default class MentionListItemView extends ListItemView {
11
+ item: MentionFeedItem;
12
+ marker: string;
13
+ highlight(): void;
14
+ removeHighlight(): void;
15
+ }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * @module mention/ui/mentionsview
7
+ */
8
+ import { ListView } from 'ckeditor5/src/ui';
9
+ import { type Locale } from 'ckeditor5/src/utils';
10
+ import type MentionListItemView from './mentionlistitemview';
11
+ import '../../theme/mentionui.css';
12
+ /**
13
+ * The mention ui view.
14
+ */
15
+ export default class MentionsView extends ListView {
16
+ selected: MentionListItemView | undefined;
17
+ position: string | undefined;
18
+ /**
19
+ * @inheritDoc
20
+ */
21
+ constructor(locale: Locale);
22
+ /**
23
+ * {@link #select Selects} the first item.
24
+ */
25
+ selectFirst(): void;
26
+ /**
27
+ * Selects next item to the currently {@link #select selected}.
28
+ *
29
+ * If the last item is already selected, it will select the first item.
30
+ */
31
+ selectNext(): void;
32
+ /**
33
+ * Selects previous item to the currently {@link #select selected}.
34
+ *
35
+ * If the first item is already selected, it will select the last item.
36
+ */
37
+ selectPrevious(): void;
38
+ /**
39
+ * Marks item at a given index as selected.
40
+ *
41
+ * Handles selection cycling when passed index is out of bounds:
42
+ * - if the index is lower than 0, it will select the last item,
43
+ * - if the index is higher than the last item index, it will select the first item.
44
+ *
45
+ * @param index Index of an item to be marked as selected.
46
+ */
47
+ select(index: number): void;
48
+ /**
49
+ * Triggers the `execute` event on the {@link #select selected} item.
50
+ */
51
+ executeSelected(): void;
52
+ /**
53
+ * Checks if an item is visible in the scrollable area.
54
+ *
55
+ * The item is considered visible when:
56
+ * - its top boundary is inside the scrollable rect
57
+ * - its bottom boundary is inside the scrollable rect (the whole item must be visible)
58
+ */
59
+ private _isItemVisibleInScrolledArea;
60
+ }