@fastkit/vui 0.12.9 → 0.12.11

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 (33) hide show
  1. package/dist/vui.css +138 -409
  2. package/dist/vui.css.map +1 -1
  3. package/dist/vui.d.ts +97 -409
  4. package/dist/vui.mjs +167 -1125
  5. package/dist/vui.mjs.map +1 -1
  6. package/package.json +18 -40
  7. package/src/components/index.ts +3 -1
  8. package/src/injections.ts +1 -1
  9. package/src/components/VWysiwygEditor/VWysiwygEditor.scss +0 -68
  10. package/src/components/VWysiwygEditor/VWysiwygEditor.tsx +0 -354
  11. package/src/components/VWysiwygEditor/extensions/color.ts +0 -72
  12. package/src/components/VWysiwygEditor/extensions/index.ts +0 -2
  13. package/src/components/VWysiwygEditor/extensions/linter/Linter.scss +0 -139
  14. package/src/components/VWysiwygEditor/extensions/linter/Linter.tsx +0 -210
  15. package/src/components/VWysiwygEditor/extensions/linter/LinterPlugin.ts +0 -65
  16. package/src/components/VWysiwygEditor/extensions/linter/index.ts +0 -5
  17. package/src/components/VWysiwygEditor/extensions/linter/plugins/BadWords.tsx +0 -50
  18. package/src/components/VWysiwygEditor/extensions/linter/plugins/HeadingLevel.ts +0 -39
  19. package/src/components/VWysiwygEditor/extensions/linter/plugins/Punctuation.ts +0 -49
  20. package/src/components/VWysiwygEditor/extensions/linter/plugins/index.ts +0 -3
  21. package/src/components/VWysiwygEditor/extensions/linter/utils.ts +0 -28
  22. package/src/components/VWysiwygEditor/index.ts +0 -4
  23. package/src/components/VWysiwygEditor/schemes.ts +0 -251
  24. package/src/components/VWysiwygEditor/tools/bullet-list.ts +0 -18
  25. package/src/components/VWysiwygEditor/tools/color.scss +0 -134
  26. package/src/components/VWysiwygEditor/tools/color.tsx +0 -90
  27. package/src/components/VWysiwygEditor/tools/format-bold.ts +0 -19
  28. package/src/components/VWysiwygEditor/tools/format-italic.ts +0 -18
  29. package/src/components/VWysiwygEditor/tools/format-underline.ts +0 -18
  30. package/src/components/VWysiwygEditor/tools/history.ts +0 -26
  31. package/src/components/VWysiwygEditor/tools/index.ts +0 -8
  32. package/src/components/VWysiwygEditor/tools/link.ts +0 -57
  33. package/src/components/VWysiwygEditor/tools/ordered-list.ts +0 -21
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fastkit/vui",
3
- "version": "0.12.9",
3
+ "version": "0.12.11",
4
4
  "description": "A simple, extensible UI kit for Vue applications.",
5
5
  "keywords": [
6
6
  "fastkit",
@@ -44,47 +44,25 @@
44
44
  "src"
45
45
  ],
