@fastkit/vui 0.6.36 → 0.6.40

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.
Files changed (188) hide show
  1. package/dist/tool/index.js +3 -0
  2. package/dist/tool/vite-plugin.d.ts.map +1 -1
  3. package/dist/vui.cjs.js +214 -19
  4. package/dist/vui.cjs.prod.js +214 -19
  5. package/dist/vui.css +69 -17
  6. package/dist/vui.d.ts +3609 -17
  7. package/dist/vui.esm-bundler.js +214 -21
  8. package/dist/vui.min.css +1 -1
  9. package/dist/vui.min.css.map +1 -1
  10. package/package.json +8 -7
  11. package/src/.DS_Store +0 -0
  12. package/src/assets/.DS_Store +0 -0
  13. package/src/assets/builtins/color-scheme.ts +9 -0
  14. package/src/assets/builtins/media-match.ts +3 -0
  15. package/src/components/.DS_Store +0 -0
  16. package/src/components/VAccordion/VAccordion.scss +2 -0
  17. package/src/components/VAccordion/VAccordion.tsx +5 -0
  18. package/src/components/VAccordion/index.ts +1 -0
  19. package/src/components/VApp/VApp.tsx +17 -0
  20. package/src/components/VApp/index.ts +1 -0
  21. package/src/components/VBreadcrumbs/VBreadcrumbs.scss +61 -0
  22. package/src/components/VBreadcrumbs/VBreadcrumbs.tsx +137 -0
  23. package/src/components/VBreadcrumbs/index.ts +1 -0
  24. package/src/components/VButton/.DS_Store +0 -0
  25. package/src/components/VButton/VButton.scss +137 -0
  26. package/src/components/VButton/VButton.tsx +148 -0
  27. package/src/components/VButton/VButtonGroup.scss +23 -0
  28. package/src/components/VButton/VButtonGroup.tsx +81 -0
  29. package/src/components/VButton/index.ts +2 -0
  30. package/src/components/VCard/VCard.scss +3 -0
  31. package/src/components/VCard/VCard.tsx +20 -0
  32. package/src/components/VCard/VCardActions.scss +10 -0
  33. package/src/components/VCard/VCardActions.tsx +16 -0
  34. package/src/components/VCard/VCardContent.scss +3 -0
  35. package/src/components/VCard/VCardContent.tsx +16 -0
  36. package/src/components/VCard/index.ts +3 -0
  37. package/src/components/VCheckable/VCheckable.scss +103 -0
  38. package/src/components/VCheckable/VCheckable.tsx +60 -0
  39. package/src/components/VCheckable/index.ts +1 -0
  40. package/src/components/VCheckbox/VCheckbox.scss +56 -0
  41. package/src/components/VCheckbox/VCheckbox.tsx +63 -0
  42. package/src/components/VCheckbox/index.ts +1 -0
  43. package/src/components/VCheckboxGroup/.DS_Store +0 -0
  44. package/src/components/VCheckboxGroup/VCheckboxGroup.tsx +11 -0
  45. package/src/components/VCheckboxGroup/index.ts +1 -0
  46. package/src/components/VContentSwitcher/VContentSwitcher.scss +73 -0
  47. package/src/components/VContentSwitcher/VContentSwitcher.tsx +156 -0
  48. package/src/components/VContentSwitcher/index.ts +1 -0
  49. package/src/components/VControlField/VControlField.scss +183 -0
  50. package/src/components/VControlField/VControlField.tsx +152 -0
  51. package/src/components/VControlField/index.ts +1 -0
  52. package/src/components/VDataTable/VDataTable.scss +230 -0
  53. package/src/components/VDataTable/VDataTable.tsx +761 -0
  54. package/src/components/VDataTable/index.ts +1 -0
  55. package/src/components/VDrawerLayout/VDrawerLayout.scss +26 -0
  56. package/src/components/VDrawerLayout/VDrawerLayout.tsx +35 -0
  57. package/src/components/VDrawerLayout/index.ts +1 -0
  58. package/src/components/VForm/VForm.tsx +77 -0
  59. package/src/components/VForm/index.ts +1 -0
  60. package/src/components/VFormControl/VFormControl.scss +59 -0
  61. package/src/components/VFormControl/VFormControl.tsx +85 -0
  62. package/src/components/VFormControl/index.ts +1 -0
  63. package/src/components/VGrid/VGridContainer.scss +4 -0
  64. package/src/components/VGrid/VGridContainer.tsx +191 -0
  65. package/src/components/VGrid/VGridItem.scss +3 -0
  66. package/src/components/VGrid/VGridItem.tsx +110 -0
  67. package/src/components/VGrid/index.ts +2 -0
  68. package/src/components/VGrid/schemes.ts +28 -0
  69. package/src/components/VHero/.DS_Store +0 -0
  70. package/src/components/VHero/VHero.scss +26 -0
  71. package/src/components/VHero/VHero.tsx +52 -0
  72. package/src/components/VHero/index.ts +1 -0
  73. package/src/components/VIcon/VIcon.scss +22 -0
  74. package/src/components/VIcon/VIcon.tsx +110 -0
  75. package/src/components/VIcon/index.ts +1 -0
  76. package/src/components/VListTile/VListTile.scss +71 -0
  77. package/src/components/VListTile/VListTile.tsx +121 -0
  78. package/src/components/VListTile/index.ts +1 -0
  79. package/src/components/VNavigation/VNavigation.scss +12 -0
  80. package/src/components/VNavigation/VNavigation.tsx +79 -0
  81. package/src/components/VNavigation/VNavigationItem.scss +14 -0
  82. package/src/components/VNavigation/VNavigationItem.tsx +252 -0
  83. package/src/components/VNavigation/index.ts +2 -0
  84. package/src/components/VOption/VOption.scss +61 -0
  85. package/src/components/VOption/VOption.tsx +52 -0
  86. package/src/components/VOption/index.ts +1 -0
  87. package/src/components/VOptionGroup/VOptionGroup.scss +3 -0
  88. package/src/components/VOptionGroup/VOptionGroup.tsx +55 -0
  89. package/src/components/VOptionGroup/index.ts +1 -0
  90. package/src/components/VPagination/VPagination.scss +100 -0
  91. package/src/components/VPagination/VPagination.tsx +346 -0
  92. package/src/components/VPagination/index.ts +1 -0
  93. package/src/components/VPaper/VPaper.scss +37 -0
  94. package/src/components/VPaper/VPaper.tsx +78 -0
  95. package/src/components/VPaper/index.ts +1 -0
  96. package/src/components/VRadio/.DS_Store +0 -0
  97. package/src/components/VRadio/VRadio.scss +66 -0
  98. package/src/components/VRadio/VRadio.tsx +56 -0
  99. package/src/components/VRadio/index.ts +1 -0
  100. package/src/components/VRadioGroup/.DS_Store +0 -0
  101. package/src/components/VRadioGroup/VRadioGroup.tsx +10 -0
  102. package/src/components/VRadioGroup/index.ts +1 -0
  103. package/src/components/VSelect/VSelect.scss +78 -0
  104. package/src/components/VSelect/VSelect.tsx +204 -0
  105. package/src/components/VSelect/index.ts +1 -0
  106. package/src/components/VSwitch/VSwitch.scss +125 -0
  107. package/src/components/VSwitch/VSwitch.tsx +66 -0
  108. package/src/components/VSwitch/index.ts +1 -0
  109. package/src/components/VSwitchGroup/.DS_Store +0 -0
  110. package/src/components/VSwitchGroup/VSwitchGroup.tsx +11 -0
  111. package/src/components/VSwitchGroup/index.ts +1 -0
  112. package/src/components/VTabs/.DS_Store +0 -0
  113. package/src/components/VTabs/VTab.scss +73 -0
  114. package/src/components/VTabs/VTab.tsx +88 -0
  115. package/src/components/VTabs/VTabs.scss +49 -0
  116. package/src/components/VTabs/VTabs.tsx +315 -0
  117. package/src/components/VTabs/index.ts +1 -0
  118. package/src/components/VTextCounter/VTextCounter.scss +3 -0
  119. package/src/components/VTextCounter/VTextCounter.tsx +21 -0
  120. package/src/components/VTextCounter/index.ts +1 -0
  121. package/src/components/VTextField/VTextField.scss +45 -0
  122. package/src/components/VTextField/VTextField.tsx +96 -0
  123. package/src/components/VTextField/index.ts +1 -0
  124. package/src/components/VTextarea/VTextarea.scss +41 -0
  125. package/src/components/VTextarea/VTextarea.tsx +93 -0
  126. package/src/components/VTextarea/index.ts +1 -0
  127. package/src/components/VToolbar/.DS_Store +0 -0
  128. package/src/components/VToolbar/VToolbar.scss +26 -0
  129. package/src/components/VToolbar/VToolbar.tsx +44 -0
  130. package/src/components/VToolbar/VToolbarEdge.scss +27 -0
  131. package/src/components/VToolbar/VToolbarEdge.tsx +35 -0
  132. package/src/components/VToolbar/VToolbarMenu.scss +7 -0
  133. package/src/components/VToolbar/VToolbarMenu.tsx +26 -0
  134. package/src/components/VToolbar/VToolbarTitle.scss +22 -0
  135. package/src/components/VToolbar/VToolbarTitle.tsx +25 -0
  136. package/src/components/VToolbar/index.ts +4 -0
  137. package/src/components/VWysiwygEditor/.DS_Store +0 -0
  138. package/src/components/VWysiwygEditor/VWysiwygEditor.scss +60 -0
  139. package/src/components/VWysiwygEditor/VWysiwygEditor.tsx +293 -0
  140. package/src/components/VWysiwygEditor/index.ts +2 -0
  141. package/src/components/VWysiwygEditor/schemes.ts +65 -0
  142. package/src/components/VWysiwygEditor/tools/bullet-list.ts +18 -0
  143. package/src/components/VWysiwygEditor/tools/format-bold.ts +19 -0
  144. package/src/components/VWysiwygEditor/tools/format-italic.ts +18 -0
  145. package/src/components/VWysiwygEditor/tools/format-underline.ts +18 -0
  146. package/src/components/VWysiwygEditor/tools/history.ts +26 -0
  147. package/src/components/VWysiwygEditor/tools/index.ts +8 -0
  148. package/src/components/VWysiwygEditor/tools/link.ts +57 -0
  149. package/src/components/VWysiwygEditor/tools/ordered-list.ts +21 -0
  150. package/src/components/VWysiwygEditor/tools/text-color.ts +14 -0
  151. package/src/components/index.ts +32 -0
  152. package/src/components/kits.ts +1 -0
  153. package/src/components/loading.ts +1 -0
  154. package/src/composables/.DS_Store +0 -0
  155. package/src/composables/control.ts +118 -0
  156. package/src/composables/elevation.ts +34 -0
  157. package/src/composables/form-selector.scss +11 -0
  158. package/src/composables/form-selector.tsx +101 -0
  159. package/src/composables/index.ts +4 -0
  160. package/src/composables/vui.ts +9 -0
  161. package/src/index.ts +10 -0
  162. package/src/injections.ts +61 -0
  163. package/src/logger.ts +7 -0
  164. package/src/plugin.tsx +76 -0
  165. package/src/schemes/control.ts +7 -0
  166. package/src/schemes/elevation.ts +26 -0
  167. package/src/schemes/index.ts +2 -0
  168. package/src/service.tsx +242 -0
  169. package/src/styles/.DS_Store +0 -0
  170. package/src/styles/after-effects/display-flow.scss +346 -0
  171. package/src/styles/after-effects/spacing.scss +155 -0
  172. package/src/styles/after-effects/text.scss +90 -0
  173. package/src/styles/after-effects.scss +3 -0
  174. package/src/styles/base.scss +14 -0
  175. package/src/styles/control.scss +11 -0
  176. package/src/styles/core/functions.scss +62 -0
  177. package/src/styles/core/typo.scss +56 -0
  178. package/src/styles/core.scss +2 -0
  179. package/src/styles/elevation.scss +9 -0
  180. package/src/styles/group.scss +57 -0
  181. package/src/styles/index.scss +9 -0
  182. package/src/styles/transition.scss +11 -0
  183. package/src/styles/typo.scss +11 -0
  184. package/src/styles/variables.scss +320 -0
  185. package/src/styles/wysiwyg.scss +24 -0
  186. package/src/tool/.DS_Store +0 -0
  187. package/src/tool/index.ts +2 -0
  188. package/src/tool/vite-plugin.ts +281 -0
