js-kompo-utils 1.0.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.
Files changed (67) hide show
  1. package/README.md +1 -0
  2. package/app.js +22 -0
  3. package/components/VlApexChart.vue +89 -0
  4. package/components/VlCKEditorTemplate.vue +52 -0
  5. package/components/VlCKEditorWithVars.vue +80 -0
  6. package/components/VlCollapsible.vue +91 -0
  7. package/components/VlCopyBox.vue +61 -0
  8. package/components/VlCreditCardInput.vue +104 -0
  9. package/components/VlDateMonthDay.vue +327 -0
  10. package/components/VlDateTextInput.vue +151 -0
  11. package/components/VlInternationalPhoneInput.vue +902 -0
  12. package/components/VlPartialDate.vue +283 -0
  13. package/components/VlPasswordInput.vue +358 -0
  14. package/components/VlQrCodeScanner.vue +91 -0
  15. package/components/VlSwipeableTab.vue +35 -0
  16. package/components/VlSwipeableTabs.vue +325 -0
  17. package/components/VlText.vue +72 -0
  18. package/components/VlTutorialStepBuilder.vue +671 -0
  19. package/components/VlValidatedInput.vue +262 -0
  20. package/components/data/countries.js +253 -0
  21. package/components/getAllDefaultComponents.js +12 -0
  22. package/docs/architecture.md +71 -0
  23. package/docs/tutorials.md +247 -0
  24. package/docs/usage.md +128 -0
  25. package/functions/index.js +7 -0
  26. package/functions/inputs.js +64 -0
  27. package/functions/loading.js +20 -0
  28. package/kompo-ckeditor-1.0.17/index.js +5 -0
  29. package/kompo-ckeditor-1.0.17/komponents/CKEditor.vue +36 -0
  30. package/kompo-ckeditor-1.0.17/komponents/CKEditorExtended.vue +66 -0
  31. package/kompo-ckeditor-1.0.17/komponents/EditableCKEditor.vue +42 -0
  32. package/kompo-ckeditor-1.0.17/komponents/TranslatableEditor.vue +28 -0
  33. package/kompo-ckeditor-1.0.17/mixins/CKEditor.js +291 -0
  34. package/kompo-ckeditor-1.0.17/mixins/CKEditorUtilities.js +52 -0
  35. package/kompo-ckeditor-1.0.17/mixins/CkUploadAdapter.js +95 -0
  36. package/kompo-ckeditor-1.0.17/mixins/translations/en.js +1 -0
  37. package/kompo-ckeditor-1.0.17/mixins/translations/fr.js +1 -0
  38. package/kompo-ckeditor-1.0.17/plugins/JsonBlockCommand.js +100 -0
  39. package/kompo-ckeditor-1.0.17/plugins/JsonBlockEditing.js +225 -0
  40. package/kompo-ckeditor-1.0.17/plugins/JsonBlockUi.js +21 -0
  41. package/kompo-ckeditor-1.0.17/plugins/MentionPlugin.js +118 -0
  42. package/orchestrator/KompoJsBuilder.js +333 -0
  43. package/package.json +25 -0
  44. package/raw_animations/count-up-animation.js +220 -0
  45. package/raw_animations/magic-poof.js +210 -0
  46. package/tutorials/TutorialConfig.js +34 -0
  47. package/tutorials/TutorialEngine.js +448 -0
  48. package/tutorials/index.js +2 -0
  49. package/tutorials/modules/AutoNext.js +86 -0
  50. package/tutorials/modules/Avatar.js +94 -0
  51. package/tutorials/modules/Bubble.js +617 -0
  52. package/tutorials/modules/Cursor.js +315 -0
  53. package/tutorials/modules/Highlight.js +282 -0
  54. package/tutorials/modules/HoverForcer.js +250 -0
  55. package/tutorials/modules/Mobile.js +148 -0
  56. package/tutorials/modules/Options.js +98 -0
  57. package/tutorials/modules/Overlay.js +142 -0
  58. package/tutorials/modules/Scroll.js +37 -0
  59. package/tutorials/modules/Typewriter.js +132 -0
  60. package/tutorials/step-builder/step-builder-bridge.js +436 -0
  61. package/tutorials/step-builder/utils/bezier-editor.js +379 -0
  62. package/tutorials/step-builder/utils/code-generator.js +127 -0
  63. package/tutorials/step-builder/utils/element-picker.js +125 -0
  64. package/tutorials/tutorial.scss +816 -0
  65. package/tutorials/utils/selectors.js +225 -0
  66. package/tutorials/utils/stability.js +76 -0
  67. package/tutorials/utils/svg.js +46 -0
