@fastkit/vui 0.6.35 → 0.6.36

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.
@@ -1,17 +1,26 @@
1
- import { createPropsOptions, createFormControlSettings, defineSlotsProps, useFormControl, renderSlotOrEmpty, createFormSelectorSettings, createFormControlProps, useFormSelectorControl, createFormSelectorItemSettings, useFormSelectorItemControl, createFormSelectorItemGroupProps, useFormSelectorItemGroupControl, resolveVNodeChildOrSlots, useParentFormNode, VMenu, createTextInputSettings, useTextInputControl, createTextareaSettings, useTextareaControl, createFormSettings, useForm, getDocumentScroller, useVScrollerRef, VScroller, useInjectTheme, VStackRoot, VueColorSchemePlugin, installVueStackPlugin } from '@fastkit/vue-kit';
1
+ import { createPropsOptions, createFormControlSettings, defineSlotsProps, useFormControl, renderSlotOrEmpty, createFormSelectorSettings, createFormControlProps, useFormSelectorControl, createFormSelectorItemSettings, useFormSelectorItemControl, createFormSelectorItemGroupProps, useFormSelectorItemGroupControl, resolveVNodeChildOrSlots, useParentFormNode, VMenu, createTextInputSettings, useTextInputControl, createTextareaSettings, useTextareaControl, createFormSettings, useForm, getDocumentScroller, useVScrollerRef, VScroller, useInjectTheme, VStackRoot, resolveVStackDynamicInput, VueColorSchemePlugin, installVueStackPlugin } from '@fastkit/vue-kit';
2
2
  export * from '@fastkit/vue-kit';
3
3
  export { VDialog, VMenu, VSnackbar } from '@fastkit/vue-kit';
4
- import { useRouter, RouterLink, useLink, useRoute } from 'vue-router';
5
- import { createPropsOptions as createPropsOptions$1, defineSlotsProps as defineSlotsProps$1, renderSlotOrEmpty as renderSlotOrEmpty$1, navigationableInheritProps, VLink, rawNumberPropType, resolveNumberish, resizeDirectiveArgument, VExpandTransition, LocationService, setDefaultRouterLink } from '@fastkit/vue-utils';
6
4
  import { inject, computed, provide, defineComponent, createVNode, mergeProps, isVNode, cloneVNode, ref, watch, withDirectives, createTextVNode, Fragment, vShow, onBeforeUpdate, vModelSelect, onMounted, onBeforeUnmount, Transition } from 'vue';
5
+ import { useRouter, RouterLink, useLink, useRoute } from 'vue-router';
6
+ import { createPropsOptions as createPropsOptions$1, defineSlotsProps as defineSlotsProps$1, renderSlotOrEmpty as renderSlotOrEmpty$1, navigationableInheritProps, VLink, isFragment, rawNumberPropType, resolveNumberish, resizeDirectiveArgument, VExpandTransition, LocationService, setDefaultRouterLink } from '@fastkit/vue-utils';
7
7
  import { useScopeColorClass, colorSchemeProps, useColorClasses, toScopeColorClass } from '@fastkit/vue-color-scheme';
8
8
  import { VProgressCircular } from '@fastkit/vue-loading';
9
9
  export * from '@fastkit/vue-loading';
10
10
  export { ICON_NAMES } from '@fastkit/icon-font';
11
11
  import { isPromise } from '@fastkit/helpers';
12
12
  import { VAppContainer, VAppLayoutControl } from '@fastkit/vue-app-layout';
13
+ import { createTextableProps, createTextableEmits, TextableControl } from '@fastkit/vue-form-control';
13
14
  import { useEditor, EditorContent, BubbleMenu } from '@tiptap/vue-3';
14
15
  import StarterKit from '@tiptap/starter-kit';
16
+ import { BulletList } from '@tiptap/extension-bullet-list';
17
+ import { Bold } from '@tiptap/extension-bold';
18
+ import { Italic } from '@tiptap/extension-italic';
19
+ import { Underline } from '@tiptap/extension-underline';
20
+ import { History } from '@tiptap/extension-history';
21
+ import { Link } from '@tiptap/extension-link';
22
+ import { validateIf, url } from '@fastkit/rules';
23
+ import { OrderedList } from '@tiptap/extension-ordered-list';
15
24
  import { getDocumentScroller as getDocumentScroller$1 } from '@fastkit/vue-scroller';
16
25
 
17
26
  const CONTROL_SIZES = ['sm', 'md', 'lg'];
@@ -23,6 +32,7 @@ const VuiControlFieldInjectionKey = Symbol();
23
32
  const VuiColorProviderInjectionKey = Symbol();
24
33
  const VUI_TEXT_FIELD_SYMBOL = 'vui-text-field';
25
34
  const VUI_TEXTAREA_SYMBOL = 'vui-textarea';
35
+ const VUI_WYSIWYG_EDITOR_SYMBOL = 'vui-wysiwyg-editor';
26
36
  const VUI_SELECT_SYMBOL = 'vui-select';
27
37
  const VUI_OPTION_SYMBOL = 'vui-option';
28
38
  const VUI_CHECKBOX_GROUP_SYMBOL = 'vui-checkbox-group';
