@fastkit/vui 0.6.33 → 0.6.37

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,15 +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 { inject, computed, provide, defineComponent, createVNode, mergeProps, isVNode, cloneVNode, ref, watch, withDirectives, createTextVNode, Fragment, vShow, onBeforeUpdate, vModelSelect, onMounted, onBeforeUnmount, Transition } from 'vue';
4
5
  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
- import { inject, computed, provide, defineComponent, createVNode, mergeProps, ref, watch, withDirectives, createTextVNode, isVNode, Fragment, vShow, onBeforeUpdate, vModelSelect, onMounted, onBeforeUnmount, Transition } from 'vue';
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';
14
+ import { useEditor, EditorContent, BubbleMenu } from '@tiptap/vue-3';
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';
13
24
  import { getDocumentScroller as getDocumentScroller$1 } from '@fastkit/vue-scroller';
14
25
 
15
26
  const CONTROL_SIZES = ['sm', 'md', 'lg'];
@@ -21,6 +32,7 @@ const VuiControlFieldInjectionKey = Symbol();
21
32
  const VuiColorProviderInjectionKey = Symbol();
22
33
  const VUI_TEXT_FIELD_SYMBOL = 'vui-text-field';
23
34
  const VUI_TEXTAREA_SYMBOL = 'vui-textarea';
35
+ const VUI_WYSIWYG_EDITOR_SYMBOL = 'vui-wysiwyg-editor';
24
36
  const VUI_SELECT_SYMBOL = 'vui-select';
25
37
  const VUI_OPTION_SYMBOL = 'vui-option';
26
38
  const VUI_CHECKBOX_GROUP_SYMBOL = 'vui-checkbox-group';
@@ -478,8 +490,10 @@ const VButton = defineComponent({
478
490
  });
479
491
  const isPlain = computed(() => color.variant.value.value === vui.setting('plainVariant') && color.color.value.value === defaults.color);
480
492
  const isLoading = computed(() => props.loading); // const isDisabled = computed(() => props.disabled);
493
+ // const isRounded = computed(() =>
494
+ // props.rounded != null ? props.rounded : !!icon.value,
495
+ // );
481
496
 