@@ -0,0 +1,327 @@
1
+ <template>
2
+ <vl-form-field v-bind="$_wrapperAttributes">
3
+ <div class="vlInputGroup vlDateMonthDay">
4
+ <div class="vlInputPrepend" v-html="$_icon" />
5
+
6
+ <div class="vlDateMonthDay-selects">
7
+ <!-- First selector -->
8
+ <div class="vlDateMonthDay-select-wrapper">
9
+ <select
10
+ v-model="firstValue"
11
+ @change="updateValue"
12
+ class="vlDateMonthDay-select"
13
+ :disabled="$_readOnly"
14
+ >
15
+ <option value="" disabled>{{ firstPlaceholder }}</option>
16
+ <option v-for="opt in firstOptions" :key="opt.value" :value="opt.value">
17
+ {{ opt.label }}
18
+ </option>
19
+ </select>
20
+ <svg class="vlDateMonthDay-chevron" viewBox="0 0 20 20" fill="currentColor">
21
+ <path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd" />
22
+ </svg>
23
+ </div>
24
+
25
+ <span class="vlDateMonthDay-separator">{{ $_separator }}</span>
26
+
27
+ <!-- Second selector -->
28
+ <div class="vlDateMonthDay-select-wrapper">
29
+ <select
30
+ v-model="secondValue"
31
+ @change="updateValue"
32
+ class="vlDateMonthDay-select"
33
+ :disabled="$_readOnly"
34
+ >
35
+ <option value="" disabled>{{ secondPlaceholder }}</option>
36
+ <option v-for="opt in secondOptions" :key="opt.value" :value="opt.value">
37
+ {{ opt.label }}
38
+ </option>
39
+ </select>
40
+ <svg class="vlDateMonthDay-chevron" viewBox="0 0 20 20" fill="currentColor">
41
+ <path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd" />
42
+ </svg>
43
+ </div>
44
+ </div>
45
+
46
+ <div class="vlInputAppend" v-if="!$_readOnly && hasValue">
47
+ <i class="icon-times cursor-pointer hover:text-red-500 transition-colors" @click.stop="clear" />
48
+ </div>
49
+ </div>
50
+ </vl-form-field>
51
+ </template>
52
+
53
+ <script>
54
+ import Field from 'vue-kompo/js/form/mixins/Field'
55
+
56
+ export default {
57
+ mixins: [Field],
58
+ data() {
59
+ return {
60
+ firstValue: '',
61
+ secondValue: ''
62
+ }
63
+ },
64
+ mounted() {
65
+ // Ensure component.value is empty string if nothing is selected initially
66
+ if (!this.component.value || this.component.value === 'null') {
67
+ this.component.value = '';
68
+ }
69
+ },
70
+ computed: {
71
+ $_mode() { return this.$_config('mode') || 'day-month' },
72
+ $_separator() { return this.$_config('separator') || '-' },
73
+ $_locale() { return this.$_config('kompo_locale') || 'en' },
74
+ $_yearStart() { return this.$_config('yearStart') || new Date().getFullYear() - 10 },
75
+ $_yearEnd() { return this.$_config('yearEnd') || new Date().getFullYear() + 10 },
76
+
77
+ hasValue() {
78
+ return this.firstValue && this.secondValue;
79
+ },
80
+
81
+ // Determine what the first and second selectors represent
82
+ firstType() {
83
+ const modes = {
84
+ 'day-month': 'day',
85
+ 'month-day': 'month',
86
+ 'month-year': 'month',
87
+ 'year-month': 'year'
88
+ };
89
+ return modes[this.$_mode] || 'day';
90
+ },
91
+ secondType() {
92
+ const modes = {
93
+ 'day-month': 'month',
94
+ 'month-day': 'day',
95
+ 'month-year': 'year',
96
+ 'year-month': 'month'
97
+ };
98
+ return modes[this.$_mode] || 'month';
99
+ },
100
+
101
+ // Placeholders
102
+ firstPlaceholder() {
103
+ return this.getPlaceholder(this.firstType);
104
+ },
105
+ secondPlaceholder() {
106
+ return this.getPlaceholder(this.secondType);
107
+ },
108
+
109
+ // Options for first selector
110
+ firstOptions() {
111
+ return this.getOptions(this.firstType);
112
+ },
113
+ // Options for second selector
114
+ secondOptions() {
115
+ return this.getOptions(this.secondType);
116
+ },
117
+
118
+ // Days depend on selected month (if month is selected)
119
+ daysInMonth() {
120
+ let month = null;
121
+ if (this.firstType === 'month') month = this.firstValue;
122
+ if (this.secondType === 'month') month = this.secondValue;
123
+
124
+ if (month) {
125
+ return new Date(2024, month, 0).getDate(); // Use leap year for Feb
126
+ }
127
+ return 31;
128
+ },
129
+
130
+ months() {
131
+ const formatter = new Intl.DateTimeFormat(this.$_locale, { month: 'long' });
132
+ return Array.from({ length: 12 }, (_, i) => {
133
+ const date = new Date(2024, i, 1);
134
+ return {
135
+ value: i + 1,
136
+ label: formatter.format(date)
137
+ };
138
+ });
139
+ },
140
+
141
+ years() {
142
+ const years = [];
143
+ for (let y = this.$_yearStart; y <= this.$_yearEnd; y++) {
144
+ years.push({ value: y, label: String(y) });
145
+ }
146
+ return years;
147
+ },
148
+
149
+ days() {
150
+ return Array.from({ length: this.daysInMonth }, (_, i) => ({
151
+ value: i + 1,
152
+ label: this.padZero(i + 1)
153
+ }));
154
+ }
155
+ },
156
+ watch: {
157
+ 'component.value': {
158
+ immediate: true,
159
+ handler(value) {
160
+ this.parseValue(value);
161
+ }
162
+ },
163
+ // Adjust day if month changes and day exceeds days in month
164
+ secondValue(newVal) {
165
+ if (this.firstType === 'day' && this.secondType === 'month' && this.firstValue) {
166
+ const maxDays = new Date(2024, newVal, 0).getDate();
167
+ if (this.firstValue > maxDays) {
168
+ this.firstValue = maxDays;
169
+ }
170
+ }
171
+ },
172
+ firstValue(newVal) {
173
+ if (this.firstType === 'month' && this.secondType === 'day' && this.secondValue) {
174
+ const maxDays = new Date(2024, newVal, 0).getDate();
175
+ if (this.secondValue > maxDays) {
176
+ this.secondValue = maxDays;
177
+ }
178
+ }
179
+ }
180
+ },
181
+ methods: {
182
+ padZero(num) {
183
+ return String(num).padStart(2, '0');
184
+ },
185
+
186
+ getPlaceholder(type) {
187
+ const configKey = type + 'Placeholder';
188
+ const configured = this.$_config(configKey);
189
+ if (configured) return configured;
190
+
191
+ const defaults = {
192
+ day: 'DD',
193
+ month: 'MM',
194
+ year: 'YYYY'
195
+ };
196
+ return defaults[type] || '';
197
+ },
198
+
199
+ getOptions(type) {
200
+ switch (type) {
201
+ case 'day': return this.days;
202
+ case 'month': return this.months;
203
+ case 'year': return this.years;
204
+ default: return [];
205
+ }
206
+ },
207
+
208
+ parseValue(value) {
209
+ if (!value || value === '' || value === 'null') {
210
+ this.firstValue = '';
211
+ this.secondValue = '';
212
+ return;
213
+ }
214
+
215
+ const separator = this.$_separator;
216
+ const parts = value.split(separator);
217
+
218
+ if (parts.length === 2) {
219
+ this.firstValue = parseInt(parts[0], 10) || '';
220
+ this.secondValue = parseInt(parts[1], 10) || '';
221
+ }
222
+ },
223
+
224
+ formatValue(val, type) {
225
+ if (type === 'year') {
226
+ return String(val);
227
+ }
228
+ return this.padZero(val);
229
+ },
230
+
231
+ updateValue() {
232
+ if (this.firstValue && this.secondValue) {
233
+ const first = this.formatValue(this.firstValue, this.firstType);
234
+ const second = this.formatValue(this.secondValue, this.secondType);
235
+ this.component.value = `${first}${this.$_separator}${second}`;
236
+ } else if (!this.firstValue && !this.secondValue) {
237
+ this.component.value = '';
238
+ }
239
+ // Don't update if only one is selected (partial state)
240
+
241
+ this.$_changeAction();
242
+ },
243
+
244
+ clear() {
245
+ this.firstValue = '';
246
+ this.secondValue = '';
247
+ this.component.value = '';
248
+ this.$_changeAction();
249
+ }
250
+ }
251
+ }
252
+ </script>
253
+
254
+ <style scoped>
255
+ .vlDateMonthDay {
256
+ display: flex;
257
+ align-items: center;
258
+ }
259
+
260
+ .vlDateMonthDay-selects {
261
+ display: flex;
262
+ align-items: center;
263
+ flex: 1;
264
+ gap: 0.25rem;
265
+ }
266
+
267
+ .vlDateMonthDay-select-wrapper {
268
+ position: relative;
269
+ flex: 1;
270
+ }
271
+
272
+ .vlDateMonthDay-select {
273
+ width: 100%;
274
+ appearance: none;
275
+ -webkit-appearance: none;
276
+ background-color: transparent;
277
+ border: none;
278
+ padding: 0.5rem 1.75rem 0.5rem 0.75rem;
279
+ font-size: 0.875rem;
280
+ cursor: pointer;
281
+ outline: none;
282
+ background-color: #f9fafb;
283
+ border-radius: 0.375rem;
284
+ transition: background-color 0.15s ease;
285
+ }
286
+
287
+ .vlDateMonthDay-select:hover:not(:disabled) {
288
+ background-color: #f3f4f6;
289
+ }
290
+
291
+ .vlDateMonthDay-select:focus {
292
+ background-color: #eff6ff;
293
+ box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.3);
294
+ }
295
+
296
+ .vlDateMonthDay-select:disabled {
297
+ opacity: 0.6;
298
+ cursor: not-allowed;
299
+ }
300
+
301
+ .vlDateMonthDay-chevron {
302
+ position: absolute;
303
+ right: 0.5rem;
304
+ top: 50%;
305
+ transform: translateY(-50%);
306
+ width: 1rem;
307
+ height: 1rem;
308
+ color: #9ca3af;
309
+ pointer-events: none;
310
+ }
311
+
312
+ .vlDateMonthDay-separator {
313
+ color: #6b7280;
314
+ font-weight: 500;
315
+ padding: 0 0.25rem;
316
+ flex-shrink: 0;
317
+ }
318
+
319
+ /* Style the options */
320
+ .vlDateMonthDay-select option {
321
+ padding: 0.5rem;
322
+ }
323
+
324
+ .vlDateMonthDay-select option:first-child {
325
+ color: #9ca3af;
326
+ }
327
+ </style>
@@ -0,0 +1,151 @@
1
+ <template>
2
+ <vl-form-field v-bind="$_wrapperAttributes">
3
+ <div :class="'vlInputGroup rounded-lg ' + (showError ? invalidClass : '')">
4
+ <input
5
+ v-model="visualValue"
6
+ class="vlFormControl"
7
+ v-bind="$_attributes"
8
+ v-on="$_events"
9
+ :placeholder="formatDateStructure"
10
+ @input="onInputDateNumber"
11
+ @focus="onFocus"
12
+ @blur="focused = false"
13
+ ref="input"
14
+ />
15
+ <div class="justify-center flex items-center px-4" v-if="showError">
16
+ <span class="invalid-icon">!</span>
17
+ </div>
18
+ </div>
19
+ </vl-form-field>
20
+ </template>
21
+
22
+ <script>
23
+ import Field from 'vue-kompo/js/form/mixins/Field'
24
+ import HasInputAttributes from 'vue-kompo/js/form/mixins/HasInputAttributes'
25
+
26
+ export default {
27
+ mixins: [Field, HasInputAttributes],
28
+ data() {
29
+ return {
30
+ visualValue: this.component?.value || '',
31
+ focused: false,
32
+ dirty: false
33
+ }
34
+ },
35
+ computed: {
36
+ $_attributes() {
37
+ return {
38
+ ...this.$_defaultFieldAttributes,
39
+ ...this.$_defaultInputAttributes
40
+ }
41
+ },
42
+ focusOnLoad(){ return this.$_config('focusOnLoad') },
43
+ invalidClass() { return this.$_config('invalidClass')},
44
+
45
+ validateJustFuture() { return this.$_config('validateJustFuture') },
46
+
47
+ formatDateStructure() { return this.$_config('dateFormat') },
48
+
49
+ rawDateNumbers() { return this.visualValue.replace(/\D/g, '') },
50
+
51
+ quantityOfNumbersDate() { return this.formatDateStructure.replace(/[^a-zA-Z]/g, '').length },
52
+
53
+ formatedDate() {
54
+ return this.formatDate(this.rawDateNumbers);
55
+ },
56
+
57
+ rawDate() {
58
+ const rawDateNumbers = this.rawDateNumbers;
59
+ const formatParts = this.formatDateStructure.split(/[^a-zA-Z]+/);
60
+ const dateParts = [];
61
+ let index = 0;
62
+
63
+ formatParts.forEach(part => {
64
+ dateParts.push(rawDateNumbers.slice(index, index + part.length));
65
+ index += part.length;
66
+ });
67
+
68
+ if (!dateParts.length) return null;
69
+
70
+ const [day, month, year] = formatParts.length === 3 ? dateParts : [null, ...dateParts];
71
+
72
+ if (formatParts.length === 3) {
73
+ return new Date(`${month}-${day}-${year}`);
74
+ } else {
75
+ return new Date(`${month}-01-${year}`);
76
+ }
77
+ },
78
+
79
+ showError() {
80
+ return !this.isValidDate && !this.focused && this.dirty;
81
+ },
82
+
83
+ isValidDate() {
84
+ const date = this.rawDate;
85
+
86
+ if (!date || date == 'Invalid Date') return false;
87
+
88
+ if (this.validateJustFuture) {
89
+ if (date < new Date()) return false;
90
+ }
91
+
92
+ return true;
93
+ }
94
+ },
95
+ methods: {
96
+ focus(){
97
+ this.$refs.input.focus()
98
+ },
99
+
100
+ onInputDateNumber() {
101
+ this.visualValue = this.formatedDate;
102
+ this.component.value = this.isValidDate ? this.rawDate.toLocaleDateString() : null;
103
+ },
104
+
105
+ onFocus() {
106
+ this.focused = true;
107
+ this.dirty = true;
108
+ },
109
+ dateToRawNumbers(date) {
110
+ if (!date) return '';
111
+
112
+ return (new Date(date)).toLocaleDateString().replace(/\D/g, '');
113
+ },
114
+ formatDate(rawDateNumbers) {
115
+ let formatted = '';
116
+ let index = 0;
117
+
118
+ for (let char of this.formatDateStructure) {
119
+ if (!rawDateNumbers[index]) break;
120
+
121
+ if (/[^a-zA-Z]/.test(char)) {
122
+ formatted += char;
123
+ } else {
124
+ formatted += rawDateNumbers[index] || '';
125
+ index++;
126
+ }
127
+ }
128
+
129
+ return formatted;
130
+ },
131
+ },
132
+ mounted(){
133
+ if(this.component.value) {
134
+ this.visualValue = this.component.value
135
+ this.onInputDateNumber()
136
+ }
137
+
138
+ if(this.focusOnLoad)
139
+ this.focus()
140
+ },
141
+ }
142
+ </script>
143
+
144
+ <style scoped>
145
+ .invalid-icon {
146
+ color: red;
147
+ font-weight: bold;
148
+ margin-left: 8px;
149
+ cursor: pointer;
150
+ }
151
+ </style>