@mythpe/quasar-ui-qui 0.2.24 → 0.2.26

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.
@@ -163,7 +163,7 @@ watch(url, (url) => {
163
163
  <MTransitionGroup>
164
164
  <div
165
165
  key="top"
166
- class="row justify-between items-center q-mb-lg"
166
+ class="row justify-between items-center q-mb-sm"
167
167
  >
168
168
  <div
169
169
  :class="{
@@ -193,7 +193,7 @@ watch(url, (url) => {
193
193
  <div
194
194
  v-if="!!errorMessage"
195
195
  key="signature-errors"
196
- class="text-negative text-caption q-mb-lg"
196
+ class="text-negative text-caption q-mb-sm"
197
197
  >
198
198
  <q-icon
199
199
  name="ion-ios-information-circle-outline"
@@ -203,10 +203,8 @@ watch(url, (url) => {
203
203
  </div>
204
204
  <div
205
205
  key="signature-pad"
206
- :class="{
207
- 'bg-negative': !!errorMessage,
208
- 'print-shadow-none bordered' : !0
209
- }"
206
+ :class="{ 'bg-negativ e': !!errorMessage, }"
207
+ class="print-shadow-none bordered"
210
208
  >
211
209
  <div>
212
210
  <slot
@@ -232,6 +230,8 @@ watch(url, (url) => {
232
230
  :height="height"
233
231
  :src="url"
234
232
  :width="width"
233
+ fit="contain"
234
+ no-spinner
235
235
  />
236
236
  </template>
237
237
  </slot>
@@ -247,19 +247,15 @@ watch(url, (url) => {
247
247
  class="q-mt-sm print-hide"
248
248
  >
249
249
  <template v-if="!confirmed">
250
- <div class="column q-gutter-sm">
251
- <MBtn
252
- :label="__('labels.confirm_signature')"
253
- color="positive"
254
- flat
255
- icon="ion-ios-hand"
256
- @click="save('image/jpeg')"
257
- />
258
- </div>
250
+ <MBtn
251
+ :label="__('labels.confirm_signature')"
252
+ class="full-width q-mb-sm"
253
+ color="positive"
254
+ @click="save('image/jpeg')"
255
+ />
259
256
  <MRow class="justify-between">
260
257
  <MBtn
261
258
  :label="__('labels.undo')"
262
- flat
263
259
  icon="ion-ios-undo"
264
260
  @click="undo"
265
261
  />
@@ -267,22 +263,20 @@ watch(url, (url) => {
267
263
  <MBtn
268
264
  :label="__('labels.clear_signature')"
269
265
  color="negative"
270
- flat
271
266
  icon="ion-ios-repeat"
272
267
  @click="clear"
273
268
  />
274
269
  </MRow>
275
270
  </template>
276
271
  <MTransition>
277
- <MColumn v-if="confirmed">
278
- <MBtn
279
- :label="__('labels.clear_signature')"
280
- color="negative"
281
- flat
282
- icon="ion-ios-refresh"
283
- @click="clear"
284
- />
285
- </MColumn>
272
+ <MBtn
273
+ v-if="confirmed"
274
+ :label="__('labels.clear_signature')"
275
+ class="full-width"
276
+ color="negative"
277
+ icon="ion-ios-refresh"
278
+ @click="clear"
279
+ />
286
280
  </MTransition>
287
281
  </div>
288
282
  </MTransitionGroup>
@@ -0,0 +1,403 @@
1
+ <!--
2
+ - MyTh Ahmed Faiz Copyright © 2016-2024 All rights reserved.
3
+ - Email: mythpe@gmail.com
4
+ - Mobile: +966590470092
5
+ - Website: https://www.4myth.com
6
+ - Github: https://github.com/mythpe
7
+ -->
8
+
9
+ <script
10
+ lang="ts"
11
+ setup
12
+ >
13
+
14
+ import { useField } from 'vee-validate'
15
+ import type { MCkeditorProps as Props } from '../../types'
16
+ import { computed, reactive, toValue, useTemplateRef } from 'vue'
17
+ import { useBindInput, useMyth } from '../../composable'
18
+
19
+ import type { EditorConfig } from 'ckeditor5'
20
+ import {
21
+ Alignment,
22
+ Autoformat,
23
+ Base64UploadAdapter,
24
+ BlockQuote,
25
+ Bold,
26
+ CKFinder,
27
+ CKFinderUploadAdapter,
28
+ ClassicEditor,
29
+ CloudServices,
30
+ Code,
31
+ CodeBlock,
32
+ Essentials,
33
+ FontBackgroundColor,
34
+ FontColor,
35
+ FontFamily,
36
+ FontSize,
37
+ Heading,
38
+ Image,
39
+ ImageCaption,
40
+ ImageResize,
41
+ ImageStyle,
42
+ ImageToolbar,
43
+ ImageUpload,
44
+ Indent,
45
+ IndentBlock,
46
+ Italic,
47
+ Link,
48
+ List,
49
+ MediaEmbed,
50
+ Mention,
51
+ Paragraph,
52
+ PasteFromOffice,
53
+ PictureEditing,
54
+ RemoveFormat,
55
+ SourceEditing,
56
+ Strikethrough,
57
+ Subscript,
58
+ Superscript,
59
+ Table,
60
+ TableColumnResize,
61
+ TableToolbar,
62
+ TextTransformation,
63
+ TodoList,
64
+ Underline
65
+ } from 'ckeditor5'
66
+ import { Ckeditor } from '@ckeditor/ckeditor5-vue'
67
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
68
+ // @ts-ignore
69
+ import arTranslations from 'ckeditor5/translations/ar.js'
70
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
71
+ // @ts-ignore
72
+ import enTranslations from 'ckeditor5/translations/en.js'
73
+
74
+ type P = {
75
+ name: Props['name'];
76
+ lang: Props['lang'];
77
+ config?: Props['config'];
78
+ tagName?: Props['tagName'];
79
+ disabled?: Props['disabled'];
80
+ disableTwoWayDataBinding?: Props['disableTwoWayDataBinding'];
81
+
82
+ auto?: Props['auto'];
83
+ col?: Props['col'];
84
+ xs?: Props['xs'];
85
+ sm?: Props['sm'];
86
+ md?: Props['md'];
87
+ lg?: Props['lg'];
88
+ xl?: Props['xl'];
89
+ label?: Props['label'];
90
+ caption?: Props['caption'];
91
+ help?: Props['help'];
92
+ required?: Props['required'];
93
+ rules?: Props['rules'];
94
+ viewMode?: Props['viewMode'];
95
+ viewModeValue?: Props['viewModeValue'];
96
+ fieldOptions?: Props['fieldOptions'];
97
+ }
98
+ const props = withDefaults(defineProps<P>(), {
99
+ name: '',
100
+ lang: 'ar',
101
+ config: undefined,
102
+ tagName: 'div',
103
+ disabled: !1,
104
+ disableTwoWayDataBinding: !1,
105
+
106
+ auto: undefined,
107
+ col: undefined,
108
+ xs: undefined,
109
+ sm: undefined,
110
+ md: undefined,
111
+ lg: undefined,
112
+ xl: undefined,
113
+ label: undefined,
114
+ caption: undefined,
115
+ help: undefined,
116
+ required: undefined,
117
+ rules: undefined,
118
+ viewMode: !1,
119
+ viewModeValue: undefined,
120
+ fieldOptions: undefined
121
+ })
122
+ defineModel<Props['modelValue']>({ required: !1, default: undefined })
123
+ const { __, props: pluginOptions } = useMyth()
124
+ const helper = useBindInput<any>(() => props, 'ckeditor')
125
+ const { getLabel, inputRules } = helper
126
+ const inputScope = useField<Props['modelValue']>(() => props.name, inputRules, {
127
+ validateOnMount: !1,
128
+ validateOnValueUpdate: !1,
129
+ syncVModel: !0,
130
+ label: getLabel,
131
+ ...toValue<any>(props.fieldOptions)
132
+ })
133
+ const { value, errorMessage, handleChange } = inputScope
134
+
135
+ const isRtl = computed(() => props.lang === 'ar')
136
+ const getConfig = computed<any>(() => {
137
+ const inpConfig: EditorConfig = {
138
+ language: {
139
+ ui: props.lang as string,
140
+ content: props.lang as string,
141
+ textPartLanguage: [
142
+ {
143
+ title: __('labels.ar'),
144
+ languageCode: 'ar',
145
+ textDirection: 'rtl'
146
+ },
147
+ {
148
+ title: __('labels.en'),
149
+ languageCode: 'en',
150
+ textDirection: 'ltr'
151
+ }
152
+ ]
153
+ },
154
+ translations: [
155
+ arTranslations,
156
+ enTranslations
157
+ ],
158
+ plugins: [
159
+ Autoformat,
160
+ BlockQuote,
161
+ Bold,
162
+ CKFinder,
163
+ CKFinderUploadAdapter,
164
+ CloudServices,
165
+ Essentials,
166
+ Heading,
167
+ Image,
168
+ ImageCaption,
169
+ ImageResize,
170
+ ImageStyle,
171
+ ImageToolbar,
172
+ ImageUpload,
173
+ Base64UploadAdapter,
174
+ Indent,
175
+ IndentBlock,
176
+ Italic,
177
+ Link,
178
+ List,
179
+ MediaEmbed,
180
+ Mention,
181
+ Paragraph,
182
+ PasteFromOffice,
183
+ PictureEditing,
184
+ Table,
185
+ TableColumnResize,
186
+ TableToolbar,
187
+ TextTransformation,
188
+ Underline,
189
+ FontSize,
190
+ FontFamily,
191
+ FontColor,
192
+ FontBackgroundColor,
193
+ RemoveFormat,
194
+ Strikethrough,
195
+ Subscript,
196
+ Code,
197
+ CodeBlock,
198
+ Alignment,
199
+ Superscript,
200
+ TodoList,
201
+ SourceEditing
202
+ ],
203
+ toolbar: {
204
+ items: [
205
+ 'undo',
206
+ 'redo',
207
+ '|',
208
+ 'bold', 'italic', 'underline', 'strikethrough', 'subscript', 'superscript', 'code',
209
+ '|',
210
+ 'fontfamily', 'fontsize', 'fontColor', 'fontBackgroundColor',
211
+ '|',
212
+ 'alignment',
213
+ 'insertTable',
214
+ 'heading',
215
+ '|',
216
+ 'link', 'uploadImage', 'blockQuote', 'codeBlock',
217
+ '|',
218
+ 'bulletedList', 'numberedList', 'todoList', 'outdent', 'indent',
219
+ '|',
220
+ // 'ckbox',
221
+ 'removeFormat',
222
+ 'mediaEmbed',
223
+ '|',
224
+ 'sourceEditing'
225
+ ],
226
+ shouldNotGroupWhenFull: true
227
+ },
228
+ heading: {
229
+ options: [
230
+ {
231
+ model: 'paragraph',
232
+ title: 'Paragraph',
233
+ class: 'ck-heading_paragraph'
234
+ },
235
+ {
236
+ model: 'heading1',
237
+ view: 'h1',
238
+ title: 'Heading 1',
239
+ class: 'ck-heading_heading1'
240
+ },
241
+ {
242
+ model: 'heading2',
243
+ view: 'h2',
244
+ title: 'Heading 2',
245
+ class: 'ck-heading_heading2'
246
+ },
247
+ {
248
+ model: 'heading3',
249
+ view: 'h3',
250
+ title: 'Heading 3',
251
+ class: 'ck-heading_heading3'
252
+ },
253
+ {
254
+ model: 'heading4',
255
+ view: 'h4',
256
+ title: 'Heading 4',
257
+ class: 'ck-heading_heading4'
258
+ }
259
+ ]
260
+ },
261
+ image: {
262
+ resizeOptions: [
263
+ {
264
+ name: 'resizeImage:original',
265
+ label: 'Default image width',
266
+ value: null
267
+ },
268
+ {
269
+ name: 'resizeImage:50',
270
+ label: '50% page width',
271
+ value: '50'
272
+ },
273
+ {
274
+ name: 'resizeImage:75',
275
+ label: '75% page width',
276
+ value: '75'
277
+ }
278
+ ],
279
+ toolbar: [
280
+ 'imageTextAlternative',
281
+ 'toggleImageCaption',
282
+ '|',
283
+ 'imageStyle:inline',
284
+ 'imageStyle:wrapText',
285
+ 'imageStyle:breakText',
286
+ '|',
287
+ 'resizeImage'
288
+ ]
289
+ },
290
+ menuBar: {
291
+ isVisible: !1
292
+ },
293
+ link: {
294
+ addTargetToExternalLinks: true,
295
+ defaultProtocol: 'https://'
296
+ },
297
+ table: {
298
+ contentToolbar: ['tableColumn', 'tableRow', 'mergeTableCells']
299
+ }
300
+ }
301
+ if (props.config) {
302
+ return props.config(inpConfig as EditorConfig)
303
+ }
304
+ return inpConfig
305
+ })
306
+ const listeners = {
307
+ 'update:modelValue': (v: Props['modelValue']) => handleChange(v, !!errorMessage.value)
308
+ }
309
+ const input = useTemplateRef<any>('input')
310
+ const scopes = reactive(inputScope)
311
+ defineExpose<typeof scopes & { input: typeof input }>({ input, ...scopes })
312
+ defineOptions({
313
+ name: 'MCkeditor',
314
+ inheritAttrs: !1
315
+ })
316
+ </script>
317
+
318
+ <template>
319
+ <MCol
320
+ :auto="auto"
321
+ :class="[$attrs.class,{'m--input__required':inputRules?.required!==undefined,'m--input__error':!!errorMessage,'m--input__view':viewMode}]"
322
+ :col="col"
323
+ :lg="lg"
324
+ :md="md"
325
+ :name="name"
326
+ :sm="sm"
327
+ :xs="xs"
328
+ >
329
+ <slot
330
+ name="top-input"
331
+ v-bind="scopes"
332
+ />
333
+ <slot name="top-label">
334
+ <MInputLabel
335
+ v-if="!!getLabel"
336
+ :field="scopes"
337
+ >
338
+ <MHelpRow
339
+ v-if="!!help"
340
+ :text="help"
341
+ tooltip
342
+ />
343
+ </MInputLabel>
344
+ </slot>
345
+ <slot name="caption">
346
+ <div
347
+ v-if="!!caption"
348
+ class="m--input__caption"
349
+ >
350
+ {{ __(caption) }}
351
+ </div>
352
+ </slot>
353
+ <slot
354
+ name="help"
355
+ v-bind="scopes"
356
+ >
357
+ <MHelpRow
358
+ v-if="!getLabel && help"
359
+ :text="help"
360
+ />
361
+ </slot>
362
+ <MTransition>
363
+ <div
364
+ v-if="!!errorMessage"
365
+ class="text-negative text-caption"
366
+ >
367
+ <q-icon
368
+ v-if="!!errorMessage"
369
+ color="negative"
370
+ name="ion-ios-information-circle-outline"
371
+ size="20px"
372
+ />
373
+ {{ errorMessage }}
374
+ </div>
375
+ </MTransition>
376
+ <div
377
+ v-if="viewMode"
378
+ v-html="value"
379
+ />
380
+ <div
381
+ v-else
382
+ :dir="isRtl ? 'rtl' : 'ltr'"
383
+ :style="`direction: ${isRtl ? 'rtl' : 'ltr'}`"
384
+ >
385
+ <ckeditor
386
+ ref="input"
387
+ :config="getConfig"
388
+ :disable-two-way-data-binding="disableTwoWayDataBinding"
389
+ :disabled="disabled"
390
+ :editor="ClassicEditor"
391
+ :model-value="value || ''"
392
+ :tag-name="tagName"
393
+ v-bind="{...$attrs,...pluginOptions.ckeditor}"
394
+ v-on="listeners"
395
+ />
396
+ <slot v-bind="scopes" />
397
+ </div>
398
+ <slot
399
+ name="bottom-input"
400
+ v-bind="scopes"
401
+ />
402
+ </MCol>
403
+ </template>
@@ -10,7 +10,7 @@ import MAxios from './MAxios.vue'
10
10
  import MAvatarViewer from './MAvatarViewer.vue'
11
11
  import MBtn from './MBtn.vue'
12
12
  import MCheckbox from './MCheckbox.vue'
13
- // import MCkeditor from './MCkeditor.vue'
13
+ import MCkeditor from './MCkeditor.vue'
14
14
  import MColor from './MColor.vue'
15
15
  import MDate from './MDate.vue'
16
16
  import MEditor from './MEditor.vue'
@@ -40,7 +40,7 @@ export {
40
40
  MAvatarViewer,
41
41
  MBtn,
42
42
  MCheckbox,
43
- // MCkeditor,
43
+ MCkeditor,
44
44
  MColor,
45
45
  MDate,
46
46
  MEditor,
@@ -0,0 +1,26 @@
1
+ /*
2
+ * MyTh Ahmed Faiz Copyright © 2016-2025 All rights reserved.
3
+ * Email: mythpe@gmail.com
4
+ * Mobile: +966590470092
5
+ * Website: https://www.4myth.com
6
+ * Github: https://github.com/mythpe
7
+ */
8
+
9
+ import { useCKEditorCloud } from '@ckeditor/ckeditor5-vue'
10
+ import { computed } from 'vue'
11
+
12
+ export function useCkeditor () {
13
+ const cloud = useCKEditorCloud({
14
+ version: '45.1.0',
15
+ translations: ['ar', 'en']
16
+ })
17
+ const editor = computed(() => {
18
+ if (!cloud.data.value) {
19
+ return null
20
+ }
21
+
22
+ return cloud.data.value.CKEditor.ClassicEditor
23
+ })
24
+
25
+ return { cloud, editor }
26
+ }
package/src/index.sass CHANGED
@@ -6,6 +6,7 @@
6
6
 
7
7
  //@import 'quasar/src/css/variables.sass'
8
8
  @import './style/main'
9
+ @import './style/m-ck.css' #{"/* rtl:ignore */"}
9
10
  @import './style/ckeditor5'
10
11
  @import './style/m-container'
11
12
  @import './style/m-dt'
@@ -1,4 +1,4 @@
1
- @import 'ckeditor5/ckeditor5.css' #{"/* rtl:ignore */"}
1
+ //@import 'ckeditor5/ckeditor5.css' #{"/* rtl:ignore */"}
2
2
 
3
3
  :root
4
4
  --ck-z-dialog: 9999 !important
@@ -0,0 +1,135 @@
1
+ /*
2
+ * MyTh Ahmed Faiz Copyright © 2016-2025 All rights reserved.
3
+ * Email: mythpe@gmail.com
4
+ * Mobile: +966590470092
5
+ * Website: https://www.4myth.com
6
+ * Github: https://github.com/mythpe
7
+ */
8
+
9
+ @import url('https://fonts.googleapis.com/css2?family=Oswald&family=PT+Serif:ital,wght@0,400;0,700;1,400&display=swap');
10
+ @import url('https://fonts.googleapis.com/css2?family=Lato:ital,wght@0,400;0,700;1,400;1,700&display=swap');
11
+
12
+ @media print {
13
+ body {
14
+ margin: 0 !important;
15
+ }
16
+ }
17
+
18
+ .main-container {
19
+ /*font-family: 'Lato';*/
20
+ width: fit-content;
21
+ margin-left: auto;
22
+ margin-right: auto;
23
+ direction: ltr;
24
+ }
25
+
26
+ .ck-content {
27
+ font-family: 'Lato', sans-serif;
28
+ line-height: 1.6;
29
+ word-break: break-word;
30
+ }
31
+
32
+ .editor-container_classic-editor .editor-container__editor {
33
+ min-width: 795px;
34
+ max-width: 795px;
35
+ }
36
+
37
+ .editor-container_include-block-toolbar {
38
+ margin-left: 42px;
39
+ }
40
+
41
+ .ck-content h3.category {
42
+ font-family: 'Oswald', serif;
43
+ font-size: 20px;
44
+ font-weight: bold;
45
+ color: #555;
46
+ letter-spacing: 10px;
47
+ margin: 0;
48
+ padding: 0;
49
+ }
50
+
51
+ .ck-content h3.document-subtitle {
52
+ font-family: 'Oswald', serif;
53
+ font-size: 20px;
54
+ color: #555;
55
+ margin: 0 0 1em;
56
+ font-weight: bold;
57
+ padding: 0;
58
+ }
59
+
60
+ .ck-content p.info-box {
61
+ --background-size: 30px;
62
+ --background-color: #e91e63;
63
+ padding: 1.2em 2em;
64
+ border: 1px solid var(--background-color);
65
+ background: linear-gradient(135deg, var(--background-color) 0%, var(--background-color) var(--background-size), transparent var(--background-size)),
66
+ linear-gradient(
67
+ 135deg,
68
+ transparent calc(100% - var(--background-size)),
69
+ var(--background-color) calc(100% - var(--background-size)),
70
+ var(--background-color)
71
+ );
72
+ border-radius: 10px;
73
+ margin: 1.5em 2em;
74
+ box-shadow: 5px 5px 0 #ffe6ef;
75
+ }
76
+
77
+ .ck-content span.marker {
78
+ background: yellow;
79
+ }
80
+
81
+ .ck-content span.spoiler {
82
+ background: #000;
83
+ color: #000;
84
+ }
85
+
86
+ .ck-content span.spoiler:hover {
87
+ background: #000;
88
+ color: #fff;
89
+ }
90
+
91
+ .ck-content .button {
92
+ display: inline-block;
93
+ width: 260px;
94
+ border-radius: 8px;
95
+ margin: 0 auto;
96
+ padding: 12px;
97
+ color: #ffffff;
98
+ font-size: 24px;
99
+ font-weight: 700;
100
+ text-align: center;
101
+ text-decoration: none;
102
+ }
103
+
104
+ .ck-content .button--green {
105
+ background-color: #406b1e;
106
+ }
107
+
108
+ .ck-content .button--black {
109
+ background-color: #141517;
110
+ }
111
+
112
+ .editor_container__word-count .ck-word-count {
113
+ color: var(--ck-color-text);
114
+ display: flex;
115
+ height: 20px;
116
+ gap: var(--ck-spacing-small);
117
+ justify-content: flex-end;
118
+ font-size: var(--ck-font-size-base);
119
+ line-height: var(--ck-line-height-base);
120
+ font-family: var(--ck-font-face);
121
+ padding: var(--ck-spacing-small) var(--ck-spacing-standard);
122
+ }
123
+
124
+ .editor-container_include-word-count.editor-container_classic-editor .editor_container__word-count {
125
+ border: 1px solid var(--ck-color-base-border);
126
+ border-radius: var(--ck-border-radius);
127
+ border-top-left-radius: 0;
128
+ border-top-right-radius: 0;
129
+ border-top: none;
130
+ }
131
+
132
+ .editor-container_include-word-count.editor-container_classic-editor .editor-container__editor .ck-editor .ck-editor__editable {
133
+ border-radius: 0;
134
+ }
135
+