@@ -524,7 +534,13 @@ const VButtonGroup = defineComponent({
524
534
  setup(props, ctx) {
525
535
  return () => {
526
536
  let buttonLength = 0;
527
- const children = (renderSlotOrEmpty$1(ctx.slots) || []).map(node => {
537
+ let tmp = renderSlotOrEmpty$1(ctx.slots) || [];
538
+
539
+ if (tmp.length === 1 && isFragment(tmp[0])) {
540
+ tmp = tmp[0].children;
541
+ }
542
+
543
+ const children = tmp.map(node => {
528
544
  if (!isVNode(node) || node.type !== VButton) {
529
545
  return {
530
546
  isButton: false,
@@ -537,16 +553,7 @@ const VButtonGroup = defineComponent({
537
553
  isButton: true,
538
554
  node
539
555
  };
540
- }); // const children = renderSlotOrEmpty(ctx.slots) || [];
541
- // const $children = children.map((child) => {
542
- // if (!isVNode(child) || child.type !== VButton) return child;
543
- // const $child = cloneVNode(child, {
544
- // ...props,
545
- // ...child.props,
546
- // });
547
- // return $child;
548
- // });
549
-
556
+ });
550
557
  let buttonIndex = 0;
551
558
  const $children = children.map(child => {
552
559
  if (child.isButton) {
@@ -574,7 +581,7 @@ const VButtonGroup = defineComponent({
574
581
 
575
582
  });
576
583
 
577
- function _isSlot$c(s) {
584
+ function _isSlot$d(s) {
578
585
  return typeof s === 'function' || Object.prototype.toString.call(s) === '[object Object]' && !isVNode(s);
579
586
  }
580
587
 
@@ -822,7 +829,7 @@ const VPagination = defineComponent({
822
829
  "class": classes,
823
830
  "to": to,
824
831
  "key": key
825
- }, _isSlot$c(children) ? children : {
832
+ }, _isSlot$d(children) ? children : {
826
833
  default: () => [children]
827
834
  });
828
835
  } else {
@@ -977,7 +984,7 @@ const VDrawerLayout = defineComponent({
977
984
 
978
985
  });
979
986
 
980
- function _isSlot$b(s) {
987
+ function _isSlot$c(s) {
981
988
  return typeof s === 'function' || Object.prototype.toString.call(s) === '[object Object]' && !isVNode(s);
982
989
  }
983
990
 
@@ -1012,7 +1019,7 @@ const VHero = defineComponent({
1012
1019
  }, {
1013
1020
  default: () => [createVNode(HTagName, {
1014
1021
  "class": "v-hero__title"
1015
- }, _isSlot$b(_slot = renderSlotOrEmpty$1(ctx.slots, 'default')) ? _slot : {
1022
+ }, _isSlot$c(_slot = renderSlotOrEmpty$1(ctx.slots, 'default')) ? _slot : {
1016
1023
  default: () => [_slot]
1017
1024
  })]
1018
1025
  })]
@@ -1022,7 +1029,7 @@ const VHero = defineComponent({
1022
1029
 
1023
1030
  });
1024
1031
 
1025
- function _isSlot$a(s) {
1032
+ function _isSlot$b(s) {
1026
1033
  return typeof s === 'function' || Object.prototype.toString.call(s) === '[object Object]' && !isVNode(s);
1027
1034
  }
1028
1035
 
@@ -1057,7 +1064,7 @@ function renderNavigationItemInput(input, extraProps) {
1057
1064
  } = resolveNavigationItemInput(input);
1058
1065
  return createVNode(VNavigationItem, { ...props,
1059
1066
  ...extraProps
1060
- }, _isSlot$a(label) ? label : {
1067
+ }, _isSlot$b(label) ? label : {
1061
1068
  default: () => [label]
1062
1069
  });
1063
1070
  }
@@ -1210,7 +1217,7 @@ const VNavigationItem = defineComponent({
1210
1217
  "class": ['v-navigation-item', classes.value],
1211
1218
  "onClick": onClick,
1212
1219
  "onChangeActive": onChangeActive
1213
- }), _isSlot$a(_slot = renderSlotOrEmpty$1(ctx.slots, 'default')) ? _slot : {
1220
+ }), _isSlot$b(_slot = renderSlotOrEmpty$1(ctx.slots, 'default')) ? _slot : {
1214
1221
  default: () => [_slot]
1215
1222
  }), _children && createVNode(VExpandTransition, null, {
1216
1223
  default: () => [withDirectives(createVNode("div", {
@@ -1390,7 +1397,7 @@ const VCheckbox = defineComponent({
1390
1397
 
1391
1398
  });
1392
1399
 
1393
- function _isSlot$9(s) {
1400
+ function _isSlot$a(s) {
1394
1401
  return typeof s === 'function' || Object.prototype.toString.call(s) === '[object Object]' && !isVNode(s);
1395
1402
  }
1396
1403
 
@@ -1402,7 +1409,7 @@ const VCheckboxGroup = defineFormSelectorComponent({
1402
1409
  itemRenderer: ({
1403
1410
  attrs,
1404
1411
  slots
1405
- }) => createVNode(VCheckbox, attrs, _isSlot$9(slots) ? slots : {
1412
+ }) => createVNode(VCheckbox, attrs, _isSlot$a(slots) ? slots : {
1406
1413
  default: () => [slots]
1407
1414
  })
1408
1415
  });
@@ -1454,7 +1461,7 @@ const VRadio = defineComponent({
1454
1461
 
1455
1462
  });
1456
1463
 
1457
- function _isSlot$8(s) {
1464
+ function _isSlot$9(s) {
1458
1465
  return typeof s === 'function' || Object.prototype.toString.call(s) === '[object Object]' && !isVNode(s);
1459
1466
  }
1460
1467
 
@@ -1465,7 +1472,7 @@ const VRadioGroup = defineFormSelectorComponent({
1465
1472
  itemRenderer: ({
1466
1473
  attrs,
1467
1474
  slots
1468
- }) => createVNode(VRadio, attrs, _isSlot$8(slots) ? slots : {
1475
+ }) => createVNode(VRadio, attrs, _isSlot$9(slots) ? slots : {
1469
1476
  default: () => [slots]
1470
1477
  })
1471
1478
  });
@@ -1527,7 +1534,7 @@ const VSwitch = defineComponent({
1527
1534
 
1528
1535
  });
1529
1536
 
1530
- function _isSlot$7(s) {
1537
+ function _isSlot$8(s) {
1531
1538
  return typeof s === 'function' || Object.prototype.toString.call(s) === '[object Object]' && !isVNode(s);
1532
1539
  }
1533
1540
 
@@ -1539,7 +1546,7 @@ const VSwitchGroup = defineFormSelectorComponent({
1539
1546
  itemRenderer: ({
1540
1547
  attrs,
1541
1548
  slots
1542
- }) => createVNode(VSwitch, attrs, _isSlot$7(slots) ? slots : {
1549
+ }) => createVNode(VSwitch, attrs, _isSlot$8(slots) ? slots : {
1543
1550
  default: () => [slots]
1544
1551
  })
1545
1552
  });
@@ -1922,15 +1929,20 @@ const {
1922
1929
  props: props$2,
1923
1930
  emits: emits$2
1924
1931
  } = createTextInputSettings();
1925
- const VTextField = defineComponent({
1926
- name: 'VTextField',
1927
- props: { ...props$2,
1932
+
1933
+ function createTextFieldProps() {
1934
+ return { ...props$2,
1928
1935
  ...createFormControlProps(),
1929
1936
  ...createControlFieldProps(),
1930
1937
  ...createControlFieldProviderProps(),
1931
1938
  ...createControlProps(),
1932
1939
  ...defineSlotsProps()
1933
- },
1940
+ };
1941
+ }
1942
+
1943
+ const VTextField = defineComponent({
1944
+ name: 'VTextField',
1945
+ props: createTextFieldProps(),
1934
1946
  emits: emits$2,
1935
1947
 
1936
1948
  setup(props, ctx) {
@@ -2039,86 +2051,377 @@ const VTextarea = defineComponent({
2039
2051
 
2040
2052
  });
2041
2053
 
2054
+ function resolveRawWysiwygEditorTool(raw, vui) {
2055
+ return typeof raw === 'function' ? raw(vui) : raw;
2056
+ }
2057
+ function resolveRawWysiwygEditorTools(raws, vui) {
2058
+ const tools = [];
2059
+ const extensions = [];
2060
+ raws.forEach((raw) => {
2061
+ let resolved = resolveRawWysiwygEditorTool(raw, vui);
2062
+ if (!Array.isArray(resolved)) {
2063
+ resolved = [resolved];
2064
+ }
2065
+ resolved.forEach((tool) => {
2066
+ tools.push(tool);
2067
+ if (tool.extensions) {
2068
+ extensions.push(...tool.extensions);
2069
+ }
2070
+ });
2071
+ });
2072
+ return {
2073
+ tools,
2074
+ extensions,
2075
+ };
2076
+ }
2077
+
2078
+ function _isSlot$7(s) {
2079
+ return typeof s === 'function' || Object.prototype.toString.call(s) === '[object Object]' && !isVNode(s);
2080
+ }
2081
+
2042
2082
  const VWysiwygEditor = defineComponent({
2043
2083
  name: 'VWysiwygEditor',
2044
2084
  props: { // ...props,
2085
+ ...createTextableProps(),
2045
2086
  ...createFormControlProps(),
2046
2087
  ...createControlFieldProps(),
2047
2088
  ...createControlFieldProviderProps(),
2048
2089
  ...createControlProps(),
2049
- ...defineSlotsProps()
2090
+ ...defineSlotsProps(),
2091
+ tools: {
2092
+ type: Array,
2093
+ default: () => []
2094
+ }
2095
+ },
2096
+ emits: { ...createTextableEmits()
2050
2097
  },
2051
2098
 
2052
- // emits,
2053
2099
  setup(props, ctx) {
2100
+ const vui = useVui();
2101
+ const textRef = ref('');
2102
+ const toolButtonActiveColor = vui.setting('primaryScope');
2103
+ const wysiwygSettings = computed(() => resolveRawWysiwygEditorTools(props.tools, vui));
2104
+ const control = useControl(props);
2105
+ useControlField(props);
2106
+ const inputControl = new TextableControl(props, ctx, {
2107
+ nodeType: VUI_WYSIWYG_EDITOR_SYMBOL,
2108
+ validationValue: () => textRef.value
2109
+ });
2110
+ const extensions = [StarterKit.configure({
2111
+ bold: false,
2112
+ bulletList: false,
2113
+ orderedList: false,
2114
+ history: false,
2115
+ italic: false
2116
+ }), ...wysiwygSettings.value.extensions];
2117
+
2118
+ const updateEditable = () => {
2119
+ if (!editor.value) return;
2120
+ editor.value.setEditable(inputControl.canOperation);
2121
+ };
2122
+
2123
+ watch(() => inputControl.canOperation, updateEditable);
2054
2124
  const editor = useEditor({
2055
- content: '<p>I’m running Tiptap with Vue.js. 🎉</p>',
2056
- extensions: [StarterKit]
2057
- }); // const vui = useVui();
2058
- // const inputControl = useTiptapControl(props, ctx, {
2059
- // nodeType: VUI_TEXTAREA_SYMBOL,
2060
- // defaultRows: vui.tiptapRows,
2061
- // });
2062
- // const control = useControl(props);
2063
- // useControlField(props);
2125
+ onCreate: ({
2126
+ editor
2127
+ }) => {
2128
+ textRef.value = editor.getText();
2129
+ updateEditable();
2130
+ },
2131
+ onFocus: ctx => {
2132
+ inputControl.focusHandler(ctx.event);
2133
+ },
2134
+ onBlur: ctx => {
2135
+ inputControl.blurHandler(ctx.event);
2136
+ },
2137
+ onUpdate: ev => {
2138
+ inputControl.value = ev.editor.getHTML();
2139
+ textRef.value = ev.editor.getText();
2140
+ },
2141
+ autofocus: props.autofocus,
2142
+ content: props.modelValue,
2143
+ extensions,
2144
+ editorProps: {
2145
+ attributes: {
2146
+ class: 'v-wysiwyg-editor__input__prose'
2147
+ }
2148
+ }
2149
+ });
2064
2150
 
2065
- return {
2066
- editor // ...inputControl.expose(),
2067
- // ...control,
2151
+ const focus = (position, options) => {
2152
+ return editor.value.chain().focus(position, options);
2153
+ };
2154
+
2155
+ const blur = () => {
2156
+ return editor.value.chain().blur();
2157
+ };
2158
+
2159
+ const wysiwygContext = computed(() => ({
2160
+ vui,
2161
+ editor: editor.value
2162
+ }));
2163
+
2164
+ const createTools = (floating = false) => {
2165
+ let _slot;
2166
+
2167
+ const {
2168
+ value: settings
2169
+ } = wysiwygSettings;
2170
+ const {
2171
+ value: context
2172
+ } = wysiwygContext;
2173
+ const tools = floating ? settings.tools.filter(t => !!t.floating) : settings.tools;
2174
+ const _editor = editor.value;
2175
+ const variant = vui.setting(floating ? 'containedVariant' : 'plainVariant');
2176
+ return createVNode(VButtonGroup, {
2177
+ "variant": variant
2178
+ }, _isSlot$7(_slot = tools.map(({
2179
+ key,
2180
+ icon,
2181
+ onClick,
2182
+ disabled,
2183
+ active
2184
+ }) => {
2185
+ const isActive = !!_editor && resolveContextableValue(context, active);
2186
+ const isDisabled = !inputControl.canOperation || !!_editor && resolveContextableValue(context, disabled);
2187
+ let iconName;
2188
+
2189
+ if (typeof icon === 'function') {
2190
+ if (_editor) {
2191
+ iconName = icon(context);
2192
+ }
2193
+ } else {
2194
+ iconName = icon;
2195
+ }
2068
2196
 
2197
+ if (!iconName) return;
2198
+ return createVNode(VButton, {
2199
+ "key": key,
2200
+ "icon": iconName,
2201
+ "onClick": ev => onClick(context, ev),
2202
+ "color": isActive ? toolButtonActiveColor : undefined,
2203
+ "disabled": isDisabled
2204
+ }, null);
2205
+ })) ? _slot : {
2206
+ default: () => [_slot]
2207
+ });
2208
+ };
2209
+
2210
+ return {
2211
+ editor,
2212
+ ...inputControl.expose(),
2213
+ ...control,
2214
+ focus,
2215
+ blur,
2216
+ createTools
2069
2217
  };
2070
2218
  },
2071
2219
 
2072
2220
  render() {
2073
2221
  return createVNode(VFormControl, {
2074
2222
  "nodeControl": this.nodeControl,
2223
+ "focused": this.nodeControl.focused,
2224
+ "class": ['v-wysiwyg-editor', this.classes],
2075
2225
  "label": this.label,
2076
2226
  "hint": this.hint,
2077
2227
  "hiddenInfo": this.hiddenInfo,
2078
- "onClickLabel": ev => {// this.focus();
2228
+ "onClickLabel": ev => {
2229
+ this.focus('start', {
2230
+ scrollIntoView: true
2231
+ });
2079
2232
  }
2080
2233
  }, { ...this.$slots,
2081
- default: () => createVNode(VControlField, {
2082
- "class": "v-wysiwyg-editor__input",
2083
- "autoHeight": true,
2084
- "startAdornment": this.startAdornment,
2085
- "endAdornment": this.endAdornment
2086
- }, { ...this.$slots,
2087
- default: () => {
2088
- const {
2089
- editor
2090
- } = this;
2091
- return createVNode(Fragment, null, [createVNode(EditorContent, {
2092
- "class": "v-wysiwyg-editor__input__element wysiwyg",
2093
- "editor": editor
2094
- }, null), !!editor && createVNode(BubbleMenu, {
2095
- "class": "v-wysiwyg-editor__bubble-menu",
2096
- "editor": editor
2097
- }, {
2098
- default: () => [createVNode(VButton, {
2099
- "size": "sm",
2100
- "onClick": () => {
2101
- editor.chain().focus().toggleBold().run();
2102
- }
2103
- }, {
2104
- default: () => [createTextVNode("Bold")]
2105
- })]
2106
- })]);
2107
- } // this.tiptapControl.createInputElement({
2108
- // class: 'v-wysiwyg-editor__input__element',
2109
- // }),
2110
-
2111
- }) // infoAppends: () => {
2112
- // const { counterResult } = this;
2113
- // if (!counterResult) return;
2114
- // return <VTextCounter {...counterResult} />;
2115
- // },
2116
-
2234
+ default: () => {
2235
+ const {
2236
+ editor
2237
+ } = this;
2238
+ return createVNode(Fragment, null, [!this.isReadonly && this.createTools(), createVNode(VControlField, {
2239
+ "class": "v-wysiwyg-editor__input",
2240
+ "autoHeight": true,
2241
+ "startAdornment": this.startAdornment,
2242
+ "endAdornment": this.endAdornment
2243
+ }, { ...this.$slots,
2244
+ default: () => {
2245
+ let _slot2;
2246
+
2247
+ return createVNode(Fragment, null, [createVNode(EditorContent, {
2248
+ "class": "v-wysiwyg-editor__input__element wysiwyg",
2249
+ "editor": editor
2250
+ }, null), !!editor && !this.isReadonly && createVNode(BubbleMenu, {
2251
+ "class": "v-wysiwyg-editor__bubble-menu",
2252
+ "editor": editor
2253
+ }, _isSlot$7(_slot2 = this.createTools(true)) ? _slot2 : {
2254
+ default: () => [_slot2]
2255
+ })]);
2256
+ }
2257
+ })]);
2258
+ },
2259
+ infoAppends: () => {
2260
+ const {
2261
+ counterResult
2262
+ } = this;
2263
+ if (!counterResult) return;
2264
+ return createVNode(VTextCounter, counterResult, null);
2265
+ }
2117
2266
  });
2118
2267
  }
2119
2268
 
2120
2269
  });
2121
2270
 
2271
+ function resolveContextableValue(ctx, source) {
2272
+ return typeof source === 'function' ? source(ctx) : source;
2273
+ }
2274
+
2275
+ const WysiwygBulletListTool = (vui, options) => {
2276
+ const tool = {
2277
+ key: 'bulletList',
2278
+ icon: vui.icon('editorformatListBulleted'),
2279
+ active: ({ editor }) => editor.isActive('bulletList'),
2280
+ onClick: ({ editor }) => {
2281
+ editor.chain().focus().toggleBulletList().run();
2282
+ },
2283
+ floating: true,
2284
+ extensions: [BulletList.configure(options)],
2285
+ };
2286
+ return tool;
2287
+ };
2288
+
2289
+ const WysiwygFormatBoldTool = (vui, options) => {
2290
+ const tool = {
2291
+ key: 'formatBold',
2292
+ icon: vui.icon('editorformatBold'),
2293
+ active: ({ editor }) => editor.isActive('bold'),
2294
+ onClick: ({ editor }) => {
2295
+ editor.chain().focus().toggleBold().run();
2296
+ },
2297
+ floating: true,
2298
+ extensions: [Bold.configure(options)],
2299
+ };
2300
+ return tool;
2301
+ };
2302
+
2303
+ const WysiwygFormatItalicTool = (vui, options) => {
2304
+ const tool = {
2305
+ key: 'formatItalic',
2306
+ icon: vui.icon('editorformatItalic'),
2307
+ active: ({ editor }) => editor.isActive('italic'),
2308
+ onClick: ({ editor }) => {
2309
+ editor.chain().focus().toggleItalic().run();
2310
+ },
2311
+ floating: true,
2312
+ extensions: [Italic.configure(options)],
2313
+ };
2314
+ return tool;
2315
+ };
2316
+
2317
+ const WysiwygFormatUnderlineTool = (vui, options) => {
2318
+ const tool = {
2319
+ key: 'formatUnderline',
2320
+ icon: vui.icon('editorformatUnderline'),
2321
+ active: ({ editor }) => editor.isActive('underline'),
2322
+ onClick: ({ editor }) => {
2323
+ editor.chain().focus().toggleUnderline().run();
2324
+ },
2325
+ floating: true,
2326
+ extensions: [Underline.configure(options)],
2327
+ };
2328
+ return tool;
2329
+ };
2330
+
2331
+ const WysiwygHistoryTool = (vui, options) => {
2332
+ const undo = {
2333
+ key: 'history-undo',
2334
+ icon: vui.icon('editorUndo'),
2335
+ disabled: ({ editor }) => !editor.can().undo(),
2336
+ onClick: ({ editor }) => {
2337
+ editor.chain().focus().undo().run();
2338
+ },
2339
+ extensions: [History.configure(options)],
2340
+ };
2341
+ const redo = {
2342
+ key: 'history-redo',
2343
+ icon: vui.icon('editorRedo'),
2344
+ disabled: ({ editor }) => !editor.can().redo(),
2345
+ onClick: ({ editor }) => {
2346
+ editor.chain().focus().redo().run();
2347
+ },
2348
+ };
2349
+ return [undo, redo];
2350
+ };
2351
+
2352
+ const WysiwygLinkTool = (vui, options) => {
2353
+ const tool = {
2354
+ key: 'link',
2355
+ icon: ({ editor }) => {
2356
+ return vui.icon(editor.isActive('link') ? 'editorLinkOff' : 'editorLink');
2357
+ },
2358
+ // icon: vui.icon('editorLink'),
2359
+ active: ({ editor }) => editor.isActive('link'),
2360
+ onClick: async ({ vui, editor }) => {
2361
+ const { href = '' } = editor.getAttributes('link');
2362
+ const result = await vui.prompt({
2363
+ input: {
2364
+ label: 'Link URL',
2365
+ rules: [validateIf, url],
2366
+ initialValue: href,
2367
+ size: 'sm',
2368
+ autofocus: true,
2369
+ },
2370
+ });
2371
+ if (result === undefined || result === false) {
2372
+ return;
2373
+ }
2374
+ const range = editor.chain().focus().extendMarkRange('link');
2375
+ console.log(range);
2376
+ if (!result) {
2377
+ range.unsetLink().run();
2378
+ }
2379
+ else {
2380
+ range
2381
+ .setLink({
2382
+ href: result,
2383
+ })
2384
+ .run();
2385
+ }
2386
+ },
2387
+ floating: true,
2388
+ extensions: [
2389
+ Link.configure({
2390
+ openOnClick: false,
2391
+ ...options,
2392
+ }),
2393
+ ],
2394
+ };
2395
+ return tool;
2396
+ };
2397
+
2398
+ const WysiwygOrderedListTool = (vui, options) => {
2399
+ const tool = {
2400
+ key: 'orderedList',
2401
+ icon: vui.icon('editorformatListNumbered'),
2402
+ active: ({ editor }) => editor.isActive('orderedList'),
2403
+ onClick: ({ editor }) => {
2404
+ editor.chain().focus().toggleOrderedList().run();
2405
+ },
2406
+ floating: true,
2407
+ extensions: [OrderedList.configure(options)],
2408
+ };
2409
+ return tool;
2410
+ };
2411
+
2412
+ const WysiwygTextColorTool = (vui) => {
2413
+ const tool = {
2414
+ key: 'textColor',
2415
+ icon: vui.icon('editorTextColor'),
2416
+ // icon: (gen) => vui.icon('editorTextColor'),
2417
+ onClick: (ctx) => {
2418
+ ctx.vui.alert('ok');
2419
+ },
2420
+ floating: true,
2421
+ };
2422
+ return tool;
2423
+ };
2424
+
2122
2425
  const {
2123
2426
  props,
2124
2427
  emits
@@ -2129,7 +2432,8 @@ const VForm = defineComponent({
2129
2432
  name: 'VForm',
2130
2433
  props: { ...props,
2131
2434
  ...createControlProps(),
2132
- ...defineSlotsProps()
2435
+ ...defineSlotsProps(),
2436
+ disableAutoScroll: Boolean
2133
2437
  },
2134
2438
  emits,
2135
2439
 
@@ -2138,6 +2442,7 @@ const VForm = defineComponent({
2138
2442
  const nodeControl = useForm(props, ctx, {
2139
2443
  nodeType: VUI_FORM_SYMBOL,
2140
2444
  onAutoValidateError: () => {
2445
+ if (props.disableAutoScroll) return;
2141
2446
  const scroller = getDocumentScroller();
2142
2447
  const {
2143
2448
  firstInvalidEl
@@ -3529,53 +3834,138 @@ const VToolbarTitle = defineComponent({
3529
3834
 
3530
3835
  });
3531
3836
 
3532
- const DEFAULT_AUTO_SCROLL_TO_ELEMENT_OFFSET_TOP = -20;
3533
- const DEFAULT_TEXTAREA_ROWS = 3;
3534
- class VuiService {
3535
- options;
3536
- selectionSeparator;
3537
- autoScrollToElementOffsetTop;
3538
- textareaRows;
3539
- requiredChip;
3540
- router;
3541
- location;
3542
- constructor(options) {
3543
- this.options = options;
3544
- this.configure();
3545
- const { selectionSeparator = () => ', ', autoScrollToElementOffsetTop = DEFAULT_AUTO_SCROLL_TO_ELEMENT_OFFSET_TOP, textareaRows = DEFAULT_TEXTAREA_ROWS, requiredChip = () => '*', } = options;
3546
- this.selectionSeparator = selectionSeparator;
3547
- this.autoScrollToElementOffsetTop = autoScrollToElementOffsetTop;
3548
- this.textareaRows = textareaRows;
3549
- this.requiredChip = requiredChip;
3550
- this.router = options.router;
3551
- this.location = new LocationService({
3552
- router: this.router,
3553
- });
3554
- }
3555
- configure(options) {
3556
- options && Object.assign(this.options, options);
3557
- setDefaultRouterLink(this.getRouterLink());
3558
- }
3559
- getRouterLink() {
3560
- return this.options.RouterLink || RouterLink;
3561
- }
3562
- setting(key) {
3563
- return this.options.uiSettings[key];
3564
- }
3565
- icon(iconType) {
3566
- return this.options.icons[iconType];
3567
- }
3568
- getAutoScrollToElementOffsetTop() {
3569
- let { autoScrollToElementOffsetTop } = this;
3570
- if (typeof autoScrollToElementOffsetTop === 'function') {
3571
- autoScrollToElementOffsetTop = autoScrollToElementOffsetTop();
3572
- }
3573
- return autoScrollToElementOffsetTop || 0;
3574
- }
3575
- getRequiredChip() {
3576
- const { requiredChip } = this;
3577
- return requiredChip && requiredChip();
3578
- }
3837
+ const DEFAULT_AUTO_SCROLL_TO_ELEMENT_OFFSET_TOP = -20;
3838
+ const DEFAULT_TEXTAREA_ROWS = 3;
3839
+ class VuiService {
3840
+ constructor(options, stackService) {
3841
+ this.options = options;
3842
+ this.configure();
3843
+ const {
3844
+ selectionSeparator = () => ', ',
3845
+ autoScrollToElementOffsetTop = DEFAULT_AUTO_SCROLL_TO_ELEMENT_OFFSET_TOP,
3846
+ textareaRows = DEFAULT_TEXTAREA_ROWS,
3847
+ requiredChip = () => '*'
3848
+ } = options;
3849
+ this.selectionSeparator = selectionSeparator;
3850
+ this.autoScrollToElementOffsetTop = autoScrollToElementOffsetTop;
3851
+ this.textareaRows = textareaRows;
3852
+ this.requiredChip = requiredChip;
3853
+ this.router = options.router;
3854
+ this.location = new LocationService({
3855
+ router: this.router
3856
+ });
3857
+ this.stack = stackService;
3858
+ }
3859
+
3860
+ configure(options) {
3861
+ options && Object.assign(this.options, options);
3862
+ setDefaultRouterLink(this.getRouterLink());
3863
+ }
3864
+
3865
+ getRouterLink() {
3866
+ return this.options.RouterLink || RouterLink;
3867
+ }
3868
+
3869
+ setting(key) {
3870
+ return this.options.uiSettings[key];
3871
+ }
3872
+
3873
+ icon(iconType) {
3874
+ return this.options.icons[iconType];
3875
+ }
3876
+
3877
+ getAutoScrollToElementOffsetTop() {
3878
+ let {
3879
+ autoScrollToElementOffsetTop
3880
+ } = this;
3881
+
3882
+ if (typeof autoScrollToElementOffsetTop === 'function') {
3883
+ autoScrollToElementOffsetTop = autoScrollToElementOffsetTop();
3884
+ }
3885
+
3886
+ return autoScrollToElementOffsetTop || 0;
3887
+ }
3888
+
3889
+ getRequiredChip() {
3890
+ const {
3891
+ requiredChip
3892
+ } = this;
3893
+ return requiredChip && requiredChip();
3894
+ }
3895
+
3896
+ dialog(...args) {
3897
+ return this.stack.dialog(...args);
3898
+ }
3899
+
3900
+ alert(...args) {
3901
+ return this.stack.alert(...args);
3902
+ }
3903
+
3904
+ confirm(...args) {
3905
+ return this.stack.confirm(...args);
3906
+ }
3907
+
3908
+ snackbar(...args) {
3909
+ return this.stack.snackbar(...args);
3910
+ }
3911
+
3912
+ prompt(rawOptions = {}) {
3913
+ const options = typeof rawOptions === 'string' ? {
3914
+ input: {
3915
+ label: rawOptions
3916
+ }
3917
+ } : { ...rawOptions
3918
+ };
3919
+ options.input = { ...options.input
3920
+ };
3921
+ options.dense = true;
3922
+ let {
3923
+ initialValue: value = ''
3924
+ } = options.input;
3925
+ const {
3926
+ size
3927
+ } = options.input;
3928
+ delete options.input.initialValue;
3929
+ let form;
3930
+ options.actions = options.actions || [this.stack.action('cancel', undefined, {
3931
+ size
3932
+ }), this.stack.action('ok', undefined, {
3933
+ size,
3934
+ onClick: () => {
3935
+ if (form) {
3936
+ const ev = new Event('submit');
3937
+ form.handleSubmit(ev);
3938
+ }
3939
+ }
3940
+ })];
3941
+ const resolved = resolveVStackDynamicInput({ ...options,
3942
+ content: stack => {
3943
+ return createVNode(VForm, {
3944
+ "disableAutoScroll": true,
3945
+ "size": size,
3946
+ "onVnodeMounted": vnode => {
3947
+ form = vnode.component.ctx.form;
3948
+ },
3949
+ "onVnodeBeforeUnmount": () => {
3950
+ form = undefined;
3951
+ },
3952
+ "onSubmit": ev => {
3953
+ stack.resolve(value);
3954
+ }
3955
+ }, {
3956
+ default: () => [createVNode(VTextField, mergeProps(options.input, {
3957
+ "modelValue": value,
3958
+ "onChange": ev => {
3959
+ stack.value = ev;
3960
+ value = ev;
3961
+ }
3962
+ }), null)]
3963
+ });
3964
+ }
3965
+ });
3966
+ return this.dialog(resolved);
3967
+ }
3968
+
3579
3969
  }
3580
3970
 
3581
3971
  class VuiPlugin {
@@ -3619,7 +4009,7 @@ class VuiPlugin {
3619
4009
  ...stack
3620
4010
  }); // Vui
3621
4011
 
3622
- const $vui = new VuiService(opts);
4012
+ const $vui = new VuiService(opts, app.config.globalProperties.$vstack);
3623
4013
  app.provide(VuiInjectionKey, $vui);
3624
4014
  app.config.globalProperties.$vui = $vui;
3625
4015
 
@@ -3635,4 +4025,4 @@ function installVuiPlugin(app, opts) {
3635
4025
  return app.use(VuiPlugin, opts);
3636
4026
  }
3637
4027
 
3638
- export { CONTROL_FIELD_VARIANTS, CONTROL_SIZES, PAGINATION_ALIGNS, VApp, VBreadcrumbs, VButton, VButtonGroup, VCard, VCardActions, VCardContent, VCheckbox, VCheckboxGroup, VContentSwitcher, VDataTable, VDrawerLayout, VForm, VHero, VIcon, VListTile, VNavigation, VNavigationItem, VOption, VOptionGroup, VPagination, VPaper, VRadio, VRadioGroup, VSelect, VSwitch, VSwitchGroup, VTabs, VTextField, VTextarea, VToolbar, VToolbarEdge, VToolbarMenu, VToolbarTitle, VUI_CHECKBOX_GROUP_SYMBOL, VUI_CHECKBOX_SYMBOL, VUI_FORM_SYMBOL, VUI_OPTION_SYMBOL, VUI_RADIO_GROUP_SYMBOL, VUI_RADIO_SYMBOL, VUI_SELECT_SYMBOL, VUI_SWITCH_GROUP_SYMBOL, VUI_SWITCH_SYMBOL, VUI_TEXTAREA_SYMBOL, VUI_TEXT_FIELD_SYMBOL, VWysiwygEditor, VuiColorProviderInjectionKey, VuiControlFieldInjectionKey, VuiControlInjectionKey, VuiInjectionKey, VuiPlugin, VuiService, configureDataTableDefaults, createCardProps, createControlFieldProviderProps, createControlProps, createElevationProps, createListTileProps, createNavigationItemProps, createPaperBaseProps, createPaperProps, defineFormSelectorComponent, iconProps, installVuiPlugin, listTileEmits, paginationProps, rawIconProp, renderNavigationItemInput, resolveNavigationItemInput, resolveRawIconProp, useControl, useControlField, useElevation, useVui, useVuiColorProvider, vueButtonProps };
4028
+ export { CONTROL_FIELD_VARIANTS, CONTROL_SIZES, PAGINATION_ALIGNS, VApp, VBreadcrumbs, VButton, VButtonGroup, VCard, VCardActions, VCardContent, VCheckbox, VCheckboxGroup, VContentSwitcher, VDataTable, VDrawerLayout, VForm, VHero, VIcon, VListTile, VNavigation, VNavigationItem, VOption, VOptionGroup, VPagination, VPaper, VRadio, VRadioGroup, VSelect, VSwitch, VSwitchGroup, VTabs, VTextField, VTextarea, VToolbar, VToolbarEdge, VToolbarMenu, VToolbarTitle, VUI_CHECKBOX_GROUP_SYMBOL, VUI_CHECKBOX_SYMBOL, VUI_FORM_SYMBOL, VUI_OPTION_SYMBOL, VUI_RADIO_GROUP_SYMBOL, VUI_RADIO_SYMBOL, VUI_SELECT_SYMBOL, VUI_SWITCH_GROUP_SYMBOL, VUI_SWITCH_SYMBOL, VUI_TEXTAREA_SYMBOL, VUI_TEXT_FIELD_SYMBOL, VUI_WYSIWYG_EDITOR_SYMBOL, VWysiwygEditor, VuiColorProviderInjectionKey, VuiControlFieldInjectionKey, VuiControlInjectionKey, VuiInjectionKey, VuiPlugin, VuiService, WysiwygBulletListTool, WysiwygFormatBoldTool, WysiwygFormatItalicTool, WysiwygFormatUnderlineTool, WysiwygHistoryTool, WysiwygLinkTool, WysiwygOrderedListTool, WysiwygTextColorTool, configureDataTableDefaults, createCardProps, createControlFieldProviderProps, createControlProps, createElevationProps, createListTileProps, createNavigationItemProps, createPaperBaseProps, createPaperProps, defineFormSelectorComponent, iconProps, installVuiPlugin, listTileEmits, paginationProps, rawIconProp, renderNavigationItemInput, resolveNavigationItemInput, resolveRawIconProp, useControl, useControlField, useElevation, useVui, useVuiColorProvider, vueButtonProps };