@@ -0,0 +1,27 @@
1
+ // @use '../../styles/core.scss';
2
+
3
+ .v-toolbar-edge {
4
+ display: flex;
5
+ flex: 0 0;
6
+ align-items: center;
7
+ align-self: stretch;
8
+
9
+ &:empty,
10
+ &--empty {
11
+ display: none;
12
+ }
13
+
14
+ $my-negative-margin: calc(-1 * var(--root-em) * 0.75); // -12
15
+ $my-margin: calc(var(--root-em) * 0.75); // -12
16
+
17
+ &--start {
18
+ margin-right: $my-margin;
19
+ margin-left: $my-negative-margin;
20
+ }
21
+
22
+ &--end {
23
+ padding-left: $my-margin;
24
+ margin-right: $my-negative-margin;
25
+ margin-left: auto;
26
+ }
27
+ }
@@ -0,0 +1,35 @@
1
+ import './VToolbarEdge.scss';
2
+ import { defineComponent, computed, PropType } from 'vue';
3
+ import { renderSlotOrEmpty } from '@fastkit/vue-utils';
4
+
5
+ export type VToolbarEdgeEdge = 'start' | 'end';
6
+
7
+ export const VToolbarEdge = defineComponent({
8
+ name: 'VToolbarEdge',
9
+ props: {
10
+ edge: {
11
+ type: String as PropType<VToolbarEdgeEdge>,
12
+ required: true,
13
+ },
14
+ },
15
+ setup(props, ctx) {
16
+ const edge = computed(() => props.edge);
17
+ return () => {
18
+ const children = renderSlotOrEmpty(ctx.slots, 'default');
19
+ const hasChildren = !!children && children.length > 0;
20
+
21
+ return (
22
+ <div
23
+ class={[
24
+ 'v-toolbar-edge',
25
+ `v-toolbar-edge--${edge.value}`,
26
+ {
27
+ [`v-toolbar-edge--empty`]: !hasChildren,
28
+ },
29
+ ]}>
30
+ {children}
31
+ </div>
32
+ );
33
+ };
34
+ },
35
+ });
@@ -0,0 +1,7 @@
1
+ // @use '../../styles/core.scss';
2
+
3
+ .v-toolbar-menu {
4
+ height: 100%;
5
+ margin: 0;
6
+ box-shadow: none;
7
+ }
@@ -0,0 +1,26 @@
1
+ import './VToolbarMenu.scss';
2
+ import { defineComponent } from 'vue';
3
+ import { renderSlotOrEmpty } from '@fastkit/vue-utils';
4
+ import { VButton, vueButtonProps } from '../VButton';
5
+ import { useVui } from '../../injections';
6
+
7
+ export type VToolbarMenuEdge = 'start' | 'end';
8
+
9
+ export const VToolbarMenu = defineComponent({
10
+ name: 'VToolbarMenu',
11
+ inheritAttrs: false,
12
+ props: {} as typeof vueButtonProps,
13
+ setup(props, ctx) {
14
+ const vui = useVui();
15
+ const plain = vui.setting('plainVariant');
16
+
17
+ return () => {
18
+ const variant = props.variant || plain;
19
+ return (
20
+ <VButton {...ctx.attrs} variant={variant} class={['v-toolbar-menu']}>
21
+ {renderSlotOrEmpty(ctx.slots)}
22
+ </VButton>
23
+ );
24
+ };
25
+ },
26
+ });
@@ -0,0 +1,22 @@
1
+ // @use '../../styles/core.scss';
2
+
3
+ .v-toolbar-title {
4
+ display: flex;
5
+ flex-grow: 1;
6
+ margin: 0;
7
+ // font-size: var(--typo-h3-size);
8
+ font-size: 1.25rem;
9
+ // font-weight: var(--typo-h3-weight);
10
+ font-weight: 400;
11
+ // font-size: 16px;
12
+ // font-weight: 500;
13
+ line-height: 1;
14
+
15
+ // font-weight: 500;
16
+ // font-size: 1.25rem;
17
+ // line-height: 1.6;
18
+ // letter-spacing: 0.0075em;
19
+ white-space: nowrap;
20
+
21
+ // @include core.typo('h2');
22
+ }
@@ -0,0 +1,25 @@
1
+ import './VToolbarTitle.scss';
2
+ import { defineComponent, computed } from 'vue';
3
+ import { renderSlotOrEmpty } from '@fastkit/vue-utils';
4
+
5
+ export const VToolbarTitle = defineComponent({
6
+ name: 'VToolbarTitle',
7
+ props: {
8
+ tag: {
9
+ type: String,
10
+ default: 'span',
11
+ },
12
+ },
13
+ setup(props, ctx) {
14
+ const _TagName = computed(() => props.tag);
15
+ return () => {
16
+ const TagName = _TagName.value as 'span';
17
+
18
+ return (
19
+ <TagName class="v-toolbar-title">
20
+ {renderSlotOrEmpty(ctx.slots, 'default')}
21
+ </TagName>
22
+ );
23
+ };
24
+ },
25
+ });
@@ -0,0 +1,4 @@
1
+ export * from './VToolbar';
2
+ export * from './VToolbarMenu';
3
+ export * from './VToolbarEdge';
4
+ export * from './VToolbarTitle';
@@ -0,0 +1,60 @@
1
+ @use '../../styles/core.scss';
2
+
3
+ .v-wysiwyg-editor {
4
+ &--sm {
5
+ --min-height: var(--wysiwyg-min-height-sm);
6
+ --max-height: var(--wysiwyg-max-height-sm);
7
+ }
8
+
9
+ &--md {
10
+ --min-height: var(--wysiwyg-min-height-md);
11
+ --max-height: var(--wysiwyg-max-height-md);
12
+ }
13
+
14
+ &--lg {
15
+ --min-height: var(--wysiwyg-min-height-lg);
16
+ --max-height: var(--wysiwyg-max-height-lg);
17
+ }
18
+
19
+ &__wrapper {
20
+ position: relative;
21
+ }
22
+
23
+ &__floating-toolbar {
24
+ position: absolute;
25
+ right: 0;
26
+ bottom: 100%;
27
+ z-index: 1;
28
+ }
29
+
30
+ &__body {
31
+ position: relative;
32
+ max-height: var(--max-height);
33
+ // max-height: 200px;
34
+ overflow: auto;
35
+ }
36
+
37
+ &__input {
38
+ cursor: text;
39
+
40
+ &__element {
41
+ width: 100%;
42
+ min-width: 0;
43
+ padding: 8px 0;
44
+ margin: 0;
45
+ }
46
+
47
+ &__prose {
48
+ min-height: var(--min-height);
49
+ outline: none;
50
+ }
51
+ }
52
+
53
+ &--disabled-min-heihgt &__input__prose {
54
+ min-height: 0;
55
+ }
56
+
57
+ &--disabled-max-heihgt &__body {
58
+ max-height: none;
59
+ }
60
+ }
@@ -0,0 +1,293 @@
1
+ import './VWysiwygEditor.scss';
2
+ import { defineComponent, Fragment, PropType, computed, ref, watch } from 'vue';
3
+ import {
4
+ createFormControlProps,
5
+ FormControlSlots,
6
+ defineSlotsProps,
7
+ } from '@fastkit/vue-kit';
8
+ import { VFormControl } from '../VFormControl';
9
+ import {
10
+ VControlField,
11
+ createControlFieldProps,
12
+ InputBoxSlots,
13
+ } from '../VControlField';
14
+ import { IconName } from '../VIcon';
15
+ import {
16
+ createTextableProps,
17
+ createTextableEmits,
18
+ TextableControl,
19
+ } from '@fastkit/vue-form-control';
20
+ import {
21
+ createControlProps,
22
+ useControl,
23
+ createControlFieldProviderProps,
24
+ useControlField,
25
+ } from '../../composables';
26
+ import { VTextCounter } from '../VTextCounter';
27
+ import { VUI_WYSIWYG_EDITOR_SYMBOL, useVui } from '../../injections';
28
+ import {
29
+ EditorContent,
30
+ useEditor,
31
+ BubbleMenu,
32
+ FocusPosition,
33
+ } from '@tiptap/vue-3';
34
+ import StarterKit from '@tiptap/starter-kit';
35
+ import { VButton, VButtonGroup } from '../VButton';
36
+ import {
37
+ RawWysiwygEditorTool,
38
+ resolveRawWysiwygEditorTools,
39
+ WysiwygEditorContext,
40
+ } from './schemes';
41
+
42
+ export const VWysiwygEditor = defineComponent({
43
+ name: 'VWysiwygEditor',
44
+ props: {
45
+ // ...props,
46
+ ...createTextableProps(),
47
+ ...createFormControlProps(),
48
+ ...createControlFieldProps(),
49
+ ...createControlFieldProviderProps(),
50
+ ...createControlProps(),
51
+ ...defineSlotsProps<FormControlSlots & InputBoxSlots>(),
52
+ tools: {
53
+ type: Array as PropType<RawWysiwygEditorTool[]>,
54
+ default: () => [],
55
+ },
56
+ floatingToolbar: Boolean,
57
+ disabledMinHeight: Boolean,
58
+ disabledMaxHeight: Boolean,
59
+ },
60
+ emits: {
61
+ ...createTextableEmits(),
62
+ },
63
+ setup(props, ctx) {
64
+ const vui = useVui();
65
+
66
+ const textRef = ref('');
67
+ const toolButtonActiveColor = vui.setting('primaryScope');
68
+
69
+ const wysiwygSettings = computed(() =>
70
+ resolveRawWysiwygEditorTools(props.tools, vui),
71
+ );
72
+
73
+ const control = useControl(props);
74
+ useControlField(props);
75
+
76
+ const inputControl = new TextableControl(props, ctx as any, {
77
+ nodeType: VUI_WYSIWYG_EDITOR_SYMBOL,
78
+ validationValue: () => textRef.value,
79
+ });
80
+
81
+ const extensions = [
82
+ StarterKit.configure({
83
+ bold: false,
84
+ bulletList: false,
85
+ orderedList: false,
86
+ history: false,
87
+ italic: false,
88
+ }),
89
+ ...wysiwygSettings.value.extensions,
90
+ ];
91
+
92
+ const updateEditable = () => {
93
+ if (!editor.value) return;
94
+ editor.value.setEditable(inputControl.canOperation);
95
+ };
96
+
97
+ watch(() => inputControl.canOperation, updateEditable);
98
+
99
+ watch(
100
+ () => props.modelValue,
101
+ (modelValue) => {
102
+ editor.value &&
103
+ editor.value.commands.setContent(
104
+ modelValue == null ? '' : modelValue,
105
+ );
106
+ },
107
+ );
108
+
109
+ const editor = useEditor({
110
+ onCreate: ({ editor }) => {
111
+ textRef.value = editor.getText();
112
+ updateEditable();
113
+ },
114
+ onFocus: (ctx) => {
115
+ inputControl.focusHandler(ctx.event);
116
+ },
117
+ onBlur: (ctx) => {
118
+ inputControl.blurHandler(ctx.event);
119
+ },
120
+ onUpdate: (ev) => {
121
+ inputControl.value = ev.editor.getHTML();
122
+ textRef.value = ev.editor.getText();
123
+ },
124
+ autofocus: props.autofocus,
125
+ content: props.modelValue,
126
+ extensions,
127
+ editorProps: {
128
+ attributes: {
129
+ class: 'v-wysiwyg-editor__input__prose',
130
+ },
131
+ },
132
+ });
133
+
134
+ // editor.value.state.doc.content
135
+
136
+ const focus = (
137
+ position?: FocusPosition,
138
+ options?: {
139
+ scrollIntoView?: boolean | undefined;
140
+ },
141
+ ) => {
142
+ return editor.value.chain().focus(position, options);
143
+ };
144
+
145
+ const blur = () => {
146
+ return editor.value.chain().blur();
147
+ };
148
+
149
+ const wysiwygContext = computed<WysiwygEditorContext>(() => ({
150
+ vui,
151
+ editor: editor.value,
152
+ }));
153
+
154
+ const createTools = (bubbleMenu = false) => {
155
+ const { value: settings } = wysiwygSettings;
156
+ const { value: context } = wysiwygContext;
157
+ const tools = bubbleMenu
158
+ ? settings.tools.filter((t) => !!t.floating)
159
+ : settings.tools;
160
+ const _editor = editor.value;
161
+ const variant = vui.setting(
162
+ bubbleMenu ? 'containedVariant' : 'plainVariant',
163
+ );
164
+
165
+ return (
166
+ <VButtonGroup
167
+ class={{
168
+ 'v-wysiwyg-editor__floating-toolbar': props.floatingToolbar,
169
+ }}
170
+ variant={variant}>
171
+ {tools.map(({ key, icon, onClick, disabled, active }) => {
172
+ const isActive =
173
+ !!_editor && resolveContextableValue(context, active);
174
+ const isDisabled =
175
+ !inputControl.canOperation ||
176
+ (!!_editor && resolveContextableValue(context, disabled));
177
+ let iconName: IconName | undefined;
178
+
179
+ if (typeof icon === 'function') {
180
+ if (_editor) {
181
+ iconName = icon(context);
182
+ }
183
+ } else {
184
+ iconName = icon;
185
+ }
186
+
187
+ if (!iconName) return;
188
+
189
+ return (
190
+ <VButton
191
+ tabindex={-1}
192
+ key={key}
193
+ icon={iconName}
194
+ onClick={(ev) => onClick(context, ev)}
195
+ color={isActive ? toolButtonActiveColor : undefined}
196
+ disabled={isDisabled}
197
+ />
198
+ );
199
+ })}
200
+ </VButtonGroup>
201
+ );
202
+ };
203
+
204
+ return {
205
+ editor,
206
+ ...inputControl.expose(),
207
+ ...control,
208
+ focus,
209
+ blur,
210
+ createTools,
211
+ };
212
+ },
213
+ render() {
214
+ return (
215
+ <VFormControl
216
+ nodeControl={this.nodeControl}
217
+ focused={this.nodeControl.focused}
218
+ class={[
219
+ 'v-wysiwyg-editor',
220
+ this.classes,
221
+ `v-wysiwyg-editor--${this.size}`,
222
+ {
223
+ 'v-wysiwyg-editor--disabled-min-heihgt': this.disabledMinHeight,
224
+ 'v-wysiwyg-editor--disabled-max-heihgt': this.disabledMaxHeight,
225
+ },
226
+ ]}
227
+ label={this.label}
228
+ hint={this.hint}
229
+ hiddenInfo={this.hiddenInfo}
230
+ onClickLabel={(ev) => {
231
+ this.focus('start', { scrollIntoView: true });
232
+ }}
233
+ v-slots={{
234
+ ...this.$slots,
235
+ default: () => {
236
+ const { editor } = this;
237
+
238
+ return (
239
+ <div class="v-wysiwyg-editor__wrapper">
240
+ {!this.isReadonly && this.createTools()}
241
+ <div class="v-wysiwyg-editor__body">
242
+ <VControlField
243
+ class="v-wysiwyg-editor__input"
244
+ autoHeight
245
+ startAdornment={this.startAdornment}
246
+ endAdornment={this.endAdornment}
247
+ // onClickHost={(ev) => {
248
+ // this.focus();
249
+ // }}
250
+ v-slots={{
251
+ ...this.$slots,
252
+ default: () => {
253
+ return (
254
+ <Fragment>
255
+ <EditorContent
256
+ class="v-wysiwyg-editor__input__element wysiwyg"
257
+ editor={editor}
258
+ />
259
+ {!this.floatingToolbar &&
260
+ !!editor &&
261
+ !this.isReadonly && (
262
+ <BubbleMenu
263
+ class="v-wysiwyg-editor__bubble-menu"
264
+ editor={editor}>
265
+ {this.createTools(true)}
266
+ </BubbleMenu>
267
+ )}
268
+ </Fragment>
269
+ );
270
+ },
271
+ }}
272
+ />
273
+ </div>
274
+ </div>
275
+ );
276
+ },
277
+ infoAppends: () => {
278
+ const { counterResult } = this;
279
+ if (!counterResult) return;
280
+ return <VTextCounter {...counterResult} />;
281
+ },
282
+ }}
283
+ />
284
+ );
285
+ },
286
+ });
287
+
288
+ function resolveContextableValue(
289
+ ctx: WysiwygEditorContext,
290
+ source?: boolean | ((ctx: WysiwygEditorContext) => boolean),
291
+ ) {
292
+ return typeof source === 'function' ? source(ctx) : source;
293
+ }
@@ -0,0 +1,2 @@
1
+ export * from './VWysiwygEditor';
2
+ export * from './tools';
@@ -0,0 +1,65 @@
1
+ import { type VuiService } from '../../service';
2
+ import { type Editor, type Extensions } from '@tiptap/vue-3';
3
+ import { type IconName } from '../VIcon';
4
+
5
+ export interface WysiwygEditorContext {
6
+ editor: Editor;
7
+ vui: VuiService;
8
+ }
9
+
10
+ export interface WysiwygEditorTool {
11
+ key: string;
12
+ icon: IconName | ((ctx: WysiwygEditorContext) => IconName);
13
+ active?: boolean | ((ctx: WysiwygEditorContext) => boolean);
14
+ disabled?: boolean | ((ctx: WysiwygEditorContext) => boolean);
15
+ onClick: (ctx: WysiwygEditorContext, ev: MouseEvent) => any;
16
+ floating?: boolean;
17
+ extensions?: Extensions;
18
+ }
19
+
20
+ export type WysiwygEditorToolFactory<Options = void> = (
21
+ vui: VuiService,
22
+ options?: Options,
23
+ ) => WysiwygEditorTool | WysiwygEditorTool[];
24
+
25
+ export type RawWysiwygEditorTool =
26
+ | WysiwygEditorTool
27
+ | WysiwygEditorToolFactory<any>;
28
+
29
+ function resolveRawWysiwygEditorTool(
30
+ raw: RawWysiwygEditorTool,
31
+ vui: VuiService,
32
+ ) {
33
+ return typeof raw === 'function' ? raw(vui) : raw;
34
+ }
35
+
36
+ export interface ResolvedWysiwygEditorSettings {
37
+ tools: WysiwygEditorTool[];
38
+ extensions: Extensions;
39
+ }
40
+
41
+ export function resolveRawWysiwygEditorTools(
42
+ raws: RawWysiwygEditorTool[],
43
+ vui: VuiService,
44
+ ): ResolvedWysiwygEditorSettings {
45
+ const tools: WysiwygEditorTool[] = [];
46
+ const extensions: Extensions = [];
47
+
48
+ raws.forEach((raw) => {
49
+ let resolved = resolveRawWysiwygEditorTool(raw, vui);
50
+ if (!Array.isArray(resolved)) {
51
+ resolved = [resolved];
52
+ }
53
+ resolved.forEach((tool) => {
54
+ tools.push(tool);
55
+ if (tool.extensions) {
56
+ extensions.push(...tool.extensions);
57
+ }
58
+ });
59
+ });
60
+
61
+ return {
62
+ tools,
63
+ extensions,
64
+ };
65
+ }
@@ -0,0 +1,18 @@
1
+ import { WysiwygEditorToolFactory, WysiwygEditorTool } from '../schemes';
2
+ import { BulletList, BulletListOptions } from '@tiptap/extension-bullet-list';
3
+
4
+ export const WysiwygBulletListTool: WysiwygEditorToolFactory<
5
+ BulletListOptions
6
+ > = (vui, options) => {
7
+ const tool: WysiwygEditorTool = {
8
+ key: 'bulletList',
9
+ icon: vui.icon('editorformatListBulleted'),
10
+ active: ({ editor }) => editor.isActive('bulletList'),
11
+ onClick: ({ editor }) => {
12
+ editor.chain().focus().toggleBulletList().run();
13
+ },
14
+ floating: true,
15
+ extensions: [BulletList.configure(options)],
16
+ };
17
+ return tool;
18
+ };
@@ -0,0 +1,19 @@
1
+ import { WysiwygEditorToolFactory, WysiwygEditorTool } from '../schemes';
2
+ import { Bold, BoldOptions } from '@tiptap/extension-bold';
3
+
4
+ export const WysiwygFormatBoldTool: WysiwygEditorToolFactory<BoldOptions> = (
5
+ vui,
6
+ options,
7
+ ) => {
8
+ const tool: WysiwygEditorTool = {
9
+ key: 'formatBold',
10
+ icon: vui.icon('editorformatBold'),
11
+ active: ({ editor }) => editor.isActive('bold'),
12
+ onClick: ({ editor }) => {
13
+ editor.chain().focus().toggleBold().run();
14
+ },
15
+ floating: true,
16
+ extensions: [Bold.configure(options)],
17
+ };
18
+ return tool;
19
+ };
@@ -0,0 +1,18 @@
1
+ import { WysiwygEditorToolFactory, WysiwygEditorTool } from '../schemes';
2
+ import { Italic, ItalicOptions } from '@tiptap/extension-italic';
3
+
4
+ export const WysiwygFormatItalicTool: WysiwygEditorToolFactory<
5
+ ItalicOptions
6
+ > = (vui, options) => {
7
+ const tool: WysiwygEditorTool = {
8
+ key: 'formatItalic',
9
+ icon: vui.icon('editorformatItalic'),
10
+ active: ({ editor }) => editor.isActive('italic'),
11
+ onClick: ({ editor }) => {
12
+ editor.chain().focus().toggleItalic().run();
13
+ },
14
+ floating: true,
15
+ extensions: [Italic.configure(options)],
16
+ };
17
+ return tool;
18
+ };
@@ -0,0 +1,18 @@
1
+ import { WysiwygEditorToolFactory, WysiwygEditorTool } from '../schemes';
2
+ import { Underline, UnderlineOptions } from '@tiptap/extension-underline';
3
+
4
+ export const WysiwygFormatUnderlineTool: WysiwygEditorToolFactory<
5
+ UnderlineOptions
6
+ > = (vui, options) => {
7
+ const tool: WysiwygEditorTool = {
8
+ key: 'formatUnderline',
9
+ icon: vui.icon('editorformatUnderline'),
10
+ active: ({ editor }) => editor.isActive('underline'),
11
+ onClick: ({ editor }) => {
12
+ editor.chain().focus().toggleUnderline().run();
13
+ },
14
+ floating: true,
15
+ extensions: [Underline.configure(options)],
16
+ };
17
+ return tool;
18
+ };
@@ -0,0 +1,26 @@
1
+ import { WysiwygEditorToolFactory, WysiwygEditorTool } from '../schemes';
2
+ import { History, HistoryOptions } from '@tiptap/extension-history';
3
+
4
+ export const WysiwygHistoryTool: WysiwygEditorToolFactory<HistoryOptions> = (
5
+ vui,
6
+ options,
7
+ ) => {
8
+ const undo: WysiwygEditorTool = {
9
+ key: 'history-undo',
10
+ icon: vui.icon('editorUndo'),
11
+ disabled: ({ editor }) => !editor.can().undo(),
12
+ onClick: ({ editor }) => {
13
+ editor.chain().focus().undo().run();
14
+ },
15
+ extensions: [History.configure(options)],
16
+ };
17
+ const redo: WysiwygEditorTool = {
18
+ key: 'history-redo',
19
+ icon: vui.icon('editorRedo'),
20
+ disabled: ({ editor }) => !editor.can().redo(),
21
+ onClick: ({ editor }) => {
22
+ editor.chain().focus().redo().run();
23
+ },
24
+ };
25
+ return [undo, redo];
26
+ };
@@ -0,0 +1,8 @@
1
+ export * from './bullet-list';
2
+ export * from './format-bold';
3
+ export * from './format-italic';
4
+ export * from './format-underline';
5
+ export * from './history';
6
+ export * from './link';
7
+ export * from './ordered-list';
8
+ export * from './text-color';