layers-design-system 2.0.10 → 2.1.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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "layers-design-system",
3
3
  "main": "src/main.js",
4
- "version": "2.0.10",
4
+ "version": "2.1.0",
5
5
  "scripts": {
6
6
  "start": "vue-cli-service serve ./src/main-docs.js",
7
7
  "build": "vue-cli-service build --target lib ./src/main.js",
@@ -26,6 +26,7 @@
26
26
  "@tiptap/extension-text": "2.0.0-beta.13",
27
27
  "@tiptap/extension-underline": "2.0.0-beta.16",
28
28
  "@tiptap/vue-2": "2.0.0-beta.60",
29
+ "autolinker": "^4.0.0",
29
30
  "currency.js": "1.2.2",
30
31
  "dayjs": "^1.11.7",
31
32
  "dompurify": "2.3.3",
@@ -33,7 +34,6 @@
33
34
  "layers-utils": "1.0.4",
34
35
  "mustache": "4.2.0",
35
36
  "tiptap": "1.32.2",
36
- "url-regex-safe": "2.0.2",
37
37
  "vant": "2.12.30",
38
38
  "vue": "2.6.14",
39
39
  "vue-router": "3.5.2",
@@ -41,7 +41,6 @@
41
41
  "vuetify": "2.5.10"
42
42
  },