46
46
  "dependencies": {
47
- "@tiptap/core": "2.0.0-beta.220",
48
- "@tiptap/extension-bold": "2.0.0-beta.220",
49
- "@tiptap/extension-bullet-list": "2.0.0-beta.220",
50
- "@tiptap/extension-history": "2.0.0-beta.220",
51
- "@tiptap/extension-italic": "2.0.0-beta.220",
52
- "@tiptap/extension-link": "2.0.0-beta.220",
53
- "@tiptap/extension-ordered-list": "2.0.0-beta.220",
54
- "@tiptap/extension-text-style": "2.0.0-beta.220",
55
- "@tiptap/extension-underline": "2.0.0-beta.220",
56
- "@tiptap/starter-kit": "2.0.0-beta.220",
57
- "@tiptap/vue-3": "2.0.0-beta.220",
58
- "prosemirror-commands": "^1.5.1",
59
- "prosemirror-dropcursor": "^1.8.0",
60
- "prosemirror-gapcursor": "^1.3.1",
61
- "prosemirror-history": "^1.3.0",
62
- "prosemirror-keymap": "^1.2.1",
63
- "prosemirror-model": "^1.19.0",
64
- "prosemirror-schema-list": "^1.2.2",
65
- "prosemirror-state": "^1.4.2",
66
- "prosemirror-transform": "^1.7.1",
67
- "prosemirror-view": "^1.30.2",
68
- "@fastkit/color-scheme": "0.12.9",
69
- "@fastkit/icon-font": "0.12.9",
70
- "@fastkit/color-scheme-gen": "0.12.9",
71
- "@fastkit/helpers": "0.12.9",
72
- "@fastkit/media-match": "0.12.9",
73
- "@fastkit/media-match-gen": "0.12.9",
74
- "@fastkit/rules": "0.12.9",
75
- "@fastkit/stylebase": "0.12.9",
76
- "@fastkit/tiny-logger": "0.12.9",
77
- "@fastkit/vue-app-layout": "0.12.9",
78
- "@fastkit/vue-color-scheme": "0.12.9",
79
- "@fastkit/vue-form-control": "0.12.9",
80
- "@fastkit/vue-loading": "0.12.9",
81
- "@fastkit/vue-media-match": "0.12.9",
82
- "@fastkit/vue-scroller": "0.12.9",
83
- "@fastkit/vue-stack": "0.12.9",
84
- "@fastkit/vue-utils": "0.12.9"
47
+ "@fastkit/color-scheme": "0.12.10",
48
+ "@fastkit/helpers": "0.12.10",
49
+ "@fastkit/icon-font": "0.12.10",
50
+ "@fastkit/media-match": "0.12.10",
51
+ "@fastkit/rules": "0.12.10",
52
+ "@fastkit/stylebase": "0.12.10",
53
+ "@fastkit/vue-app-layout": "0.12.11",
54
+ "@fastkit/vue-color-scheme": "0.12.10",
55
+ "@fastkit/vue-form-control": "0.12.10",
56
+ "@fastkit/color-scheme-gen": "0.12.10",
57
+ "@fastkit/vue-loading": "0.12.10",
58
+ "@fastkit/vue-media-match": "0.12.10",
59
+ "@fastkit/tiny-logger": "0.12.10",
60
+ "@fastkit/vue-scroller": "0.12.10",
61
+ "@fastkit/vue-stack": "0.12.10",
62
+ "@fastkit/media-match-gen": "0.12.10",
63
+ "@fastkit/vue-utils": "0.12.10"
85
64
  },
86
65
  "peerDependencies": {
87
- "vite": "^4.0.4",
88
66
  "vue": "^3.2.0",
89
67
  "vue-router": "^4.1.0"
90
68
  },
@@ -15,6 +15,8 @@ export * from './VDrawerLayout';
15
15
  export * from './VHero';
16
16
  // export * from './VAccordion';
17
17
  export * from './VNavigation';
18
+ export * from './VControlField';
19
+ export * from './VTextCounter';
18
20
  export * from './VFormControl';
19
21
  export * from './VCheckbox';
20
22
  export * from './VCheckboxGroup';
@@ -28,7 +30,7 @@ export * from './VSelect';
28
30
  export * from './VTextField';
29
31
  export * from './VNumberField';
30
32
  export * from './VTextarea';
31
- export * from './VWysiwygEditor';
33
+ // export * from './VWysiwygEditor';
32
34
  export * from './VForm';
33
35
  export * from './VTabs';
34
36
  export * from './VBreadcrumbs';
package/src/injections.ts CHANGED
@@ -18,7 +18,7 @@ export const VuiColorProviderInjectionKey: InjectionKey<VuiColorProvider> =
18
18
 
