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,247 @@
1
+ # Tutorial System
2
+
3
+ ## Overview
4
+
5
+ The tutorial system provides guided walkthroughs for users. Tutorials are defined as JSON files, processed server-side by PHP (translations, conditions, user variables), and rendered client-side by the TutorialEngine.
6
+
7
+ ## Architecture
8
+
9
+ ```
10
+ resources/tutorials/dashboard-view.json ← You author this (pure data)
11
+ ↓
12
+ PHP: TutorialProcessor ← Translates, filters, replaces variables
13
+ ↓
14
+ GET /api/tutorials/dashboard-view ← Serves processed JSON
15
+ ↓
16
+ JS: TutorialEngine ← Renders overlay, bubble, cursor, highlights
17
+ ```
18
+
19
+ ### Key components
20
+
21
+ | Component | Role |
22
+ |-----------|------|
23
+ | **TutorialEngine** (JS) | Orchestrates modules: Overlay, Bubble, Cursor, Highlight, etc. |
24
+ | **TutorialProcessor** (PHP) | Loads JSON, translates strings, evaluates conditions, replaces `{{variables}}` |
25
+ | **TutorialConditionEvaluator** (PHP) | Safe expression parser for `showIf` conditions |
26
+ | **HasTutorial** (PHP plugin) | Auto-detects tutorials for Kompo components, triggers on first visit |
27
+ | **TutorialStepBuilder** (PHP + JS) | Dev-only visual editor for editing steps live |
28
+
29
+ ## Creating a Tutorial
30
+
31
+ ### 1. Create the JSON file
32
+
33
+ Place it in `resources/tutorials/{component-slug}.json`. The slug matches the Kompo component name (e.g., `DashboardView` → `dashboard-view`).
34
+
35
+ ```json
36
+ {
37
+ "steps": [
38
+ {
39
+ "html": "tutorial.welcome"
40
+ },
41
+ {
42
+ "html": "tutorial.click-here",
43
+ "highlight": { "groups": [{ "elements": ["#my-button"] }] },
44
+ "position": "right"
45
+ },
46
+ {
47
+ "html": "tutorial.fill-form",
48
+ "highlight": { "groups": [{ "elements": [".form-field", ".submit-btn"] }] },
49
+ "cursor": {
50
+ "from": ".form-field",
51
+ "to": ".submit-btn",
52
+ "click": true,
53
+ "duration": 1.5
54
+ }
55
+ }
56
+ ]
57
+ }
58
+ ```
59
+
60
+ ### 2. Add translations
61
+
62
+ In your translation files (`resources/lang/en/tutorial.php`):
63
+
64
+ ```php
65
+ return [
66
+ 'welcome' => 'Welcome, {{user_first_name}}! Let me show you around.',
67
+ 'click-here' => 'Click this button to get started.',
68
+ 'fill-form' => 'Fill in the form and hit submit.',
69
+ ];
70
+ ```
71
+
72
+ The PHP processor translates keys and replaces `{{user_first_name}}`, `{{user_last_name}}`, `{{user_name}}` automatically.
73
+
74
+ ### 3. That's it
75
+
76
+ The `HasTutorial` plugin auto-detects the JSON file based on the component slug and starts the tutorial on first visit. A replay button in the navbar lets users re-watch it anytime.
77
+
78
+ ## Step Configuration
79
+
80
+ Each step supports these properties:
81
+
82
+ ```json
83
+ {
84
+ "html": "translation.key",
85
+
86
+ "position": "left | right | top | bottom",
87
+ "align": "left | center | right",
88
+ "overlay": true,
89
+
90
+ "highlight": {
91
+ "groups": [{ "elements": [".selector1", ".selector2"] }],
92
+ "padding": 8,
93
+ "borderRadius": 8
94
+ },
95
+
96
+ "cursor": {
97
+ "from": ".start-element",
98
+ "to": ".end-element",
99
+ "click": true,
100
+ "duration": 1.5,
101
+ "loop": true
102
+ },
103
+
104
+ "hover": ".element-to-force-hover",
105
+
106
+ "scrollTo": ".element-to-scroll-into-view",
107
+ "scrollInside": { "selector": ".container", "by": 200, "duration": 1 },
108
+
109
+ "options": [
110
+ { "label": "tutorial.option-a", "goToStep": 4 },
111
+ { "label": "tutorial.option-b", "done": true },
112
+ { "label": "tutorial.option-c", "redirect": "/other-page" }
113
+ ],
114
+
115
+ "autoNext": 3,
116
+ "advance": "click | afterAnimation",
117
+ "silentClick": ".element-to-auto-click",
118
+ "showBack": true,
119
+ "chatMode": true,
120
+
121
+ "showIf": "permission:ManageTeam && !setting:hide_tutorial",
122
+
123
+ "redirect": "/next-page"
124
+ }
125
+ ```
126
+
127
+ ## Triggering Tutorials
128
+
129
+ ### Automatic (first visit)
130
+
131
+ The `HasTutorial` plugin handles this. If `resources/tutorials/{component-slug}.json` exists, the tutorial starts on first visit and is marked as viewed.
132
+
133
+ ### Button click (replay)
134
+
135
+ ```php
136
+ // Uses 'default' — auto-resolves to current page's tutorial
137
+ _Button('Help')->initTutorial();
138
+
139
+ // Or specify a tutorial explicitly
140
+ _Button('Start Tour')->initTutorial('campaign-settings');
141
+
142
+ // Start at a specific step
143
+ _Button('Show Step 3')->initTutorial('campaign-settings', stepNumber: 2);
144
+ ```
145
+
146
+ ### On page load (cross-page redirect)
147
+
148
+ Use `_Tutorial()` in a component's `render()` method:
149
+
150
+ ```php
151
+ function render()
152
+ {
153
+ return _Rows(
154
+ _Tutorial('onboarding-step-2'),
155
+ // ... rest of component
156
+ );
157
+ }
158
+ ```
159
+
160
+ This supports cross-page chaining — when a tutorial redirects to another page with `?tutorial=name&fromStep=N`, the `_Tutorial()` helper picks it up and starts automatically.
161
+
162
+ ## Conditional Steps
163
+
164
+ Use `showIf` to conditionally show steps based on user permissions, settings, or DOM elements:
165
+
166
+ ```json
167
+ { "showIf": "permission:ManageTeam" }
168
+ { "showIf": "permission:EditCampaign && !setting:onboarding_done" }
169
+ { "showIf": "(role:admin || role:manager) && permission:ViewFinances" }
170
+ { "showIf": "selector:.optional-feature-panel" }
171
+ ```
172
+
173
+ **Built-in condition types:**
174
+ - `permission:X` — checks `user->hasPermission(X)`
175
+ - `setting:X` — checks `user->getSettingValue(X)`
176
+ - `role:X` — checks `user->hasRole(X)`
177
+ - `selector:X` — checks if DOM element exists (evaluated client-side)
178
+
179
+ **Custom conditions** — register in a service provider:
180
+
181
+ ```php
182
+ TutorialConditionEvaluator::register('hasActiveSubscription',
183
+ fn() => auth()->user()->subscription?->isActive() ?? false
184
+ );
185
+ ```
186
+
187
+ Then use: `"showIf": "hasActiveSubscription && permission:ManageBilling"`
188
+
189
+ ## Cross-Page Tutorials
190
+
191
+ When a step needs to redirect to another page and continue:
192
+
193
+ ```json
194
+ {
195
+ "html": "tutorial.go-to-settings",
196
+ "options": [
197
+ {
198
+ "label": "tutorial.lets-go",
199
+ "redirect": "/campaign/settings",
200
+ "startTutorial": "campaign-settings"
201
+ }
202
+ ]
203
+ }
204
+ ```
205
+
206
+ The target page should have `_Tutorial('campaign-settings')` in its render method to pick up the redirect.
207
+
208
+ ## Dev Mode: Step Builder
209
+
210
+ In debug mode (`APP_DEBUG=true`):
211
+ - A step builder panel is available in the navbar
212
+ - Clicking the replay button also opens the visual editor
213
+ - Edit step properties, pick elements, preview live changes
214
+ - Copy the JSON output to update your tutorial file
215
+
216
+ ## File Structure
217
+
218
+ ```
219
+ js-kompo-utils/tutorials/
220
+ ├── TutorialEngine.js # Main orchestrator
221
+ ├── TutorialConfig.js # Defaults + config
222
+ ├── tutorial.scss # All tutorial styles
223
+ ├── modules/
224
+ │ ├── Avatar.js # Container + avatar image
225
+ │ ├── Overlay.js # Full-screen overlay
226
+ │ ├── Bubble.js # Speech bubble + positioning
227
+ │ ├── Typewriter.js # Character-by-character text
228
+ │ ├── Cursor.js # Animated cursor + click pulse
229
+ │ ├── Highlight.js # SVG cutout overlay
230
+ │ ├── HoverForcer.js # Force :hover styles
231
+ │ ├── Scroll.js # Scroll helpers
232
+ │ ├── Options.js # Choice buttons
233
+ │ ├── AutoNext.js # Timed progress bar
234
+ │ └── Mobile.js # Mobile detection + tab handling
235
+ ├── utils/
236
+ │ ├── selectors.js # CSS selector utilities
237
+ │ ├── svg.js # SVG element helpers
238
+ │ └── stability.js # Element position polling
239
+ └── step-builder/ # Dev-only visual editor
240
+ ├── step-builder-bridge.js
241
+ └── utils/
242
+
243
+ utils/src/Tutorials/
244
+ ├── TutorialProcessor.php # JSON loading + translation + conditions
245
+ ├── TutorialConditionEvaluator.php # Safe expression parser
246
+ └── TutorialStepBuilder.php # Kompo Form for visual editor
247
+ ```
package/docs/usage.md ADDED
@@ -0,0 +1,128 @@
1
+ # js-kompo-utils - Usage Guide
2
+
3
+ ## Quick Start
4
+
5
+ In your Laravel app's `app.js`:
6
+
7
+ ```javascript
8
+ import { defaultConfig, KompoJsInitializer } from 'js-kompo-utils';
9
+
10
+ const config = defaultConfig
11
+ .bootstrap(() => require('./bootstrap'));
12
+
13
+ new KompoJsInitializer(config, window).initialize();
14
+ ```
15
+
16
+ This gives you: jQuery, Vue + vue-kompo, CKEditor, Google Maps, QR code reader, all default components, window utilities, and animations.
17
+
18
+ ## What's included by default
19
+
20
+ | Feature | Default | Toggle off |
21
+ |---------|---------|------------|
22
+ | jQuery | on | `.withoutJquery()` |
23
+ | CKEditor | on | `.withoutCkEditor()` |
24
+ | Google Maps | on | `.withoutKompoMaps()` |
25
+ | Tutorial Engine | on | `.withoutTutorialEngine()` |
26
+ | QR Code Reader | on (Vue plugin) | - |
27
+ | Default components | all `./components/*.vue` | `.excludeComponent('Name')` |
28
+ | Window utils | input + loading functions | - |
29
+ | Animations | count-up, magic-poof | - |
30
+
31
+ ## Adding and removing components
32
+
33
+ ```javascript
34
+ // Add an app-specific component
35
+ config.addComponent('MyComponent', require('./components/MyComponent.vue').default);
36
+
37
+ // Add multiple
38
+ config.addComponents({
39
+ 'CompA': require('./components/CompA.vue').default,
40
+ 'CompB': require('./components/CompB.vue').default,
41
+ });
42
+
43
+ // Remove a default component you don't need
44
+ config.excludeComponent('VlApexChart');
45
+ config.excludeComponents(['VlCKEditorTemplate', 'VlCKEditorWithVars']);
46
+ ```
47
+
48
+ ## Adding Vue plugins
49
+
50
+ ```javascript
51
+ import SomePlugin from 'some-vue-plugin';
52
+
53
+ config.addVuePlugin(SomePlugin);
54
+ ```
55
+
56
+ ## Adding files to import
57
+
58
+ Pass callbacks — webpack resolves the path at build time:
59
+
60
+ ```javascript
61
+ config.addFilesToImport([
62
+ () => require('./my-custom-script.js'),
63
+ () => require('./another-script.js'),
64
+ ]);
65
+ ```
66
+
67
+ ## Window utilities
68
+
69
+ ```javascript
70
+ // Add individual functions to window
71
+ config.addWindowUtilsItem('myHelper', () => { /* ... */ });
72
+
73
+ // Merge an object of functions
74
+ config.mergeWindowUtils({
75
+ helperA: () => { /* ... */ },
76
+ helperB: () => { /* ... */ },
77
+ });
78
+
79
+ // Add a decorator that receives window and does custom setup
80
+ config.addWindowDecorator((window) => {
81
+ // custom window setup
82
+ });
83
+ ```
84
+
85
+ ## Lifecycle hooks
86
+
87
+ Hook into any initialization step with before/after callbacks:
88
+
89
+ ```javascript
90
+ config.addAfterStepCallback('bootstrapExecution', () => {
91
+ // runs after bootstrap, e.g. add axios interceptors
92
+ window.axios.interceptors.request.use(config => {
93
+ config.headers['X-Custom'] = 'value';
94
+ return config;
95
+ });
96
+ });
97
+
98
+ config.addBeforeStepCallback('instanceApp', () => {
99
+ // runs right before Vue mounts
100
+ });
101
+ ```
102
+
103
+ **Available step names:** `bootstrapExecution`, `requireFilesToImport`, `bootJqueryIfRequired`, `bootVue`, `decorateWindow`, `bootCkEditorIfRequired`, `bootMapsIfRequired`, `instanceApp`
104
+
105
+ ## Changing the mount selector
106
+
107
+ Default is `#app` (matches kompo's `vue_app_id` config). Override if needed:
108
+
109
+ ```javascript
110
+ config.setAppSelector('#my-app');
111
+ ```
112
+
113
+ ## Starting from scratch
114
+
115
+ If `defaultConfig` includes too much, build your own:
116
+
117
+ ```javascript
118
+ import { KompoJsConfigBuilder, KompoJsInitializer } from 'js-kompo-utils';
119
+
120
+ const config = new KompoJsConfigBuilder()
121
+ .bootstrap(() => require('./bootstrap'))
122
+ .withJquery()
123
+ .withoutCkEditor()
124
+ .withoutKompoMaps()
125
+ .addComponent('MyOnly', require('./components/MyOnly.vue').default);
126
+
127
+ new KompoJsInitializer(config, window).initialize();
128
+ ```
@@ -0,0 +1,7 @@
1
+ import inputFunctions from './inputs.js';
2
+ import loadingFunctions from './loading.js';
3
+
4
+ export default {
5
+ ...inputFunctions,
6
+ ...loadingFunctions
7
+ };
@@ -0,0 +1,64 @@
1
+ export function getYesNoValue(id)
2
+ {
3
+ const group = $('#' + id);
4
+
5
+ const rawValue = group.find('.selected').find('*[data-value]').data('value');
6
+
7
+ if (rawValue == undefined) {
8
+ return null;
9
+ }
10
+
11
+ const value = rawValue == 'yes' ? 1 : 0;
12
+
13
+ return value;
14
+ }
15
+
16
+ export function getToggle(name)
17
+ {
18
+ return $('input[type=checkbox][name="' + name + '"]');
19
+ }
20
+
21
+ export function getToggleValue(name)
22
+ {
23
+ const toggleCheckbox = getToggle(name);
24
+ const checked = toggleCheckbox.attr('aria-checked') == "true";
25
+
26
+ return checked ? 1 : 0;
27
+ }
28
+
29
+ export function toggleYesNo(name) {
30
+ const groupId = 'temp_' + name;
31
+ const toggleName = name + '_toggle';
32
+
33
+ const groupValue = getYesNoValue(groupId);
34
+ const toggleValue = getToggleValue(toggleName);
35
+
36
+ // This want to fix the first "no" select when the default is null
37
+ if(groupValue == null) {
38
+ $('#' + name + '-off-input').hide();
39
+ $('#' + name + '-on-input').hide();
40
+
41
+ return;
42
+ }
43
+
44
+ if (groupValue != toggleValue) {
45
+ console.log(getToggle(toggleName));
46
+ getToggle(toggleName).each(function(key, toggle) {
47
+ const evt = new Event( 'click', { bubbles: true } );
48
+ toggle.nextElementSibling.dispatchEvent(evt);
49
+ });
50
+ } else if (groupValue == 1) {
51
+ $('#' + name + '-off-input').hide();
52
+ $('#' + name + '-on-input').show();
53
+ } else if(groupValue == 0) {
54
+ $('#' + name + '-off-input').show();
55
+ $('#' + name + '-on-input').hide();
56
+ }
57
+ }
58
+
59
+ export default {
60
+ getYesNoValue,
61
+ getToggle,
62
+ getToggleValue,
63
+ toggleYesNo
64
+ }
@@ -0,0 +1,20 @@
1
+ export function setLoadingScreen()
2
+ {
3
+ const loadingInnerHtml = `
4
+ <div class="loading-screen">
5
+ <i id="vl-spinner" class="icon-spinner" style="display: block;"></i>
6
+ </div>
7
+ `;
8
+
9
+ $('body').append(loadingInnerHtml);
10
+ }
11
+
12
+ export function removeLoadingScreen()
13
+ {
14
+ $('.loading-screen').remove();
15
+ }
16
+
17
+ export default {
18
+ setLoadingScreen,
19
+ removeLoadingScreen
20
+ }
@@ -0,0 +1,5 @@
1
+ const files = require.context('./komponents/', true, /\.vue$/i)
2
+
3
+ files.keys().map(key => {
4
+ Vue.component('Vl'+key.split('/').pop().split('.')[0], files(key).default)
5
+ })
@@ -0,0 +1,36 @@
1
+ <template>
2
+ <vl-form-field v-bind="$_wrapperAttributes" @labelclick="focus">
3
+ <ckeditor
4
+ class="vlFormControl"
5
+ ref="content"
6
+ v-model="component.value"
7
+ v-bind="$_attributes"
8
+ v-on="$_events"
9
+ @keydown.stop
10
+ @ready="onReady"
11
+
12
+ :editor="editor"
13
+ :config="editorConfig" />
14
+ <div
15
+ v-if="mentions.length"
16
+ class="mention-triggers border-t border-gray-200 p-2 flex">
17
+ <div
18
+ v-for="(mention, index) in mentions"
19
+ v-html="getButtonHtml(mention)"
20
+ @click="activateMention(mention)"
21
+ />
22
+ </div>
23
+ <a v-if="customTextInsertion"
24
+ @click="insertCustomText"
25
+ class="cursor-pointer absolute bottom-2 right-2 text-sm"
26
+ v-html="customTextInsertLabel" />
27
+ </vl-form-field>
28
+ </template>
29
+
30
+ <script>
31
+ import CKEditor from '../mixins/CKEditor'
32
+
33
+ export default {
34
+ mixins: [CKEditor]
35
+ }
36
+ </script>
@@ -0,0 +1,66 @@
1
+ <template>
2
+ <vl-form-field v-bind="$_wrapperAttributes" @labelclick="focus">
3
+ <ckeditor
4
+ class="vlFormControl"
5
+ ref="content"
6
+ v-model="component.value"
7
+ v-bind="$_attributes"
8
+ v-on="$_events"
9
+ @keydown.stop
10
+
11
+ :editor="editor"
12
+ :config="editorConfig" />
13
+ <div
14
+ v-if="mentions.length"
15
+ class="mention-triggers border-t border-gray-200 p-2 flex">
16
+ <div
17
+ v-for="(mention, index) in mentions"
18
+ :key="index"
19
+ v-html="getButtonHtml(mention)"
20
+ @click="activateMention(mention)"
21
+ />
22
+ <VlDate
23
+ :vkompo="$_config('date-component')"
24
+ @open="onOpen"
25
+ @change="onChange"
26
+ @close="onClose"
27
+ />
28
+ </div>
29
+ </vl-form-field>
30
+ </template>
31
+
32
+ <script>
33
+ import CKEditor from '../mixins/CKEditor'
34
+ import DoesAxiosRequests from 'vue-kompo/js/form/mixins/DoesAxiosRequests'
35
+ import EmitsEvents from 'vue-kompo/js/element/mixins/EmitsEvents'
36
+ import HasId from 'vue-kompo/js/element/mixins/HasId'
37
+ import HasConfig from 'vue-kompo/js/element/mixins/HasConfig'
38
+ import CKEditorUtilities from '../mixins/CKEditorUtilities'
39
+
40
+ export default {
41
+ mixins: [CKEditor, DoesAxiosRequests, CKEditorUtilities, EmitsEvents, HasId, HasConfig],
42
+ data(){
43
+ return {
44
+
45
+ }
46
+ },
47
+ methods: {
48
+ onOpen(value, event){ //not used anymore
49
+ return
50
+ },
51
+ onChange(value, event){ //not used anymore
52
+ return
53
+ },
54
+ onClose(value, event){
55
+ value = value.substr(0, 16)
56
+ var html = '<span class="mention ckeditor-mention icon-calendar" data-mention="icon-calendar|'+value+'">'+value+'</span>'
57
+ this.insertHtml(html)
58
+ },
59
+ },
60
+ created(){
61
+ return
62
+ }
63
+
64
+ }
65
+ </script>
66
+
@@ -0,0 +1,42 @@
1
+ <template>
2
+ <div class="vlEditableWrapper">
3
+ <div
4
+ class="vlEditableContent cursor-pointer"
5
+ v-if="!editing"
6
+ v-html="$_value || $_label"
7
+ @click.stop="startEditing"/>
8
+
9
+ <VlCKEditor
10
+ v-if="editing"
11
+ :vkompo="component"
12
+ v-click-out="close"
13
+ @change="change"/>
14
+ </div>
15
+ </template>
16
+
17
+ <script>
18
+ import CKEditor from '../mixins/CKEditor'
19
+ export default {
20
+ mixins: [CKEditor],
21
+ data(){
22
+ return {
23
+ editing: false
24
+ }
25
+ },
26
+ computed: {
27
+
28
+ },
29
+ methods: {
30
+ startEditing(){
31
+ this.editing = true
32
+ },
33
+ close(){
34
+ this.editing = !this.editing
35
+ },
36
+ change(value){
37
+ this.component.value = value
38
+ }
39
+ }
40
+ }
41
+ </script>
42
+
@@ -0,0 +1,28 @@
1
+ <template>
2
+ <vl-form-field v-bind="$_wrapperAttributes">
3
+ <vlLocaleTabs
4
+ :locales="locales"
5
+ :activeLocale="activeLocale"
6
+ @changeLocale="changeTab"/>
7
+ <ckeditor
8
+ class="vlFormControl"
9
+ ref="content"
10
+ v-model="currentTranslation"
11
+ v-bind="$_attributes"
12
+ v-on="$_events"
13
+ @keydown.stop
14
+
15
+ :editor="editor"
16
+ :config="editorConfig" />
17
+ </vl-form-field>
18
+ </template>
19
+
20
+ <script>
21
+ import CKEditor from '../mixins/CKEditor'
22
+ import Translatable from 'vue-kompo/js/form/mixins/Translatable'
23
+
24
+ export default {
25
+ mixins: [CKEditor, Translatable],
26
+ }
27
+ </script>
28
+