@fastkit/vui 0.6.35 → 0.6.39

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.
@@ -3,16 +3,25 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var vueKit = require('@fastkit/vue-kit');
6
+ var vue = require('vue');
6
7
  var vueRouter = require('vue-router');
7
8
  var vueUtils = require('@fastkit/vue-utils');
8
- var vue = require('vue');
9
9
  var vueColorScheme = require('@fastkit/vue-color-scheme');
10
10
  var vueLoading = require('@fastkit/vue-loading');
11
11
  var iconFont = require('@fastkit/icon-font');
12
12
  var helpers = require('@fastkit/helpers');
13
13
  var vueAppLayout = require('@fastkit/vue-app-layout');
14
+ var vueFormControl = require('@fastkit/vue-form-control');
14
15
  var vue3 = require('@tiptap/vue-3');
15
16
  var StarterKit = require('@tiptap/starter-kit');
17
+ var extensionBulletList = require('@tiptap/extension-bullet-list');
18
+ var extensionBold = require('@tiptap/extension-bold');
19
+ var extensionItalic = require('@tiptap/extension-italic');
20
+ var extensionUnderline = require('@tiptap/extension-underline');
21
+ var extensionHistory = require('@tiptap/extension-history');
22
+ var extensionLink = require('@tiptap/extension-link');
23
+ var rules = require('@fastkit/rules');
24
+ var extensionOrderedList = require('@tiptap/extension-ordered-list');
16
25
  var vueScroller = require('@fastkit/vue-scroller');
17
26
 
18
27
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e["default"] : e; }
@@ -28,6 +37,7 @@ const VuiControlFieldInjectionKey = Symbol();
28
37
  const VuiColorProviderInjectionKey = Symbol();
29
38
  const VUI_TEXT_FIELD_SYMBOL = 'vui-text-field';
30
39
  const VUI_TEXTAREA_SYMBOL = 'vui-textarea';
40
+ const VUI_WYSIWYG_EDITOR_SYMBOL = 'vui-wysiwyg-editor';
31
41
  const VUI_SELECT_SYMBOL = 'vui-select';
32
42
  const VUI_OPTION_SYMBOL = 'vui-option';
33
43
  const VUI_CHECKBOX_GROUP_SYMBOL = 'vui-checkbox-group';
@@ -440,7 +450,8 @@ function resolveRawVButtonIcon(raw, type = 'main') {
440
450
  }, null);
441
451
  }
442
452
 
