@mixd-id/web-scaffold 0.2.250801014 → 0.2.260801002

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.
Files changed (113) hide show
  1. package/README.md +25 -1
  2. package/docs/components/AIDashboard.md +117 -32
  3. package/docs/components/Alert.md +3 -1
  4. package/docs/components/Card.md +5 -0
  5. package/docs/components/PivotList.md +207 -0
  6. package/docs/components/Textbox.md +20 -1
  7. package/docs/components/Tooltip.md +148 -0
  8. package/package.json +17 -61
  9. package/src/components/AIChat.vue +14 -5
  10. package/src/components/AIChatItem.vue +34 -3
  11. package/src/components/AIDashboard.vue +144 -98
  12. package/src/components/Alert.vue +58 -35
  13. package/src/components/Card.vue +55 -6
  14. package/src/components/Carousel.vue +1 -1
  15. package/src/{widgets → components}/CartSetting.vue +1 -0
  16. package/src/components/Chart.vue +2 -2
  17. package/src/components/Checkbox.vue +22 -24
  18. package/src/components/CodeEditor.vue +2 -0
  19. package/src/{widgets → components}/CollapsiblePanelSetting.vue +1 -0
  20. package/src/components/ColorPicker.vue +2 -2
  21. package/src/{widgets → components}/ComponentSetting2.vue +1 -1
  22. package/src/components/Confirm.vue +2 -0
  23. package/src/{widgets → components}/ContactForm.vue +1 -1
  24. package/src/components/CopyToClipboard.vue +0 -1
  25. package/src/components/Datepicker.vue +2 -0
  26. package/src/components/Datetimepicker.vue +1 -1
  27. package/src/components/Dropdown.vue +1 -1
  28. package/src/{widgets → components}/FeatureList.vue +1 -1
  29. package/src/components/Gmaps.vue +1 -1
  30. package/src/{widgets → components}/IconList.vue +1 -1
  31. package/src/components/Image.vue +1 -1
  32. package/src/components/ImagePreview.vue +32 -51
  33. package/src/components/List.vue +45 -8
  34. package/src/components/MarkdownEdit.vue +1 -1
  35. package/src/components/MarkdownPreview.vue +4 -1
  36. package/src/{widgets → components}/MenuItem1Setting.vue +1 -0
  37. package/src/components/Metric.vue +30 -7
  38. package/src/components/MultiDropdown.vue +3 -1
  39. package/src/{widgets → components}/MultiValueSetting.vue +2 -2
  40. package/src/{widgets → components}/MultiValueSetting2.vue +2 -2
  41. package/src/components/OTPField.vue +3 -1
  42. package/src/components/PivotList.vue +1239 -0
  43. package/src/{widgets → components}/PresetBar.vue +1 -1
  44. package/src/components/PresetSelectorFilterItem.vue +1 -1
  45. package/src/components/Radio.vue +1 -1
  46. package/src/{widgets → components}/Share.vue +1 -1
  47. package/src/components/SvgEditor.vue +1 -1
  48. package/src/components/Switch.vue +1 -1
  49. package/src/components/TextWithTag.vue +2 -2
  50. package/src/components/Textbox.vue +63 -5
  51. package/src/components/Toast.vue +2 -1
  52. package/src/components/Tooltip.vue +626 -0
  53. package/src/components/VirtualGrid.vue +2 -2
  54. package/src/components/VirtualTable.vue +4 -3
  55. package/src/{widgets → components}/WebDatasourceSelector.vue +2 -0
  56. package/src/{widgets → components}/WebLayoutSelector.vue +1 -1
  57. package/src/directives/tooltip.js +131 -0
  58. package/src/index.js +11 -235
  59. package/src/themes/default/index.js +16 -0
  60. package/src/utils/ai-dashboard.js +163 -38
  61. package/src/utils/helpers.mjs +52 -5
  62. package/src/utils/list.mjs +4 -1
  63. package/src/utils/pivot-formula.mjs +358 -0
  64. package/src/utils/pivot-list.mjs +557 -0
  65. package/src/utils/tooltip.mjs +243 -0
  66. package/src/utils/wss.js +26 -6
  67. package/src/utils/wss.mjs +29 -2
  68. /package/src/{widgets → components}/AhrefSetting.vue +0 -0
  69. /package/src/{widgets → components}/ArticleSetting.vue +0 -0
  70. /package/src/{widgets → components}/BackgroundColorSetting.vue +0 -0
  71. /package/src/{widgets → components}/BlockSetting.vue +0 -0
  72. /package/src/{widgets → components}/BorderColorSetting.vue +0 -0
  73. /package/src/{widgets → components}/ButtonSetting.vue +0 -0
  74. /package/src/{widgets → components}/CarouselSetting.vue +0 -0
  75. /package/src/{widgets → components}/ColumnSelector.vue +0 -0
  76. /package/src/{widgets → components}/ComponentSetting.vue +0 -0
  77. /package/src/{widgets → components}/ContactFormSetting.vue +0 -0
  78. /package/src/{widgets → components}/CountdownSetting.vue +0 -0
  79. /package/src/{widgets → components}/DataListSetting.vue +0 -0
  80. /package/src/{widgets → components}/EmbeddedVideo.vue +0 -0
  81. /package/src/{widgets → components}/EmbeddedVideoSetting.vue +0 -0
  82. /package/src/{widgets → components}/FAQ.vue +0 -0
  83. /package/src/{widgets → components}/FAQSetting.vue +0 -0
  84. /package/src/{widgets → components}/FeatureListSetting.vue +0 -0
  85. /package/src/{widgets → components}/FlexSetting.vue +0 -0
  86. /package/src/{widgets → components}/GridSetting.vue +0 -0
  87. /package/src/{widgets → components}/Header2.vue +0 -0
  88. /package/src/{widgets → components}/Header2Setting.vue +0 -0
  89. /package/src/{widgets → components}/IconListSetting.vue +0 -0
  90. /package/src/{widgets → components}/ImageSetting.vue +0 -0
  91. /package/src/{widgets → components}/LLMChat.vue +0 -0
  92. /package/src/{widgets → components}/LinkSetting.vue +0 -0
  93. /package/src/{widgets → components}/LinkSettingModal.vue +0 -0
  94. /package/src/{widgets → components}/ModalSetting.vue +0 -0
  95. /package/src/{widgets → components}/OGSettingModal.vue +0 -0
  96. /package/src/{widgets → components}/ParagraphSetting.vue +0 -0
  97. /package/src/{widgets → components}/PositionSetting.vue +0 -0
  98. /package/src/{widgets → components}/PresetBarPivot.vue +0 -0
  99. /package/src/{widgets → components}/PresetBarPivotColumnEdit.vue +0 -0
  100. /package/src/{widgets → components}/PresetBarPivotValueEdit.vue +0 -0
  101. /package/src/{widgets → components}/PresetSelector.vue +0 -0
  102. /package/src/{widgets → components}/Review.vue +0 -0
  103. /package/src/{widgets → components}/ReviewSetting.vue +0 -0
  104. /package/src/{widgets → components}/SearchModalSetting.vue +0 -0
  105. /package/src/{widgets → components}/ShareSetting.vue +0 -0
  106. /package/src/{widgets → components}/SvgSetting.vue +0 -0
  107. /package/src/{widgets → components}/TableSetting.vue +0 -0
  108. /package/src/{widgets → components}/TestimonialSetting.vue +0 -0
  109. /package/src/{widgets → components}/TextBlockSetting.vue +0 -0
  110. /package/src/{widgets → components}/ThumbnailSetting.vue +0 -0
  111. /package/src/{widgets → components}/WebComponentSelector.vue +0 -0
  112. /package/src/{widgets → components}/WebPageBuilder.vue +0 -0
  113. /package/src/{widgets → components}/YoutubeVideoSetting.vue +0 -0