19
19
  export const VUI_TEXT_FIELD_SYMBOL = 'vui-text-field';
20
20
  export const VUI_TEXTAREA_SYMBOL = 'vui-textarea';
21
- export const VUI_WYSIWYG_EDITOR_SYMBOL = 'vui-wysiwyg-editor';
21
+ // export const VUI_WYSIWYG_EDITOR_SYMBOL = 'vui-wysiwyg-editor';
22
22
  export const VUI_SELECT_SYMBOL = 'vui-select';
23
23
  export const VUI_OPTION_SYMBOL = 'vui-option';
24
24
  export const VUI_CHECKBOX_GROUP_SYMBOL = 'vui-checkbox-group';
@@ -1,68 +0,0 @@
1
- @use '../../styles/core.scss';
2
-
3
- @layer vui {
4
- .v-wysiwyg-editor {
5
- &--sm {
6
- --min-height: var(--wysiwyg-min-height-sm);
7
- --max-height: var(--wysiwyg-max-height-sm);
8
- }
9
-
10
- &--md {
11
- --min-height: var(--wysiwyg-min-height-md);
12
- --max-height: var(--wysiwyg-max-height-md);
13
- }
14
-
15
- &--lg {
16
- --min-height: var(--wysiwyg-min-height-lg);
17
- --max-height: var(--wysiwyg-max-height-lg);
18
- }
19
-
20
- &__wrapper {
21
- position: relative;
22
- }
23
-
24
- .v-control-field__body {
25
- width: 100%;
26
- }
27
-
28
- &__floating-toolbar {
29
- position: absolute;
30
- right: 0;
31
- bottom: 100%;
32
- z-index: 1;
33
- }
34
-
35
- &__body {
36
- position: relative;
37
- width: 100%;
38
- max-height: var(--max-height);
39
- // max-height: 200px;
40
- overflow: auto;
41
- }
42
-
43
- &__input {
44
- cursor: text;
45
-
46
- &__element {
47
- width: 100%;
48
- min-width: 0;
49
- padding: 8px 0;
50
- margin: 0;
51
- }
52
-
53
- &__prose {
54
- width: 100%;
55
- min-height: var(--min-height);
56
- outline: none;
57
- }
58
- }
59
-
60
- &--disabled-min-heihgt &__input__prose {
61
- min-height: 0;
62
- }
63
-
64
- &--disabled-max-heihgt &__body {
65
- max-height: none;
66
- }
67
- }
68
- }
@@ -1,354 +0,0 @@
1
- import './VWysiwygEditor.scss';
2
- import {
3
- defineComponent,
4
- PropType,
5
- computed,
6
- ref,
7
- watch,
8
- onBeforeUnmount,
9
- VNodeChild,
10
- } from 'vue';
11
- import {
12
- createFormControlProps,
13
- FormControlSlots,
14
- } from '@fastkit/vue-form-control';
15
- import { defineSlotsProps } from '@fastkit/vue-utils';
16
- import { VFormControl } from '../VFormControl';
17
- import {
18
- VControlField,
19
- createControlFieldProps,
20
- InputBoxSlots,
21
- } from '../VControlField';
22
- import { IconName } from '../VIcon';
23
- import {
24
- createTextableProps,
25
- createTextableEmits,
26
- TextableControl,
27
- } from '@fastkit/vue-form-control';
28
- import {
29
- createControlProps,
30
- useControl,
31
- createControlFieldProviderProps,
32
- useControlField,
33
- } from '../../composables';
34
- import { VTextCounter } from '../VTextCounter';
35
- import { VUI_WYSIWYG_EDITOR_SYMBOL, useVui } from '../../injections';
36
- import {
37
- EditorContent,
38
- useEditor,
39
- BubbleMenu,
40
- FocusPosition,
41
- } from '@tiptap/vue-3';
42
- import { StarterKit } from '@tiptap/starter-kit';
43
- import { VButton, VButtonGroup } from '../VButton';
44
- import {
45
- RawWysiwygExtension,
46
- resolveRawWysiwygExtensions,
47
- RawWysiwygEditorTool,
48
- resolveRawWysiwygEditorTools,
49
- WysiwygEditorContext,
50
- // EditorEventsOptions,
51
- WysiwygEditorInitializeContext,
52
- } from './schemes';
53
-
54
- export const VWysiwygEditor = defineComponent({
55
- name: 'VWysiwygEditor',
56
- props: {
57
- // ...props,
58
- ...createTextableProps(),
59
- ...createFormControlProps(),
60
- ...createControlFieldProps(),
61
- ...createControlFieldProviderProps(),
62
- ...createControlProps(),
63
- ...defineSlotsProps<FormControlSlots & InputBoxSlots>(),
64
- extensions: {
65
- type: Array as PropType<RawWysiwygExtension[]>,
66
- default: () => [],
67
- },
68
- tools: {
69
- type: Array as PropType<RawWysiwygEditorTool[]>,
70
- default: () => [],
71
- },
72
- floatingToolbar: Boolean,
73
- disabledMinHeight: Boolean,
74
- disabledMaxHeight: Boolean,
75
- },
76
- emits: {
77
- ...createTextableEmits(),
78
- },
79
- setup(props, ctx) {
80
- const vui = useVui();
81
-
82
- const textRef = ref('');
83
- const toolButtonActiveColor = vui.setting('primaryScope');
84
-
85
- const wysiwygSettings = computed(() =>
86
- resolveRawWysiwygEditorTools(props.tools, vui),
87
- );
88
-
89
- const control = useControl(props);
90
- useControlField(props);
91
-
92
- const inputControl = new TextableControl(props, ctx as any, {
93
- nodeType: VUI_WYSIWYG_EDITOR_SYMBOL,
94
- validationValue: () => textRef.value,
95
- });
96
-
97
- const initializeCtx = new WysiwygEditorInitializeContext(() => vui, {
98
- onCreate: ({ editor }) => {
99
- textRef.value = editor.getText();
100
- updateEditable();
101
- },
102
- onFocus: ({ event }) => {
103
- inputControl.focusHandler(event);
104
- },
105
- onBlur: ({ event }) => {
106
- inputControl.blurHandler(event);
107
- },
108
- onUpdate: ({ editor }) => {
109
- inputControl.value = editor.getHTML();
110
- textRef.value = editor.getText();
111
- },
112
- });
113
-
114
- const extensions = [
115
- StarterKit.configure({
116
- bold: false,
117
- bulletList: false,
118
- orderedList: false,
119
- history: false,
120
- italic: false,
121
- }),
122
- // Linter.configure({
123
- // plugins: [BadWords(['abc', 'evidently']), Punctuation, HeadingLevel],
124
- // }),
125
- ...resolveRawWysiwygExtensions(props.extensions, initializeCtx),
126
- ...wysiwygSettings.value.extensions,
127
- ];
128
-
129
- const updateEditable = () => {
130
- if (!editor.value) return;
131
- editor.value.setEditable(inputControl.canOperation);
132
- };
133
-
134
- watch(() => inputControl.canOperation, updateEditable);
135
-
136
- watch(
137
- () => props.modelValue,
138
- (modelValue) => {
139
- const $editor = editor.value;
140
- if (!$editor || $editor.getHTML() === modelValue) return;
141
-
142
- $editor.commands.setContent(
143
- modelValue == null ? '' : modelValue,
144
- false,
145
- );
146
- textRef.value = $editor.getText();
147
- },
148
- );
149
-
150
- initializeCtx.on('create', ({ editor }) => {
151
- textRef.value = editor.getText();
152
- updateEditable();
153
- });
154
-
155
- const editor = useEditor({
156
- ...initializeCtx.editorOptions(),
157
- autofocus: props.autofocus,
158
- content: props.modelValue,
159
- extensions,
160
- editorProps: {
161
- attributes: {
162
- class: 'v-wysiwyg-editor__input__prose',
163
- },
164
- },
165
- });
166
-
167
- // editor.value.state.doc.content
168
-
169
- const focus = (
170
- position?: FocusPosition,
171
- options?: {
172
- scrollIntoView?: boolean | undefined;
173
- },
174
- ) => {
175
- if (!editor.value) return;
176
- return editor.value.chain().focus(position, options);
177
- };
178
-
179
- const blur = () => {
180
- if (!editor.value) return;
181
- return editor.value.chain().blur();
182
- };
183
-
184
- const wysiwygContext = computed<WysiwygEditorContext>(() => {
185
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
186
- const _editor = editor.value!;
187
- // if (!_editor) {
188
- // throw new Error('missing editor value');
189
- // }
190
- return {
191
- vui,
192
- editor: _editor,
193
- };
194
- });
195
-
196
- const createTools = (bubbleMenu = false) => {
197
- const { value: settings } = wysiwygSettings;
198
- const { value: context } = wysiwygContext;
199
- const tools = bubbleMenu
200
- ? settings.tools.filter((t) => !!t.floating)
201
- : settings.tools;
202
- const _editor = editor.value;
203
- const variant = vui.setting(
204
- bubbleMenu ? 'containedVariant' : 'plainVariant',
205
- );
206
-
207
- return (
208
- <VButtonGroup
209
- class={[
210
- 'v-wysiwyg-editor__toolbar',
211
- {
212
- 'v-wysiwyg-editor__floating-toolbar': props.floatingToolbar,
213
- },
214
- ]}
215
- variant={variant}>
216
- {tools.map(({ key, icon, onClick, disabled, active }) => {
217
- const isActive =
218
- !!_editor && resolveContextableValue(context, active);
219
- const isDisabled =
220
- !inputControl.canOperation ||
221
- (!!_editor && resolveContextableValue(context, disabled));
222
- let iconName: IconName | undefined;
223
- let child: VNodeChild;
224
-
225
- if (typeof icon === 'function') {
226
- if (_editor) {
227
- const _child = icon(context);
228
- if (typeof _child === 'function') {
229
- child = _child();
230
- } else {
231
- iconName = _child as any;
232
- }
233
- }
234
- } else {
235
- iconName = icon;
236
- }
237
-
238
- if (!iconName && child == null) return;
239
-
240
- return (
241
- <VButton
242
- tabindex={-1}
243
- key={key}
244
- icon={iconName}
245
- onClick={(ev) => onClick(context, ev)}
246
- color={isActive ? toolButtonActiveColor : undefined}
247
- disabled={isDisabled}>
248
- {child}
249
- </VButton>
250
- );
251
- })}
252
- </VButtonGroup>
253
- );
254
- };
255
-
256
- onBeforeUnmount(() => {
257
- editor.value && editor.value.destroy();
258
- });
259
-
260
- return {
261
- editor,
262
- ...inputControl.expose(),
263
- ...control,
264
- focus,
265
- blur,
266
- createTools,
267
- };
268
- },
269
- render() {
270
- return (
271
- <VFormControl
272
- nodeControl={this.nodeControl}
273
- focused={this.nodeControl.focused}
274
- class={[
275
- 'v-wysiwyg-editor',
276
- this.classes,
277
- `v-wysiwyg-editor--${this.size}`,
278
- {
279
- 'v-wysiwyg-editor--disabled-min-heihgt': this.disabledMinHeight,
280
- 'v-wysiwyg-editor--disabled-max-heihgt': this.disabledMaxHeight,
281
- },
282
- ]}
283
- label={this.label}
284
- hint={this.hint}
285
- hinttip={this.hinttip}
286
- hiddenInfo={this.hiddenInfo}
287
- requiredChip={this.requiredChip}
288
- onClickLabel={(ev) => {
289
- this.focus('start', { scrollIntoView: true });
290
- }}
291
- v-slots={{
292
- ...this.$slots,
293
- default: () => {
294
- const { editor } = this;
295
-
296
- return (
297
- <div class="v-wysiwyg-editor__wrapper">
298
- {!this.isReadonly && this.createTools()}
299
- <VControlField
300
- class="v-wysiwyg-editor__input"
301
- autoHeight
302
- startAdornment={this.startAdornment}
303
- endAdornment={this.endAdornment}
304
- size={this.size}
305
- // onClickHost={(ev) => {
306
- // this.focus();
307
- // }}
308
- v-slots={{
309
- ...this.$slots,
310
- default: () => {
311
- return (
312
- <div class="v-wysiwyg-editor__body">
313
- <EditorContent
314
- {...({
315
- class: 'v-wysiwyg-editor__input__element wysiwyg',
316
- } as any)}
317
- editor={editor}
318
- />
319
- {!this.floatingToolbar &&
320
- !!editor &&
321
- !this.isReadonly && (
322
- <BubbleMenu
323
- {...({
324
- class: 'v-wysiwyg-editor__bubble-menu',
325
- } as any)}
326
- editor={editor}>
327
- {this.createTools(true)}
328
- </BubbleMenu>
329
- )}
330
- </div>
331
- );
332
- },
333
- }}
334
- />
335
- </div>
336
- );
337
- },
338
- infoAppends: () => {
339
- const { counterResult } = this;
340
- if (!counterResult) return;
341
- return <VTextCounter {...counterResult} />;
342
- },
343
- }}
344
- />
345
- );
346
- },
347
- });
348
-
349
- function resolveContextableValue(
350
- ctx: WysiwygEditorContext,
351
- source?: boolean | ((ctx: WysiwygEditorContext) => boolean),
352
- ) {
353
- return typeof source === 'function' ? source(ctx) : source;
354
- }
@@ -1,72 +0,0 @@
1
- import { Extension } from '@tiptap/core';
2
- import '@tiptap/extension-text-style';
3
-
4
- export type WysiwygColorOptions = {
5
- types: string[];
6
- };
7
-
8
- declare module '@tiptap/core' {
9
- interface Commands<ReturnType> {
10
- color: {
11
- /**
12
- * Set the text color
13
- */
14
- setColor: (color: string) => ReturnType;
15
- /**
16
- * Unset the text color
17
- */
18
- unsetColor: () => ReturnType;
19
- };
20
- }
21
- }
22
-
23
- export const WysiwygColorExtension = Extension.create<WysiwygColorOptions>({
24
- name: 'color',
25
-
26
- addOptions() {
27
- return {
28
- types: ['textStyle'],
29
- };
30
- },
31
-
32
- addGlobalAttributes() {
33
- return [
34
- {
35
- types: this.options.types,
36
- attributes: {
37
- color: {
38
- default: null,
39
- parseHTML: (element) => element.style.color.replace(/['"]+/g, ''),
40
- renderHTML: (attributes) => {
41
- if (!attributes.color) {
42
- return {};
43
- }
44
-
45
- return {
46
- style: `color: ${attributes.color}`,
47
- };
48
- },
49
- },
50
- },
51
- },
52
- ];
53
- },
54
-
55
- addCommands() {
56
- return {
57
- setColor:
58
- (color) =>
59
- ({ chain }) => {
60
- return chain().setMark('textStyle', { color }).run();
61
- },
62
- unsetColor:
63
- () =>
64
- ({ chain }) => {
65
- return chain()
66
- .setMark('textStyle', { color: null })
67
- .removeEmptyTextStyle()
68
- .run();
69
- },
70
- };
71
- },
72
- });
@@ -1,2 +0,0 @@
1
- export * from './linter';
2
- export * from './color';