pimelon-ui 0.1.111 → 0.1.113

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,6 +1,6 @@
1
1
  {
2
2
  "name": "pimelon-ui",
3
- "version": "0.1.111",
3
+ "version": "0.1.113",
4
4
  "description": "A set of components and utilities for rapid UI development",
5
5
  "main": "./src/index.js",
6
6
  "scripts": {
@@ -30,6 +30,7 @@
30
30
  "@popperjs/core": "^2.11.2",
31
31
  "@tailwindcss/forms": "^0.5.3",
32
32
  "@tailwindcss/typography": "^0.5.16",
33
+ "@tiptap/extension-code-block-lowlight": "^2.11.5",
33
34
  "@tiptap/extension-color": "^2.0.3",
34
35
  "@tiptap/extension-highlight": "^2.0.3",
35
36
  "@tiptap/extension-image": "^2.0.3",
@@ -52,6 +53,7 @@
52
53
  "feather-icons": "^4.28.0",
53
54
  "husky": "^9.1.7",
54
55
  "idb-keyval": "^6.2.0",
56
+ "lowlight": "^3.3.0",
55
57
  "ora": "5.4.1",
56
58
  "prettier": "^3.3.2",
57
59
  "radix-vue": "^1.5.3",
@@ -0,0 +1,168 @@
1
+ <template>
2
+ <node-view-wrapper>
3
+ <div class="code-block-container">
4
+ <select
5
+ class="language-selector form-select"
6
+ contenteditable="false"
7
+ v-model="selectedLanguage"
8
+ >
9
+ <option :value="null">auto</option>
10
+ <option disabled>—</option>
11
+ <option
12
+ v-for="(language, index) in languages"
13
+ :value="language.value"
14
+ :key="language.value"
15
+ >
16
+ {{ language.label }}
17
+ </option>
18
+ </select>
19
+ <pre><code><node-view-content /></code></pre>
20
+ </div>
21
+ </node-view-wrapper>
22
+ </template>
23
+
24
+ <script>
25
+ import { NodeViewContent, nodeViewProps, NodeViewWrapper } from '@tiptap/vue-3'
26
+
27
+ export default {
28
+ components: {
29
+ NodeViewWrapper,
30
+ NodeViewContent,
31
+ },
32
+ props: nodeViewProps,
33
+ computed: {
34
+ selectedLanguage: {
35
+ get() {
36
+ return this.node.attrs.language
37
+ },
38
+ set(language) {
39
+ this.updateAttributes({ language })
40
+ },
41
+ },
42
+ languages() {
43
+ let supportedLanguages = this.extension.options.lowlight.listLanguages()
44
+ return supportedLanguages
45
+ .map((language) => {
46
+ return {
47
+ label: language,
48
+ value: language,
49
+ }
50
+ })
51
+ .concat([{ label: 'html', value: 'xml' }])
52
+ .sort((a, b) => a.label.localeCompare(b.label))
53
+ },
54
+ },
55
+ }
56
+ </script>
57
+
58
+ <style>
59
+ /* CodeBlock styles */
60
+ .code-block {
61
+ position: relative;
62
+ }
63
+
64
+ .code-block-container {
65
+ position: relative;
66
+ }
67
+
68
+ .language-selector {
69
+ position: absolute;
70
+ top: 0.25rem;
71
+ right: 0.25rem;
72
+ padding-top: 0;
73
+ padding-bottom: 0;
74
+ opacity: 0;
75
+ z-index: 10;
76
+ transition-property: opacity;
77
+ transition-duration: 0.2s;
78
+ transition-timing-function: ease-in-out;
79
+ transition-delay: 0s;
80
+ pointer-events: none;
81
+ }
82
+
83
+ .code-block-container:hover .language-selector {
84
+ opacity: 1;
85
+ transition-delay: 0s;
86
+ pointer-events: auto;
87
+ }
88
+
89
+ .language-selector:focus-within {
90
+ opacity: 1;
91
+ transition-delay: 0s;
92
+ pointer-events: auto;
93
+ }
94
+
95
+ /* When mouse leaves the code block, delay the hiding */
96
+ .code-block-container:not(:hover) .language-selector:not(:focus-within) {
97
+ transition-delay: 1.5s;
98
+ }
99
+
100
+ .ProseMirror pre {
101
+ background: #0d0d0d;
102
+ color: #fff;
103
+ font-family: ui-monospace, Menlo, Monaco, 'Cascadia Mono', 'Segoe UI Mono',
104
+ 'Roboto Mono', 'Oxygen Mono', 'Ubuntu Mono', 'Source Code Pro', 'Fira Mono',
105
+ 'Droid Sans Mono', 'Consolas', 'Courier New', monospace;
106
+ padding: 0.75rem 1rem;
107
+ border-radius: 0.75rem;
108
+ caret-color: #fff;
109
+ }
110
+
111
+ .ProseMirror pre code {
112
+ color: inherit;
113
+ padding: 0;
114
+ background: none;
115
+ font-size: 12px;
116
+ }
117
+
118
+ .ProseMirror pre .hljs-comment,
119
+ .ProseMirror pre .hljs-quote {
120
+ color: #999;
121
+ }
122
+
123
+ .ProseMirror pre .hljs-variable,
124
+ .ProseMirror pre .hljs-template-variable,
125
+ .ProseMirror pre .hljs-attribute,
126
+ .ProseMirror pre .hljs-tag,
127
+ .ProseMirror pre .hljs-name,
128
+ .ProseMirror pre .hljs-regexp,
129
+ .ProseMirror pre .hljs-link,
130
+ .ProseMirror pre .hljs-selector-id,
131
+ .ProseMirror pre .hljs-selector-class {
132
+ color: #f2777a;
133
+ }
134
+
135
+ .ProseMirror pre .hljs-number,
136
+ .ProseMirror pre .hljs-meta,
137
+ .ProseMirror pre .hljs-built_in,
138
+ .ProseMirror pre .hljs-builtin-name,
139
+ .ProseMirror pre .hljs-literal,
140
+ .ProseMirror pre .hljs-type,
141
+ .ProseMirror pre .hljs-params {
142
+ color: #f99157;
143
+ }
144
+
145
+ .ProseMirror pre .hljs-string,
146
+ .ProseMirror pre .hljs-symbol,
147
+ .ProseMirror pre .hljs-bullet {
148
+ color: #99cc99;
149
+ }
150
+
151
+ .ProseMirror pre .hljs-title,
152
+ .ProseMirror pre .hljs-section {
153
+ color: #ffcc66;
154
+ }
155
+
156
+ .ProseMirror pre .hljs-keyword,
157
+ .ProseMirror pre .hljs-selector-tag {
158
+ color: #6196cc;
159
+ }
160
+
161
+ .ProseMirror pre .hljs-emphasis {
162
+ font-style: italic;
163
+ }
164
+
165
+ .ProseMirror pre .hljs-strong {
166
+ font-weight: 700;
167
+ }
168
+ </style>
@@ -5,7 +5,24 @@ import TextEditor from './TextEditor.vue'
5
5
  import TextEditorFixedMenu from './TextEditorFixedMenu.vue'
6
6
  import { Button } from '../Button'
7
7
 
8
- const value = ref('')
8
+ const value = ref(`
9
+ <div>
10
+ <h2>Heading 2</h2>
11
+ <p>
12
+ This is a paragraph with <strong>bold</strong> and <em>italic</em> text.
13
+ </p>
14
+ <ul>
15
+ <li>Item 1</li>
16
+ <li>Item 2</li>
17
+ </ul>
18
+ <p>
19
+ <a href="https://devel.monakerp.com">Melon</a>
20
+ </p>
21
+ <pre><code class="language-javascript">import { Button } from 'pimelon-ui'
22
+ const value = ref(true);</code>
23
+ </pre>
24
+ </div>
25
+ `)
9
26
  const customValue = ref('')
10
27
  const customButtons = [
11
28
  'Paragraph',
@@ -17,7 +17,7 @@
17
17
  <script>
18
18
  import { normalizeClass } from 'vue'
19
19
  import { computed } from '@vue/reactivity'
20
- import { Editor, EditorContent } from '@tiptap/vue-3'
20
+ import { Editor, EditorContent, VueNodeViewRenderer } from '@tiptap/vue-3'
21
21
  import StarterKit from '@tiptap/starter-kit'
22
22
  import Placeholder from '@tiptap/extension-placeholder'
23
23
  import TextAlign from '@tiptap/extension-text-align'
@@ -32,6 +32,9 @@ import Typography from '@tiptap/extension-typography'
32
32
  import TextStyle from '@tiptap/extension-text-style'
33
33
  import Highlight from '@tiptap/extension-highlight'
34
34
  import { Color } from '@tiptap/extension-color'
35
+ import { common, createLowlight } from 'lowlight'
36
+ import CodeBlockLowlight from '@tiptap/extension-code-block-lowlight'
37
+ import CodeBlockComponent from './CodeBlockComponent.vue'
35
38
  import configureMention from './mention'
36
39
  import TextEditorFixedMenu from './TextEditorFixedMenu.vue'
37
40
  import TextEditorBubbleMenu from './TextEditorBubbleMenu.vue'
@@ -40,6 +43,8 @@ import EmojiExtension from './emoji-extension'
40
43
  import { detectMarkdown, markdownToHTML } from '../../utils/markdown'
41
44
  import { DOMParser } from 'prosemirror-model'
42
45
 
46
+ const lowlight = createLowlight(common)
47
+
43
48
  export default {
44
49
  name: 'TextEditor',
45
50
  inheritAttrs: false,
@@ -136,6 +141,7 @@ export default {
136
141
  extensions: [
137
142
  StarterKit.configure({
138
143
  ...this.starterkitOptions,
144
+ codeBlock: false,
139
145
  }),
140
146
  Table.configure({
141
147
  resizable: true,
@@ -150,6 +156,11 @@ export default {
150
156
  TextStyle,
151
157
  Color,
152
158
  Highlight.configure({ multicolor: true }),
159
+ CodeBlockLowlight.extend({
160
+ addNodeView() {
161
+ return VueNodeViewRenderer(CodeBlockComponent)
162
+ },
163
+ }).configure({ lowlight }),
153
164
  Image,
154
165
  Video,
155
166
  Link.configure({
@@ -8,6 +8,9 @@ interface UploadOptions {
8
8
  method?: string
9
9
  type?: string
10
10
  upload_endpoint?: string
11
+ optimize?: boolean
12
+ max_width?: number
13
+ max_height?: number
11
14
  }
12
15
 
13
16
  type EventListenerOption = 'start' | 'progress' | 'finish' | 'error'
@@ -129,6 +132,16 @@ class FileUploadHandler {
129
132
  form_data.append('type', options.type)
130
133
  }
131
134
 
135
+ if (options.optimize) {
136
+ form_data.append('optimize', '1')
137
+ if (options.max_width) {
138
+ form_data.append('max_width', options.max_width.toString())
139
+ }
140
+ if (options.max_height) {
141
+ form_data.append('max_height', options.max_height.toString())
142
+ }
143
+ }
144
+
132
145
  xhr.send(form_data)
133
146
  })
134
147
  }