@@ -628,7 +628,7 @@ export default{
628
628
  enumCache: Object,
629
629
 
630
630
  useAssistant: {
631
- type: undefined,
631
+ type: [ Boolean, String ],
632
632
  default: false
633
633
  }
634
634
 
@@ -124,7 +124,7 @@ export default{
124
124
 
125
125
  column: {
126
126
  type: Object,
127
- default: {}
127
+ default: () => ({})
128
128
  },
129
129
 
130
130
  enabled: Boolean,
@@ -85,7 +85,7 @@ export default{
85
85
  }
86
86
 
87
87
  .indicator{
88
- @apply w-[21px] h-[21px] border-[1px] rounded-full border-border-200 bg-base-300;
88
+ @apply w-[21px] h-[21px] border-[1px] rounded-full border-border-200 bg-base-200;
89
89
  @apply flex items-center justify-center overflow-hidden;
90
90
  transition: border 300ms cubic-bezier(0.25, 1, 0.5, 1);
91
91
  }
@@ -78,7 +78,7 @@ export default{
78
78
 
79
79
  config: {
80
80
  type: Object,
81
- default: {}
81
+ default: () => ({})
82
82
  },
83
83
 
84
84
  direction: {
@@ -160,7 +160,7 @@ function sizeChanged(){
160
160
  }
161
161
 
162
162
  .comp code{
163
- @apply border-[1px] border-border-200 bg-base-300 rounded-lg flex flex-col overflow-hidden;
163
+ @apply border-[1px] border-border-200 bg-base-200 rounded-lg flex flex-col overflow-hidden;
164
164
  @apply p-6;
165
165
  white-space: pre-wrap;
166
166
  tab-size: 1rem;
@@ -75,7 +75,7 @@ export default{
75
75
  }
76
76
 
77
77
  .switch label{
78
- @apply w-[3rem] inline-block rounded-2xl bg-base-300 h-[2rem];
78
+ @apply w-[3rem] inline-block rounded-2xl bg-base-200 h-[2rem];
79
79
  @apply border-[1px] border-border-200 hover:border-border-300;
80
80
  }
81
81
 
@@ -17,7 +17,7 @@
17
17
  </slot>
18
18
  </div>
19
19
 
20
- <div v-if="variant !== 'minimal' && !readonly" class="flex flex-row bg-base-300" @dblclick.alt="log(JSON.stringify(modelValue))">
20
+ <div v-if="variant !== 'minimal' && !readonly" class="flex flex-row bg-base-200" @dblclick.alt="log(JSON.stringify(modelValue))">
21
21
  <div class="flex-1 flex flex-row gap-2 overflow-x-auto p-1" :class="$style.noScrollbar">
22
22
  <button type="button" v-for="item in viewedItems" :class="$style.tag2" class="text-xs" @click="add(item)">{{ item.text ?? item.value }}</button>
23
23
  </div>
@@ -271,7 +271,7 @@ export default{
271
271
  <style module>
272
272
 
273
273
  .comp {
274
- @apply border-[1px] border-border-200 bg-base-300 rounded-lg min-w-[100px];
274
+ @apply border-[1px] border-border-200 bg-base-200 rounded-lg min-w-[100px];
275
275
  @apply flex flex-col gap-2;
276
276
  @apply overflow-hidden;
277
277
  @apply divide-y divide-text-100;
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <div :class="computedClass">
3
3
  <slot name="start"></slot>
4
- <input :type="computedType" :disabled="isDisabled" @focus="isActive = true"
4
+ <input :type="computedType" :disabled="isDisabled" @focus="onFocus"
5
5
  @input="onInput"
6
6
  @blur="onBlur"
7
7
  @keyup="(e) => $emit('keyup', e)"
@@ -10,7 +10,7 @@
10
10
  :class="itemClass" @click="$emit('input-click')"
11
11
  @keydown="onKeyDown"/>
12
12
  <button class="mr-2" v-show="Boolean(clearable) && !Boolean(readonly) && state >= 1 && modelValue" type="button" @click="$emit('clear')">
13
- <svg :class="$style.svg" width="19" height="19" viewBox="0 0 24 24" class="fill-text-200 hover:fill-red-500" xmlns="http://www.w3.org/2000/svg">
13
+ <svg :class="$style.svg" width="19" height="19" viewBox="0 0 24 24" class="fill-text-300 hover:fill-red-500" xmlns="http://www.w3.org/2000/svg">
14
14
  <path d="M6.53034 5.46965C6.23745 5.17676 5.76257 5.17676 5.46968 5.46965C5.17679 5.76255 5.17679 6.23742 5.46968 6.53031L10.9393 12L5.46967 17.4697C5.17678 17.7626 5.17678 18.2374 5.46967 18.5303C5.76256 18.8232 6.23744 18.8232 6.53033 18.5303L12 13.0606L17.4697 18.5303C17.7626 18.8232 18.2375 18.8232 18.5303 18.5303C18.8232 18.2374 18.8232 17.7626 18.5303 17.4697L13.0607 12L18.5303 6.53032C18.8232 6.23743 18.8232 5.76256 18.5303 5.46966C18.2374 5.17677 17.7626 5.17677 17.4697 5.46966L12 10.9393L6.53034 5.46965Z"/>
15
15
  </svg>
16
16
  </button>
@@ -86,9 +86,19 @@ export default{
86
86
  return this.state === 2
87
87
  },
88
88
 
89
+ // What this locale writes a decimal point as — a dot in en, a comma in id,
90
+ // de, fr and most of Europe. `tel` accepts either key and shows this one,
91
+ // so the number reads the way the person typing it expects.
92
+ decimalSeparator(){
93
+ return new Intl.NumberFormat().formatToParts(1.1).find(part => part.type === 'decimal')?.value ?? '.'
94
+ },
95
+
89
96
  displayedValue(){
90
97
  if(this.isActive){
91
- return this.modelValue ?? this.value
98
+ // While typing, what was typed — the value behind it is always
99
+ // written with a dot, and swapping it back mid-keystroke would
100
+ // take the separator away as soon as it was pressed.
101
+ return this.draft ?? this.modelValue ?? this.value
92
102
  }
93
103
  else{
94
104
  switch(this.type){
@@ -97,6 +107,9 @@ export default{
97
107
  const val = parseFloat(this.modelValue)
98
108
  return isNaN(val) ? '' : val.toLocaleString()
99
109
 
110
+ case 'tel':
111
+ return `${this.modelValue ?? this.value ?? ''}`.replace('.', this.decimalSeparator)
112
+
100
113
  default:
101
114
  return this.modelValue ?? this.value
102
115
 
@@ -120,7 +133,10 @@ export default{
120
133
 
121
134
  data(){
122
135
  return {
123
- isActive: false
136
+ isActive: false,
137
+ // What is on screen while the field has focus, which is not the same
138
+ // as the value behind it once a comma is involved.
139
+ draft: null
124
140
  }
125
141
  },
126
142
 
@@ -135,12 +151,50 @@ export default{
135
151
  },
136
152
 
137
153
  onInput(e){
154
+ if(this.type === 'tel'){
155
+ const text = this.asDecimal(e.target.value)
156
+
157
+ // The box shows the separator this locale uses; what goes out is
158
+ // written with a dot, so `Number()` and `v-model.number` read it
159
+ // the same wherever it was typed.
160
+ this.draft = text
161
+
162
+ // Only when something was actually dropped: assigning on every
163
+ // keystroke puts the caret back at the end, which makes editing
164
+ // the middle of a number impossible.
165
+ if(e.target.value !== text) e.target.value = text
166
+
167
+ this.$emit('update:modelValue', text.replace(this.decimalSeparator, '.'))
168
+ this.$emit('input', e)
169
+ return
170
+ }
171
+
138
172
  this.$emit('update:modelValue', e.target.value)
139
173
  this.$emit('input', e)
140
174
  },
141
175
 
176
+ // Either key means the same thing, and only the first one is a separator:
177
+ // everything after it belongs to the fraction.
178
+ asDecimal(value){
179
+ const separator = this.decimalSeparator
180
+ const text = `${value ?? ''}`.replace(/[^0-9.,]/g, '').replace(/[.,]/g, separator)
181
+
182
+ const first = text.indexOf(separator)
183
+ if(first < 0) return text
184
+
185
+ return text.slice(0, first + 1) + text.slice(first + 1).split(separator).join('')
186
+ },
187
+
188
+ onFocus(){
189
+ this.isActive = true
190
+ this.draft = this.type === 'tel'
191
+ ? `${this.modelValue ?? this.value ?? ''}`.replace('.', this.decimalSeparator)
192
+ : null
193
+ },
194
+
142
195
  onBlur(e){
143
196
  this.isActive = false
197
+ this.draft = null
144
198
  this.$emit('blur', e)
145
199
  },
146
200
 
@@ -150,7 +204,7 @@ export default{
150
204
  let text = (e.clipboardData || window.clipboardData).getData("text");
151
205
  switch(this.type){
152
206
  case 'tel':
153
- text = text.replace(/[^0-9]/g, '')
207
+ text = this.asDecimal(text)
154
208
  break
155
209
  }
156
210
  if(parseInt(this.maxlength) > 0){
@@ -162,6 +216,10 @@ export default{
162
216
 
163
217
  onKeyDown(e){
164
218
  if([ 'number', 'tel' ].includes(this.type)){
219
+ // Matched on the character rather than the key code: which key
220
+ // carries a comma moves with the layout, the character does not.
221
+ if(this.type === 'tel' && (e.key === '.' || e.key === ',')) return
222
+
165
223
  if(((e.keyCode >= 48 && e.keyCode <= 57) || (e.keyCode >= 96 && e.keyCode <= 105) ||
166
224
  [ 8, 9, 13, 27, 37, 38, 39, 40, 46 ].includes(e.keyCode)) && !e.ctrlKey && !e.metaKey && !e.shiftKey && !e.altKey);
167
225
  else if(e.keyCode === 65 && (e.ctrlKey || e.metaKey));
@@ -105,12 +105,13 @@ export default{
105
105
  <style module>
106
106
 
107
107
  .toast{
108
+ @apply absolute top-0 left-0 w-full pointer-events-none;
108
109
  }
109
110
 
110
111
  .item{
111
112
  @apply flex p-3 gap-4;
112
113
  @apply max-w-[90vw] md:max-w-[480px] bg-base-500 mx-auto rounded-xl border-[1px] border-border-100;
113
- @apply min-h-[var(--h-cp)];
114
+ @apply min-h-[var(--h-cp)] pointer-events-auto;
114
115
  z-index: 61;
115
116
  }
116
117