482
- const isRounded = computed(() => props.rounded || !!icon.value);
483
497
  const spacer = computed(() => {
484
498
  const _spacer = props.spacer;
485
499
  if (!_spacer) return;
@@ -489,7 +503,7 @@ const VButton = defineComponent({
489
503
  spacer.value ? `v-button--spacer-${spacer.value}` : undefined, `v-button--${control.size.value}`, {
490
504
  'v-button--loading': isLoading.value,
491
505
  'v-button--icon': !!icon.value,
492
- 'v-button--rounded': isRounded.value,
506
+ 'v-button--rounded': props.rounded,
493
507
  'v-button--plain': isPlain.value
494
508
  }]);
495
509
  return () => {
@@ -510,7 +524,64 @@ const VButton = defineComponent({
510
524
 
511
525
  });
512
526
 
513
- function _isSlot$c(s) {
527
+ const VButtonGroup = defineComponent({
528
+ name: 'VButtonGroup',
529
+ props: { ...colorSchemeProps(),
530
+ ...createControlProps(),
531
+ disabled: Boolean
532
+ },
533
+
534
+ setup(props, ctx) {
535
+ return () => {
536
+ let buttonLength = 0;
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 => {
544
+ if (!isVNode(node) || node.type !== VButton) {
545
+ return {
546
+ isButton: false,
547
+ node
548
+ };
549
+ }
550
+
551
+ buttonLength++;
552
+ return {
553
+ isButton: true,
554
+ node
555
+ };
556
+ });
557
+ let buttonIndex = 0;
558
+ const $children = children.map(child => {
559
+ if (child.isButton) {
560
+ buttonIndex++;
561
+ const hasLeft = buttonIndex > 1;
562
+ const hasRight = buttonIndex < buttonLength;
563
+ const childProps = child.node.props;
564
+ return cloneVNode(child.node, { ...props,
565
+ ...childProps,
566
+ rouded: false,
567
+ class: ['v-button-group__item', {
568
+ 'v-button-group__item--has-left': hasLeft,
569
+ 'v-button-group__item--has-right': hasRight
570
+ }]
571
+ });
572
+ }
573
+
574
+ return child.node;
575
+ });
576
+ return createVNode("div", {
577
+ "class": "v-button-group"
578
+ }, [$children]);
579
+ };
580
+ }
581
+
582
+ });
583
+
584
+ function _isSlot$d(s) {
514
585
  return typeof s === 'function' || Object.prototype.toString.call(s) === '[object Object]' && !isVNode(s);
515
586
  }
516
587
 
@@ -758,7 +829,7 @@ const VPagination = defineComponent({
758
829
  "class": classes,
759
830
  "to": to,
760
831
  "key": key
761
- }, _isSlot$c(children) ? children : {
832
+ }, _isSlot$d(children) ? children : {
762
833
  default: () => [children]
763
834
  });
764
835
  } else {
@@ -913,7 +984,7 @@ const VDrawerLayout = defineComponent({
913
984
 
914
985
  });
915
986
 
916
- function _isSlot$b(s) {
987
+ function _isSlot$c(s) {
917
988
  return typeof s === 'function' || Object.prototype.toString.call(s) === '[object Object]' && !isVNode(s);
918
989
  }
919
990
 
@@ -948,7 +1019,7 @@ const VHero = defineComponent({
948
1019
  }, {
949
1020
  default: () => [createVNode(HTagName, {
950
1021
  "class": "v-hero__title"
951
- }, _isSlot$b(_slot = renderSlotOrEmpty$1(ctx.slots, 'default')) ? _slot : {
1022
+ }, _isSlot$c(_slot = renderSlotOrEmpty$1(ctx.slots, 'default')) ? _slot : {
952
1023
  default: () => [_slot]
953
1024
  })]
954
1025
  })]
@@ -958,7 +1029,7 @@ const VHero = defineComponent({
958
1029
 
959
1030
  });
960
1031
 
961
- function _isSlot$a(s) {
1032
+ function _isSlot$b(s) {
962
1033
  return typeof s === 'function' || Object.prototype.toString.call(s) === '[object Object]' && !isVNode(s);
963
1034
  }
964
1035
 
@@ -993,7 +1064,7 @@ function renderNavigationItemInput(input, extraProps) {
993
1064
  } = resolveNavigationItemInput(input);
994
1065
  return createVNode(VNavigationItem, { ...props,
995
1066
  ...extraProps
996
- }, _isSlot$a(label) ? label : {
1067
+ }, _isSlot$b(label) ? label : {
997
1068
  default: () => [label]
998
1069
  });
999
1070
  }
@@ -1016,9 +1087,11 @@ const VNavigationItem = defineComponent({
1016
1087
  const to = computed(() => ctx.attrs.to);
1017
1088
  const match = computed(() => {
1018
1089
  const {
1019
- match,
1020
- to
1090
+ match
1021
1091
  } = props;
1092
+ const {
1093
+ to
1094
+ } = ctx.attrs;
1022
1095
  if (match) return match;
1023
1096
  if (!to) return;
1024
1097
  if (typeof to === 'string') return to;
@@ -1144,7 +1217,7 @@ const VNavigationItem = defineComponent({
1144
1217
  "class": ['v-navigation-item', classes.value],
1145
1218
  "onClick": onClick,
1146
1219
  "onChangeActive": onChangeActive
1147
- }), _isSlot$a(_slot = renderSlotOrEmpty$1(ctx.slots, 'default')) ? _slot : {
1220
+ }), _isSlot$b(_slot = renderSlotOrEmpty$1(ctx.slots, 'default')) ? _slot : {
1148
1221
  default: () => [_slot]
1149
1222
  }), _children && createVNode(VExpandTransition, null, {
1150
1223
  default: () => [withDirectives(createVNode("div", {
@@ -1324,7 +1397,7 @@ const VCheckbox = defineComponent({
1324
1397
 
1325
1398
  });
1326
1399
 
1327
- function _isSlot$9(s) {
1400
+ function _isSlot$a(s) {
1328
1401
  return typeof s === 'function' || Object.prototype.toString.call(s) === '[object Object]' && !isVNode(s);
1329
1402
  }
1330
1403
 
@@ -1336,7 +1409,7 @@ const VCheckboxGroup = defineFormSelectorComponent({
1336
1409
  itemRenderer: ({
1337
1410
  attrs,
1338
1411
  slots
1339
- }) => createVNode(VCheckbox, attrs, _isSlot$9(slots) ? slots : {
1412
+ }) => createVNode(VCheckbox, attrs, _isSlot$a(slots) ? slots : {
1340
1413
  default: () => [slots]
1341
1414
  })
1342
1415
  });
@@ -1388,7 +1461,7 @@ const VRadio = defineComponent({
1388
1461
 
1389
1462
  });
1390
1463
 
1391
- function _isSlot$8(s) {
1464
+ function _isSlot$9(s) {
1392
1465
  return typeof s === 'function' || Object.prototype.toString.call(s) === '[object Object]' && !isVNode(s);
1393
1466
  }
1394
1467
 
@@ -1399,7 +1472,7 @@ const VRadioGroup = defineFormSelectorComponent({
1399
1472
  itemRenderer: ({
1400
1473
  attrs,
1401
1474
  slots
1402
- }) => createVNode(VRadio, attrs, _isSlot$8(slots) ? slots : {
1475
+ }) => createVNode(VRadio, attrs, _isSlot$9(slots) ? slots : {
1403
1476
  default: () => [slots]
1404
1477
  })
1405
1478
  });
@@ -1461,7 +1534,7 @@ const VSwitch = defineComponent({
1461
1534
 
1462
1535
  });
1463
1536
 
1464
- function _isSlot$7(s) {
1537
+ function _isSlot$8(s) {
1465
1538
  return typeof s === 'function' || Object.prototype.toString.call(s) === '[object Object]' && !isVNode(s);
1466
1539
  }
1467
1540
 
@@ -1473,7 +1546,7 @@ const VSwitchGroup = defineFormSelectorComponent({
1473
1546
  itemRenderer: ({
1474
1547
  attrs,
1475
1548
  slots
1476
- }) => createVNode(VSwitch, attrs, _isSlot$7(slots) ? slots : {
1549
+ }) => createVNode(VSwitch, attrs, _isSlot$8(slots) ? slots : {
1477
1550
  default: () => [slots]
1478
1551
  })
1479
1552
  });
@@ -1856,15 +1929,20 @@ const {
1856
1929
  props: props$2,
1857
1930
  emits: emits$2
1858
1931
  } = createTextInputSettings();
1859
- const VTextField = defineComponent({
1860
- name: 'VTextField',
1861
- props: { ...props$2,
1932
+
1933
+ function createTextFieldProps() {
1934
+ return { ...props$2,
1862
1935
  ...createFormControlProps(),
1863
1936
  ...createControlFieldProps(),
1864
1937
  ...createControlFieldProviderProps(),
1865
1938
  ...createControlProps(),
1866
1939
  ...defineSlotsProps()
1867
- },
1940
+ };
1941
+ }
1942
+
1943
+ const VTextField = defineComponent({
1944
+ name: 'VTextField',
1945
+ props: createTextFieldProps(),
1868
1946
  emits: emits$2,
1869
1947
 
1870
1948
  setup(props, ctx) {
@@ -1973,6 +2051,396 @@ const VTextarea = defineComponent({
1973
2051
 
1974
2052
  });
1975
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
+
2082
+ const VWysiwygEditor = defineComponent({
2083
+ name: 'VWysiwygEditor',
2084
+ props: { // ...props,
2085
+ ...createTextableProps(),
2086
+ ...createFormControlProps(),
2087
+ ...createControlFieldProps(),
2088
+ ...createControlFieldProviderProps(),
2089
+ ...createControlProps(),
2090
+ ...defineSlotsProps(),
2091
+ tools: {
2092
+ type: Array,
2093
+ default: () => []
2094
+ },
2095
+ floatingToolbar: Boolean,
2096
+ disabledMinHeight: Boolean,
2097
+ disabledMaxHeight: Boolean
2098
+ },
2099
+ emits: { ...createTextableEmits()
2100
+ },
2101
+
2102
+ setup(props, ctx) {
2103
+ const vui = useVui();
2104
+ const textRef = ref('');
2105
+ const toolButtonActiveColor = vui.setting('primaryScope');
2106
+ const wysiwygSettings = computed(() => resolveRawWysiwygEditorTools(props.tools, vui));
2107
+ const control = useControl(props);
2108
+ useControlField(props);
2109
+ const inputControl = new TextableControl(props, ctx, {
2110
+ nodeType: VUI_WYSIWYG_EDITOR_SYMBOL,
2111
+ validationValue: () => textRef.value
2112
+ });
2113
+ const extensions = [StarterKit.configure({
2114
+ bold: false,
2115
+ bulletList: false,
2116
+ orderedList: false,
2117
+ history: false,
2118
+ italic: false
2119
+ }), ...wysiwygSettings.value.extensions];
2120
+
2121
+ const updateEditable = () => {
2122
+ if (!editor.value) return;
2123
+ editor.value.setEditable(inputControl.canOperation);
2124
+ };
2125
+
2126
+ watch(() => inputControl.canOperation, updateEditable);
2127
+ watch(() => props.modelValue, modelValue => {
2128
+ editor.value && editor.value.commands.setContent(modelValue == null ? '' : modelValue);
2129
+ });
2130
+ const editor = useEditor({
2131
+ onCreate: ({
2132
+ editor
2133
+ }) => {
2134
+ textRef.value = editor.getText();
2135
+ updateEditable();
2136
+ },
2137
+ onFocus: ctx => {
2138
+ inputControl.focusHandler(ctx.event);
2139
+ },
2140
+ onBlur: ctx => {
2141
+ inputControl.blurHandler(ctx.event);
2142
+ },
2143
+ onUpdate: ev => {
2144
+ inputControl.value = ev.editor.getHTML();
2145
+ textRef.value = ev.editor.getText();
2146
+ },
2147
+ autofocus: props.autofocus,
2148
+ content: props.modelValue,
2149
+ extensions,
2150
+ editorProps: {
2151
+ attributes: {
2152
+ class: 'v-wysiwyg-editor__input__prose'
2153
+ }
2154
+ }
2155
+ }); // editor.value.state.doc.content
2156
+
2157
+ const focus = (position, options) => {
2158
+ return editor.value.chain().focus(position, options);
2159
+ };
2160
+
2161
+ const blur = () => {
2162
+ return editor.value.chain().blur();
2163
+ };
2164
+
2165
+ const wysiwygContext = computed(() => ({
2166
+ vui,
2167
+ editor: editor.value
2168
+ }));
2169
+
2170
+ const createTools = (bubbleMenu = false) => {
2171
+ let _slot;
2172
+
2173
+ const {
2174
+ value: settings
2175
+ } = wysiwygSettings;
2176
+ const {
2177
+ value: context
2178
+ } = wysiwygContext;
2179
+ const tools = bubbleMenu ? settings.tools.filter(t => !!t.floating) : settings.tools;
2180
+ const _editor = editor.value;
2181
+ const variant = vui.setting(bubbleMenu ? 'containedVariant' : 'plainVariant');
2182
+ return createVNode(VButtonGroup, {
2183
+ "class": {
2184
+ 'v-wysiwyg-editor__floating-toolbar': props.floatingToolbar
2185
+ },
2186
+ "variant": variant
2187
+ }, _isSlot$7(_slot = tools.map(({
2188
+ key,
2189
+ icon,
2190
+ onClick,
2191
+ disabled,
2192
+ active
2193
+ }) => {
2194
+ const isActive = !!_editor && resolveContextableValue(context, active);
2195
+ const isDisabled = !inputControl.canOperation || !!_editor && resolveContextableValue(context, disabled);
2196
+ let iconName;
2197
+
2198
+ if (typeof icon === 'function') {
2199
+ if (_editor) {
2200
+ iconName = icon(context);
2201
+ }
2202
+ } else {
2203
+ iconName = icon;
2204
+ }
2205
+
2206
+ if (!iconName) return;
2207
+ return createVNode(VButton, {
2208
+ "key": key,
2209
+ "icon": iconName,
2210
+ "onClick": ev => onClick(context, ev),
2211
+ "color": isActive ? toolButtonActiveColor : undefined,
2212
+ "disabled": isDisabled
2213
+ }, null);
2214
+ })) ? _slot : {
2215
+ default: () => [_slot]
2216
+ });
2217
+ };
2218
+
2219
+ return {
2220
+ editor,
2221
+ ...inputControl.expose(),
2222
+ ...control,
2223
+ focus,
2224
+ blur,
2225
+ createTools
2226
+ };
2227
+ },
2228
+
2229
+ render() {
2230
+ return createVNode(VFormControl, {
2231
+ "nodeControl": this.nodeControl,
2232
+ "focused": this.nodeControl.focused,
2233
+ "class": ['v-wysiwyg-editor', this.classes, `v-wysiwyg-editor--${this.size}`, {
2234
+ 'v-wysiwyg-editor--disabled-min-heihgt': this.disabledMinHeight,
2235
+ 'v-wysiwyg-editor--disabled-max-heihgt': this.disabledMaxHeight
2236
+ }],
2237
+ "label": this.label,
2238
+ "hint": this.hint,
2239
+ "hiddenInfo": this.hiddenInfo,
2240
+ "onClickLabel": ev => {
2241
+ this.focus('start', {
2242
+ scrollIntoView: true
2243
+ });
2244
+ }
2245
+ }, { ...this.$slots,
2246
+ default: () => {
2247
+ const {
2248
+ editor
2249
+ } = this;
2250
+ return createVNode("div", {
2251
+ "class": "v-wysiwyg-editor__wrapper"
2252
+ }, [!this.isReadonly && this.createTools(), createVNode("div", {
2253
+ "class": "v-wysiwyg-editor__body"
2254
+ }, [createVNode(VControlField, {
2255
+ "class": "v-wysiwyg-editor__input",
2256
+ "autoHeight": true,
2257
+ "startAdornment": this.startAdornment,
2258
+ "endAdornment": this.endAdornment
2259
+ }, { ...this.$slots,
2260
+ default: () => {
2261
+ let _slot2;
2262
+
2263
+ return createVNode(Fragment, null, [createVNode(EditorContent, {
2264
+ "class": "v-wysiwyg-editor__input__element wysiwyg",
2265
+ "editor": editor
2266
+ }, null), !this.floatingToolbar && !!editor && !this.isReadonly && createVNode(BubbleMenu, {
2267
+ "class": "v-wysiwyg-editor__bubble-menu",
2268
+ "editor": editor
2269
+ }, _isSlot$7(_slot2 = this.createTools(true)) ? _slot2 : {
2270
+ default: () => [_slot2]
2271
+ })]);
2272
+ }
2273
+ })])]);
2274
+ },
2275
+ infoAppends: () => {
2276
+ const {
2277
+ counterResult
2278
+ } = this;
2279
+ if (!counterResult) return;
2280
+ return createVNode(VTextCounter, counterResult, null);
2281
+ }
2282
+ });
2283
+ }
2284
+
2285
+ });
2286
+
2287
+ function resolveContextableValue(ctx, source) {
2288
+ return typeof source === 'function' ? source(ctx) : source;
2289
+ }
2290
+
2291
+ const WysiwygBulletListTool = (vui, options) => {
2292
+ const tool = {
2293
+ key: 'bulletList',
2294
+ icon: vui.icon('editorformatListBulleted'),
2295
+ active: ({ editor }) => editor.isActive('bulletList'),
2296
+ onClick: ({ editor }) => {
2297
+ editor.chain().focus().toggleBulletList().run();
2298
+ },
2299
+ floating: true,
2300
+ extensions: [BulletList.configure(options)],
2301
+ };
2302
+ return tool;
2303
+ };
2304
+
2305
+ const WysiwygFormatBoldTool = (vui, options) => {
2306
+ const tool = {
2307
+ key: 'formatBold',
2308
+ icon: vui.icon('editorformatBold'),
2309
+ active: ({ editor }) => editor.isActive('bold'),
2310
+ onClick: ({ editor }) => {
2311
+ editor.chain().focus().toggleBold().run();
2312
+ },
2313
+ floating: true,
2314
+ extensions: [Bold.configure(options)],
2315
+ };
2316
+ return tool;
2317
+ };
2318
+
2319
+ const WysiwygFormatItalicTool = (vui, options) => {
2320
+ const tool = {
2321
+ key: 'formatItalic',
2322
+ icon: vui.icon('editorformatItalic'),
2323
+ active: ({ editor }) => editor.isActive('italic'),
2324
+ onClick: ({ editor }) => {
2325
+ editor.chain().focus().toggleItalic().run();
2326
+ },
2327
+ floating: true,
2328
+ extensions: [Italic.configure(options)],
2329
+ };
2330
+ return tool;
2331
+ };
2332
+
2333
+ const WysiwygFormatUnderlineTool = (vui, options) => {
2334
+ const tool = {
2335
+ key: 'formatUnderline',
2336
+ icon: vui.icon('editorformatUnderline'),
2337
+ active: ({ editor }) => editor.isActive('underline'),
2338
+ onClick: ({ editor }) => {
2339
+ editor.chain().focus().toggleUnderline().run();
2340
+ },
2341
+ floating: true,
2342
+ extensions: [Underline.configure(options)],
2343
+ };
2344
+ return tool;
2345
+ };
2346
+
2347
+ const WysiwygHistoryTool = (vui, options) => {
2348
+ const undo = {
2349
+ key: 'history-undo',
2350
+ icon: vui.icon('editorUndo'),
2351
+ disabled: ({ editor }) => !editor.can().undo(),
2352
+ onClick: ({ editor }) => {
2353
+ editor.chain().focus().undo().run();
2354
+ },
2355
+ extensions: [History.configure(options)],
2356
+ };
2357
+ const redo = {
2358
+ key: 'history-redo',
2359
+ icon: vui.icon('editorRedo'),
2360
+ disabled: ({ editor }) => !editor.can().redo(),
2361
+ onClick: ({ editor }) => {
2362
+ editor.chain().focus().redo().run();
2363
+ },
2364
+ };
2365
+ return [undo, redo];
2366
+ };
2367
+
2368
+ const WysiwygLinkTool = (vui, options) => {
2369
+ const tool = {
2370
+ key: 'link',
2371
+ // icon: ({ editor }) => {
2372
+ // return vui.icon(editor.isActive('link') ? 'editorLinkOff' : 'editorLink');
2373
+ // },
2374
+ icon: vui.icon('editorLink'),
2375
+ active: ({ editor }) => editor.isActive('link'),
2376
+ // disabled: ({ editor }) => {
2377
+ // const { $from, $to } = editor.view.state.selection;
2378
+ // return $to.pos - $from.pos === 0;
2379
+ // },
2380
+ onClick: async ({ vui, editor }) => {
2381
+ const { href = '' } = editor.getAttributes('link');
2382
+ const result = await vui.prompt({
2383
+ input: {
2384
+ label: 'Link URL',
2385
+ rules: [validateIf, url],
2386
+ initialValue: href,
2387
+ size: 'sm',
2388
+ autofocus: true,
2389
+ },
2390
+ });
2391
+ if (result === undefined || result === false) {
2392
+ return;
2393
+ }
2394
+ const range = editor.chain().focus().extendMarkRange('link');
2395
+ if (!result) {
2396
+ range.unsetLink().run();
2397
+ }
2398
+ else {
2399
+ range
2400
+ .setLink({
2401
+ href: result,
2402
+ })
2403
+ .run();
2404
+ }
2405
+ },
2406
+ floating: true,
2407
+ extensions: [
2408
+ Link.configure({
2409
+ openOnClick: false,
2410
+ ...options,
2411
+ }),
2412
+ ],
2413
+ };
2414
+ return tool;
2415
+ };
2416
+
2417
+ const WysiwygOrderedListTool = (vui, options) => {
2418
+ const tool = {
2419
+ key: 'orderedList',
2420
+ icon: vui.icon('editorformatListNumbered'),
2421
+ active: ({ editor }) => editor.isActive('orderedList'),
2422
+ onClick: ({ editor }) => {
2423
+ editor.chain().focus().toggleOrderedList().run();
2424
+ },
2425
+ floating: true,
2426
+ extensions: [OrderedList.configure(options)],
2427
+ };
2428
+ return tool;
2429
+ };
2430
+
2431
+ const WysiwygTextColorTool = (vui) => {
2432
+ const tool = {
2433
+ key: 'textColor',
2434
+ icon: vui.icon('editorTextColor'),
2435
+ // icon: (gen) => vui.icon('editorTextColor'),
2436
+ onClick: (ctx) => {
2437
+ ctx.vui.alert('ok');
2438
+ },
2439
+ floating: true,
2440
+ };
2441
+ return tool;
2442
+ };
2443
+
1976
2444
  const {
1977
2445
  props,
1978
2446
  emits
@@ -1983,7 +2451,8 @@ const VForm = defineComponent({
1983
2451
  name: 'VForm',
1984
2452
  props: { ...props,
1985
2453
  ...createControlProps(),
1986
- ...defineSlotsProps()
2454
+ ...defineSlotsProps(),
2455
+ disableAutoScroll: Boolean
1987
2456
  },
1988
2457
  emits,
1989
2458
 
@@ -1992,6 +2461,7 @@ const VForm = defineComponent({
1992
2461
  const nodeControl = useForm(props, ctx, {
1993
2462
  nodeType: VUI_FORM_SYMBOL,
1994
2463
  onAutoValidateError: () => {
2464
+ if (props.disableAutoScroll) return;
1995
2465
  const scroller = getDocumentScroller();
1996
2466
  const {
1997
2467
  firstInvalidEl
@@ -3383,53 +3853,138 @@ const VToolbarTitle = defineComponent({
3383
3853
 
3384
3854
  });
3385
3855
 
3386
- const DEFAULT_AUTO_SCROLL_TO_ELEMENT_OFFSET_TOP = -20;
3387
- const DEFAULT_TEXTAREA_ROWS = 3;
3388
- class VuiService {
3389
- options;
3390
- selectionSeparator;
3391
- autoScrollToElementOffsetTop;
3392
- textareaRows;
3393
- requiredChip;
3394
- router;
3395
- location;
3396
- constructor(options) {
3397
- this.options = options;
3398
- this.configure();
3399
- const { selectionSeparator = () => ', ', autoScrollToElementOffsetTop = DEFAULT_AUTO_SCROLL_TO_ELEMENT_OFFSET_TOP, textareaRows = DEFAULT_TEXTAREA_ROWS, requiredChip = () => '*', } = options;
3400
- this.selectionSeparator = selectionSeparator;
3401
- this.autoScrollToElementOffsetTop = autoScrollToElementOffsetTop;
3402
- this.textareaRows = textareaRows;
3403
- this.requiredChip = requiredChip;
3404
- this.router = options.router;
3405
- this.location = new LocationService({
3406
- router: this.router,
3407
- });
3408
- }
3409
- configure(options) {
3410
- options && Object.assign(this.options, options);
3411
- setDefaultRouterLink(this.getRouterLink());
3412
- }
3413
- getRouterLink() {
3414
- return this.options.RouterLink || RouterLink;
3415
- }
3416
- setting(key) {
3417
- return this.options.uiSettings[key];
3418
- }
3419
- icon(iconType) {
3420
- return this.options.icons[iconType];
3421
- }
3422
- getAutoScrollToElementOffsetTop() {
3423
- let { autoScrollToElementOffsetTop } = this;
3424
- if (typeof autoScrollToElementOffsetTop === 'function') {
3425
- autoScrollToElementOffsetTop = autoScrollToElementOffsetTop();
3426
- }
3427
- return autoScrollToElementOffsetTop || 0;
3428
- }
3429
- getRequiredChip() {
3430
- const { requiredChip } = this;
3431
- return requiredChip && requiredChip();
3432
- }
3856
+ const DEFAULT_AUTO_SCROLL_TO_ELEMENT_OFFSET_TOP = -20;
3857
+ const DEFAULT_TEXTAREA_ROWS = 3;
3858
+ class VuiService {
3859
+ constructor(options, stackService) {
3860
+ this.options = options;
3861
+ this.configure();
3862
+ const {
3863
+ selectionSeparator = () => ', ',
3864
+ autoScrollToElementOffsetTop = DEFAULT_AUTO_SCROLL_TO_ELEMENT_OFFSET_TOP,
3865
+ textareaRows = DEFAULT_TEXTAREA_ROWS,
3866
+ requiredChip = () => '*'
3867
+ } = options;
3868
+ this.selectionSeparator = selectionSeparator;
3869
+ this.autoScrollToElementOffsetTop = autoScrollToElementOffsetTop;
3870
+ this.textareaRows = textareaRows;
3871
+ this.requiredChip = requiredChip;
3872
+ this.router = options.router;
3873
+ this.location = new LocationService({
3874
+ router: this.router
3875
+ });
3876
+ this.stack = stackService;
3877
+ }
3878
+
3879
+ configure(options) {
3880
+ options && Object.assign(this.options, options);
3881
+ setDefaultRouterLink(this.getRouterLink());
3882
+ }
3883
+
3884
+ getRouterLink() {
3885
+ return this.options.RouterLink || RouterLink;
3886
+ }
3887
+
3888
+ setting(key) {
3889
+ return this.options.uiSettings[key];
3890
+ }
3891
+
3892
+ icon(iconType) {
3893
+ return this.options.icons[iconType];
3894
+ }
3895
+
3896
+ getAutoScrollToElementOffsetTop() {
3897
+ let {
3898
+ autoScrollToElementOffsetTop
3899
+ } = this;
3900
+
3901
+ if (typeof autoScrollToElementOffsetTop === 'function') {
3902
+ autoScrollToElementOffsetTop = autoScrollToElementOffsetTop();
3903
+ }
3904
+
3905
+ return autoScrollToElementOffsetTop || 0;
3906
+ }
3907
+
3908
+ getRequiredChip() {
3909
+ const {
3910
+ requiredChip
3911
+ } = this;
3912
+ return requiredChip && requiredChip();
3913
+ }
3914
+
3915
+ dialog(...args) {
3916
+ return this.stack.dialog(...args);
3917
+ }
3918
+
3919
+ alert(...args) {
3920
+ return this.stack.alert(...args);
3921
+ }
3922
+
3923
+ confirm(...args) {
3924
+ return this.stack.confirm(...args);
3925
+ }
3926
+
3927
+ snackbar(...args) {
3928
+ return this.stack.snackbar(...args);
3929
+ }
3930
+
3931
+ prompt(rawOptions = {}) {
3932
+ const options = typeof rawOptions === 'string' ? {
3933
+ input: {
3934
+ label: rawOptions
3935
+ }
3936
+ } : { ...rawOptions
3937
+ };
3938
+ options.input = { ...options.input
3939
+ };
3940
+ options.dense = true;
3941
+ let {
3942
+ initialValue: value = ''
3943
+ } = options.input;
3944
+ const {
3945
+ size
3946
+ } = options.input;
3947
+ delete options.input.initialValue;
3948
+ let form;
3949
+ options.actions = options.actions || [this.stack.action('cancel', undefined, {
3950
+ size
3951
+ }), this.stack.action('ok', undefined, {
3952
+ size,
3953
+ onClick: () => {
3954
+ if (form) {
3955
+ const ev = new Event('submit');
3956
+ form.handleSubmit(ev);
3957
+ }
3958
+ }
3959
+ })];
3960
+ const resolved = resolveVStackDynamicInput({ ...options,
3961
+ content: stack => {
3962
+ return createVNode(VForm, {
3963
+ "disableAutoScroll": true,
3964
+ "size": size,
3965
+ "onVnodeMounted": vnode => {
3966
+ form = vnode.component.ctx.form;
3967
+ },
3968
+ "onVnodeBeforeUnmount": () => {
3969
+ form = undefined;
3970
+ },
3971
+ "onSubmit": ev => {
3972
+ stack.resolve(value);
3973
+ }
3974
+ }, {
3975
+ default: () => [createVNode(VTextField, mergeProps(options.input, {
3976
+ "modelValue": value,
3977
+ "onChange": ev => {
3978
+ stack.value = ev;
3979
+ value = ev;
3980
+ }
3981
+ }), null)]
3982
+ });
3983
+ }
3984
+ });
3985
+ return this.dialog(resolved);
3986
+ }
3987
+
3433
3988
  }
3434
3989
 
3435
3990
  class VuiPlugin {
@@ -3473,7 +4028,7 @@ class VuiPlugin {
3473
4028
  ...stack
3474
4029
  }); // Vui
3475
4030
 
3476
- const $vui = new VuiService(opts);
4031
+ const $vui = new VuiService(opts, app.config.globalProperties.$vstack);
3477
4032
  app.provide(VuiInjectionKey, $vui);
3478
4033
  app.config.globalProperties.$vui = $vui;
3479
4034
 
@@ -3489,4 +4044,4 @@ function installVuiPlugin(app, opts) {
3489
4044
  return app.use(VuiPlugin, opts);
3490
4045
  }
3491
4046
 
3492
- export { CONTROL_FIELD_VARIANTS, CONTROL_SIZES, PAGINATION_ALIGNS, VApp, VBreadcrumbs, VButton, 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, 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 };
4047
+ 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 };