@fastkit/vui 0.6.32 → 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,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,377 @@ 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
+ },
2096
+ emits: { ...createTextableEmits()
2097
+ },
2098
+
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);
2124
+ const editor = useEditor({
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
+ });
2150
+
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
+ }
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
2217
+ };
2218
+ },
2219
+
2220
+ render() {
2221
+ return createVNode(VFormControl, {
2222
+ "nodeControl": this.nodeControl,
2223
+ "focused": this.nodeControl.focused,
2224
+ "class": ['v-wysiwyg-editor', this.classes],
2225
+ "label": this.label,
2226
+ "hint": this.hint,
2227
+ "hiddenInfo": this.hiddenInfo,
2228
+ "onClickLabel": ev => {
2229
+ this.focus('start', {
2230
+ scrollIntoView: true
2231
+ });
2232
+ }
2233
+ }, { ...this.$slots,
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
+ }
2266
+ });
2267
+ }
2268
+
2269
+ });
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
+
1976
2425
  const {
1977
2426
  props,
1978
2427
  emits
@@ -1983,7 +2432,8 @@ const VForm = defineComponent({
1983
2432
  name: 'VForm',
1984
2433
  props: { ...props,
1985
2434
  ...createControlProps(),
1986
- ...defineSlotsProps()
2435
+ ...defineSlotsProps(),
2436
+ disableAutoScroll: Boolean
1987
2437
  },
1988
2438
  emits,
1989
2439
 
@@ -1992,6 +2442,7 @@ const VForm = defineComponent({
1992
2442
  const nodeControl = useForm(props, ctx, {
1993
2443
  nodeType: VUI_FORM_SYMBOL,
1994
2444
  onAutoValidateError: () => {
2445
+ if (props.disableAutoScroll) return;
1995
2446
  const scroller = getDocumentScroller();
1996
2447
  const {
1997
2448
  firstInvalidEl
@@ -3383,53 +3834,138 @@ const VToolbarTitle = defineComponent({
3383
3834
 
3384
3835
  });
3385
3836
 
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
- }
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
+
3433
3969
  }
3434
3970
 
3435
3971
  class VuiPlugin {
@@ -3473,7 +4009,7 @@ class VuiPlugin {
3473
4009
  ...stack
3474
4010
  }); // Vui
3475
4011
 
3476
- const $vui = new VuiService(opts);
4012
+ const $vui = new VuiService(opts, app.config.globalProperties.$vstack);
3477
4013
  app.provide(VuiInjectionKey, $vui);
3478
4014
  app.config.globalProperties.$vui = $vui;
3479
4015
 
@@ -3489,4 +4025,4 @@ function installVuiPlugin(app, opts) {
3489
4025
  return app.use(VuiPlugin, opts);
3490
4026
  }
3491
4027
 
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 };
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 };