@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.
@@ -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';
@@ -435,7 +445,8 @@ function resolveRawVButtonIcon(raw, type = 'main') {
435
445
  }, null);
436
446
  }
437
447
 
438
- const vueButtonProps = createPropsOptions$1({ ...colorSchemeProps(),
448
+ const vueButtonProps = createPropsOptions$1({ ...undefined,
449
+ ...colorSchemeProps(),
439
450
  ...navigationableInheritProps,
440
451
  spacer: [Boolean, String],
441
452
  loading: Boolean,
@@ -524,7 +535,13 @@ const VButtonGroup = defineComponent({
524
535
  setup(props, ctx) {
525
536
  return () => {
526
537
  let buttonLength = 0;
527
- const children = (renderSlotOrEmpty$1(ctx.slots) || []).map(node => {
538
+ let tmp = renderSlotOrEmpty$1(ctx.slots) || [];
539
+
540
+ if (tmp.length === 1 && isFragment(tmp[0])) {
541
+ tmp = tmp[0].children;
542
+ }
543
+
544
+ const children = tmp.map(node => {
528
545
  if (!isVNode(node) || node.type !== VButton) {
529
546
  return {
530
547
  isButton: false,
@@ -537,16 +554,7 @@ const VButtonGroup = defineComponent({
537
554
  isButton: true,
538
555
  node
539
556
  };
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
-
557
+ });
550
558
  let buttonIndex = 0;
551
559
  const $children = children.map(child => {
552
560
  if (child.isButton) {
@@ -574,7 +582,7 @@ const VButtonGroup = defineComponent({
574
582
 
575
583
  });
576
584
 
577
- function _isSlot$c(s) {
585
+ function _isSlot$d(s) {
578
586
  return typeof s === 'function' || Object.prototype.toString.call(s) === '[object Object]' && !isVNode(s);
579
587
  }
580
588
 
@@ -822,7 +830,7 @@ const VPagination = defineComponent({
822
830
  "class": classes,
823
831
  "to": to,
824
832
  "key": key
825
- }, _isSlot$c(children) ? children : {
833
+ }, _isSlot$d(children) ? children : {
826
834
  default: () => [children]
827
835
  });
828
836
  } else {
@@ -977,7 +985,7 @@ const VDrawerLayout = defineComponent({
977
985
 
978
986
  });
979
987
 
980
- function _isSlot$b(s) {
988
+ function _isSlot$c(s) {
981
989
  return typeof s === 'function' || Object.prototype.toString.call(s) === '[object Object]' && !isVNode(s);
982
990
  }
983
991
 
@@ -1012,7 +1020,7 @@ const VHero = defineComponent({
1012
1020
  }, {
1013
1021
  default: () => [createVNode(HTagName, {
1014
1022
  "class": "v-hero__title"
1015
- }, _isSlot$b(_slot = renderSlotOrEmpty$1(ctx.slots, 'default')) ? _slot : {
1023
+ }, _isSlot$c(_slot = renderSlotOrEmpty$1(ctx.slots, 'default')) ? _slot : {
1016
1024
  default: () => [_slot]
1017
1025
  })]
1018
1026
  })]
@@ -1022,7 +1030,7 @@ const VHero = defineComponent({
1022
1030
 
1023
1031
  });
1024
1032
 
1025
- function _isSlot$a(s) {
1033
+ function _isSlot$b(s) {
1026
1034
  return typeof s === 'function' || Object.prototype.toString.call(s) === '[object Object]' && !isVNode(s);
1027
1035
  }
1028
1036
 
@@ -1057,7 +1065,7 @@ function renderNavigationItemInput(input, extraProps) {
1057
1065
  } = resolveNavigationItemInput(input);
1058
1066
  return createVNode(VNavigationItem, { ...props,
1059
1067
  ...extraProps
1060
- }, _isSlot$a(label) ? label : {
1068
+ }, _isSlot$b(label) ? label : {
1061
1069
  default: () => [label]
1062
1070
  });
1063
1071
  }
@@ -1210,7 +1218,7 @@ const VNavigationItem = defineComponent({
1210
1218
  "class": ['v-navigation-item', classes.value],
1211
1219
  "onClick": onClick,
1212
1220
  "onChangeActive": onChangeActive
1213
- }), _isSlot$a(_slot = renderSlotOrEmpty$1(ctx.slots, 'default')) ? _slot : {
1221
+ }), _isSlot$b(_slot = renderSlotOrEmpty$1(ctx.slots, 'default')) ? _slot : {
1214
1222
  default: () => [_slot]
1215
1223
  }), _children && createVNode(VExpandTransition, null, {
1216
1224
  default: () => [withDirectives(createVNode("div", {
@@ -1390,7 +1398,7 @@ const VCheckbox = defineComponent({
1390
1398
 
1391
1399
  });
1392
1400
 
1393
- function _isSlot$9(s) {
1401
+ function _isSlot$a(s) {
1394
1402
  return typeof s === 'function' || Object.prototype.toString.call(s) === '[object Object]' && !isVNode(s);
1395
1403
  }
1396
1404
 
@@ -1402,7 +1410,7 @@ const VCheckboxGroup = defineFormSelectorComponent({
1402
1410
  itemRenderer: ({
1403
1411
  attrs,
1404
1412
  slots
1405
- }) => createVNode(VCheckbox, attrs, _isSlot$9(slots) ? slots : {
1413
+ }) => createVNode(VCheckbox, attrs, _isSlot$a(slots) ? slots : {
1406
1414
  default: () => [slots]
1407
1415
  })
1408
1416
  });
@@ -1454,7 +1462,7 @@ const VRadio = defineComponent({
1454
1462
 
1455
1463
  });
1456
1464
 
1457
- function _isSlot$8(s) {
1465
+ function _isSlot$9(s) {
1458
1466
  return typeof s === 'function' || Object.prototype.toString.call(s) === '[object Object]' && !isVNode(s);
1459
1467
  }
1460
1468
 
@@ -1465,7 +1473,7 @@ const VRadioGroup = defineFormSelectorComponent({
1465
1473
  itemRenderer: ({
1466
1474
  attrs,
1467
1475
  slots
1468
- }) => createVNode(VRadio, attrs, _isSlot$8(slots) ? slots : {
1476
+ }) => createVNode(VRadio, attrs, _isSlot$9(slots) ? slots : {
1469
1477
  default: () => [slots]
1470
1478
  })
1471
1479
  });
@@ -1527,7 +1535,7 @@ const VSwitch = defineComponent({
1527
1535
 
1528
1536
  });
1529
1537
 
1530
- function _isSlot$7(s) {
1538
+ function _isSlot$8(s) {
1531
1539
  return typeof s === 'function' || Object.prototype.toString.call(s) === '[object Object]' && !isVNode(s);
1532
1540
  }
1533
1541
 
@@ -1539,7 +1547,7 @@ const VSwitchGroup = defineFormSelectorComponent({
1539
1547
  itemRenderer: ({
1540
1548
  attrs,
1541
1549
  slots
1542
- }) => createVNode(VSwitch, attrs, _isSlot$7(slots) ? slots : {
1550
+ }) => createVNode(VSwitch, attrs, _isSlot$8(slots) ? slots : {
1543
1551
  default: () => [slots]
1544
1552
  })
1545
1553
  });
@@ -1922,15 +1930,20 @@ const {
1922
1930
  props: props$2,
1923
1931
  emits: emits$2
1924
1932
  } = createTextInputSettings();
1925
- const VTextField = defineComponent({
1926
- name: 'VTextField',
1927
- props: { ...props$2,
1933
+
1934
+ function createTextFieldProps() {
1935
+ return { ...props$2,
1928
1936
  ...createFormControlProps(),
1929
1937
  ...createControlFieldProps(),
1930
1938
  ...createControlFieldProviderProps(),
1931
1939
  ...createControlProps(),
1932
1940
  ...defineSlotsProps()
1933
- },
1941
+ };
1942
+ }
1943
+
1944
+ const VTextField = defineComponent({
1945
+ name: 'VTextField',
1946
+ props: createTextFieldProps(),
1934
1947
  emits: emits$2,
1935
1948
 
1936
1949
  setup(props, ctx) {
@@ -2039,86 +2052,396 @@ const VTextarea = defineComponent({
2039
2052
 
2040
2053
  });
2041
2054
 
2055
+ function resolveRawWysiwygEditorTool(raw, vui) {
2056
+ return typeof raw === 'function' ? raw(vui) : raw;
2057
+ }
2058
+ function resolveRawWysiwygEditorTools(raws, vui) {
2059
+ const tools = [];
2060
+ const extensions = [];
2061
+ raws.forEach((raw) => {
2062
+ let resolved = resolveRawWysiwygEditorTool(raw, vui);
2063
+ if (!Array.isArray(resolved)) {
2064
+ resolved = [resolved];
2065
+ }
2066
+ resolved.forEach((tool) => {
2067
+ tools.push(tool);
2068
+ if (tool.extensions) {
2069
+ extensions.push(...tool.extensions);
2070
+ }
2071
+ });
2072
+ });
2073
+ return {
2074
+ tools,
2075
+ extensions,
2076
+ };
2077
+ }
2078
+
2079
+ function _isSlot$7(s) {
2080
+ return typeof s === 'function' || Object.prototype.toString.call(s) === '[object Object]' && !isVNode(s);
2081
+ }
2082
+
2042
2083
  const VWysiwygEditor = defineComponent({
2043
2084
  name: 'VWysiwygEditor',
2044
2085
  props: { // ...props,
2086
+ ...createTextableProps(),
2045
2087
  ...createFormControlProps(),
2046
2088
  ...createControlFieldProps(),
2047
2089
  ...createControlFieldProviderProps(),
2048
2090
  ...createControlProps(),
2049
- ...defineSlotsProps()
2091
+ ...defineSlotsProps(),
2092
+ tools: {
2093
+ type: Array,
2094
+ default: () => []
2095
+ },
2096
+ floatingToolbar: Boolean,
2097
+ disabledMinHeight: Boolean,
2098
+ disabledMaxHeight: Boolean
2099
+ },
2100
+ emits: { ...createTextableEmits()
2050
2101
  },
2051
2102
 
2052
- // emits,
2053
2103
  setup(props, ctx) {
2104
+ const vui = useVui();
2105
+ const textRef = ref('');
2106
+ const toolButtonActiveColor = vui.setting('primaryScope');
2107
+ const wysiwygSettings = computed(() => resolveRawWysiwygEditorTools(props.tools, vui));
2108
+ const control = useControl(props);
2109
+ useControlField(props);
2110
+ const inputControl = new TextableControl(props, ctx, {
2111
+ nodeType: VUI_WYSIWYG_EDITOR_SYMBOL,
2112
+ validationValue: () => textRef.value
2113
+ });
2114
+ const extensions = [StarterKit.configure({
2115
+ bold: false,
2116
+ bulletList: false,
2117
+ orderedList: false,
2118
+ history: false,
2119
+ italic: false
2120
+ }), ...wysiwygSettings.value.extensions];
2121
+
2122
+ const updateEditable = () => {
2123
+ if (!editor.value) return;
2124
+ editor.value.setEditable(inputControl.canOperation);
2125
+ };
2126
+
2127
+ watch(() => inputControl.canOperation, updateEditable);
2128
+ watch(() => props.modelValue, modelValue => {
2129
+ editor.value && editor.value.commands.setContent(modelValue == null ? '' : modelValue);
2130
+ });
2054
2131
  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);
2132
+ onCreate: ({
2133
+ editor
2134
+ }) => {
2135
+ textRef.value = editor.getText();
2136
+ updateEditable();
2137
+ },
2138
+ onFocus: ctx => {
2139
+ inputControl.focusHandler(ctx.event);
2140
+ },
2141
+ onBlur: ctx => {
2142
+ inputControl.blurHandler(ctx.event);
2143
+ },
2144
+ onUpdate: ev => {
2145
+ inputControl.value = ev.editor.getHTML();
2146
+ textRef.value = ev.editor.getText();
2147
+ },
2148
+ autofocus: props.autofocus,
2149
+ content: props.modelValue,
2150
+ extensions,
2151
+ editorProps: {
2152
+ attributes: {
2153
+ class: 'v-wysiwyg-editor__input__prose'
2154
+ }
2155
+ }
2156
+ }); // editor.value.state.doc.content
2064
2157
 
2065
- return {
2066
- editor // ...inputControl.expose(),
2067
- // ...control,
2158
+ const focus = (position, options) => {
2159
+ return editor.value.chain().focus(position, options);
2160
+ };
2068
2161
 
2162
+ const blur = () => {
2163
+ return editor.value.chain().blur();
2164
+ };
2165
+
2166
+ const wysiwygContext = computed(() => ({
2167
+ vui,
2168
+ editor: editor.value
2169
+ }));
2170
+
2171
+ const createTools = (bubbleMenu = false) => {
2172
+ let _slot;
2173
+
2174
+ const {
2175
+ value: settings
2176
+ } = wysiwygSettings;
2177
+ const {
2178
+ value: context
2179
+ } = wysiwygContext;
2180
+ const tools = bubbleMenu ? settings.tools.filter(t => !!t.floating) : settings.tools;
2181
+ const _editor = editor.value;
2182
+ const variant = vui.setting(bubbleMenu ? 'containedVariant' : 'plainVariant');
2183
+ return createVNode(VButtonGroup, {
2184
+ "class": {
2185
+ 'v-wysiwyg-editor__floating-toolbar': props.floatingToolbar
2186
+ },
2187
+ "variant": variant
2188
+ }, _isSlot$7(_slot = tools.map(({
2189
+ key,
2190
+ icon,
2191
+ onClick,
2192
+ disabled,
2193
+ active
2194
+ }) => {
2195
+ const isActive = !!_editor && resolveContextableValue(context, active);
2196
+ const isDisabled = !inputControl.canOperation || !!_editor && resolveContextableValue(context, disabled);
2197
+ let iconName;
2198
+
2199
+ if (typeof icon === 'function') {
2200
+ if (_editor) {
2201
+ iconName = icon(context);
2202
+ }
2203
+ } else {
2204
+ iconName = icon;
2205
+ }
2206
+
2207
+ if (!iconName) return;
2208
+ return createVNode(VButton, {
2209
+ "key": key,
2210
+ "icon": iconName,
2211
+ "onClick": ev => onClick(context, ev),
2212
+ "color": isActive ? toolButtonActiveColor : undefined,
2213
+ "disabled": isDisabled
2214
+ }, null);
2215
+ })) ? _slot : {
2216
+ default: () => [_slot]
2217
+ });
2218
+ };
2219
+
2220
+ return {
2221
+ editor,
2222
+ ...inputControl.expose(),
2223
+ ...control,
2224
+ focus,
2225
+ blur,
2226
+ createTools
2069
2227
  };
2070
2228
  },
2071
2229
 
2072
2230
  render() {
2073
2231
  return createVNode(VFormControl, {
2074
2232
  "nodeControl": this.nodeControl,
2233
+ "focused": this.nodeControl.focused,
2234
+ "class": ['v-wysiwyg-editor', this.classes, `v-wysiwyg-editor--${this.size}`, {
2235
+ 'v-wysiwyg-editor--disabled-min-heihgt': this.disabledMinHeight,
2236
+ 'v-wysiwyg-editor--disabled-max-heihgt': this.disabledMaxHeight
2237
+ }],
2075
2238
  "label": this.label,
2076
2239
  "hint": this.hint,
2077
2240
  "hiddenInfo": this.hiddenInfo,
2078
- "onClickLabel": ev => {// this.focus();
2241
+ "onClickLabel": ev => {
2242
+ this.focus('start', {
2243
+ scrollIntoView: true
2244
+ });
2079
2245
  }
2080
2246
  }, { ...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
-
2247
+ default: () => {
2248
+ const {
2249
+ editor
2250
+ } = this;
2251
+ return createVNode("div", {
2252
+ "class": "v-wysiwyg-editor__wrapper"
2253
+ }, [!this.isReadonly && this.createTools(), createVNode("div", {
2254
+ "class": "v-wysiwyg-editor__body"
2255
+ }, [createVNode(VControlField, {
2256
+ "class": "v-wysiwyg-editor__input",
2257
+ "autoHeight": true,
2258
+ "startAdornment": this.startAdornment,
2259
+ "endAdornment": this.endAdornment
2260
+ }, { ...this.$slots,
2261
+ default: () => {
2262
+ let _slot2;
2263
+
2264
+ return createVNode(Fragment, null, [createVNode(EditorContent, {
2265
+ "class": "v-wysiwyg-editor__input__element wysiwyg",
2266
+ "editor": editor
2267
+ }, null), !this.floatingToolbar && !!editor && !this.isReadonly && createVNode(BubbleMenu, {
2268
+ "class": "v-wysiwyg-editor__bubble-menu",
2269
+ "editor": editor
2270
+ }, _isSlot$7(_slot2 = this.createTools(true)) ? _slot2 : {
2271
+ default: () => [_slot2]
2272
+ })]);
2273
+ }
2274
+ })])]);
2275
+ },
2276
+ infoAppends: () => {
2277
+ const {
2278
+ counterResult
2279
+ } = this;
2280
+ if (!counterResult) return;
2281
+ return createVNode(VTextCounter, counterResult, null);
2282
+ }
2117
2283
  });
2118
2284
  }
2119
2285
 
2120
2286
  });
2121
2287
 
2288
+ function resolveContextableValue(ctx, source) {
2289
+ return typeof source === 'function' ? source(ctx) : source;
2290
+ }
2291
+
2292
+ const WysiwygBulletListTool = (vui, options) => {
2293
+ const tool = {
2294
+ key: 'bulletList',
2295
+ icon: vui.icon('editorformatListBulleted'),
2296
+ active: ({ editor }) => editor.isActive('bulletList'),
2297
+ onClick: ({ editor }) => {
2298
+ editor.chain().focus().toggleBulletList().run();
2299
+ },
2300
+ floating: true,
2301
+ extensions: [BulletList.configure(options)],
2302
+ };
2303
+ return tool;
2304
+ };
2305
+
2306
+ const WysiwygFormatBoldTool = (vui, options) => {
2307
+ const tool = {
2308
+ key: 'formatBold',
2309
+ icon: vui.icon('editorformatBold'),
2310
+ active: ({ editor }) => editor.isActive('bold'),
2311
+ onClick: ({ editor }) => {
2312
+ editor.chain().focus().toggleBold().run();
2313
+ },
2314
+ floating: true,
2315
+ extensions: [Bold.configure(options)],
2316
+ };
2317
+ return tool;
2318
+ };
2319
+
2320
+ const WysiwygFormatItalicTool = (vui, options) => {
2321
+ const tool = {
2322
+ key: 'formatItalic',
2323
+ icon: vui.icon('editorformatItalic'),
2324
+ active: ({ editor }) => editor.isActive('italic'),
2325
+ onClick: ({ editor }) => {
2326
+ editor.chain().focus().toggleItalic().run();
2327
+ },
2328
+ floating: true,
2329
+ extensions: [Italic.configure(options)],
2330
+ };
2331
+ return tool;
2332
+ };
2333
+
2334
+ const WysiwygFormatUnderlineTool = (vui, options) => {
2335
+ const tool = {
2336
+ key: 'formatUnderline',
2337
+ icon: vui.icon('editorformatUnderline'),
2338
+ active: ({ editor }) => editor.isActive('underline'),
2339
+ onClick: ({ editor }) => {
2340
+ editor.chain().focus().toggleUnderline().run();
2341
+ },
2342
+ floating: true,
2343
+ extensions: [Underline.configure(options)],
2344
+ };
2345
+ return tool;
2346
+ };
2347
+
2348
+ const WysiwygHistoryTool = (vui, options) => {
2349
+ const undo = {
2350
+ key: 'history-undo',
2351
+ icon: vui.icon('editorUndo'),
2352
+ disabled: ({ editor }) => !editor.can().undo(),
2353
+ onClick: ({ editor }) => {
2354
+ editor.chain().focus().undo().run();
2355
+ },
2356
+ extensions: [History.configure(options)],
2357
+ };
2358
+ const redo = {
2359
+ key: 'history-redo',
2360
+ icon: vui.icon('editorRedo'),
2361
+ disabled: ({ editor }) => !editor.can().redo(),
2362
+ onClick: ({ editor }) => {
2363
+ editor.chain().focus().redo().run();
2364
+ },
2365
+ };
2366
+ return [undo, redo];
2367
+ };
2368
+
2369
+ const WysiwygLinkTool = (vui, options) => {
2370
+ const tool = {
2371
+ key: 'link',
2372
+ // icon: ({ editor }) => {
2373
+ // return vui.icon(editor.isActive('link') ? 'editorLinkOff' : 'editorLink');
2374
+ // },
2375
+ icon: vui.icon('editorLink'),
2376
+ active: ({ editor }) => editor.isActive('link'),
2377
+ // disabled: ({ editor }) => {
2378
+ // const { $from, $to } = editor.view.state.selection;
2379
+ // return $to.pos - $from.pos === 0;
2380
+ // },
2381
+ onClick: async ({ vui, editor }) => {
2382
+ const { href = '' } = editor.getAttributes('link');
2383
+ const result = await vui.prompt({
2384
+ input: {
2385
+ label: 'Link URL',
2386
+ rules: [validateIf, url],
2387
+ initialValue: href,
2388
+ size: 'sm',
2389
+ autofocus: true,
2390
+ },
2391
+ });
2392
+ if (result === undefined || result === false) {
2393
+ return;
2394
+ }
2395
+ const range = editor.chain().focus().extendMarkRange('link');
2396
+ if (!result) {
2397
+ range.unsetLink().run();
2398
+ }
2399
+ else {
2400
+ range
2401
+ .setLink({
2402
+ href: result,
2403
+ })
2404
+ .run();
2405
+ }
2406
+ },
2407
+ floating: true,
2408
+ extensions: [
2409
+ Link.configure({
2410
+ openOnClick: false,
2411
+ ...options,
2412
+ }),
2413
+ ],
2414
+ };
2415
+ return tool;
2416
+ };
2417
+
2418
+ const WysiwygOrderedListTool = (vui, options) => {
2419
+ const tool = {
2420
+ key: 'orderedList',
2421
+ icon: vui.icon('editorformatListNumbered'),
2422
+ active: ({ editor }) => editor.isActive('orderedList'),
2423
+ onClick: ({ editor }) => {
2424
+ editor.chain().focus().toggleOrderedList().run();
2425
+ },
2426
+ floating: true,
2427
+ extensions: [OrderedList.configure(options)],
2428
+ };
2429
+ return tool;
2430
+ };
2431
+
2432
+ const WysiwygTextColorTool = (vui) => {
2433
+ const tool = {
2434
+ key: 'textColor',
2435
+ icon: vui.icon('editorTextColor'),
2436
+ // icon: (gen) => vui.icon('editorTextColor'),
2437
+ onClick: (ctx) => {
2438
+ ctx.vui.alert('ok');
2439
+ },
2440
+ floating: true,
2441
+ };
2442
+ return tool;
2443
+ };
2444
+
2122
2445
  const {
2123
2446
  props,
2124
2447
  emits
@@ -2129,7 +2452,8 @@ const VForm = defineComponent({
2129
2452
  name: 'VForm',
2130
2453
  props: { ...props,
2131
2454
  ...createControlProps(),
2132
- ...defineSlotsProps()
2455
+ ...defineSlotsProps(),
2456
+ disableAutoScroll: Boolean
2133
2457
  },
2134
2458
  emits,
2135
2459
 
@@ -2138,6 +2462,7 @@ const VForm = defineComponent({
2138
2462
  const nodeControl = useForm(props, ctx, {
2139
2463
  nodeType: VUI_FORM_SYMBOL,
2140
2464
  onAutoValidateError: () => {
2465
+ if (props.disableAutoScroll) return;
2141
2466
  const scroller = getDocumentScroller();
2142
2467
  const {
2143
2468
  firstInvalidEl
@@ -3529,53 +3854,138 @@ const VToolbarTitle = defineComponent({
3529
3854
 
3530
3855
  });
3531
3856
 
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
- }
3857
+ const DEFAULT_AUTO_SCROLL_TO_ELEMENT_OFFSET_TOP = -20;
3858
+ const DEFAULT_TEXTAREA_ROWS = 3;
3859
+ class VuiService {
3860
+ constructor(options, stackService) {
3861
+ this.options = options;
3862
+ this.configure();
3863
+ const {
3864
+ selectionSeparator = () => ', ',
3865
+ autoScrollToElementOffsetTop = DEFAULT_AUTO_SCROLL_TO_ELEMENT_OFFSET_TOP,
3866
+ textareaRows = DEFAULT_TEXTAREA_ROWS,
3867
+ requiredChip = () => '*'
3868
+ } = options;
3869
+ this.selectionSeparator = selectionSeparator;
3870
+ this.autoScrollToElementOffsetTop = autoScrollToElementOffsetTop;
3871
+ this.textareaRows = textareaRows;
3872
+ this.requiredChip = requiredChip;
3873
+ this.router = options.router;
3874
+ this.location = new LocationService({
3875
+ router: this.router
3876
+ });
3877
+ this.stack = stackService;
3878
+ }
3879
+
3880
+ configure(options) {
3881
+ options && Object.assign(this.options, options);
3882
+ setDefaultRouterLink(this.getRouterLink());
3883
+ }
3884
+
3885
+ getRouterLink() {
3886
+ return this.options.RouterLink || RouterLink;
3887
+ }
3888
+
3889
+ setting(key) {
3890
+ return this.options.uiSettings[key];
3891
+ }
3892
+
3893
+ icon(iconType) {
3894
+ return this.options.icons[iconType];
3895
+ }
3896
+
3897
+ getAutoScrollToElementOffsetTop() {
3898
+ let {
3899
+ autoScrollToElementOffsetTop
3900
+ } = this;
3901
+
3902
+ if (typeof autoScrollToElementOffsetTop === 'function') {
3903
+ autoScrollToElementOffsetTop = autoScrollToElementOffsetTop();
3904
+ }
3905
+
3906
+ return autoScrollToElementOffsetTop || 0;
3907
+ }
3908
+
3909
+ getRequiredChip() {
3910
+ const {
3911
+ requiredChip
3912
+ } = this;
3913
+ return requiredChip && requiredChip();
3914
+ }
3915
+
3916
+ dialog(...args) {
3917
+ return this.stack.dialog(...args);
3918
+ }
3919
+
3920
+ alert(...args) {
3921
+ return this.stack.alert(...args);
3922
+ }
3923
+
3924
+ confirm(...args) {
3925
+ return this.stack.confirm(...args);
3926
+ }
3927
+
3928
+ snackbar(...args) {
3929
+ return this.stack.snackbar(...args);
3930
+ }
3931
+
3932
+ prompt(rawOptions = {}) {
3933
+ const options = typeof rawOptions === 'string' ? {
3934
+ input: {
3935
+ label: rawOptions
3936
+ }
3937
+ } : { ...rawOptions
3938
+ };
3939
+ options.input = { ...options.input
3940
+ };
3941
+ options.dense = true;
3942
+ let {
3943
+ initialValue: value = ''
3944
+ } = options.input;
3945
+ const {
3946
+ size
3947
+ } = options.input;
3948
+ delete options.input.initialValue;
3949
+ let form;
3950
+ options.actions = options.actions || [this.stack.action('cancel', undefined, {
3951
+ size
3952
+ }), this.stack.action('ok', undefined, {
3953
+ size,
3954
+ onClick: () => {
3955
+ if (form) {
3956
+ const ev = new Event('submit');
3957
+ form.handleSubmit(ev);
3958
+ }
3959
+ }
3960
+ })];
3961
+ const resolved = resolveVStackDynamicInput({ ...options,
3962
+ content: stack => {
3963
+ return createVNode(VForm, {
3964
+ "disableAutoScroll": true,
3965
+ "size": size,
3966
+ "onVnodeMounted": vnode => {
3967
+ form = vnode.component.ctx.form;
3968
+ },
3969
+ "onVnodeBeforeUnmount": () => {
3970
+ form = undefined;
3971
+ },
3972
+ "onSubmit": ev => {
3973
+ stack.resolve(value);
3974
+ }
3975
+ }, {
3976
+ default: () => [createVNode(VTextField, mergeProps(options.input, {
3977
+ "modelValue": value,
3978
+ "onChange": ev => {
3979
+ stack.value = ev;
3980
+ value = ev;
3981
+ }
3982
+ }), null)]
3983
+ });
3984
+ }
3985
+ });
3986
+ return this.dialog(resolved);
3987
+ }
3988
+
3579
3989
  }
3580
3990
 
3581
3991
  class VuiPlugin {
@@ -3619,7 +4029,7 @@ class VuiPlugin {
3619
4029
  ...stack
3620
4030
  }); // Vui
3621
4031
 
3622
- const $vui = new VuiService(opts);
4032
+ const $vui = new VuiService(opts, app.config.globalProperties.$vstack);
3623
4033
  app.provide(VuiInjectionKey, $vui);
3624
4034
  app.config.globalProperties.$vui = $vui;
3625
4035
 
@@ -3635,4 +4045,4 @@ function installVuiPlugin(app, opts) {
3635
4045
  return app.use(VuiPlugin, opts);
3636
4046
  }
3637
4047
 
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 };
4048
+ 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 };