js-kompo-utils 1.0.14 → 1.0.16

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 (34) hide show
  1. package/components/VlText.vue +4 -0
  2. package/components/VlTutorialStepBuilder.vue +137 -586
  3. package/components/step-builder/SbContextMenu.vue +41 -0
  4. package/components/step-builder/SbGraphView.vue +93 -0
  5. package/components/step-builder/SbHeader.vue +16 -0
  6. package/components/step-builder/SbHistoryDrawer.vue +43 -0
  7. package/components/step-builder/SbPathPreview.vue +57 -0
  8. package/components/step-builder/SbStepList.vue +87 -0
  9. package/components/step-builder/SbTimeline.vue +66 -0
  10. package/components/step-builder/cards/SbActionsCard.vue +26 -0
  11. package/components/step-builder/cards/SbAdvanceCard.vue +43 -0
  12. package/components/step-builder/cards/SbConditionsCard.vue +20 -0
  13. package/components/step-builder/cards/SbContentCard.vue +45 -0
  14. package/components/step-builder/cards/SbCursorCard.vue +102 -0
  15. package/components/step-builder/cards/SbGlobalOptsCard.vue +40 -0
  16. package/components/step-builder/cards/SbHighlightCard.vue +40 -0
  17. package/components/step-builder/cards/SbHoverCard.vue +32 -0
  18. package/components/step-builder/cards/SbOptionsCard.vue +50 -0
  19. package/components/step-builder/cards/SbOutputCard.vue +17 -0
  20. package/components/step-builder/cards/SbPositionCard.vue +87 -0
  21. package/components/step-builder/cards/SbScrollCard.vue +17 -0
  22. package/docs/extending-tutorial-system.md +376 -0
  23. package/package.json +10 -9
  24. package/tutorials/TutorialConfig.js +4 -0
  25. package/tutorials/TutorialEngine.js +49 -3
  26. package/tutorials/extensions/HideIfExtension.js +12 -0
  27. package/tutorials/extensions/LinkNextExtension.js +117 -0
  28. package/tutorials/modules/Cursor.js +24 -4
  29. package/tutorials/modules/Highlight.js +7 -5
  30. package/tutorials/modules/HoverForcer.js +1 -0
  31. package/tutorials/modules/Overlay.js +2 -0
  32. package/tutorials/step-builder/StepBuilderState.js +265 -0
  33. package/tutorials/tutorial.scss +186 -0
  34. package/tutorials/step-builder/step-builder-bridge.js +0 -436