443
- const vueButtonProps = vueUtils.createPropsOptions({ ...vueColorScheme.colorSchemeProps(),
453
+ const vueButtonProps = vueUtils.createPropsOptions({ ...undefined,
454
+ ...vueColorScheme.colorSchemeProps(),
444
455
  ...vueUtils.navigationableInheritProps,
445
456
  spacer: [Boolean, String],
446
457
  loading: Boolean,
@@ -529,7 +540,13 @@ const VButtonGroup = vue.defineComponent({
529
540
  setup(props, ctx) {
530
541
  return () => {
531
542
  let buttonLength = 0;
532
- const children = (vueUtils.renderSlotOrEmpty(ctx.slots) || []).map(node => {
543
+ let tmp = vueUtils.renderSlotOrEmpty(ctx.slots) || [];
544
+
545
+ if (tmp.length === 1 && vueUtils.isFragment(tmp[0])) {
546
+ tmp = tmp[0].children;
547
+ }
548
+
549
+ const children = tmp.map(node => {
533
550
  if (!vue.isVNode(node) || node.type !== VButton) {
534
551
  return {
535
552
  isButton: false,
@@ -542,16 +559,7 @@ const VButtonGroup = vue.defineComponent({
542
559
  isButton: true,
543
560
  node
544
561
  };
545
- }); // const children = renderSlotOrEmpty(ctx.slots) || [];
546
- // const $children = children.map((child) => {
547
- // if (!isVNode(child) || child.type !== VButton) return child;
548
- // const $child = cloneVNode(child, {
549
- // ...props,
550
- // ...child.props,
551
- // });
552
- // return $child;
553
- // });
554
-
562
+ });
555
563
  let buttonIndex = 0;
556
564
  const $children = children.map(child => {
557
565
  if (child.isButton) {
@@ -579,7 +587,7 @@ const VButtonGroup = vue.defineComponent({
579
587
 
580
588
  });
581
589
 
582
- function _isSlot$c(s) {
590
+ function _isSlot$d(s) {
583
591
  return typeof s === 'function' || Object.prototype.toString.call(s) === '[object Object]' && !vue.isVNode(s);
584
592
  }
585
593
 
@@ -827,7 +835,7 @@ const VPagination = vue.defineComponent({
827
835
  "class": classes,
828
836
  "to": to,
829
837
  "key": key
830
- }, _isSlot$c(children) ? children : {
838
+ }, _isSlot$d(children) ? children : {
831
839
  default: () => [children]
832
840
  });
833
841
  } else {
@@ -982,7 +990,7 @@ const VDrawerLayout = vue.defineComponent({
982
990
 
983
991
  });
984
992
 
985
- function _isSlot$b(s) {
993
+ function _isSlot$c(s) {
986
994
  return typeof s === 'function' || Object.prototype.toString.call(s) === '[object Object]' && !vue.isVNode(s);
987
995
  }
988
996
 
@@ -1017,7 +1025,7 @@ const VHero = vue.defineComponent({
1017
1025
  }, {
1018
1026
  default: () => [vue.createVNode(HTagName, {
1019
1027
  "class": "v-hero__title"
1020
- }, _isSlot$b(_slot = vueUtils.renderSlotOrEmpty(ctx.slots, 'default')) ? _slot : {
1028
+ }, _isSlot$c(_slot = vueUtils.renderSlotOrEmpty(ctx.slots, 'default')) ? _slot : {
1021
1029
  default: () => [_slot]
1022
1030
  })]
1023
1031
  })]
@@ -1027,7 +1035,7 @@ const VHero = vue.defineComponent({
1027
1035
 
1028
1036
  });
1029
1037
 
1030
- function _isSlot$a(s) {
1038
+ function _isSlot$b(s) {
1031
1039
  return typeof s === 'function' || Object.prototype.toString.call(s) === '[object Object]' && !vue.isVNode(s);
1032
1040
  }
1033
1041
 
@@ -1062,7 +1070,7 @@ function renderNavigationItemInput(input, extraProps) {
1062
1070
  } = resolveNavigationItemInput(input);
1063
1071
  return vue.createVNode(VNavigationItem, { ...props,
1064
1072
  ...extraProps
1065
- }, _isSlot$a(label) ? label : {
1073
+ }, _isSlot$b(label) ? label : {
1066
1074
  default: () => [label]
1067
1075
  });
1068
1076
  }
@@ -1215,7 +1223,7 @@ const VNavigationItem = vue.defineComponent({
1215
1223
  "class": ['v-navigation-item', classes.value],
1216
1224
  "onClick": onClick,
1217
1225
  "onChangeActive": onChangeActive
1218
- }), _isSlot$a(_slot = vueUtils.renderSlotOrEmpty(ctx.slots, 'default')) ? _slot : {
1226
+ }), _isSlot$b(_slot = vueUtils.renderSlotOrEmpty(ctx.slots, 'default')) ? _slot : {
1219
1227
  default: () => [_slot]
1220
1228
  }), _children && vue.createVNode(vueUtils.VExpandTransition, null, {
1221
1229
  default: () => [vue.withDirectives(vue.createVNode("div", {
@@ -1395,7 +1403,7 @@ const VCheckbox = vue.defineComponent({
1395
1403
 
1396
1404
  });
1397
1405
 
1398
- function _isSlot$9(s) {
1406
+ function _isSlot$a(s) {
1399
1407
  return typeof s === 'function' || Object.prototype.toString.call(s) === '[object Object]' && !vue.isVNode(s);
1400
1408
  }
1401
1409
 
@@ -1407,7 +1415,7 @@ const VCheckboxGroup = defineFormSelectorComponent({
1407
1415
  itemRenderer: ({
1408
1416
  attrs,
1409
1417
  slots
1410
- }) => vue.createVNode(VCheckbox, attrs, _isSlot$9(slots) ? slots : {
1418
+ }) => vue.createVNode(VCheckbox, attrs, _isSlot$a(slots) ? slots : {
1411
1419
  default: () => [slots]
1412
1420
  })
1413
1421
  });
@@ -1459,7 +1467,7 @@ const VRadio = vue.defineComponent({
1459
1467
 
1460
1468
  });
1461
1469
 
1462
- function _isSlot$8(s) {
1470
+ function _isSlot$9(s) {
1463
1471
  return typeof s === 'function' || Object.prototype.toString.call(s) === '[object Object]' && !vue.isVNode(s);
1464
1472
  }
1465
1473
 
@@ -1470,7 +1478,7 @@ const VRadioGroup = defineFormSelectorComponent({
1470
1478
  itemRenderer: ({
1471
1479
  attrs,
1472
1480
  slots
1473
- }) => vue.createVNode(VRadio, attrs, _isSlot$8(slots) ? slots : {
1481
+ }) => vue.createVNode(VRadio, attrs, _isSlot$9(slots) ? slots : {
1474
1482
  default: () => [slots]
1475
1483
  })
1476
1484
  });
@@ -1532,7 +1540,7 @@ const VSwitch = vue.defineComponent({
1532
1540
 
1533
1541
  });
1534
1542
 
1535
- function _isSlot$7(s) {
1543
+ function _isSlot$8(s) {
1536
1544
  return typeof s === 'function' || Object.prototype.toString.call(s) === '[object Object]' && !vue.isVNode(s);
1537
1545
  }
1538
1546
 
@@ -1544,7 +1552,7 @@ const VSwitchGroup = defineFormSelectorComponent({
1544
1552
  itemRenderer: ({
1545
1553
  attrs,
1546
1554
  slots
1547
- }) => vue.createVNode(VSwitch, attrs, _isSlot$7(slots) ? slots : {
1555
+ }) => vue.createVNode(VSwitch, attrs, _isSlot$8(slots) ? slots : {
1548
1556
  default: () => [slots]
1549
1557
  })
1550
1558
  });
@@ -1927,15 +1935,20 @@ const {
1927
1935
  props: props$2,
1928
1936
  emits: emits$2
1929
1937
  } = vueKit.createTextInputSettings();
1930
- const VTextField = vue.defineComponent({
1931
- name: 'VTextField',
1932
- props: { ...props$2,
1938
+
1939
+ function createTextFieldProps() {
1940
+ return { ...props$2,
1933
1941
  ...vueKit.createFormControlProps(),
1934
1942
  ...createControlFieldProps(),
1935
1943
  ...createControlFieldProviderProps(),
1936
1944
  ...createControlProps(),
1937
1945
  ...vueKit.defineSlotsProps()
1938
- },
1946
+ };
1947
+ }
1948
+
1949
+ const VTextField = vue.defineComponent({
1950
+ name: 'VTextField',
1951
+ props: createTextFieldProps(),
1939
1952
  emits: emits$2,
1940
1953
 
1941
1954
  setup(props, ctx) {
@@ -2044,86 +2057,396 @@ const VTextarea = vue.defineComponent({
2044
2057
 
2045
2058
  });
2046
2059
 
2060
+ function resolveRawWysiwygEditorTool(raw, vui) {
2061
+ return typeof raw === 'function' ? raw(vui) : raw;
2062
+ }
2063
+ function resolveRawWysiwygEditorTools(raws, vui) {
2064
+ const tools = [];
2065
+ const extensions = [];
2066
+ raws.forEach((raw) => {
2067
+ let resolved = resolveRawWysiwygEditorTool(raw, vui);
2068
+ if (!Array.isArray(resolved)) {
2069
+ resolved = [resolved];
2070
+ }
2071
+ resolved.forEach((tool) => {
2072
+ tools.push(tool);
2073
+ if (tool.extensions) {
2074
+ extensions.push(...tool.extensions);
2075
+ }
2076
+ });
2077
+ });
2078
+ return {
2079
+ tools,
2080
+ extensions,
2081
+ };
2082
+ }
2083
+
2084
+ function _isSlot$7(s) {
2085
+ return typeof s === 'function' || Object.prototype.toString.call(s) === '[object Object]' && !vue.isVNode(s);
2086
+ }
2087
+
2047
2088
  const VWysiwygEditor = vue.defineComponent({
2048
2089
  name: 'VWysiwygEditor',
2049
2090
  props: { // ...props,
2091
+ ...vueFormControl.createTextableProps(),
2050
2092
  ...vueKit.createFormControlProps(),
2051
2093
  ...createControlFieldProps(),
2052
2094
  ...createControlFieldProviderProps(),
2053
2095
  ...createControlProps(),
2054
- ...vueKit.defineSlotsProps()
2096
+ ...vueKit.defineSlotsProps(),
2097
+ tools: {
2098
+ type: Array,
2099
+ default: () => []
2100
+ },
2101
+ floatingToolbar: Boolean,
2102
+ disabledMinHeight: Boolean,
2103
+ disabledMaxHeight: Boolean
2104
+ },
2105
+ emits: { ...vueFormControl.createTextableEmits()
2055
2106
  },
2056
2107
 
2057
- // emits,
2058
2108
  setup(props, ctx) {
2109
+ const vui = useVui();
2110
+ const textRef = vue.ref('');
2111
+ const toolButtonActiveColor = vui.setting('primaryScope');
2112
+ const wysiwygSettings = vue.computed(() => resolveRawWysiwygEditorTools(props.tools, vui));
2113
+ const control = useControl(props);
2114
+ useControlField(props);
2115
+ const inputControl = new vueFormControl.TextableControl(props, ctx, {
2116
+ nodeType: VUI_WYSIWYG_EDITOR_SYMBOL,
2117
+ validationValue: () => textRef.value
2118
+ });
2119
+ const extensions = [StarterKit__default.configure({
2120
+ bold: false,
2121
+ bulletList: false,
2122
+ orderedList: false,
2123
+ history: false,
2124
+ italic: false
2125
+ }), ...wysiwygSettings.value.extensions];
2126
+
2127
+ const updateEditable = () => {
2128
+ if (!editor.value) return;
2129
+ editor.value.setEditable(inputControl.canOperation);
2130
+ };
2131
+
2132
+ vue.watch(() => inputControl.canOperation, updateEditable);
2133
+ vue.watch(() => props.modelValue, modelValue => {
2134
+ editor.value && editor.value.commands.setContent(modelValue == null ? '' : modelValue);
2135
+ });
2059
2136
  const editor = vue3.useEditor({
2060
- content: '<p>I’m running Tiptap with Vue.js. 🎉</p>',
2061
- extensions: [StarterKit__default]
2062
- }); // const vui = useVui();
2063
- // const inputControl = useTiptapControl(props, ctx, {
2064
- // nodeType: VUI_TEXTAREA_SYMBOL,
2065
- // defaultRows: vui.tiptapRows,
2066
- // });
2067
- // const control = useControl(props);
2068
- // useControlField(props);
2137
+ onCreate: ({
2138
+ editor
2139
+ }) => {
2140
+ textRef.value = editor.getText();
2141
+ updateEditable();
2142
+ },
2143
+ onFocus: ctx => {
2144
+ inputControl.focusHandler(ctx.event);
2145
+ },
2146
+ onBlur: ctx => {
2147
+ inputControl.blurHandler(ctx.event);
2148
+ },
2149
+ onUpdate: ev => {
2150
+ inputControl.value = ev.editor.getHTML();
2151
+ textRef.value = ev.editor.getText();
2152
+ },
2153
+ autofocus: props.autofocus,
2154
+ content: props.modelValue,
2155
+ extensions,
2156
+ editorProps: {
2157
+ attributes: {
2158
+ class: 'v-wysiwyg-editor__input__prose'
2159
+ }
2160
+ }
2161
+ }); // editor.value.state.doc.content
2069
2162
 
2070
- return {
2071
- editor // ...inputControl.expose(),
2072
- // ...control,
2163
+ const focus = (position, options) => {
2164
+ return editor.value.chain().focus(position, options);
2165
+ };
2073
2166
 
2167
+ const blur = () => {
2168
+ return editor.value.chain().blur();
2169
+ };
2170
+
2171
+ const wysiwygContext = vue.computed(() => ({
2172
+ vui,
2173
+ editor: editor.value
2174
+ }));
2175
+
2176
+ const createTools = (bubbleMenu = false) => {
2177
+ let _slot;
2178
+
2179
+ const {
2180
+ value: settings
2181
+ } = wysiwygSettings;
2182
+ const {
2183
+ value: context
2184
+ } = wysiwygContext;
2185
+ const tools = bubbleMenu ? settings.tools.filter(t => !!t.floating) : settings.tools;
2186
+ const _editor = editor.value;
2187
+ const variant = vui.setting(bubbleMenu ? 'containedVariant' : 'plainVariant');
2188
+ return vue.createVNode(VButtonGroup, {
2189
+ "class": {
2190
+ 'v-wysiwyg-editor__floating-toolbar': props.floatingToolbar
2191
+ },
2192
+ "variant": variant
2193
+ }, _isSlot$7(_slot = tools.map(({
2194
+ key,
2195
+ icon,
2196
+ onClick,
2197
+ disabled,
2198
+ active
2199
+ }) => {
2200
+ const isActive = !!_editor && resolveContextableValue(context, active);
2201
+ const isDisabled = !inputControl.canOperation || !!_editor && resolveContextableValue(context, disabled);
2202
+ let iconName;
2203
+
2204
+ if (typeof icon === 'function') {
2205
+ if (_editor) {
2206
+ iconName = icon(context);
2207
+ }
2208
+ } else {
2209
+ iconName = icon;
2210
+ }
2211
+
2212
+ if (!iconName) return;
2213
+ return vue.createVNode(VButton, {
2214
+ "key": key,
2215
+ "icon": iconName,
2216
+ "onClick": ev => onClick(context, ev),
2217
+ "color": isActive ? toolButtonActiveColor : undefined,
2218
+ "disabled": isDisabled
2219
+ }, null);
2220
+ })) ? _slot : {
2221
+ default: () => [_slot]
2222
+ });
2223
+ };
2224
+
2225
+ return {
2226
+ editor,
2227
+ ...inputControl.expose(),
2228
+ ...control,
2229
+ focus,
2230
+ blur,
2231
+ createTools
2074
2232
  };
2075
2233
  },
2076
2234
 
2077
2235
  render() {
2078
2236
  return vue.createVNode(VFormControl, {
2079
2237
  "nodeControl": this.nodeControl,
2238
+ "focused": this.nodeControl.focused,
2239
+ "class": ['v-wysiwyg-editor', this.classes, `v-wysiwyg-editor--${this.size}`, {
2240
+ 'v-wysiwyg-editor--disabled-min-heihgt': this.disabledMinHeight,
2241
+ 'v-wysiwyg-editor--disabled-max-heihgt': this.disabledMaxHeight
2242
+ }],
2080
2243
  "label": this.label,
2081
2244
  "hint": this.hint,
2082
2245
  "hiddenInfo": this.hiddenInfo,
2083
- "onClickLabel": ev => {// this.focus();
2246
+ "onClickLabel": ev => {
2247
+ this.focus('start', {
2248
+ scrollIntoView: true
2249
+ });
2084
2250
  }
2085
2251
  }, { ...this.$slots,
2086
- default: () => vue.createVNode(VControlField, {
2087
- "class": "v-wysiwyg-editor__input",
2088
- "autoHeight": true,
2089
- "startAdornment": this.startAdornment,
2090
- "endAdornment": this.endAdornment
2091
- }, { ...this.$slots,
2092
- default: () => {
2093
- const {
2094
- editor
2095
- } = this;
2096
- return vue.createVNode(vue.Fragment, null, [vue.createVNode(vue3.EditorContent, {
2097
- "class": "v-wysiwyg-editor__input__element wysiwyg",
2098
- "editor": editor
2099
- }, null), !!editor && vue.createVNode(vue3.BubbleMenu, {
2100
- "class": "v-wysiwyg-editor__bubble-menu",
2101
- "editor": editor
2102
- }, {
2103
- default: () => [vue.createVNode(VButton, {
2104
- "size": "sm",
2105
- "onClick": () => {
2106
- editor.chain().focus().toggleBold().run();
2107
- }
2108
- }, {
2109
- default: () => [vue.createTextVNode("Bold")]
2110
- })]
2111
- })]);
2112
- } // this.tiptapControl.createInputElement({
2113
- // class: 'v-wysiwyg-editor__input__element',
2114
- // }),
2115
-
2116
- }) // infoAppends: () => {
2117
- // const { counterResult } = this;
2118
- // if (!counterResult) return;
2119
- // return <VTextCounter {...counterResult} />;
2120
- // },
2121
-
2252
+ default: () => {
2253
+ const {
2254
+ editor
2255
+ } = this;
2256
+ return vue.createVNode("div", {
2257
+ "class": "v-wysiwyg-editor__wrapper"
2258
+ }, [!this.isReadonly && this.createTools(), vue.createVNode("div", {
2259
+ "class": "v-wysiwyg-editor__body"
2260
+ }, [vue.createVNode(VControlField, {
2261
+ "class": "v-wysiwyg-editor__input",
2262
+ "autoHeight": true,
2263
+ "startAdornment": this.startAdornment,
2264
+ "endAdornment": this.endAdornment
2265
+ }, { ...this.$slots,
2266
+ default: () => {
2267
+ let _slot2;
2268
+
2269
+ return vue.createVNode(vue.Fragment, null, [vue.createVNode(vue3.EditorContent, {
2270
+ "class": "v-wysiwyg-editor__input__element wysiwyg",
2271
+ "editor": editor
2272
+ }, null), !this.floatingToolbar && !!editor && !this.isReadonly && vue.createVNode(vue3.BubbleMenu, {
2273
+ "class": "v-wysiwyg-editor__bubble-menu",
2274
+ "editor": editor
2275
+ }, _isSlot$7(_slot2 = this.createTools(true)) ? _slot2 : {
2276
+ default: () => [_slot2]
2277
+ })]);
2278
+ }
2279
+ })])]);
2280
+ },
2281
+ infoAppends: () => {
2282
+ const {
2283
+ counterResult
2284
+ } = this;
2285
+ if (!counterResult) return;
2286
+ return vue.createVNode(VTextCounter, counterResult, null);
2287
+ }
2122
2288
  });
2123
2289
  }
2124
2290
 
2125
2291
  });
2126
2292
 
2293
+ function resolveContextableValue(ctx, source) {
2294
+ return typeof source === 'function' ? source(ctx) : source;
2295
+ }
2296
+
2297
+ const WysiwygBulletListTool = (vui, options) => {
2298
+ const tool = {
2299
+ key: 'bulletList',
2300
+ icon: vui.icon('editorformatListBulleted'),
2301
+ active: ({ editor }) => editor.isActive('bulletList'),
2302
+ onClick: ({ editor }) => {
2303
+ editor.chain().focus().toggleBulletList().run();
2304
+ },
2305
+ floating: true,
2306
+ extensions: [extensionBulletList.BulletList.configure(options)],
2307
+ };
2308
+ return tool;
2309
+ };
2310
+
2311
+ const WysiwygFormatBoldTool = (vui, options) => {
2312
+ const tool = {
2313
+ key: 'formatBold',
2314
+ icon: vui.icon('editorformatBold'),
2315
+ active: ({ editor }) => editor.isActive('bold'),
2316
+ onClick: ({ editor }) => {
2317
+ editor.chain().focus().toggleBold().run();
2318
+ },
2319
+ floating: true,
2320
+ extensions: [extensionBold.Bold.configure(options)],
2321
+ };
2322
+ return tool;
2323
+ };
2324
+
2325
+ const WysiwygFormatItalicTool = (vui, options) => {
2326
+ const tool = {
2327
+ key: 'formatItalic',
2328
+ icon: vui.icon('editorformatItalic'),
2329
+ active: ({ editor }) => editor.isActive('italic'),
2330
+ onClick: ({ editor }) => {
2331
+ editor.chain().focus().toggleItalic().run();
2332
+ },
2333
+ floating: true,
2334
+ extensions: [extensionItalic.Italic.configure(options)],
2335
+ };
2336
+ return tool;
2337
+ };
2338
+
2339
+ const WysiwygFormatUnderlineTool = (vui, options) => {
2340
+ const tool = {
2341
+ key: 'formatUnderline',
2342
+ icon: vui.icon('editorformatUnderline'),
2343
+ active: ({ editor }) => editor.isActive('underline'),
2344
+ onClick: ({ editor }) => {
2345
+ editor.chain().focus().toggleUnderline().run();
2346
+ },
2347
+ floating: true,
2348
+ extensions: [extensionUnderline.Underline.configure(options)],
2349
+ };
2350
+ return tool;
2351
+ };
2352
+
2353
+ const WysiwygHistoryTool = (vui, options) => {
2354
+ const undo = {
2355
+ key: 'history-undo',
2356
+ icon: vui.icon('editorUndo'),
2357
+ disabled: ({ editor }) => !editor.can().undo(),
2358
+ onClick: ({ editor }) => {
2359
+ editor.chain().focus().undo().run();
2360
+ },
2361
+ extensions: [extensionHistory.History.configure(options)],
2362
+ };
2363
+ const redo = {
2364
+ key: 'history-redo',
2365
+ icon: vui.icon('editorRedo'),
2366
+ disabled: ({ editor }) => !editor.can().redo(),
2367
+ onClick: ({ editor }) => {
2368
+ editor.chain().focus().redo().run();
2369
+ },
2370
+ };
2371
+ return [undo, redo];
2372
+ };
2373
+
2374
+ const WysiwygLinkTool = (vui, options) => {
2375
+ const tool = {
2376
+ key: 'link',
2377
+ // icon: ({ editor }) => {
2378
+ // return vui.icon(editor.isActive('link') ? 'editorLinkOff' : 'editorLink');
2379
+ // },
2380
+ icon: vui.icon('editorLink'),
2381
+ active: ({ editor }) => editor.isActive('link'),
2382
+ // disabled: ({ editor }) => {
2383
+ // const { $from, $to } = editor.view.state.selection;
2384
+ // return $to.pos - $from.pos === 0;
2385
+ // },
2386
+ onClick: async ({ vui, editor }) => {
2387
+ const { href = '' } = editor.getAttributes('link');
2388
+ const result = await vui.prompt({
2389
+ input: {
2390
+ label: 'Link URL',
2391
+ rules: [rules.validateIf, rules.url],
2392
+ initialValue: href,
2393
+ size: 'sm',
2394
+ autofocus: true,
2395
+ },
2396
+ });
2397
+ if (result === undefined || result === false) {
2398
+ return;
2399
+ }
2400
+ const range = editor.chain().focus().extendMarkRange('link');
2401
+ if (!result) {
2402
+ range.unsetLink().run();
2403
+ }
2404
+ else {
2405
+ range
2406
+ .setLink({
2407
+ href: result,
2408
+ })
2409
+ .run();
2410
+ }
2411
+ },
2412
+ floating: true,
2413
+ extensions: [
2414
+ extensionLink.Link.configure({
2415
+ openOnClick: false,
2416
+ ...options,
2417
+ }),
2418
+ ],
2419
+ };
2420
+ return tool;
2421
+ };
2422
+
2423
+ const WysiwygOrderedListTool = (vui, options) => {
2424
+ const tool = {
2425
+ key: 'orderedList',
2426
+ icon: vui.icon('editorformatListNumbered'),
2427
+ active: ({ editor }) => editor.isActive('orderedList'),
2428
+ onClick: ({ editor }) => {
2429
+ editor.chain().focus().toggleOrderedList().run();
2430
+ },
2431
+ floating: true,
2432
+ extensions: [extensionOrderedList.OrderedList.configure(options)],
2433
+ };
2434
+ return tool;
2435
+ };
2436
+
2437
+ const WysiwygTextColorTool = (vui) => {
2438
+ const tool = {
2439
+ key: 'textColor',
2440
+ icon: vui.icon('editorTextColor'),
2441
+ // icon: (gen) => vui.icon('editorTextColor'),
2442
+ onClick: (ctx) => {
2443
+ ctx.vui.alert('ok');
2444
+ },
2445
+ floating: true,
2446
+ };
2447
+ return tool;
2448
+ };
2449
+
2127
2450
  const {
2128
2451
  props,
2129
2452
  emits
@@ -2134,7 +2457,8 @@ const VForm = vue.defineComponent({
2134
2457
  name: 'VForm',
2135
2458
  props: { ...props,
2136
2459
  ...createControlProps(),
2137
- ...vueKit.defineSlotsProps()
2460
+ ...vueKit.defineSlotsProps(),
2461
+ disableAutoScroll: Boolean
2138
2462
  },
2139
2463
  emits,
2140
2464
 
@@ -2143,6 +2467,7 @@ const VForm = vue.defineComponent({
2143
2467
  const nodeControl = vueKit.useForm(props, ctx, {
2144
2468
  nodeType: VUI_FORM_SYMBOL,
2145
2469
  onAutoValidateError: () => {
2470
+ if (props.disableAutoScroll) return;
2146
2471
  const scroller = vueKit.getDocumentScroller();
2147
2472
  const {
2148
2473
  firstInvalidEl
@@ -3534,53 +3859,138 @@ const VToolbarTitle = vue.defineComponent({
3534
3859
 
3535
3860
  });
3536
3861
 
3537
- const DEFAULT_AUTO_SCROLL_TO_ELEMENT_OFFSET_TOP = -20;
3538
- const DEFAULT_TEXTAREA_ROWS = 3;
3539
- class VuiService {
3540
- options;
3541
- selectionSeparator;
3542
- autoScrollToElementOffsetTop;
3543
- textareaRows;
3544
- requiredChip;
3545
- router;
3546
- location;
3547
- constructor(options) {
3548
- this.options = options;
3549
- this.configure();
3550
- const { selectionSeparator = () => ', ', autoScrollToElementOffsetTop = DEFAULT_AUTO_SCROLL_TO_ELEMENT_OFFSET_TOP, textareaRows = DEFAULT_TEXTAREA_ROWS, requiredChip = () => '*', } = options;
3551
- this.selectionSeparator = selectionSeparator;
3552
- this.autoScrollToElementOffsetTop = autoScrollToElementOffsetTop;
3553
- this.textareaRows = textareaRows;
3554
- this.requiredChip = requiredChip;
3555
- this.router = options.router;
3556
- this.location = new vueUtils.LocationService({
3557
- router: this.router,
3558
- });
3559
- }
3560
- configure(options) {
3561
- options && Object.assign(this.options, options);
3562
- vueUtils.setDefaultRouterLink(this.getRouterLink());
3563
- }
3564
- getRouterLink() {
3565
- return this.options.RouterLink || vueRouter.RouterLink;
3566
- }
3567
- setting(key) {
3568
- return this.options.uiSettings[key];
3569
- }
3570
- icon(iconType) {
3571
- return this.options.icons[iconType];
3572
- }
3573
- getAutoScrollToElementOffsetTop() {
3574
- let { autoScrollToElementOffsetTop } = this;
3575
- if (typeof autoScrollToElementOffsetTop === 'function') {
3576
- autoScrollToElementOffsetTop = autoScrollToElementOffsetTop();
3577
- }
3578
- return autoScrollToElementOffsetTop || 0;
3579
- }
3580
- getRequiredChip() {
3581
- const { requiredChip } = this;
3582
- return requiredChip && requiredChip();
3583
- }
3862
+ const DEFAULT_AUTO_SCROLL_TO_ELEMENT_OFFSET_TOP = -20;
3863
+ const DEFAULT_TEXTAREA_ROWS = 3;
3864
+ class VuiService {
3865
+ constructor(options, stackService) {
3866
+ this.options = options;
3867
+ this.configure();
3868
+ const {
3869
+ selectionSeparator = () => ', ',
3870
+ autoScrollToElementOffsetTop = DEFAULT_AUTO_SCROLL_TO_ELEMENT_OFFSET_TOP,
3871
+ textareaRows = DEFAULT_TEXTAREA_ROWS,
3872
+ requiredChip = () => '*'
3873
+ } = options;
3874
+ this.selectionSeparator = selectionSeparator;
3875
+ this.autoScrollToElementOffsetTop = autoScrollToElementOffsetTop;
3876
+ this.textareaRows = textareaRows;
3877
+ this.requiredChip = requiredChip;
3878
+ this.router = options.router;
3879
+ this.location = new vueUtils.LocationService({
3880
+ router: this.router
3881
+ });
3882
+ this.stack = stackService;
3883
+ }
3884
+
3885
+ configure(options) {
3886
+ options && Object.assign(this.options, options);
3887
+ vueUtils.setDefaultRouterLink(this.getRouterLink());
3888
+ }
3889
+
3890
+ getRouterLink() {
3891
+ return this.options.RouterLink || vueRouter.RouterLink;
3892
+ }
3893
+
3894
+ setting(key) {
3895
+ return this.options.uiSettings[key];
3896
+ }
3897
+
3898
+ icon(iconType) {
3899
+ return this.options.icons[iconType];
3900
+ }
3901
+
3902
+ getAutoScrollToElementOffsetTop() {
3903
+ let {
3904
+ autoScrollToElementOffsetTop
3905
+ } = this;
3906
+
3907
+ if (typeof autoScrollToElementOffsetTop === 'function') {
3908
+ autoScrollToElementOffsetTop = autoScrollToElementOffsetTop();
3909
+ }
3910
+
3911
+ return autoScrollToElementOffsetTop || 0;
3912
+ }
3913
+
3914
+ getRequiredChip() {
3915
+ const {
3916
+ requiredChip
3917
+ } = this;
3918
+ return requiredChip && requiredChip();
3919
+ }
3920
+
3921
+ dialog(...args) {
3922
+ return this.stack.dialog(...args);
3923
+ }
3924
+
3925
+ alert(...args) {
3926
+ return this.stack.alert(...args);
3927
+ }
3928
+
3929
+ confirm(...args) {
3930
+ return this.stack.confirm(...args);
3931
+ }
3932
+
3933
+ snackbar(...args) {
3934
+ return this.stack.snackbar(...args);
3935
+ }
3936
+
3937
+ prompt(rawOptions = {}) {
3938
+ const options = typeof rawOptions === 'string' ? {
3939
+ input: {
3940
+ label: rawOptions
3941
+ }
3942
+ } : { ...rawOptions
3943
+ };
3944
+ options.input = { ...options.input
3945
+ };
3946
+ options.dense = true;
3947
+ let {
3948
+ initialValue: value = ''
3949
+ } = options.input;
3950
+ const {
3951
+ size
3952
+ } = options.input;
3953
+ delete options.input.initialValue;
3954
+ let form;
3955
+ options.actions = options.actions || [this.stack.action('cancel', undefined, {
3956
+ size
3957
+ }), this.stack.action('ok', undefined, {
3958
+ size,
3959
+ onClick: () => {
3960
+ if (form) {
3961
+ const ev = new Event('submit');
3962
+ form.handleSubmit(ev);
3963
+ }
3964
+ }
3965
+ })];
3966
+ const resolved = vueKit.resolveVStackDynamicInput({ ...options,
3967
+ content: stack => {
3968
+ return vue.createVNode(VForm, {
3969
+ "disableAutoScroll": true,
3970
+ "size": size,
3971
+ "onVnodeMounted": vnode => {
3972
+ form = vnode.component.ctx.form;
3973
+ },
3974
+ "onVnodeBeforeUnmount": () => {
3975
+ form = undefined;
3976
+ },
3977
+ "onSubmit": ev => {
3978
+ stack.resolve(value);
3979
+ }
3980
+ }, {
3981
+ default: () => [vue.createVNode(VTextField, vue.mergeProps(options.input, {
3982
+ "modelValue": value,
3983
+ "onChange": ev => {
3984
+ stack.value = ev;
3985
+ value = ev;
3986
+ }
3987
+ }), null)]
3988
+ });
3989
+ }
3990
+ });
3991
+ return this.dialog(resolved);
3992
+ }
3993
+
3584
3994
  }
3585
3995
 
3586
3996
  class VuiPlugin {
@@ -3624,7 +4034,7 @@ class VuiPlugin {
3624
4034
  ...stack
3625
4035
  }); // Vui
3626
4036
 
3627
- const $vui = new VuiService(opts);
4037
+ const $vui = new VuiService(opts, app.config.globalProperties.$vstack);
3628
4038
  app.provide(VuiInjectionKey, $vui);
3629
4039
  app.config.globalProperties.$vui = $vui;
3630
4040
 
@@ -3692,6 +4102,7 @@ exports.VUI_SWITCH_GROUP_SYMBOL = VUI_SWITCH_GROUP_SYMBOL;
3692
4102
  exports.VUI_SWITCH_SYMBOL = VUI_SWITCH_SYMBOL;
3693
4103
  exports.VUI_TEXTAREA_SYMBOL = VUI_TEXTAREA_SYMBOL;
3694
4104
  exports.VUI_TEXT_FIELD_SYMBOL = VUI_TEXT_FIELD_SYMBOL;
4105
+ exports.VUI_WYSIWYG_EDITOR_SYMBOL = VUI_WYSIWYG_EDITOR_SYMBOL;
3695
4106
  exports.VWysiwygEditor = VWysiwygEditor;
3696
4107
  exports.VuiColorProviderInjectionKey = VuiColorProviderInjectionKey;
3697
4108
  exports.VuiControlFieldInjectionKey = VuiControlFieldInjectionKey;
@@ -3699,6 +4110,14 @@ exports.VuiControlInjectionKey = VuiControlInjectionKey;
3699
4110
  exports.VuiInjectionKey = VuiInjectionKey;
3700
4111
  exports.VuiPlugin = VuiPlugin;
3701
4112
  exports.VuiService = VuiService;
4113
+ exports.WysiwygBulletListTool = WysiwygBulletListTool;
4114
+ exports.WysiwygFormatBoldTool = WysiwygFormatBoldTool;
4115
+ exports.WysiwygFormatItalicTool = WysiwygFormatItalicTool;
4116
+ exports.WysiwygFormatUnderlineTool = WysiwygFormatUnderlineTool;
4117
+ exports.WysiwygHistoryTool = WysiwygHistoryTool;
4118
+ exports.WysiwygLinkTool = WysiwygLinkTool;
4119
+ exports.WysiwygOrderedListTool = WysiwygOrderedListTool;
4120
+ exports.WysiwygTextColorTool = WysiwygTextColorTool;
3702
4121
  exports.configureDataTableDefaults = configureDataTableDefaults;
3703
4122
  exports.createCardProps = createCardProps;
3704
4123
  exports.createControlFieldProviderProps = createControlFieldProviderProps;