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
package/package.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "js-kompo-utils",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "main": "app.js",
6
+ "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1"
8
+ },
9
+ "keywords": [],
10
+ "author": "xkairo",
11
+ "license": "ISC",
12
+ "dependencies": {
13
+ "@ckeditor/ckeditor5-vue2": "^3.0.1",
14
+ "@floating-ui/dom": "^1.7.6",
15
+ "apexcharts": "^5.10.4",
16
+ "ckeditor5": "^44.3.0",
17
+ "gsap": "^3.14.2",
18
+ "highlight.js": "^11.11.1",
19
+ "jquery": "^3.6.0",
20
+ "kompo-googlemaps": "^1.0.14",
21
+ "libphonenumber-js": "^1.12.40",
22
+ "typed.js": "^3.0.0",
23
+ "vue-qrcode-reader": "^3.1.0"
24
+ }
25
+ }
@@ -0,0 +1,220 @@
1
+ // Inject hiding style IMMEDIATELY (before DOMContentLoaded) so values are never visible
2
+ (function() {
3
+ var style = document.createElement('style');
4
+ style.id = 'count-up-hide';
5
+ style.textContent = `
6
+ .box-label-val:not([data-count-up-done]) {
7
+ -webkit-text-fill-color: transparent !important;
8
+ position: relative !important;
9
+ }
10
+ .box-label-val:not([data-count-up-done])::before {
11
+ content: '0';
12
+ -webkit-text-fill-color: initial !important;
13
+ position: absolute !important;
14
+ right: 0 !important;
15
+ }
16
+ `;
17
+ // Insert into head ASAP
18
+ if (document.head) {
19
+ document.head.appendChild(style);
20
+ } else {
21
+ document.addEventListener('DOMContentLoaded', function() {
22
+ document.head.appendChild(style);
23
+ });
24
+ }
25
+ })();
26
+
27
+ var SELECTORS = '.box-label-val';
28
+
29
+ function parseNumericValue(text) {
30
+ var cleaned = text.trim();
31
+ if (!cleaned || cleaned === '-' || cleaned === 'N/A') return null;
32
+
33
+ var match = cleaned.match(/-?[\d][\d\s,.]*/);
34
+ if (!match) return null;
35
+
36
+ var numStr = match[0].trim();
37
+ var idx = cleaned.indexOf(numStr);
38
+ var prefix = cleaned.substring(0, idx);
39
+ var suffix = cleaned.substring(idx + numStr.length);
40
+
41
+ var lastComma = numStr.lastIndexOf(',');
42
+ var lastDot = numStr.lastIndexOf('.');
43
+
44
+ var decimals = 0;
45
+ var value;
46
+ var frFormat = false;
47
+
48
+ if (lastComma > lastDot) {
49
+ frFormat = true;
50
+ var afterComma = numStr.substring(lastComma + 1);
51
+ if (afterComma.length <= 2) {
52
+ decimals = afterComma.length;
53
+ value = parseFloat(numStr.replace(/\s/g, '').replace(',', '.'));
54
+ } else {
55
+ value = parseFloat(numStr.replace(/[,\s]/g, ''));
56
+ }
57
+ } else if (lastDot > lastComma) {
58
+ var afterDot = numStr.substring(lastDot + 1);
59
+ if (afterDot.length <= 2) {
60
+ decimals = afterDot.length;
61
+ value = parseFloat(numStr.replace(/[,\s]/g, ''));
62
+ } else {
63
+ value = parseFloat(numStr.replace(/[.\s]/g, ''));
64
+ }
65
+ } else {
66
+ value = parseInt(numStr.replace(/[,.\s]/g, ''), 10);
67
+ }
68
+
69
+ if (isNaN(value) || value === 0) return null;
70
+
71
+ return {
72
+ value: value,
73
+ decimals: decimals,
74
+ prefix: prefix,
75
+ suffix: suffix,
76
+ frFormat: frFormat,
77
+ original: cleaned
78
+ };
79
+ }
80
+
81
+ function formatValue(val, info) {
82
+ var abs = Math.abs(val);
83
+ var fixed = abs.toFixed(info.decimals);
84
+ var parts = fixed.split('.');
85
+
86
+ parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, info.frFormat ? ' ' : ',');
87
+
88
+ var formatted;
89
+ if (info.decimals > 0) {
90
+ formatted = parts.join(info.frFormat ? ',' : '.');
91
+ } else {
92
+ formatted = parts[0];
93
+ }
94
+
95
+ return info.prefix + (val < 0 ? '-' : '') + formatted + info.suffix;
96
+ }
97
+
98
+ function animateElement(el) {
99
+ if (el.dataset.countUpDone) return;
100
+
101
+ // If data-amount is set, use that as the target value
102
+ var targetText = el.dataset.amount || el.textContent;
103
+ var info = parseNumericValue(targetText);
104
+
105
+ if (!info && targetText.trim() !== '0' && targetText.trim() !== '-') {
106
+ // No numeric value - just reveal it
107
+ el.dataset.countUpReady = '1';
108
+ return;
109
+ }
110
+
111
+ el.dataset.countUpDone = '1';
112
+
113
+ var duration = Math.random() * 1500 + 800;
114
+ var startTime = null;
115
+
116
+ function step(timestamp) {
117
+ if (!startTime) startTime = timestamp;
118
+ var progress = Math.min((timestamp - startTime) / duration, 1);
119
+ var eased = 1 - Math.pow(1 - progress, 3);
120
+
121
+ var current = info.value * eased;
122
+ el.textContent = formatValue(current, info);
123
+
124
+ if (progress < 1) {
125
+ requestAnimationFrame(step);
126
+ } else {
127
+ el.textContent = info.original;
128
+ }
129
+ }
130
+
131
+ requestAnimationFrame(step);
132
+ }
133
+
134
+ /* Pie chart animation (conic-gradient fill + percentage count-up) */
135
+ function animatePieChart(pie) {
136
+ if (pie.dataset.pieAnimDone) return;
137
+
138
+ var style = pie.getAttribute('style') || '';
139
+ var gradientMatch = style.match(/conic-gradient\(\s*(\S+)\s+([\d.]+)deg/);
140
+ if (!gradientMatch) return;
141
+
142
+ var color = gradientMatch[1];
143
+ var targetDegrees = parseFloat(gradientMatch[2]);
144
+
145
+ var innerDiv = pie.querySelector('.flex-center');
146
+ if (!innerDiv) return;
147
+
148
+ var text = innerDiv.textContent.trim();
149
+ var numMatch = text.match(/(-?\d+)/);
150
+ if (!numMatch) return;
151
+
152
+ var targetPct = parseInt(numMatch[0]);
153
+ var suffix = text.substring(text.indexOf(numMatch[0]) + numMatch[0].length);
154
+
155
+ pie.dataset.pieAnimDone = '1';
156
+
157
+ var duration = 1200;
158
+ var startTime = null;
159
+
160
+ function step(timestamp) {
161
+ if (!startTime) startTime = timestamp;
162
+ var progress = Math.min((timestamp - startTime) / duration, 1);
163
+ var eased = 1 - Math.pow(1 - progress, 3);
164
+
165
+ var currentDeg = targetDegrees * eased;
166
+ var currentPct = Math.round(targetPct * eased);
167
+ var grayStart = currentDeg > 0 ? currentDeg + 2 : 0;
168
+
169
+ pie.style.backgroundImage = 'conic-gradient(' + color + ' ' + currentDeg + 'deg, #f0f0f0 ' + grayStart + 'deg ' + (360 - currentDeg) + 'deg)';
170
+ innerDiv.textContent = currentPct + suffix;
171
+
172
+ if (progress < 1) {
173
+ requestAnimationFrame(step);
174
+ } else {
175
+ pie.style.backgroundImage = 'conic-gradient(' + color + ' ' + targetDegrees + 'deg, #f0f0f0 ' + (targetDegrees > 0 ? targetDegrees + 2 : 0) + 'deg ' + (360 - targetDegrees) + 'deg)';
176
+ innerDiv.textContent = targetPct + suffix;
177
+ }
178
+ }
179
+
180
+ requestAnimationFrame(step);
181
+ }
182
+
183
+ function processElements() {
184
+ document.querySelectorAll(SELECTORS).forEach(animateElement);
185
+ document.querySelectorAll('[style*="conic-gradient"]').forEach(animatePieChart);
186
+ }
187
+
188
+ const interval = setInterval(function () {
189
+ const newElements = document.querySelectorAll(SELECTORS + ':not([data-count-up-done]), [style*="conic-gradient"]:not([data-pie-anim-done])');
190
+
191
+ if (newElements.length) {
192
+ processElements();
193
+ }
194
+ }, 30);
195
+ setTimeout(() => clearInterval(interval), 3000);
196
+
197
+ var observer = new MutationObserver(function(mutations) {
198
+ var found = false;
199
+ mutations.forEach(function(mutation) {
200
+ mutation.addedNodes.forEach(function(node) {
201
+ if (node.nodeType === 1) {
202
+ if (node.matches && node.matches(SELECTORS)) {
203
+ found = true;
204
+ } else if (node.querySelectorAll) {
205
+ if (node.querySelectorAll(SELECTORS).length || node.querySelectorAll('[style*="conic-gradient"]').length) {
206
+ found = true;
207
+ }
208
+ }
209
+ if (node.getAttribute && (node.getAttribute('style') || '').indexOf('conic-gradient') !== -1) {
210
+ found = true;
211
+ }
212
+ }
213
+ });
214
+ });
215
+ if (found) {
216
+ setTimeout(processElements, 50);
217
+ }
218
+ });
219
+
220
+ observer.observe(document.body, { childList: true, subtree: true });
@@ -0,0 +1,210 @@
1
+ /**
2
+ * Magic Poof Animation (Created by claude)
3
+ *
4
+ * Usage:
5
+ * MagicPoof.appear(element, options) - Make element appear with magic effect
6
+ * MagicPoof.disappear(element, options) - Make element disappear with magic effect
7
+ * MagicPoof.toggle(element, options) - Toggle visibility with magic effect
8
+ *
9
+ * Options:
10
+ * color: 'gold' | 'purple' | 'blue' | 'pink' | custom hex (default: 'purple')
11
+ * sparkles: number of sparkles (default: 12)
12
+ * smoke: boolean to show smoke puff (default: true)
13
+ * onComplete: callback when animation finishes
14
+ */
15
+
16
+ const MagicPoof = (function() {
17
+
18
+ const sparkleColors = {
19
+ gold: ['#FFD700', '#FFA500', '#FFEC8B', '#FFE4B5'],
20
+ purple: ['#9B59B6', '#8E44AD', '#D4A5FF', '#E8DAEF'],
21
+ blue: ['#3498DB', '#2980B9', '#85C1E9', '#AED6F1'],
22
+ pink: ['#FF69B4', '#FF1493', '#FFB6C1', '#FFC0CB'],
23
+ };
24
+
25
+ const defaultOptions = {
26
+ color: 'purple',
27
+ sparkles: 12,
28
+ smoke: true,
29
+ onComplete: null
30
+ };
31
+
32
+ function getColors(color) {
33
+ if (sparkleColors[color]) {
34
+ return sparkleColors[color];
35
+ }
36
+ // If custom hex color, generate variations
37
+ return [color, color, color, color];
38
+ }
39
+
40
+ function createSparkle(x, y, colors) {
41
+ const sparkle = document.createElement('div');
42
+ sparkle.className = 'magic-sparkle';
43
+
44
+ // Random direction and distance
45
+ const angle = Math.random() * Math.PI * 2;
46
+ const distance = 30 + Math.random() * 50;
47
+ const tx = Math.cos(angle) * distance;
48
+ const ty = Math.sin(angle) * distance;
49
+
50
+ sparkle.style.cssText = `
51
+ left: ${x}px;
52
+ top: ${y}px;
53
+ --tx: ${tx}px;
54
+ --ty: ${ty}px;
55
+ color: ${colors[Math.floor(Math.random() * colors.length)]};
56
+ `;
57
+
58
+ return sparkle;
59
+ }
60
+
61
+ function createSmoke(x, y, size, color) {
62
+ const smoke = document.createElement('div');
63
+ smoke.className = 'magic-smoke';
64
+
65
+ const smokeColor = sparkleColors[color]
66
+ ? `rgba(${hexToRgb(sparkleColors[color][0])}, 0.4)`
67
+ : `rgba(155, 89, 182, 0.4)`;
68
+
69
+ smoke.style.cssText = `
70
+ left: ${x - size/2}px;
71
+ top: ${y - size/2}px;
72
+ width: ${size}px;
73
+ height: ${size}px;
74
+ background: radial-gradient(circle, rgba(255,255,255,0.9) 0%, ${smokeColor} 40%, transparent 70%);
75
+ `;
76
+
77
+ return smoke;
78
+ }
79
+
80
+ function hexToRgb(hex) {
81
+ const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
82
+ return result
83
+ ? `${parseInt(result[1], 16)}, ${parseInt(result[2], 16)}, ${parseInt(result[3], 16)}`
84
+ : '155, 89, 182';
85
+ }
86
+
87
+ function getElementCenter(element) {
88
+ const rect = element.getBoundingClientRect();
89
+ return {
90
+ x: rect.left + rect.width / 2 + window.scrollX,
91
+ y: rect.top + rect.height / 2 + window.scrollY,
92
+ width: rect.width,
93
+ height: rect.height
94
+ };
95
+ }
96
+
97
+ function createEffectsContainer() {
98
+ let container = document.getElementById('magic-poof-effects');
99
+ if (!container) {
100
+ container = document.createElement('div');
101
+ container.id = 'magic-poof-effects';
102
+ container.style.cssText = 'position: absolute; top: 0; left: 0; pointer-events: none; z-index: 9999; overflow: visible;';
103
+ document.body.appendChild(container);
104
+ }
105
+ return container;
106
+ }
107
+
108
+ function playEffect(element, options) {
109
+ const container = createEffectsContainer();
110
+ const center = getElementCenter(element);
111
+ const colors = getColors(options.color);
112
+
113
+ // Create smoke puff
114
+ if (options.smoke) {
115
+ const smokeSize = Math.max(center.width, center.height) * 1.5;
116
+ const smoke = createSmoke(center.x, center.y, smokeSize, options.color);
117
+ container.appendChild(smoke);
118
+ setTimeout(() => smoke.remove(), 600);
119
+ }
120
+
121
+ // Create sparkles
122
+ for (let i = 0; i < options.sparkles; i++) {
123
+ setTimeout(() => {
124
+ const offsetX = (Math.random() - 0.5) * center.width * 0.8;
125
+ const offsetY = (Math.random() - 0.5) * center.height * 0.8;
126
+ const sparkle = createSparkle(center.x + offsetX, center.y + offsetY, colors);
127
+ container.appendChild(sparkle);
128
+ setTimeout(() => sparkle.remove(), 700);
129
+ }, Math.random() * 100);
130
+ }
131
+ }
132
+
133
+ function appear(element, userOptions = {}) {
134
+ const options = { ...defaultOptions, ...userOptions };
135
+
136
+ // Ensure element is in DOM but hidden initially
137
+ element.style.opacity = '0';
138
+ element.style.maxHeight = '';
139
+ element.style.visibility = 'visible';
140
+ element.style.display = '';
141
+
142
+ // Play effects
143
+ playEffect(element, options);
144
+
145
+ // Trigger appear animation
146
+ element.classList.remove('magic-poof-out');
147
+ element.classList.add('magic-poof');
148
+
149
+ // Cleanup and callback
150
+ setTimeout(() => {
151
+ element.classList.remove('magic-poof');
152
+ element.style.opacity = '';
153
+ if (options.onComplete) options.onComplete(element);
154
+ }, 500);
155
+ }
156
+
157
+ function disappear(element, userOptions = {}) {
158
+ const options = { ...defaultOptions, ...userOptions };
159
+
160
+ // Play effects
161
+ playEffect(element, options);
162
+
163
+ // Trigger disappear animation
164
+ element.classList.remove('magic-poof');
165
+ element.classList.add('magic-poof-out');
166
+
167
+ // Hide and cleanup
168
+ setTimeout(() => {
169
+ element.style.maxHeight = '0';
170
+ element.style.visibility = 'hidden';
171
+ element.classList.remove('magic-poof-out');
172
+ if (options.onComplete) options.onComplete(element);
173
+ }, 400);
174
+ }
175
+
176
+ function toggle(element, userOptions = {}) {
177
+ const isHidden = element.style.display === 'none' ||
178
+ window.getComputedStyle(element).display === 'none';
179
+
180
+ if (isHidden) {
181
+ appear(element, userOptions);
182
+ } else {
183
+ disappear(element, userOptions);
184
+ }
185
+ }
186
+
187
+ // Auto-init: Listen for elements with data-magic-poof attribute
188
+ document.addEventListener('DOMContentLoaded', function() {
189
+ document.addEventListener('click', function(e) {
190
+ const trigger = e.target.closest('[data-magic-poof-trigger]');
191
+ if (trigger) {
192
+ const targetSelector = trigger.dataset.magicPoofTrigger;
193
+ const target = document.querySelector(targetSelector);
194
+ if (target) {
195
+ const color = trigger.dataset.magicPoofColor || 'purple';
196
+ toggle(target, { color });
197
+ }
198
+ }
199
+ });
200
+ });
201
+
202
+ return {
203
+ appear,
204
+ disappear,
205
+ toggle
206
+ };
207
+
208
+ })();
209
+
210
+ window.MagicPoof = MagicPoof;
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Tutorial configuration with fluent builder API.
3
+ */
4
+ export class TutorialConfig {
5
+ static DEFAULTS = {
6
+ avatar: '/images/tutorial-avatar.png',
7
+ cursorImage: null,
8
+ cursorSize: 'clamp(32px, 8vw, 48px)',
9
+ avatarHeight: 'clamp(200px, 50vh, 475px)',
10
+ avatarMaxHeight: '50vh',
11
+ typewriteSpeed: 25,
12
+ nextLabel: 'tutorial.next',
13
+ doneLabel: 'tutorial.done',
14
+ bubbleFontSize: 'clamp(14px, 3.5vw, 16px)',
15
+ bubbleLineHeight: '1.6',
16
+ bubbleMaxWidth: 'clamp(260px, 85vw, 550px)',
17
+ bubbleMinWidth: 'clamp(200px, 70vw, 350px)',
18
+ devMode: false,
19
+ };
20
+
21
+ constructor(userOptions = {}) {
22
+ const windowDefaults = window.TutorialDefaults || {};
23
+ this.options = { ...TutorialConfig.DEFAULTS, ...windowDefaults, ...userOptions };
24
+ }
25
+
26
+ set(key, value) {
27
+ this.options[key] = value;
28
+ return this;
29
+ }
30
+
31
+ get(key) {
32
+ return this.options[key];
33
+ }
34
+ }