@@ -0,0 +1,102 @@
1
+ <template>
2
+ <div class="sb-card" :class="{ 'sb-card--open': sb.cards.cursor }">
3
+ <div class="sb-card-head" @click="sb.toggle('cursor')">
4
+ <span>CURSOR</span>
5
+ <span class="sb-chevron">{{ sb.cards.cursor ? '&#9660;' : '&#9654;' }}</span>
6
+ </div>
7
+ <div v-show="sb.cards.cursor" class="sb-card-body">
8
+ <div class="sb-row sb-row--pick">
9
+ <label class="sb-lbl">From</label>
10
+ <input :value="sb.step.cursor && sb.step.cursor.from || ''" @input="setCursor('from', $event.target.value)" class="sb-input">
11
+ <button class="sb-pick" @click="pickCursor('from')">Pick</button>
12
+ </div>
13
+ <div v-if="sb.step.cursor && sb.step.cursor.fromAnchor" class="sb-row">
14
+ <span class="sb-badge">anchor: {{ sb.step.cursor.fromAnchor.x }}, {{ sb.step.cursor.fromAnchor.y }}</span>
15
+ <button class="sb-pick sb-pick--danger sb-btn-sm" @click="clearAnchor('fromAnchor')">&times;</button>
16
+ </div>
17
+ <div class="sb-row sb-row--pick">
18
+ <label class="sb-lbl">To</label>
19
+ <input :value="sb.step.cursor && sb.step.cursor.to || ''" @input="setCursor('to', $event.target.value)" class="sb-input">
20
+ <button class="sb-pick" @click="pickCursor('to')">Pick</button>
21
+ </div>
22
+ <div v-if="sb.step.cursor && sb.step.cursor.toAnchor" class="sb-row">
23
+ <span class="sb-badge">anchor: {{ sb.step.cursor.toAnchor.x }}, {{ sb.step.cursor.toAnchor.y }}</span>
24
+ <button class="sb-pick sb-pick--danger sb-btn-sm" @click="clearAnchor('toAnchor')">&times;</button>
25
+ </div>
26
+ <div class="sb-row">
27
+ <label class="sb-lbl">Duration</label>
28
+ <input type="number" :value="sb.step.cursor && sb.step.cursor.duration || 1.5" @input="setCursor('duration', parseFloat($event.target.value) || 1.5)" class="sb-input sb-input--num" step="0.1">
29
+ </div>
30
+ <div class="sb-row">
31
+ <label class="sb-check"><input type="checkbox" :checked="!!(sb.step.cursor && sb.step.cursor.click)" @change="setCursor('click', $event.target.checked)"> Click</label>
32
+ <label class="sb-check"><input type="checkbox" :checked="!!(sb.step.cursor && sb.step.cursor.loop)" @change="setCursor('loop', $event.target.checked)"> Loop</label>
33
+ </div>
34
+ <div v-if="sb.step.cursor" style="margin-top:8px">
35
+ <label class="sb-lbl">WAYPOINTS</label>
36
+ <div v-for="(wp, wi) in (sb.step.cursor.waypoints || [])" :key="wi" class="sb-wp-row">
37
+ <div class="sb-row sb-row--pick" style="margin-bottom:4px">
38
+ <input :value="wp.target" @input="setWaypoint(wi, 'target', $event.target.value)" class="sb-input" placeholder="selector">
39
+ <button class="sb-pick" @click="pickWaypoint(wi)">Pick</button>
40
+ </div>
41
+ <div class="sb-row">
42
+ <select :value="wp.action || 'path'" @change="setWaypoint(wi, 'action', $event.target.value)" class="sb-input sb-input--sm">
43
+ <option value="path">Path</option>
44
+ <option value="click">Click</option>
45
+ <option value="hover">Hover</option>
46
+ </select>
47
+ <input type="number" :value="wp.pause || 0" @input="setWaypoint(wi, 'pause', parseFloat($event.target.value) || 0)" class="sb-input sb-input--num" step="0.1" placeholder="pause">
48
+ <button class="sb-pick sb-pick--danger" @click="removeWaypoint(wi)">&times;</button>
49
+ </div>
50
+ </div>
51
+ <button class="sb-btn sb-btn-sm sb-btn-green" @click="addWaypoint">+ Waypoint</button>
52
+ </div>
53
+ </div>
54
+ </div>
55
+ </template>
56
+ <script>
57
+ export default {
58
+ inject: ['sb'],
59
+ methods: {
60
+ ensureCursor() {
61
+ if (!this.sb.step.cursor) this.$set(this.sb.step, 'cursor', {});
62
+ },
63
+ setCursor(key, val) {
64
+ this.sb.state.beginEdit('Edit step #' + this.sb.idx + ' \u2192 cursor.' + key);
65
+ this.ensureCursor();
66
+ this.$set(this.sb.step.cursor, key, val);
67
+ if (!this.sb.step.cursor.from && !this.sb.step.cursor.to) {
68
+ this.$delete(this.sb.step, 'cursor');
69
+ }
70
+ },
71
+ async pickCursor(key) {
72
+ const { pickElement } = await import('../../../tutorials/step-builder/utils/element-picker.js');
73
+ const sel = await pickElement();
74
+ if (sel) this.setCursor(key, sel);
75
+ },
76
+ addWaypoint() {
77
+ this.sb.state.beginEdit('Edit step #' + this.sb.idx + ' \u2192 add waypoint');
78
+ this.ensureCursor();
79
+ if (!this.sb.step.cursor.waypoints) this.$set(this.sb.step.cursor, 'waypoints', []);
80
+ this.sb.step.cursor.waypoints.push({ target: '', action: 'path', pause: 0 });
81
+ },
82
+ removeWaypoint(wi) {
83
+ this.sb.state.beginEdit('Edit step #' + this.sb.idx + ' \u2192 remove waypoint');
84
+ this.sb.step.cursor.waypoints.splice(wi, 1);
85
+ if (!this.sb.step.cursor.waypoints.length) this.$delete(this.sb.step.cursor, 'waypoints');
86
+ },
87
+ setWaypoint(wi, key, val) {
88
+ this.sb.state.beginEdit('Edit step #' + this.sb.idx + ' \u2192 waypoint.' + key);
89
+ this.$set(this.sb.step.cursor.waypoints[wi], key, val);
90
+ },
91
+ async pickWaypoint(wi) {
92
+ const { pickElement } = await import('../../../tutorials/step-builder/utils/element-picker.js');
93
+ const sel = await pickElement();
94
+ if (sel) this.setWaypoint(wi, 'target', sel);
95
+ },
96
+ clearAnchor(key) {
97
+ this.sb.state.beginEdit('Edit step #' + this.sb.idx + ' \u2192 clear ' + key);
98
+ this.$delete(this.sb.step.cursor, key);
99
+ },
100
+ },
101
+ };
102
+ </script>
@@ -0,0 +1,40 @@
1
+ <template>
2
+ <div class="sb-card" :class="{ 'sb-card--open': sb.cards.globalOpts }">
3
+ <div class="sb-card-head" @click="sb.toggle('globalOpts')">
4
+ <span>GLOBAL OPTIONS</span><span class="sb-chevron">{{ sb.cards.globalOpts ? '&#9660;' : '&#9654;' }}</span>
5
+ </div>
6
+ <div v-show="sb.cards.globalOpts" class="sb-card-body">
7
+ <label class="sb-lbl">Highlight Color</label>
8
+ <div class="sb-row">
9
+ <input type="color" :value="opt('highlightColor', '#ffd700')" @input="setOpt('highlightColor', $event.target.value)" class="sb-color-input">
10
+ <input :value="opt('highlightColor', '#ffd700')" @input="setOpt('highlightColor', $event.target.value)" class="sb-input" style="flex:1">
11
+ <button class="sb-pick" @click="resetOpt('highlightColor')" title="Reset">&#8634;</button>
12
+ </div>
13
+ <label class="sb-lbl">Border Radius (px)</label>
14
+ <div class="sb-row">
15
+ <input type="number" :value="opt('highlightBorderRadius', 8)" @input="setOpt('highlightBorderRadius', parseInt($event.target.value) || 8)" class="sb-input sb-input--num">
16
+ <button class="sb-pick" @click="resetOpt('highlightBorderRadius')" title="Reset">&#8634;</button>
17
+ </div>
18
+ <label class="sb-lbl" style="margin-top:8px">Bubble Max Width</label>
19
+ <input :value="opt('bubbleMaxWidth', 'clamp(260px, 85vw, 550px)')" @input="setOpt('bubbleMaxWidth', $event.target.value)" class="sb-input">
20
+ <label class="sb-lbl">Bubble Min Width</label>
21
+ <input :value="opt('bubbleMinWidth', 'clamp(200px, 70vw, 350px)')" @input="setOpt('bubbleMinWidth', $event.target.value)" class="sb-input">
22
+ <label class="sb-lbl">Bubble Font Size</label>
23
+ <input :value="opt('bubbleFontSize', 'clamp(14px, 3.5vw, 16px)')" @input="setOpt('bubbleFontSize', $event.target.value)" class="sb-input">
24
+ </div>
25
+ </div>
26
+ </template>
27
+ <script>
28
+ export default {
29
+ inject: ['sb'],
30
+ methods: {
31
+ opt(key, fallback) { return this.sb.engine?.config?.get(key) ?? fallback; },
32
+ setOpt(key, value) { if (this.sb.engine?.config) { this.sb.engine.config.set(key, value); this.sb.previewNow(); } },
33
+ resetOpt(key) {
34
+ if (!this.sb.engine?.config) return;
35
+ this.sb.engine.config.set(key, this.sb.engine.config.constructor.DEFAULTS[key]);
36
+ this.sb.previewNow();
37
+ },
38
+ },
39
+ };
40
+ </script>
@@ -0,0 +1,40 @@
1
+ <template>
2
+ <div class="sb-card" :class="{ 'sb-card--open': sb.cards.highlight }">
3
+ <div class="sb-card-head" @click="sb.toggle('highlight')">
4
+ <span>HIGHLIGHT</span><span class="sb-chevron">{{ sb.cards.highlight ? '&#9660;' : '&#9654;' }}</span>
5
+ </div>
6
+ <div v-show="sb.cards.highlight" class="sb-card-body">
7
+ <div class="sb-row sb-row--pick">
8
+ <label class="sb-lbl">Elements</label>
9
+ <input :value="highlightElements" @input="setHighlightElements($event.target.value)" class="sb-input" placeholder="sel1, sel2">
10
+ <button class="sb-pick" @click="pickHighlight">Pick</button>
11
+ </div>
12
+ </div>
13
+ </div>
14
+ </template>
15
+ <script>
16
+ export default {
17
+ inject: ['sb'],
18
+ computed: {
19
+ highlightElements() {
20
+ return this.sb.step.highlight?.groups?.flatMap(g => g.elements || g)?.join(', ') || '';
21
+ },
22
+ },
23
+ methods: {
24
+ setHighlightElements(val) {
25
+ this.sb.state.beginEdit('Edit step #' + this.sb.idx + ' \u2192 highlight');
26
+ if (!val) { this.$delete(this.sb.step, 'highlight'); return; }
27
+ const elements = val.split(',').map(s => s.trim()).filter(Boolean);
28
+ this.$set(this.sb.step, 'highlight', { groups: [{ elements }] });
29
+ },
30
+ async pickHighlight() {
31
+ const { pickElement } = await import('../../../tutorials/step-builder/utils/element-picker.js');
32
+ const sel = await pickElement();
33
+ if (sel) {
34
+ const current = this.highlightElements;
35
+ this.setHighlightElements(current ? current + ', ' + sel : sel);
36
+ }
37
+ },
38
+ },
39
+ };
40
+ </script>
@@ -0,0 +1,32 @@
1
+ <template>
2
+ <div class="sb-card" :class="{ 'sb-card--open': sb.cards.hover }">
3
+ <div class="sb-card-head" @click="sb.toggle('hover')">
4
+ <span>HOVER</span><span class="sb-chevron">{{ sb.cards.hover ? '&#9660;' : '&#9654;' }}</span>
5
+ </div>
6
+ <div v-show="sb.cards.hover" class="sb-card-body">
7
+ <div class="sb-row sb-row--pick">
8
+ <input :value="hoverDisplay" @input="setHover($event.target.value)" class="sb-input" placeholder="CSS selector">
9
+ <button class="sb-pick" @click="sb.pickField('hover')">Pick</button>
10
+ </div>
11
+ </div>
12
+ </div>
13
+ </template>
14
+ <script>
15
+ export default {
16
+ inject: ['sb'],
17
+ computed: {
18
+ hoverDisplay() {
19
+ const h = this.sb.step.hover;
20
+ return Array.isArray(h) ? h.join(', ') : (h || '');
21
+ },
22
+ },
23
+ methods: {
24
+ setHover(val) {
25
+ this.sb.state.beginEdit('Edit step #' + this.sb.idx + ' \u2192 hover');
26
+ if (!val) { this.$delete(this.sb.step, 'hover'); return; }
27
+ const parts = val.split(',').map(s => s.trim()).filter(Boolean);
28
+ this.$set(this.sb.step, 'hover', parts.length === 1 ? parts[0] : parts);
29
+ },
30
+ },
31
+ };
32
+ </script>
@@ -0,0 +1,50 @@
1
+ <template>
2
+ <div class="sb-card" :class="{ 'sb-card--open': sb.cards.options }">
3
+ <div class="sb-card-head" @click="sb.toggle('options')">
4
+ <span>OPTIONS</span><span class="sb-chevron">{{ sb.cards.options ? '&#9660;' : '&#9654;' }}</span>
5
+ </div>
6
+ <div v-show="sb.cards.options" class="sb-card-body">
7
+ <div v-for="(opt, oi) in (sb.step.options || [])" :key="oi" class="sb-opt-row">
8
+ <input :value="opt.label" @input="setLabel(oi, $event.target.value)" class="sb-input" placeholder="Label">
9
+ <select :value="opt._action" @change="setAction(oi, $event.target.value)" class="sb-input sb-input--sm">
10
+ <option value="next">Next</option>
11
+ <option value="done">Done</option>
12
+ <option value="goToStep">Go To</option>
13
+ <option value="redirect">Redirect</option>
14
+ </select>
15
+ <button class="sb-pick sb-pick--danger" @click="removeOption(oi)">&times;</button>
16
+ </div>
17
+ <button class="sb-btn sb-btn-sm sb-btn-green" @click="addOption">+ Option</button>
18
+ </div>
19
+ </div>
20
+ </template>
21
+ <script>
22
+ export default {
23
+ inject: ['sb'],
24
+ methods: {
25
+ setLabel(oi, val) {
26
+ this.sb.state.beginEdit('Edit step #' + this.sb.idx + ' \u2192 option label');
27
+ this.$set(this.sb.step.options[oi], 'label', val);
28
+ },
29
+ addOption() {
30
+ this.sb.state.beginEdit('Edit step #' + this.sb.idx + ' \u2192 add option');
31
+ if (!this.sb.step.options) this.$set(this.sb.step, 'options', []);
32
+ this.sb.step.options.push({ label: 'New Option', _action: 'next' });
33
+ },
34
+ removeOption(i) {
35
+ this.sb.state.beginEdit('Edit step #' + this.sb.idx + ' \u2192 remove option');
36
+ this.sb.step.options.splice(i, 1);
37
+ if (!this.sb.step.options.length) this.$delete(this.sb.step, 'options');
38
+ },
39
+ setAction(i, action) {
40
+ this.sb.state.beginEdit('Edit step #' + this.sb.idx + ' \u2192 option action');
41
+ const opt = this.sb.step.options[i];
42
+ delete opt.done; delete opt.goToStep; delete opt.redirect;
43
+ this.$set(opt, '_action', action);
44
+ if (action === 'done') this.$set(opt, 'done', true);
45
+ else if (action === 'goToStep') this.$set(opt, 'goToStep', this.sb.idx + 1);
46
+ else if (action === 'redirect') this.$set(opt, 'redirect', '/');
47
+ },
48
+ },
49
+ };
50
+ </script>
@@ -0,0 +1,17 @@
1
+ <template>
2
+ <div class="sb-card" :class="{ 'sb-card--open': sb.cards.output }">
3
+ <div class="sb-card-head" @click="sb.toggle('output')">
4
+ <span>OUTPUT (JSON)</span><span class="sb-chevron">{{ sb.cards.output ? '&#9660;' : '&#9654;' }}</span>
5
+ </div>
6
+ <div v-show="sb.cards.output" class="sb-card-body">
7
+ <pre class="sb-code">{{ sb.outputJson }}</pre>
8
+ <div class="sb-row" style="margin-top:8px;justify-content:flex-end">
9
+ <button class="sb-btn sb-btn-sm sb-btn-ghost" @click="sb.copyStep()">Copy Step</button>
10
+ <button class="sb-btn sb-btn-sm sb-btn-ghost" @click="sb.copyAll()">Copy All</button>
11
+ </div>
12
+ </div>
13
+ </div>
14
+ </template>
15
+ <script>
16
+ export default { inject: ['sb'] };
17
+ </script>
@@ -0,0 +1,87 @@
1
+ <template>
2
+ <div class="sb-card" :class="{ 'sb-card--open': sb.cards.position }">
3
+ <div class="sb-card-head" @click="sb.toggle('position')">
4
+ <span>POSITION</span>
5
+ <span class="sb-chevron">{{ sb.cards.position ? '&#9660;' : '&#9654;' }}</span>
6
+ </div>
7
+ <div v-show="sb.cards.position" class="sb-card-body">
8
+ <div class="sb-row">
9
+ <label class="sb-lbl">Position</label>
10
+ <select :value="sb.step.position" @change="setPosition($event.target.value)" class="sb-input">
11
+ <option value="left">Left of avatar</option>
12
+ <option value="right">Right of avatar</option>
13
+ <option value="top">Above avatar</option>
14
+ <option value="bottom">Below avatar</option>
15
+ <option value="custom">Custom (manual)</option>
16
+ </select>
17
+ </div>
18
+ <template v-if="sb.step.position === 'custom'">
19
+ <div class="sb-row">
20
+ <label class="sb-lbl">Left</label>
21
+ <input :value="sb.step.bubbleLeft || ''" @input="sb.setStepProp('bubbleLeft', $event.target.value)" class="sb-input" placeholder="e.g. 50%, 300px, 20vw">
22
+ </div>
23
+ <div class="sb-row">
24
+ <label class="sb-lbl">Top</label>
25
+ <input :value="sb.step.bubbleTop || ''" @input="sb.setStepProp('bubbleTop', $event.target.value)" class="sb-input" placeholder="e.g. 50%, 200px, 30vh">
26
+ </div>
27
+ </template>
28
+ <div class="sb-row">
29
+ <label class="sb-lbl">Avatar Pos</label>
30
+ <select :value="sb.step.align" @change="setAlign($event.target.value)" class="sb-input">
31
+ <option value="left">Left</option>
32
+ <option value="center">Center</option>
33
+ <option value="right">Right</option>
34
+ <option value="custom">Custom (manual)</option>
35
+ </select>
36
+ </div>
37
+ <template v-if="sb.step.align === 'custom'">
38
+ <div class="sb-row">
39
+ <label class="sb-lbl">Left</label>
40
+ <input :value="sb.step.avatarLeft || ''" @input="sb.setStepProp('avatarLeft', $event.target.value)" class="sb-input" placeholder="e.g. 30%, 200px">
41
+ </div>
42
+ <div class="sb-row">
43
+ <label class="sb-lbl">Top</label>
44
+ <input :value="sb.step.avatarTop || ''" @input="sb.setStepProp('avatarTop', $event.target.value)" class="sb-input" placeholder="e.g. 60%, 400px">
45
+ </div>
46
+ </template>
47
+ <div class="sb-row">
48
+ <label class="sb-lbl">Avatar Size</label>
49
+ <input :value="sb.step.avatarSize || ''" @input="sb.setStepProp('avatarSize', $event.target.value); applyAvatarSize()" class="sb-input" placeholder="e.g. 200px, 30vh (empty = default)">
50
+ </div>
51
+ <label class="sb-check"><input type="checkbox" :checked="!!sb.step.chatMode" @change="toggleChatMode"> Chat Mode</label>
52
+ <div class="sb-row sb-row--pick">
53
+ <label class="sb-lbl">Target</label>
54
+ <input :value="sb.step.positionTarget || ''" @input="sb.setStepProp('positionTarget', $event.target.value)" class="sb-input" placeholder="CSS selector">
55
+ <button class="sb-pick" @click="sb.pickField('positionTarget')">Pick</button>
56
+ </div>
57
+ </div>
58
+ </div>
59
+ </template>
60
+ <script>
61
+ export default {
62
+ inject: ['sb'],
63
+ methods: {
64
+ setPosition(val) {
65
+ this.sb.state.beginEdit('Edit step #' + this.sb.idx + ' \u2192 position');
66
+ this.$set(this.sb.step, 'position', val);
67
+ },
68
+ setAlign(val) {
69
+ this.sb.state.beginEdit('Edit step #' + this.sb.idx + ' \u2192 align');
70
+ this.$set(this.sb.step, 'align', val);
71
+ },
72
+ toggleChatMode(e) {
73
+ this.sb.state.beginEdit('Edit step #' + this.sb.idx + ' \u2192 chatMode');
74
+ if (e.target.checked) this.$set(this.sb.step, 'chatMode', true);
75
+ else this.$delete(this.sb.step, 'chatMode');
76
+ },
77
+ applyAvatarSize() {
78
+ const size = this.sb.step.avatarSize;
79
+ if (this.sb.engine?.avatar?.img) {
80
+ this.sb.engine.avatar.img.style.height = size || this.sb.engine.config?.get('avatarHeight') || '';
81
+ this.sb.engine.avatar.img.style.maxHeight = size || this.sb.engine.config?.get('avatarMaxHeight') || '';
82
+ }
83
+ this.sb.previewNow();
84
+ },
85
+ },
86
+ };
87
+ </script>
@@ -0,0 +1,17 @@
1
+ <template>
2
+ <div class="sb-card" :class="{ 'sb-card--open': sb.cards.scroll }">
3
+ <div class="sb-card-head" @click="sb.toggle('scroll')">
4
+ <span>SCROLL</span><span class="sb-chevron">{{ sb.cards.scroll ? '&#9660;' : '&#9654;' }}</span>
5
+ </div>
6
+ <div v-show="sb.cards.scroll" class="sb-card-body">
7
+ <div class="sb-row sb-row--pick">
8
+ <label class="sb-lbl">Scroll To</label>
9
+ <input :value="sb.step.scrollTo || ''" @input="sb.setStepProp('scrollTo', $event.target.value)" class="sb-input">
10
+ <button class="sb-pick" @click="sb.pickField('scrollTo')">Pick</button>
11
+ </div>
12
+ </div>
13
+ </div>
14
+ </template>
15
+ <script>
16
+ export default { inject: ['sb'] };
17
+ </script>