@mixd-id/web-scaffold 0.1.230406148 → 0.1.230406150

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": "@mixd-id/web-scaffold",
3
3
  "private": false,
4
- "version": "0.1.230406148",
4
+ "version": "0.1.230406150",
5
5
  "scripts": {
6
6
  "dev": "vite serve",
7
7
  "build": "vite build",
@@ -22,7 +22,8 @@
22
22
  },
23
23
  "./importer": "./src/utils/importer.js",
24
24
  "./listpage1": "./src/utils/listpage1.js",
25
- "./listview": "./src/utils/listview.js"
25
+ "./listview": "./src/utils/listview.js",
26
+ "./web": "./src/utils/web.js"
26
27
  },
27
28
  "dependencies": {
28
29
  "@faker-js/faker": "^7.3.0",
@@ -1,10 +1,12 @@
1
1
  <template>
2
- <article :class="$style.comp"
3
- v-html="htmlText"
4
- :contenteditable="editable"
5
- @input="onInput"
6
- @click="onClick"
7
- @paste="onPaste"></article>
2
+ <div :class="$style.comp">
3
+ <article :class="$style.article"
4
+ v-html="htmlText"
5
+ :contenteditable="editMode"
6
+ @input="onInput"
7
+ @click="onClick"
8
+ @paste="onPaste"></article>
9
+ </div>
8
10
  </template>
9
11
 
10
12
  <script>
@@ -46,13 +48,13 @@ export default{
46
48
  },
47
49
 
48
50
  onInput(){
49
- if(this.editable){
51
+ if(this.editMode){
50
52
  this.triggerUpdate()
51
53
  }
52
54
  },
53
55
 
54
56
  onClick(){
55
- if(this.editable){
57
+ if(this.editMode){
56
58
  let { element } = getSelection(this.$el)
57
59
 
58
60
  const table = this.closest(element, 'table')
@@ -211,18 +213,14 @@ export default{
211
213
 
212
214
  },
213
215
 
214
- data(){
215
- return {
216
- editable: false
217
- }
218
- },
219
-
220
216
  mounted() {
221
217
  if('edit-mode' in this.$route.query){
222
218
  window.addEventListener('message', (e) => {
223
219
 
224
220
  const { data, source } = e
225
221
 
222
+ if(!data || !source) return
223
+
226
224
  if(data.uid === this.uid){
227
225
 
228
226
  const { action, type, value } = data.data ?? {}
@@ -325,7 +323,6 @@ export default{
325
323
  }
326
324
 
327
325
  })
328
- this.editable = true
329
326
  }
330
327
  }
331
328
 
@@ -336,38 +333,42 @@ export default{
336
333
  <style module>
337
334
 
338
335
  .comp{
339
- background-image: v-bind(bgImages[0]);
336
+ @apply relative;
337
+ background-image: v-bind(bgImages[0]);
338
+ }
339
+
340
+ .article{
340
341
  }
341
- .comp *{
342
+ .article *{
342
343
  }
343
- .comp[contenteditable]{
344
+ .article[contenteditable]{
344
345
  @apply outline-none;
345
346
  }
346
347
 
347
- .comp a{
348
+ .article a{
348
349
  @apply text-primary underline;
349
350
  }
350
351
 
351
- .comp ul li{
352
+ .article ul li{
352
353
  @apply list-disc list-inside;
353
354
  }
354
- .comp ol li{
355
+ .article ol li{
355
356
  @apply list-decimal list-inside;
356
357
  }
357
358
 
358
- font[size='1']{ @apply text-xs; }
359
- font[size='2']{ @apply text-sm; }
360
- font[size='3']{ @apply text-lg; }
361
- font[size='4']{ @apply text-xl; }
362
- font[size='5']{ @apply text-2xl; }
363
- font[size='6']{ @apply text-3xl; }
364
- font[size='7']{ @apply text-4xl; }
359
+ .article font[size='1']{ @apply text-xs; }
360
+ .article font[size='2']{ @apply text-sm; }
361
+ .article font[size='3']{ @apply text-lg; }
362
+ .article font[size='4']{ @apply text-xl; }
363
+ .article font[size='5']{ @apply text-2xl; }
364
+ .article font[size='6']{ @apply text-3xl; }
365
+ .article font[size='7']{ @apply text-4xl; }
365
366
 
366
- .comp table{
367
+ .article table{
367
368
  @apply border-[1px] border-text-200 border-collapse w-full;
368
369
  table-layout: fixed;
369
370
  }
370
- .comp table th, .comp table td{
371
+ .article table th, .article table td{
371
372
  @apply border-[1px] border-text-200 p-3 text-left;
372
373
  @apply break-words;
373
374
  }
@@ -125,7 +125,7 @@ export default{
125
125
  }
126
126
  },
127
127
 
128
- }
128
+ },
129
129
 
130
130
  }
131
131
 
@@ -4,8 +4,7 @@
4
4
  <div ref="inner" :class="computedContainerClass">
5
5
  <div v-for="item in items" :class="computedItemClass">
6
6
  <component :is="item.type"
7
- :="item"
8
- @click.stop="editModeClick(item.uid)" />
7
+ :="item" />
9
8
  </div>
10
9
  </div>
11
10
 
@@ -39,8 +38,6 @@ import {componentMixin} from "../mixin/component";
39
38
 
40
39
  export default{
41
40
 
42
- inject: [ 'editModeClick' ],
43
-
44
41
  mixins: [ componentMixin ],
45
42
 
46
43
  props:{
@@ -3,8 +3,7 @@
3
3
 
4
4
  <component v-for="(item, idx) in items"
5
5
  :is="item.type"
6
- :="item"
7
- @click.stop="editModeClick(item.uid)" />
6
+ :="item" />
8
7
 
9
8
  </div>
10
9
  </template>
@@ -15,8 +14,6 @@ import {componentMixin} from "../mixin/component";
15
14
 
16
15
  export default{
17
16
 
18
- inject: [ 'editModeClick' ],
19
-
20
17
  mixins: [ componentMixin ],
21
18
 
22
19
  props:{
@@ -3,8 +3,7 @@
3
3
 
4
4
  <component v-for="item in items"
5
5
  :is="item.type"
6
- :="item"
7
- @click.stop="editModeClick(item.uid)" />
6
+ :="item" />
8
7
 
9
8
  </div>
10
9
  </template>
@@ -15,8 +14,6 @@ import {componentMixin} from "../mixin/component";
15
14
 
16
15
  export default{
17
16
 
18
- inject: [ 'editModeClick' ],
19
-
20
17
  mixins: [ componentMixin ],
21
18
 
22
19
  props:{
@@ -372,7 +372,8 @@ export default{
372
372
  },
373
373
 
374
374
  async loadConfig(){
375
- if(!this.configStoreObj || 'reset' in ((this.$route ?? {}).query ?? {})){
375
+ if(!this.configStoreObj ||
376
+ Object.keys(((this.$route ?? {}).query ?? {})).map(_ => _.toLowerCase()).includes('reset')){
376
377
  this.configLoaded = true
377
378
  if('reset' in ((this.$route ?? {}).query ?? {}))
378
379
  await this.saveConfig()
@@ -239,7 +239,7 @@ export default{
239
239
  }
240
240
 
241
241
  .modalBody{
242
- @apply flex-1 min-h-0 overflow-y-auto flex bg-base-400 dark:bg-base-300;
242
+ @apply flex-1 min-h-0 overflow-y-auto flex bg-base-400;
243
243
  }
244
244
 
245
245
  .overlay{
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div :class="computedClass">
3
- <button v-for="(item, index) in items" :class="tabClass(item)"
3
+ <button v-for="(item, index) in filteredItems" :class="tabClass(item)"
4
4
  @click="onClick(item)" type="button" >
5
5
  <slot v-if="$slots.tab" name="tab" :="{ item, index }"></slot>
6
6
  <div v-else :class="$style.item">
@@ -35,7 +35,11 @@ export default{
35
35
 
36
36
  computedClass(){
37
37
  return this.$style[this.variant]
38
- }
38
+ },
39
+
40
+ filteredItems(){
41
+ return this.items.filter(_=>_)
42
+ }
39
43
 
40
44
  },
41
45
 
@@ -79,7 +83,7 @@ export default{
79
83
  }
80
84
 
81
85
  .item{
82
- @apply whitespace-nowrap overflow-hidden;
86
+ @apply whitespace-nowrap overflow-hidden p-0.5;
83
87
  }
84
88
 
85
89
  .button{
package/src/index.js CHANGED
@@ -332,6 +332,7 @@ export default{
332
332
  app.config.globalProperties.warn = consoleWarn
333
333
  app.config.globalProperties.info = consoleInfo
334
334
 
335
+ app.component('Ahref', defineAsyncComponent(() => import("./components/Ahref.vue")))
335
336
  app.component('Alert', defineAsyncComponent(() => import("./components/Alert.vue")))
336
337
  app.component('Article', defineAsyncComponent(() => import("./components/Article.vue")))
337
338
  app.component('Block', defineAsyncComponent(() => import("./components/Block.vue")))
@@ -352,7 +353,6 @@ export default{
352
353
  app.component('Feed', defineAsyncComponent(() => import("./components/Feed.vue")))
353
354
  app.component('Gmaps', defineAsyncComponent(() => import("./components/Gmaps.vue")))
354
355
  app.component('HTMLEditor', defineAsyncComponent(() => import("./components/HTMLEditor.vue")))
355
- app.component('Ahref', defineAsyncComponent(() => import("./components/Ahref.vue")))
356
356
  app.component('Switch', defineAsyncComponent(() => import("./components/Switch.vue")))
357
357
  app.component('IconMenu', defineAsyncComponent(() => import("./components/IconMenu.vue")))
358
358
  app.component('IconMenu2', defineAsyncComponent(() => import("./components/IconMenu2.vue")))
@@ -402,22 +402,19 @@ export default{
402
402
  app.component('TextBlock', defineAsyncComponent(() => import("./components/TextBlock.vue")))
403
403
  app.component('TextEditor', defineAsyncComponent(() => import("./components/TextEditor.vue")))
404
404
 
405
- app.component('WebPageBuilder', defineAsyncComponent(() => import("./widgets/WebPageBuilder.vue")))
406
- app.component('WebPageSelector', defineAsyncComponent(() => import("./widgets/WebPageSelector.vue")))
407
- app.component('WebLayoutSelector', defineAsyncComponent(() => import("./widgets/WebLayoutSelector.vue")))
408
- app.component('ComponentSetting', defineAsyncComponent(() => import("./widgets/ComponentSetting.vue")))
405
+ app.component('AhrefItem', defineAsyncComponent(() => import("./widgets/AhrefItem.vue")))
406
+ app.component('AhrefSetting', defineAsyncComponent(() => import("./widgets/AhrefSetting.vue")))
409
407
  app.component('ArticleItem', defineAsyncComponent(() => import("./widgets/ArticleItem.vue")))
410
408
  app.component('ArticleSetting', defineAsyncComponent(() => import("./widgets/ArticleSetting.vue")))
411
409
  app.component('BlockItem', defineAsyncComponent(() => import("./widgets/BlockItem.vue")))
412
410
  app.component('BlockSetting', defineAsyncComponent(() => import("./widgets/BlockSetting.vue")))
413
411
  app.component('BoxItem', defineAsyncComponent(() => import("./widgets/BoxItem.vue")))
414
412
  app.component('BoxSetting', defineAsyncComponent(() => import("./widgets/BoxSetting.vue")))
415
- app.component('AhrefItem', defineAsyncComponent(() => import("./widgets/AhrefItem.vue")))
416
- app.component('AhrefSetting', defineAsyncComponent(() => import("./widgets/AhrefSetting.vue")))
417
413
  app.component('ButtonItem', defineAsyncComponent(() => import("./widgets/ButtonItem.vue")))
418
414
  app.component('ButtonSetting', defineAsyncComponent(() => import("./widgets/ButtonSetting.vue")))
419
415
  app.component('CarouselItem', defineAsyncComponent(() => import("./widgets/CarouselItem.vue")))
420
416
  app.component('CarouselSetting', defineAsyncComponent(() => import("./widgets/CarouselSetting.vue")))
417
+ app.component('ComponentSetting', defineAsyncComponent(() => import("./widgets/ComponentSetting.vue")))
421
418
  app.component('ContactForm', defineAsyncComponent(() => import("./widgets/ContactForm.vue")))
422
419
  app.component('ContactFormItem', defineAsyncComponent(() => import("./widgets/ContactFormItem.vue")))
423
420
  app.component('ContactFormSetting', defineAsyncComponent(() => import("./widgets/ContactFormSetting.vue")))
@@ -457,5 +454,10 @@ export default{
457
454
  app.component('TestimonialSetting', defineAsyncComponent(() => import("./widgets/TestimonialSetting.vue")))
458
455
  app.component('TextBlockItem', defineAsyncComponent(() => import("./widgets/TextBlockItem.vue")))
459
456
  app.component('TextBlockSetting', defineAsyncComponent(() => import("./widgets/TextBlockSetting.vue")))
457
+ app.component('WebPageBuilder', defineAsyncComponent(() => import("./widgets/WebPageBuilder.vue")))
458
+ app.component('WebComponentSelector', defineAsyncComponent(() => import("./widgets/WebComponentSelector.vue")))
459
+ app.component('WebDatasourceSelector', defineAsyncComponent(() => import("./widgets/WebDatasourceSelector.vue")))
460
+ app.component('WebPageSelector', defineAsyncComponent(() => import("./widgets/WebPageSelector.vue")))
461
+ app.component('WebLayoutSelector', defineAsyncComponent(() => import("./widgets/WebLayoutSelector.vue")))
460
462
  }
461
463
  }
@@ -1,4 +1,8 @@
1
1
  // mixin/component.js
2
+ import { inject } from 'vue'
3
+ import {parseBoolean} from "../utils/helpers.mjs";
4
+
5
+ let guide, guide2
2
6
 
3
7
  export const componentMixin = {
4
8
 
@@ -46,7 +50,12 @@ export const componentMixin = {
46
50
  opacity: Array,
47
51
 
48
52
  containerClass: String,
49
- itemClass: String
53
+ itemClass: String,
54
+
55
+ editSelectable: {
56
+ type: undefined,
57
+ default: true
58
+ },
50
59
  },
51
60
 
52
61
  computed: {
@@ -63,7 +72,7 @@ export const componentMixin = {
63
72
  (this.bgImage && this.bgImage[0] && this.bgImage[0].imageUrl ?
64
73
  `url('${import.meta.env.VITE_IMAGE_HOST + '/' + this.bgImage[0].imageUrl}')` : '')
65
74
  ]
66
- }
75
+ },
67
76
 
68
77
  },
69
78
 
@@ -72,7 +81,80 @@ export const componentMixin = {
72
81
  imageSrc(src){
73
82
  return typeof src === 'string' ?
74
83
  import.meta.env.VITE_IMAGE_HOST + '/' + src : src
84
+ },
85
+
86
+ componentClick(e){
87
+ e.stopPropagation()
88
+ e.preventDefault()
89
+
90
+ this.editModeClick ? this.editModeClick(this.uid) : null
91
+ },
92
+
93
+ componentMouseOver(e){
94
+ e.stopPropagation()
95
+ e.preventDefault()
96
+
97
+ this.lastStyle.position = this.$el.style.position
98
+ this.$el.style.position = 'relative'
99
+
100
+ this.$el.appendChild(this.getGuide())
101
+ },
102
+
103
+ componentMouseOut(e){
104
+ this.$el.style.position = this.lastStyle.position
105
+ },
106
+
107
+ getGuide(){
108
+ if(!guide){
109
+ guide = document.createElement('div')
110
+ guide.className = "absolute top-0 left-0 right-0 bottom-0 border-[3px] border-blue-600" +
111
+ " pointer-events-none"
112
+ }
113
+
114
+ return guide
115
+ },
116
+
117
+ getGuide2(){
118
+ if(!guide2){
119
+ guide2 = document.createElement('div')
120
+ guide2.className = "absolute top-0 left-0 right-0 bottom-0 border-[3px] border-blue-600" +
121
+ " pointer-events-none"
122
+ }
123
+
124
+ return guide2
125
+ },
126
+
127
+ select(){
128
+ this.$el.appendChild(this.getGuide2())
129
+ },
130
+
131
+ },
132
+
133
+ data(){
134
+ return {
135
+ editMode: false,
136
+ lastStyle: {}
137
+ }
138
+ },
139
+
140
+ mounted(){
141
+ if('edit-mode' in this.$route.query){
142
+ this.editMode = true
143
+ this.editModeClick = inject('editModeClick', () => {})
144
+ this.editRegisterComponent = inject('editRegisterComponent', () => {})
145
+
146
+ if(parseBoolean(this.editSelectable)){
147
+ this.$el.addEventListener('click', this.componentClick)
148
+ this.$el.addEventListener('mouseover', this.componentMouseOver)
149
+ this.$el.addEventListener('mouseout', this.componentMouseOut)
150
+ }
151
+
152
+ this.editRegisterComponent(this.uid, this)
75
153
  }
154
+ },
155
+
156
+ unmounted(){
157
+ this.$el.removeEventListener('click', this.componentClick)
158
+ },
76
159
 
77
- }
78
160
  };
@@ -0,0 +1,48 @@
1
+ const { accessNestedObject } = require("./helpers");
2
+
3
+ const applyDatasourceReplacer = (value, datasource) => {
4
+ let matches = value.match(/\{([^}]+)\}/g);
5
+ (matches ?? []).forEach(matchKey => {
6
+ matchKey = matchKey.slice(1, -1)
7
+ const matchValue = accessNestedObject(datasource, matchKey) ?? ''
8
+ value = value.replace(`{${matchKey}}`, matchValue, 'gi')
9
+ });
10
+
11
+ return value
12
+ }
13
+
14
+ const applyDatasource = async (items, datasource, keys = [ 'htmlText', 'text' ]) => {
15
+
16
+ for(let idx in items){
17
+ const item = items[idx]
18
+
19
+ for(let key of keys){
20
+
21
+ // Replace array type value
22
+ if(Array.isArray(item[key])){
23
+ for(let itemIdx in item[key]){
24
+ item[key][itemIdx] = applyDatasourceReplacer(item[key][itemIdx], datasource)
25
+ }
26
+ }
27
+
28
+ // Replace primitive type value
29
+ else if(item[key]){
30
+ item[key] = applyDatasourceReplacer(item[key], datasource)
31
+ }
32
+ }
33
+
34
+ // Iterate child items
35
+ if(Array.isArray(item.items)){
36
+ item.items = await applyDatasource(item.items, datasource, keys)
37
+ }
38
+
39
+ items[idx] = item
40
+ }
41
+
42
+ return items
43
+ }
44
+
45
+ module.exports = {
46
+ applyDatasource,
47
+ applyDatasourceReplacer
48
+ }