43
43
  "devDependencies": {
44
- "sass-loader": "7.3.1",
45
44
  "@vue/cli-plugin-babel": "4.5.14",
46
45
  "@vue/cli-plugin-eslint": "4.5.14",
47
46
  "@vue/cli-service": "4.5.14",
@@ -50,6 +49,7 @@
50
49
  "eslint-plugin-vue": "5.2.3",
51
50
  "hard-source-webpack-plugin": "0.13.1",
52
51
  "sass": "1.43.2",
52
+ "sass-loader": "7.3.1",
53
53
  "vue-cli-plugin-element": "1.0.1",
54
54
  "vue-cli-plugin-vuetify": "2.4.3",
55
55
  "vue-template-compiler": "2.6.14",
@@ -54,7 +54,7 @@
54
54
  </template>
55
55
 
56
56
  <script>
57
- import LIcon from '../LIcon'
57
+ import LIcon from '../LIcon/index.vue'
58
58
 
59
59
  let typeMap = {
60
60
  success: 'success',
@@ -1,7 +1,7 @@
1
- import StringEditor from "./StringEditor";
2
- import AmountEditor from "./AmountEditor";
3
- import NumberEditor from "./NumberEditor";
4
- import DateEditor from "./DateEditor";
1
+ import StringEditor from "./StringEditor.vue";
2
+ import AmountEditor from "./AmountEditor.vue";
3
+ import NumberEditor from "./NumberEditor.vue";
4
+ import DateEditor from "./DateEditor.vue";
5
5
 
6
6
  import { FieldTypeComponents } from '../../../../helpers/FieldTypeComponents'
7
7
 
@@ -1,7 +1,7 @@
1
- import StringView from "./StringView";
2
- import AmountView from "./AmountView";
3
- import NumberView from "./NumberView";
4
- import DateView from "./DateView";
1
+ import StringView from "./StringView.vue";
2
+ import AmountView from "./AmountView.vue";
3
+ import NumberView from "./NumberView.vue";
4
+ import DateView from "./DateView.vue";
5
5
 
6
6
  import { FieldTypeComponents } from '../../../../helpers/FieldTypeComponents'
7
7
 
@@ -49,8 +49,8 @@ import isEqual from "lodash/isEqual";
49
49
  import findIndex from "lodash/findIndex";
50
50
  import find from "lodash/find";
51
51
 
52
- import AddFilterButton from "./AddFilterButton";
53
- import FilterChip from "./Filters/FilterChip";
52
+ import AddFilterButton from "./AddFilterButton.vue";
53
+ import FilterChip from "./Filters/FilterChip.vue";
54
54
 
55
55
  export default {
56
56
  tagName: "l-search-bar",
@@ -1,8 +1,8 @@
1
- import StringView from "./StringView";
2
- import NumberView from "./NumberView";
3
- import AmountView from "./AmountView";
4
- import EmailView from "./EmailView";
5
- import DateView from "./DateView";
1
+ import StringView from "./StringView.vue";
2
+ import NumberView from "./NumberView.vue";
3
+ import AmountView from "./AmountView.vue";
4
+ import EmailView from "./EmailView.vue";
5
+ import DateView from "./DateView.vue";
6
6
 
7
7
  import { FieldTypeComponents } from '../../../helpers/FieldTypeComponents'
8
8
 
@@ -31,8 +31,8 @@
31
31
  </template>
32
32
 
33
33
  <script>
34
- import LTableHeaderCell from "./LTableHeaderCell";
35
- import LTableHeaderLoader from "./LTableHeaderLoader";
34
+ import LTableHeaderCell from "./LTableHeaderCell.vue";
35
+ import LTableHeaderLoader from "./LTableHeaderLoader.vue";
36
36
 
37
37
  export default {
38
38
  components: { LTableHeaderCell, LTableHeaderLoader },
@@ -57,7 +57,7 @@
57
57
  </template>
58
58
 
59
59
  <script>
60
- import LTableHeaderResizer from "./LTableHeaderResizer";
60
+ import LTableHeaderResizer from "./LTableHeaderResizer.vue";
61
61
 
62
62
  export default {
63
63
  components: { LTableHeaderResizer },
@@ -78,13 +78,13 @@
78
78
  import FieldTypes from "./FieldTypes";
79
79
  FieldTypes.register();
80
80
 
81
- import LTableBody from "./LTableBody";
82
- import LTableHeader from "./LTableHeader";
83
- import LTableEndspace from "./LTableEndspace"
84
- import LTableLoadMore from "./LTableLoadMore";
85
- import LTableReloader from "./LTableReloader";
86
- import LTableBodySpacer from "./LTableBodySpacer";
87
- import LTablePagination from "./LTablePagination";
81
+ import LTableBody from "./LTableBody.vue";
82
+ import LTableHeader from "./LTableHeader.vue";
83
+ import LTableEndspace from "./LTableEndspace.vue"
84
+ import LTableLoadMore from "./LTableLoadMore.vue";
85
+ import LTableReloader from "./LTableReloader.vue";
86
+ import LTableBodySpacer from "./LTableBodySpacer.vue";
87
+ import LTablePagination from "./LTablePagination.vue";
88
88
 
89
89
  import {changeSelection} from './helpers'
90
90
 
@@ -27,8 +27,8 @@
27
27
  </template>
28
28
 
29
29
  <script>
30
- import urlRegex from 'url-regex-safe'
31
- import { addProtocol } from './helpers/manageLinks'
30
+ import Autolinker from 'autolinker'
31
+ import { addProtocol } from './helpers/addProtocol'
32
32
 
33
33
  export default {
34
34
  props: {
@@ -57,7 +57,10 @@ export default {
57
57
  },
58
58
 
59
59
  isLinkValid(link) {
60
- return urlRegex({ exact: true }).test(link)
60
+ const validating = Autolinker.link(link, {
61
+ email: false,
62
+ })
63
+ return validating.includes('href')
61
64
  },
62
65
  },
63
66
 
@@ -0,0 +1,5 @@
1
+ export function addProtocol(link) {
2
+ return link.startsWith('http://') || link.startsWith('https://')
3
+ ? link
4
+ : 'https://' + link
5
+ }
@@ -63,36 +63,36 @@
63
63
  </template>
64
64
 
65
65
  <script>
66
- import { Editor, EditorContent, BubbleMenu } from '@tiptap/vue-2'
67
- import Document from '@tiptap/extension-document'
68
- import Text from '@tiptap/extension-text'
69
- import ListItem from '@tiptap/extension-list-item'
66
+ import { Editor, EditorContent, BubbleMenu } from "@tiptap/vue-2";
67
+ import Document from "@tiptap/extension-document";
68
+ import Text from "@tiptap/extension-text";
69
+ import ListItem from "@tiptap/extension-list-item";
70
70
 
71
71
  //Layers Custom Extensions
72
- import LayersParagraph from './extensions/LayersParagraph'
73
- import LayersBold from './extensions/LayersBold'
74
- import LayersItalic from './extensions/LayersItalic'
75
- import LayersUnderline from './extensions/LayersUnderline'
76
- import LayersHeading from './extensions/LayersHeading'
77
- import LayersBulletList from './extensions/LayersBulletList'
78
- import LayersOrderedList from './extensions/LayersOrderedList'
79
- import LayersBlockquote from './extensions/LayersBlockquote'
80
- import LayersLink from './extensions/LayersLink'
81
- import LayersPlaceholder from './extensions/LayersPlaceholder'
82
- import LayersBreakLine from './extensions/LayersBreakLine'
83
- import LayersHistory from './extensions/LayersHistory'
72
+ import LayersParagraph from "./extensions/LayersParagraph";
73
+ import LayersBold from "./extensions/LayersBold";
74
+ import LayersItalic from "./extensions/LayersItalic";
75
+ import LayersUnderline from "./extensions/LayersUnderline";
76
+ import LayersHeading from "./extensions/LayersHeading";
77
+ import LayersBulletList from "./extensions/LayersBulletList";
78
+ import LayersOrderedList from "./extensions/LayersOrderedList";
79
+ import LayersBlockquote from "./extensions/LayersBlockquote";
80
+ import LayersLink from "./extensions/LayersLink";
81
+ import LayersPlaceholder from "./extensions/LayersPlaceholder";
82
+ import LayersBreakLine from "./extensions/LayersBreakLine";
83
+ import LayersHistory from "./extensions/LayersHistory";
84
84
 
85
85
  //Custom Components
86
- import LinkBox from './LinkBox'
87
- import FloatingLink from './FloatingLink.vue'
86
+ import LinkBox from "./LinkBox.vue";
87
+ import FloatingLink from "./FloatingLink.vue";
88
88
 
89
89
  //Helpers
90
- import { getTagA, mountLink } from './helpers/manageLinks.js'
91
- import removeEmptyTags from './helpers/removeEmptyTags.js'
92
- import DOMPurify from 'dompurify'
90
+ import removeEmptyTags from "./helpers/removeEmptyTags.js";
91
+ import DOMPurify from "dompurify";
92
+ import Autolinker from "autolinker";
93
93
 
94
94
  export default {
95
- tagName: 'l-text-editor',
95
+ tagName: "l-text-editor",
96
96
 
97
97
  props: {
98
98
  value: String,
@@ -110,77 +110,77 @@ export default {
110
110
  editor: null,
111
111
  markUps: [
112
112
  {
113
- name: 'bold',
114
- tooltip: 'Negrito',
115
- icon: 'uil-bold',
113
+ name: "bold",
114
+ tooltip: "Negrito",
115
+ icon: "uil-bold",
116
116
  },
117
117
  {
118
- name: 'italic',
119
- tooltip: 'Itálico',
120
- icon: 'uil-italic',
118
+ name: "italic",
119
+ tooltip: "Itálico",
120
+ icon: "uil-italic",
121
121
  },
122
122
  {
123
- name: 'underline',
124
- tooltip: 'Sublinhado',
125
- icon: 'uil-underline',
123
+ name: "underline",
124
+ tooltip: "Sublinhado",
125
+ icon: "uil-underline",
126
126
  },
127
127
  {
128
- name: 'heading',
129
- tooltip: 'Título',
130
- icon: require('../../assets/button-text-editor/title.svg'),
128
+ name: "heading",
129
+ tooltip: "Título",
130
+ icon: require("../../assets/button-text-editor/title.svg"),
131
131
  },
132
132
  {
133
- name: 'bulletList',
134
- tooltip: 'Lista com marcadores',
135
- icon: 'uil-list-ul',
133
+ name: "bulletList",
134
+ tooltip: "Lista com marcadores",
135
+ icon: "uil-list-ul",
136
136
  },
137
137
  {
138
- name: 'orderedList',
139
- tooltip: 'Lista numerada',
140
- icon: 'uil-list-ol-alt',
138
+ name: "orderedList",
139
+ tooltip: "Lista numerada",
140
+ icon: "uil-list-ol-alt",
141
141
  },
142
142
  {
143
- name: 'link',
144
- tooltip: 'Inserir link',
145
- icon: 'uil-link-alt',
143
+ name: "link",
144
+ tooltip: "Inserir link",
145
+ icon: "uil-link-alt",
146
146
  },
147
147
  {
148
- name: 'blockquote',
149
- tooltip: 'Citação',
150
- icon: require('../../assets/button-text-editor/double-quotes.svg'),
148
+ name: "blockquote",
149
+ tooltip: "Citação",
150
+ icon: require("../../assets/button-text-editor/double-quotes.svg"),
151
151
  },
152
152
  {
153
- name: 'removeFormatting',
154
- tooltip: 'Remover formatação',
155
- icon: require('../../assets/button-text-editor/remove-formatting.svg'),
153
+ name: "removeFormatting",
154
+ tooltip: "Remover formatação",
155
+ icon: require("../../assets/button-text-editor/remove-formatting.svg"),
156
156
  },
157
157
  ],
158
158
  showLinkBox: false,
159
159
  isEditorFocused: null,
160
160
  tooltipDelay: 125,
161
- }
161
+ };
162
162
  },
163
163
 
164
164
  methods: {
165
165
  isUnicon(value) {
166
- return value.startsWith('uil-')
166
+ return value.startsWith("uil-");
167
167
  },
168
168
 
169
169
  markUpText(type) {
170
- if (type === 'link') {
171
- this.toggleLinkBox()
172
- return
170
+ if (type === "link") {
171
+ this.toggleLinkBox();
172
+ return;
173
173
  }
174
- const commandChain = this.editor.chain().focus()
175
- commandChain.setMarkUp(type).run()
174
+ const commandChain = this.editor.chain().focus();
175
+ commandChain.setMarkUp(type).run();
176
176
  },
177
177
 
178
178
  toggleLinkBox() {
179
- this.showLinkBox = !this.showLinkBox
179
+ this.showLinkBox = !this.showLinkBox;
180
180
  },
181
181
  closeLinkBox() {
182
- this.editor.commands.focus()
183
- this.toggleLinkBox()
182
+ this.editor.commands.focus();
183
+ this.toggleLinkBox();
184
184
  },
185
185
 
186
186
  markUpLink(info) {
@@ -188,91 +188,89 @@ export default {
188
188
  this.editor
189
189
  .chain()
190
190
  .focus()
191
- .extendMarkRange('link')
192
- .setLink({ href: info.url, target: '_blank' })
193
- .run()
191
+ .extendMarkRange("link")
192
+ .setLink({ href: info.url, target: "_blank" })
193
+ .run();
194
194
  } else {
195
- this.editor.commands.insertContent(getTagA(info.url, info.insertedText))
195
+ this.editor.commands.insertContent(Autolinker.link(info.insertedText));
196
196
  }
197
197
  },
198
198
  markOffLink() {
199
- this.editor
200
- .chain()
201
- .focus()
202
- .extendMarkRange('link')
203
- .unsetLink()
204
- .run()
199
+ this.editor.chain().focus().extendMarkRange("link").unsetLink().run();
205
200
  },
206
201
 
207
202
  hasSomeMarkUpActive() {
208
- const textEditorContent = this.editor.getJSON().content
209
- const textEditorMarkUps = this.markUps.map((markUp) => markUp.name)
203
+ const textEditorContent = this.editor.getJSON().content;
204
+ const textEditorMarkUps = this.markUps.map((markUp) => markUp.name);
210
205
 
211
- const textNodesActive = textEditorContent.map((node) => node.type)
206
+ const textNodesActive = textEditorContent.map((node) => node.type);
212
207
 
213
208
  const hasSomeNode = textNodesActive.some((node) =>
214
209
  textEditorMarkUps.includes(node)
215
- )
210
+ );
216
211
  const hasSomeMark = textEditorContent.some((node) => {
217
- if (node.hasOwnProperty('content')) {
218
- return node.content.some((content) => content.hasOwnProperty('marks'))
212
+ if (node.hasOwnProperty("content")) {
213
+ return node.content.some((content) =>
214
+ content.hasOwnProperty("marks")
215
+ );
219
216
  }
220
- })
217
+ });
221
218
 
222
- return hasSomeNode || hasSomeMark
219
+ return hasSomeNode || hasSomeMark;
223
220
  },
224
221
 
225
222
  addSpaceToFinalParagraphTag(text) {
226
- return text.replace(/<\/p>/g, ' </p>')
223
+ return text.replace(/<\/p>/g, " </p>");
227
224
  },
228
225
  },
229
226
 
230
227
  computed: {
231
228
  previousURL() {
232
- return this.editor.getAttributes('link').href
229
+ return this.editor.getAttributes("link").href;
233
230
  },
234
231
  showFloatingLink() {
235
- return this.editor.isActive('link')
232
+ return this.editor.isActive("link");
236
233
  },
237
234
  finalText() {
238
- const textEditorHTML = this.editor.getHTML()
239
- const textEditorHTMLSpaced = this.addSpaceToFinalParagraphTag(textEditorHTML)
240
- const textEditorHTMLWithLinks = mountLink(textEditorHTMLSpaced)
235
+ const textEditorHTML = this.editor.getHTML();
236
+ const textEditorHTMLSpaced =
237
+ this.addSpaceToFinalParagraphTag(textEditorHTML);
238
+ const textEditorHTMLWithLinks = Autolinker.link(textEditorHTMLSpaced);
241
239
 
242
240
  return DOMPurify.sanitize(removeEmptyTags(textEditorHTMLWithLinks), {
243
- ADD_ATTR: ['target'],
244
- })
241
+ ADD_ATTR: ["target"],
242
+ });
245
243
  },
246
244
  currentTextSelection() {
247
- const { view, state } = this.editor
248
- const { from, to } = view.state.selection
249
- return state.doc.textBetween(from, to, '')
245
+ const { view, state } = this.editor;
246
+ const { from, to } = view.state.selection;
247
+ return state.doc.textBetween(from, to, "");
250
248
  },
251
249
  arrowXPosition() {
252
- const arrowWidth = 16.8 //px
253
- const buttonLink = this.$refs.link[0].$el
250
+ const arrowWidth = 16.8; //px
251
+ const buttonLink = this.$refs.link[0].$el;
254
252
 
255
253
  //formula to position the arrow based on the button link position
256
254
  const arrowLeftOffset =
257
- buttonLink.offsetLeft + (buttonLink.offsetWidth - arrowWidth) / 2
258
- return { left: `${arrowLeftOffset}px` }
255
+ buttonLink.offsetLeft + (buttonLink.offsetWidth - arrowWidth) / 2;
256
+ return { left: `${arrowLeftOffset}px` };
259
257
  },
260
258
  linkBoxPosition() {
261
- const linkBoxWidth = 456 //px
262
- const textEditorWidth = this.$refs.texteditor.$el.offsetWidth
263
- const buttonLink = this.$refs.link[0].$el
264
- let linkBoxLeftOffset
265
- const overflowLimit = 500
259
+ const linkBoxWidth = 456; //px
260
+ const textEditorWidth = this.$refs.texteditor.$el.offsetWidth;
261
+ const buttonLink = this.$refs.link[0].$el;
262
+ let linkBoxLeftOffset;
263
+ const overflowLimit = 500;
266
264
 
267
265
  if (textEditorWidth > overflowLimit) {
268
266
  //formula to position the link box based on the screen width
269
- linkBoxLeftOffset = `${buttonLink.offsetLeft +
270
- buttonLink.offsetWidth / 2 -
271
- linkBoxWidth / 2}px`
267
+ linkBoxLeftOffset = `${
268
+ buttonLink.offsetLeft + buttonLink.offsetWidth / 2 - linkBoxWidth / 2
269
+ }px`;
272
270
  } else {
273
- linkBoxLeftOffset = '1rem'
271
+ linkBoxLeftOffset = "1rem";
274
272
  }
275
- return { left: linkBoxLeftOffset }
273
+ return { left: linkBoxLeftOffset };
276
274
  },
277
275
  },
278
276
 
@@ -298,23 +296,23 @@ export default {
298
296
  content: this.value,
299
297
  autofocus: false,
300
298
  onUpdate: () => {
301
- this.$emit('input', this.finalText)
302
- this.$emit('useMarkUp', this.hasSomeMarkUpActive())
299
+ this.$emit("input", this.finalText);
300
+ this.$emit("useMarkUp", this.hasSomeMarkUpActive());
303
301
  },
304
302
  onFocus: () => {
305
- this.isEditorFocused = true
306
- this.$emit('focus', true)
303
+ this.isEditorFocused = true;
304
+ this.$emit("focus", true);
307
305
  },
308
306
  onBlur: () => {
309
- this.isEditorFocused = false
307
+ this.isEditorFocused = false;
310
308
  },
311
- })
309
+ });
312
310
  },
