@madgex/design-system-ce 5.1.2 → 5.3.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/.eslintrc.js +9 -2
- package/CHANGELOG.md +49 -0
- package/components/internals/MdsIcon.vue +29 -0
- package/components/text-editor/TextEditor.ce.vue +71 -0
- package/components/text-editor/TextEditorButton.vue +60 -0
- package/components/text-editor/TextEditorContent.vue +76 -0
- package/components/text-editor/TextEditorPopover.vue +113 -0
- package/components/text-editor/TextEditorPopoverLink.vue +100 -0
- package/components/text-editor/TextEditorToolbar.vue +178 -0
- package/components/text-editor/apply-missing-protocol.js +7 -0
- package/custom-elements/mds-combobox.js +13 -0
- package/custom-elements/mds-text-editor.js +12 -0
- package/dist/custom-elements/mds-combobox.js +1 -0
- package/dist/custom-elements/mds-text-editor.js +94 -0
- package/dist/index.js +1 -2
- package/dist/manifest.json +25 -11
- package/dist/plugin-vue_export-helper.js +2 -0
- package/index-dev.js +2 -0
- package/index.js +8 -11
- package/package.json +6 -2
- package/vite.config.js +7 -15
- package/dist/assets/polyfills-legacy.bfe7dd4c.js +0 -1
- package/dist/index-legacy.js +0 -1
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="mds-text-editor__menu" role="toolbar" :aria-label="i18nText.toolbarLabel" :aria-controls="id">
|
|
3
|
+
<TextEditorButton
|
|
4
|
+
v-for="button in menuButtons"
|
|
5
|
+
:id="button.id"
|
|
6
|
+
ref="menuButton"
|
|
7
|
+
:key="button.id"
|
|
8
|
+
:label="button.label"
|
|
9
|
+
:icon-name="button.iconName"
|
|
10
|
+
:is-active="button.isActive?.(editor)"
|
|
11
|
+
:disabled="button.isDisabled?.(editor)"
|
|
12
|
+
:initial-tabindex="firstFocusableButton.id === button.id ? 0 : -1"
|
|
13
|
+
:aria-pressed="button.id === 'undo' || button.id === 'redo' ? null : button.isActive?.(editor)"
|
|
14
|
+
:aria-expanded="button.ariaExpanded?.()"
|
|
15
|
+
@click="button.onClick(editor)"
|
|
16
|
+
@keyup.left="setFocusToSibling('previous', $event)"
|
|
17
|
+
@keyup.up="setFocusToSibling('previous', $event)"
|
|
18
|
+
@keyup.right="setFocusToSibling('next', $event)"
|
|
19
|
+
@keyup.down="setFocusToSibling('next', $event)"
|
|
20
|
+
@update-tab-index="updateTabIndex"
|
|
21
|
+
/>
|
|
22
|
+
<!-- <TextEditorPopoverLink v-if="editor" v-model:linkUrl="linkUrl" v-model:visible="showLinkEditor" :editor="editor" /> -->
|
|
23
|
+
</div>
|
|
24
|
+
</template>
|
|
25
|
+
|
|
26
|
+
<script>
|
|
27
|
+
import TextEditorButton from './TextEditorButton.vue';
|
|
28
|
+
// import TextEditorPopoverLink from './TextEditorPopoverLink.vue';
|
|
29
|
+
|
|
30
|
+
export default {
|
|
31
|
+
name: 'TextEditorToolbar',
|
|
32
|
+
|
|
33
|
+
components: {
|
|
34
|
+
TextEditorButton,
|
|
35
|
+
// TextEditorPopoverLink,
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
inject: ['id', 'customMenuButtons', 'i18nText'],
|
|
39
|
+
|
|
40
|
+
props: {
|
|
41
|
+
editor: {
|
|
42
|
+
type: Object,
|
|
43
|
+
required: true,
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
|
|
47
|
+
data() {
|
|
48
|
+
return {
|
|
49
|
+
defaultMenuButtons: [
|
|
50
|
+
{
|
|
51
|
+
id: 'bold',
|
|
52
|
+
label: 'Bold',
|
|
53
|
+
iconName: 'text-bold',
|
|
54
|
+
onClick: (editor) => editor.commands.toggleBold(),
|
|
55
|
+
isActive: (editor) => editor.isActive('bold'),
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
id: 'italic',
|
|
59
|
+
label: 'Italic',
|
|
60
|
+
iconName: 'text-italic',
|
|
61
|
+
onClick: (editor) => editor.commands.toggleItalic(),
|
|
62
|
+
isActive: (editor) => editor.isActive('italic'),
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
id: 'strike',
|
|
66
|
+
label: 'Strike',
|
|
67
|
+
iconName: 'text-strike-through',
|
|
68
|
+
onClick: (editor) => editor.commands.toggleStrike(),
|
|
69
|
+
isActive: (editor) => editor.isActive('strike'),
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
id: 'bulletList',
|
|
73
|
+
label: 'Bullet list',
|
|
74
|
+
iconName: 'list-bullets',
|
|
75
|
+
onClick: (editor) => editor.commands.toggleBulletList(),
|
|
76
|
+
isActive: (editor) => editor.isActive('bulletList'),
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
id: 'orderedList',
|
|
80
|
+
label: 'Ordered list',
|
|
81
|
+
iconName: 'list-numbers',
|
|
82
|
+
onClick: (editor) => editor.commands.toggleOrderedList(),
|
|
83
|
+
isActive: (editor) => editor.isActive('orderedList'),
|
|
84
|
+
},
|
|
85
|
+
/* {
|
|
86
|
+
id: 'link',
|
|
87
|
+
label: 'Link',
|
|
88
|
+
iconName: 'text-link',
|
|
89
|
+
ariaExpanded: () => this.showLinkEditor,
|
|
90
|
+
onClick: (editor) => {
|
|
91
|
+
if (this.shouldShowLinkEditor()) {
|
|
92
|
+
// only show the bubble menu for links
|
|
93
|
+
this.showLinkEditor = true;
|
|
94
|
+
// update link in text input if we should show it
|
|
95
|
+
const previousUrl = editor.getAttributes('link').href;
|
|
96
|
+
this.linkUrl = previousUrl ?? '';
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
isActive: (editor) => editor.isActive('link'),
|
|
100
|
+
isDisabled: () => {
|
|
101
|
+
return !this.shouldShowLinkEditor();
|
|
102
|
+
},
|
|
103
|
+
}, */
|
|
104
|
+
{
|
|
105
|
+
id: 'undo',
|
|
106
|
+
label: 'Undo',
|
|
107
|
+
iconName: 'undo',
|
|
108
|
+
onClick: (editor) => editor.commands.undo(),
|
|
109
|
+
isDisabled: (editor) => !editor.can().undo(),
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
id: 'redo',
|
|
113
|
+
label: 'Redo',
|
|
114
|
+
iconName: 'redo',
|
|
115
|
+
onClick: (editor) => editor.commands.redo(),
|
|
116
|
+
isDisabled: (editor) => !editor.can().redo(),
|
|
117
|
+
},
|
|
118
|
+
],
|
|
119
|
+
// showLinkEditor: false,
|
|
120
|
+
// linkUrl: '',
|
|
121
|
+
};
|
|
122
|
+
},
|
|
123
|
+
computed: {
|
|
124
|
+
menuButtons() {
|
|
125
|
+
if (this.customMenuButtons?.length) {
|
|
126
|
+
const toolbar = [];
|
|
127
|
+
this.customMenuButtons.forEach((customBtn) => {
|
|
128
|
+
const defaultButton = this.defaultMenuButtons.find((defaultBtn) => defaultBtn.id === customBtn.id);
|
|
129
|
+
toolbar.push({
|
|
130
|
+
...defaultButton,
|
|
131
|
+
...customBtn,
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
return toolbar;
|
|
135
|
+
}
|
|
136
|
+
return this.defaultMenuButtons;
|
|
137
|
+
},
|
|
138
|
+
firstFocusableButton() {
|
|
139
|
+
return this.menuButtons.find((button) => !button.isDisabled?.(this.editor));
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
methods: {
|
|
143
|
+
findSiblings(currentElement, position) {
|
|
144
|
+
let sibling = position === 'previous' ? currentElement.previousElementSibling : currentElement.nextElementSibling;
|
|
145
|
+
|
|
146
|
+
if (sibling?.hasAttribute('disabled')) {
|
|
147
|
+
sibling = this.findSiblings(sibling, position);
|
|
148
|
+
}
|
|
149
|
+
return sibling;
|
|
150
|
+
},
|
|
151
|
+
setFocusToSibling(position, event) {
|
|
152
|
+
const element = this.findSiblings(event.target, position);
|
|
153
|
+
if (element) {
|
|
154
|
+
element.focus();
|
|
155
|
+
}
|
|
156
|
+
},
|
|
157
|
+
updateTabIndex(buttonId) {
|
|
158
|
+
// if the id of the button is not passed we get the first focusable button from the list instead
|
|
159
|
+
if (!buttonId) {
|
|
160
|
+
buttonId = this.firstFocusableButton.id;
|
|
161
|
+
}
|
|
162
|
+
this.$refs.menuButton.forEach((button) => {
|
|
163
|
+
if (button.id === buttonId) {
|
|
164
|
+
button.tabindex = 0;
|
|
165
|
+
} else {
|
|
166
|
+
button.tabindex = -1;
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
},
|
|
170
|
+
/* shouldShowLinkEditor() {
|
|
171
|
+
// no selection, so cant open link editor
|
|
172
|
+
const hasSelection = this.editor.state.selection.$from.pos !== this.editor.state.selection.$to.pos;
|
|
173
|
+
const cursorIsAtLink = this.editor.isActive('link');
|
|
174
|
+
return hasSelection || cursorIsAtLink;
|
|
175
|
+
}, */
|
|
176
|
+
},
|
|
177
|
+
};
|
|
178
|
+
</script>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import '@ungap/custom-elements';
|
|
2
|
+
/**
|
|
3
|
+
* We're using a modified `defineCustomElement` where we can choose not to use shadowDom
|
|
4
|
+
* shadowDom prevents access to external CSS, which is how design-system css works!
|
|
5
|
+
* https://github.com/vuejs/core/issues/4314#issuecomment-1021393430
|
|
6
|
+
*/
|
|
7
|
+
import { defineCustomElement } from '../temp-define-custom-element';
|
|
8
|
+
// --- Components ---
|
|
9
|
+
import Combobox from '../components/combobox/Combobox.ce.vue';
|
|
10
|
+
|
|
11
|
+
const MdsCombobox = defineCustomElement(Combobox, { shadowRoot: false });
|
|
12
|
+
|
|
13
|
+
export default MdsCombobox;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import '@ungap/custom-elements';
|
|
2
|
+
/**
|
|
3
|
+
* We're using a modified `defineCustomElement` where we can choose not to use shadowDom
|
|
4
|
+
* shadowDom prevents access to external CSS, which is how design-system css works!
|
|
5
|
+
* https://github.com/vuejs/core/issues/4314#issuecomment-1021393430
|
|
6
|
+
*/
|
|
7
|
+
import { defineCustomElement } from '../temp-define-custom-element';
|
|
8
|
+
import TextEditor from '../components/text-editor/TextEditor.ce.vue';
|
|
9
|
+
|
|
10
|
+
const MdsTextEditor = defineCustomElement(TextEditor, { shadowRoot: false });
|
|
11
|
+
|
|
12
|
+
export default MdsTextEditor;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{_ as h,o as a,c as l,a as c,w as r,t as m,b as v,r as I,n as g,d as p,e as x,f as _,g as C,h as B,F as k,i as w,j as L}from"../plugin-vue_export-helper.js";const V={name:"ComboboxClear",inject:["iconPath","clearInput"]},S=["aria-label","title"],T={"aria-hidden":"true",focusable:"false",class:"mds-icon mds-icon--close mds-icon--sm"},M=["href"];function E(t,i,n,u,o,e){return a(),l("button",{class:"mds-combobox__clear mds-button mds-button--plain",type:"button",onClick:i[0]||(i[0]=d=>t.$emit("clear",d)),onKeydown:i[1]||(i[1]=r(d=>t.$emit("clear",d),["enter"])),"aria-label":e.clearInput,title:e.clearInput},[(a(),l("svg",T,[c("use",{href:`${e.iconPath}#icon-close`},null,8,M)]))],40,S)}var H=h(V,[["render",E]]);const K={name:"ListBox",props:{hidden:{type:Boolean,default:!0},isLoading:{type:Boolean,default:!0},comboboxid:{type:String,required:!0}},inject:["iconPath","loadingText"]},F=["aria-labelledby","hidden"],A={key:0,class:"mds-combobox-loading"},q={"aria-hidden":"true",focusable:"true",class:"mds-icon mds-icon--spinner mds-icon--after"},G=["href"],P={class:"mds-visually-hidden"};function j(t,i,n,u,o,e){return a(),l("ul",{class:"mds-combobox__listbox",role:"listbox","aria-labelledby":`${n.comboboxid}-label`,hidden:n.hidden},[n.isLoading?(a(),l("li",A,[(a(),l("svg",q,[c("use",{href:`${e.iconPath}#icon-spinner`},null,8,G)])),c("span",P,m(e.loadingText),1)])):v("",!0),I(t.$slots,"default")],8,F)}var N=h(K,[["render",j]]);const D={name:"ListBoxOption",props:{option:{type:Object,required:!0},focused:{type:Boolean,default:!1},searchValue:{type:String,default:""}},watch:{searchValue(t){return t},focused(t){t&&this.$refs.listItem.scrollIntoView(!1)}},methods:{highlightOption(){return this.option.label.replace(new RegExp(this.searchValue,"gi"),i=>`<span class="mds-combobox__option--marked">${i}</span>`)}}},R=["aria-selected","innerHTML"];function U(t,i,n,u,o,e){return a(),l("li",{ref:"listItem",class:g(["mds-combobox__option",{"mds-combobox__option--focused":n.focused}]),role:"option","aria-selected":n.focused.toString(),onMousedown:i[0]||(i[0]=d=>t.$emit("mousedown",d)),innerHTML:e.highlightOption()},null,42,R)}var $=h(D,[["render",U]]);const z={name:"Combobox",components:{ComboboxClear:H,ListBox:N,ListBoxOption:$},emits:["search","select-option","clear-all"],props:{comboboxid:{type:String,required:!0},placeholder:{type:String,default:""},name:{type:[String,Boolean],default:!1},value:{type:String,default:""},options:{type:Array,default:()=>[]},filterOptions:{type:Boolean,default:!0},iconpath:{type:String,default:"/assets/icons.svg"},dataAriaInvalid:{type:String,default:""},i18n:{type:String,default:""}},data(){return{expanded:!1,selected:null,chosen:null,searchValue:this.$props.value,resultCountMessage:null}},provide(){return{iconPath:this.iconpath,loadingText:this.i18nText.loadingText,clearInput:this.i18nText.clearInput}},mounted(){var n,u,o,e;const t=(u=(n=this.$el.parentElement)==null?void 0:n.parentElement)==null?void 0:u.querySelector(".mds-form-element__fallback input"),i=(e=(o=this.$el.parentElement)==null?void 0:o.parentElement)==null?void 0:e.querySelector(".mds-form-element__fallback select");t&&t.remove(),i&&i.removeAttribute("id")},computed:{inputValue(){return this.chosenOption?this.chosenOption.label:this.searchValue},selectedOption:{get(){return this.selected},set(t){this.selected=t}},chosenOption:{get(){return this.chosen},set(t){this.chosen=t,this.selectedOption=t,this.$emit("select-option",this.chosen)}},visibleOptions(){return this.filterOptions?this.options.filter(t=>t.label.toLowerCase().includes(this.searchValue.toLowerCase())):this.options},listBoxId(){return`${this.comboboxid}-listbox`},optionId(){return`${this.comboboxid}-option`},describedBy(){return`${this.comboboxid}-assistiveHint`},isLoading(){return this.options.length===0&&this.expanded},selectedOptionId(){const t=this.visibleOptions.indexOf(this.selectedOption);if(t>-1)return`${this.optionId}-${t}`},listBoxHidden(){return!this.expanded},lastOptionIndex(){return this.visibleOptions.length-1},ariaExpanded(){return this.expanded?"true":"false"},ariaInvalid(){return this.dataAriaInvalid?"true":"false"},i18nText(){return this.i18n?JSON.parse(this.i18n):{loadingText:"Loading",describedByText:"When autocomplete results are available, use up and down arrows to review and enter to select.",resultsMessage:"{count} result available",resultsMessage_plural:"{count} results available",clearInput:"clear input"}}},methods:{makeActive(){this.expanded=!0},makeInactive(){this.expanded=!1},handleInput(t){this.chosenOption=null,this.searchValue=t.target?t.target.value:"",this.handleChange(),this.$emit("search",this.searchValue),this.visibleOptions.length>0&&this.updateCount()},handleChange(){this.searchValue.length===0&&this.clearField(),this.searchValue.length>1?(this.makeActive(),this.updateCount()):this.makeInactive()},handleFocus(){this.handleChange(),this.visibleOptions.length>1&&this.updateCount()},handleClear(){this.clearField(),this.$refs.comboInput.focus()},clearField(){this.searchValue="",this.chosenOption=null,this.$emit("clear-all")},clickOption(t=this.selectedOption){this.chosenOption=t,this.makeInactive()},chooseOption(){this.chosenOption=this.selectedOption,this.makeInactive(),this.clearCount()},hiddenGuard(t){this.listBoxHidden||t.call(this)},onInputBlur(){this.makeInactive(),this.clearCount()},onKeyDown(){if(this.selectedOption){const t=this.visibleOptions.findIndex(n=>n.value===this.selectedOption.value),i=t===this.lastOptionIndex?t:t+1;this.selectedOption=this.visibleOptions[i]}else[this.selectedOption]=this.visibleOptions},onKeyUp(){if(this.selectedOption){const t=this.visibleOptions.findIndex(n=>n.value===this.selectedOption.value),i=t===0?t:t-1;this.selectedOption=this.visibleOptions[i]}else this.selectedOption=this.visibleOptions[this.lastOptionIndex]},onKeyHome(){[this.selectedOption]=this.visibleOptions},onKeyEnd(){this.selectedOption=this.visibleOptions[this.lastOptionIndex]},updateCount(){this.clearCount(),setTimeout(()=>{const t=this.visibleOptions.length===1?this.i18nText.resultsMessage:this.i18nText.resultsMessage_plural;this.resultCountMessage=t.replace("{count}",this.visibleOptions.length)},1400)},clearCount(){this.resultCountMessage=null}}},J=["value","id","name","placeholder","aria-owns","aria-expanded","aria-activedescendant","aria-invalid","aria-describedby"],W={"aria-live":"polite",role:"status",class:"mds-visually-hidden"},Q=["id"];function X(t,i,n,u,o,e){const d=p("ComboboxClear"),O=p("ListBoxOption"),y=p("ListBox");return a(),l("div",{class:g(["mds-combobox",{"mds-combobox--active":!e.listBoxHidden}]),onKeydown:[i[4]||(i[4]=r(s=>e.hiddenGuard(e.onKeyDown),["down"])),i[5]||(i[5]=r(s=>e.hiddenGuard(e.onKeyUp),["up"])),i[6]||(i[6]=r(s=>e.hiddenGuard(e.onKeyHome),["home"])),i[7]||(i[7]=r(s=>e.hiddenGuard(e.onKeyEnd),["end"])),i[8]||(i[8]=r((...s)=>e.makeInactive&&e.makeInactive(...s),["esc"])),i[9]||(i[9]=r(B((...s)=>e.chooseOption&&e.chooseOption(...s),["stop","prevent"]),["enter"]))]},[c("input",{onInput:i[0]||(i[0]=(...s)=>e.handleInput&&e.handleInput(...s)),value:e.inputValue,class:"mds-form-control",autocomplete:"off",type:"text",role:"combobox",ref:"comboInput",id:n.comboboxid,name:n.name,placeholder:n.placeholder,"aria-owns":e.listBoxId,"aria-expanded":e.ariaExpanded,"aria-autocomplete":"list","aria-activedescendant":e.selectedOptionId,"aria-invalid":e.ariaInvalid,"aria-describedby":e.describedBy,onChange:i[1]||(i[1]=(...s)=>e.handleChange&&e.handleChange(...s)),onBlur:i[2]||(i[2]=(...s)=>e.onInputBlur&&e.onInputBlur(...s)),onFocus:i[3]||(i[3]=(...s)=>e.handleFocus&&e.handleFocus(...s))},null,40,J),o.searchValue.length>0?(a(),x(d,{key:0,onClear:e.handleClear},null,8,["onClear"])):v("",!0),_(y,{id:e.listBoxId,hidden:e.listBoxHidden,isLoading:e.isLoading,comboboxid:n.comboboxid},{default:C(()=>[(a(!0),l(k,null,w(e.visibleOptions,(s,b)=>{var f;return a(),x(O,{key:b,option:s,id:`${e.optionId}-${b}`,focused:((f=e.selectedOption)==null?void 0:f.value)===(s==null?void 0:s.value),onMousedown:Z=>e.clickOption(s),searchValue:o.searchValue},null,8,["option","id","focused","onMousedown","searchValue"])}),128))]),_:1},8,["id","hidden","isLoading","comboboxid"]),c("div",W,m(o.resultCountMessage),1),c("span",{id:e.describedBy,style:{display:"none"}},m(e.i18nText.describedByText),9,Q)],34)}var Y=h(z,[["render",X]]);const te=L(Y,{shadowRoot:!1});export{te as default};
|