313
311
 
314
312
  beforeDestroy() {
315
- this.editor.destroy()
313
+ this.editor.destroy();
316
314
  },
317
- }
315
+ };
318
316
  </script>
319
317
 
320
318
  <style scoped>
@@ -1,60 +0,0 @@
1
- const urlRegex = require('url-regex-safe')
2
-
3
- const customUrlRegex = new RegExp(
4
- '((href=")?)' +
5
- urlRegex({
6
- localhost: false,
7
- apostrophes: false,
8
- returnString: true,
9
- }) +
10
- ' ((</a>)?)',
11
- 'g'
12
- )
13
-
14
- function mountTagA(url) {
15
- const href = addProtocol(url)
16
- return getTagA(removeAnchorTag(href), url)
17
- }
18
-
19
- export function getTagA(href, insertedText) {
20
- return `<a target="_blank" rel="noopener noreferrer nofollow" class="color-link"
21
- style="text-decoration: underline" href="${href}">${insertedText}</a>`
22
- }
23
-
24
- function removeAnchorTag(string) {
25
- return string.replace("</a>", "")
26
- }
27
-
28
- export function addProtocol(link) {
29
- return link.startsWith('http://') || link.startsWith('https://')
30
- ? link
31
- : 'https://' + link
32
- }
33
-
34
- export function mountLink(text) {
35
- // Regular expression to match email addresses
36
- const emailRegex = /(\b[\w.%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b)/g;
37
-
38
- // Replace each email address in text with a mailto link
39
- let finalText = text.replace(emailRegex, (email) => {
40
- const href = `mailto:${email}`;
41
- return getTagA(href, email);
42
- });
43
- let match;
44
-
45
- // Loop through the text to find and replace URLs
46
- while ((match = customUrlRegex.exec(finalText)) !== null) {
47
- const url = match[0];
48
-
49
- // Skip URLs that are parto of email addresses or already within anchor tags
50
- if (finalText[match.index - 1] === '@' || url.startsWith('href="') || url.endsWith('</a>')) {
51
- continue;
52
- }
53
- const finalIndex = match.index + url.length;
54
- const finalUrl = mountTagA(url);
55
-
56
- // Replace the URL with the formatted ancho tag
57
- finalText = finalText.substring(0, match.index) + finalUrl + finalText.substring(finalIndex);
58
- }
59
- return finalText;
60
- }