@bitrix24/b24ui-nuxt 2.1.11 → 2.1.15
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.
- package/.nuxt/b24ui.css +2 -0
- package/README-AI.md +1 -1
- package/dist/meta.d.mts +98705 -785
- package/dist/meta.mjs +98705 -785
- package/dist/module.json +1 -1
- package/dist/module.mjs +1 -1
- package/dist/runtime/air-design-tokens/003_b24_context_light.css +1 -1
- package/dist/runtime/air-design-tokens/004_b24_context_dark.css +1 -1
- package/dist/runtime/air-design-tokens/components/popup.css +1 -1
- package/dist/runtime/air-design-tokens/tw-style/font-size.css +1 -1
- package/dist/runtime/components/ContextMenu.d.vue.ts +6 -2
- package/dist/runtime/components/ContextMenu.vue.d.ts +6 -2
- package/dist/runtime/components/ContextMenuContent.vue +3 -2
- package/dist/runtime/components/DropdownMenu.d.vue.ts +6 -2
- package/dist/runtime/components/DropdownMenu.vue +2 -2
- package/dist/runtime/components/DropdownMenu.vue.d.ts +6 -2
- package/dist/runtime/components/DropdownMenuContent.vue +5 -4
- package/dist/runtime/components/Editor.d.vue.ts +87 -0
- package/dist/runtime/components/Editor.vue +185 -0
- package/dist/runtime/components/Editor.vue.d.ts +87 -0
- package/dist/runtime/components/EditorDragHandle.d.vue.ts +60 -0
- package/dist/runtime/components/EditorDragHandle.vue +128 -0
- package/dist/runtime/components/EditorDragHandle.vue.d.ts +60 -0
- package/dist/runtime/components/EditorEmojiMenu.d.vue.ts +35 -0
- package/dist/runtime/components/EditorEmojiMenu.vue +70 -0
- package/dist/runtime/components/EditorEmojiMenu.vue.d.ts +35 -0
- package/dist/runtime/components/EditorMentionMenu.d.vue.ts +39 -0
- package/dist/runtime/components/EditorMentionMenu.vue +74 -0
- package/dist/runtime/components/EditorMentionMenu.vue.d.ts +39 -0
- package/dist/runtime/components/EditorSuggestionMenu.d.vue.ts +52 -0
- package/dist/runtime/components/EditorSuggestionMenu.vue +79 -0
- package/dist/runtime/components/EditorSuggestionMenu.vue.d.ts +52 -0
- package/dist/runtime/components/EditorToolbar.d.vue.ts +80 -0
- package/dist/runtime/components/EditorToolbar.vue +241 -0
- package/dist/runtime/components/EditorToolbar.vue.d.ts +80 -0
- package/dist/runtime/components/FormField.vue +2 -2
- package/dist/runtime/components/InputMenu.d.vue.ts +2 -0
- package/dist/runtime/components/InputMenu.vue +14 -1
- package/dist/runtime/components/InputMenu.vue.d.ts +2 -0
- package/dist/runtime/components/PageCard.vue +2 -1
- package/dist/runtime/components/Pagination.d.vue.ts +0 -1
- package/dist/runtime/components/Pagination.vue.d.ts +0 -1
- package/dist/runtime/components/Select.d.vue.ts +2 -0
- package/dist/runtime/components/Select.vue +14 -1
- package/dist/runtime/components/Select.vue.d.ts +2 -0
- package/dist/runtime/components/SelectMenu.d.vue.ts +2 -0
- package/dist/runtime/components/SelectMenu.vue +14 -1
- package/dist/runtime/components/SelectMenu.vue.d.ts +2 -0
- package/dist/runtime/components/User.vue +0 -1
- package/dist/runtime/components/color-mode/ColorModeSelect.vue +1 -0
- package/dist/runtime/components/locale/LocaleSelect.vue +6 -3
- package/dist/runtime/components/prose/Accordion.vue +1 -1
- package/dist/runtime/components/prose/Callout.vue +0 -1
- package/dist/runtime/components/prose/Card.vue +0 -1
- package/dist/runtime/composables/defineShortcuts.d.ts +2 -1
- package/dist/runtime/composables/defineShortcuts.js +62 -15
- package/dist/runtime/composables/useEditorMenu.d.ts +64 -0
- package/dist/runtime/composables/useEditorMenu.js +448 -0
- package/dist/runtime/dictionary/icons.d.ts +1 -0
- package/dist/runtime/dictionary/icons.js +5 -3
- package/dist/runtime/locale/in.d.ts +3 -0
- package/dist/runtime/locale/in.js +136 -0
- package/dist/runtime/locale/index.d.ts +25 -23
- package/dist/runtime/locale/index.js +11 -10
- package/dist/runtime/types/editor.d.ts +69 -0
- package/dist/runtime/types/editor.js +0 -0
- package/dist/runtime/types/index.d.ts +7 -0
- package/dist/runtime/types/index.js +7 -0
- package/dist/runtime/types/prose.d.ts +2 -0
- package/dist/runtime/types/prose.js +2 -0
- package/dist/runtime/utils/editor.d.ts +69 -0
- package/dist/runtime/utils/editor.js +364 -0
- package/dist/runtime/utils/tv.js +2 -1
- package/dist/runtime/vue/components/color-mode/ColorModeSelect.vue +1 -0
- package/dist/shared/{b24ui-nuxt.Dh5A-7HA.mjs → b24ui-nuxt.BYDi-4ID.mjs} +323 -132
- package/dist/unplugin.mjs +1 -1
- package/dist/vite.mjs +1 -1
- package/package.json +22 -8
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { AppConfig } from '@nuxt/schema';
|
|
2
|
+
import type { Editor } from '@tiptap/vue-3';
|
|
3
|
+
import type { BubbleMenuPluginProps } from '@tiptap/extension-bubble-menu';
|
|
4
|
+
import type { FloatingMenuPluginProps } from '@tiptap/extension-floating-menu';
|
|
5
|
+
import theme from '#build/b24ui/editor-toolbar';
|
|
6
|
+
import type { ButtonProps, DropdownMenuProps, DropdownMenuItem, TooltipProps, LinkPropsKeys } from '../types';
|
|
7
|
+
import type { EditorItem, EditorCustomHandlers } from '../types/editor';
|
|
8
|
+
import type { ArrayOrNested, DynamicSlots, MergeTypes, NestedItem } from '../types/utils';
|
|
9
|
+
import type { ComponentConfig } from '../types/tv';
|
|
10
|
+
type EditorToolbar = ComponentConfig<typeof theme, AppConfig, 'editorToolbar'>;
|
|
11
|
+
type ButtonItem = Omit<ButtonProps, 'type'> & {
|
|
12
|
+
'slot'?: string;
|
|
13
|
+
'tooltip'?: TooltipProps;
|
|
14
|
+
'aria-label'?: string;
|
|
15
|
+
};
|
|
16
|
+
type EditorToolbarButtonItem<H extends EditorCustomHandlers = EditorCustomHandlers> = Omit<ButtonItem, LinkPropsKeys> & EditorItem<H>;
|
|
17
|
+
type EditorToolbarDropdownChildItem<H extends EditorCustomHandlers = EditorCustomHandlers> = DropdownMenuItem | (Omit<DropdownMenuItem, 'type'> & EditorItem<H>);
|
|
18
|
+
type EditorToolbarDropdownItem<H extends EditorCustomHandlers = EditorCustomHandlers> = ButtonItem & DropdownMenuProps<ArrayOrNested<EditorToolbarDropdownChildItem<H>>>;
|
|
19
|
+
export type EditorToolbarItem<H extends EditorCustomHandlers = EditorCustomHandlers> = ButtonItem | EditorToolbarButtonItem<H> | EditorToolbarDropdownItem<H>;
|
|
20
|
+
type EditorToolbarBaseProps<T extends ArrayOrNested<EditorToolbarItem> = ArrayOrNested<EditorToolbarItem>> = {
|
|
21
|
+
/**
|
|
22
|
+
* The element or component this component should render as.
|
|
23
|
+
* @defaultValue 'div'
|
|
24
|
+
*/
|
|
25
|
+
as?: any;
|
|
26
|
+
/**
|
|
27
|
+
* The color of the toolbar controls.
|
|
28
|
+
* @defaultValue 'air-tertiary-no-accent'
|
|
29
|
+
*/
|
|
30
|
+
color?: ButtonProps['color'];
|
|
31
|
+
/**
|
|
32
|
+
* The color of the active toolbar control.
|
|
33
|
+
* @defaultValue 'air-tertiary-accent'
|
|
34
|
+
*/
|
|
35
|
+
activeColor?: ButtonProps['color'];
|
|
36
|
+
/**
|
|
37
|
+
* The size of the toolbar controls.
|
|
38
|
+
* @defaultValue 'sm'
|
|
39
|
+
*/
|
|
40
|
+
size?: ButtonProps['size'];
|
|
41
|
+
items?: T;
|
|
42
|
+
editor: Editor;
|
|
43
|
+
class?: any;
|
|
44
|
+
b24ui?: EditorToolbar['slots'];
|
|
45
|
+
};
|
|
46
|
+
export type EditorToolbarProps<T extends ArrayOrNested<EditorToolbarItem> = ArrayOrNested<EditorToolbarItem>> = (EditorToolbarBaseProps<T> & {
|
|
47
|
+
layout?: 'fixed';
|
|
48
|
+
}) | (EditorToolbarBaseProps<T> & Partial<Omit<BubbleMenuPluginProps, 'editor' | 'element'>> & {
|
|
49
|
+
layout?: 'bubble';
|
|
50
|
+
}) | (EditorToolbarBaseProps<T> & Partial<Omit<FloatingMenuPluginProps, 'editor' | 'element'>> & {
|
|
51
|
+
layout?: 'floating';
|
|
52
|
+
});
|
|
53
|
+
type SlotPropsProps = {
|
|
54
|
+
index: number;
|
|
55
|
+
isActive: (item: EditorToolbarItem) => boolean;
|
|
56
|
+
isDisabled: (item: EditorToolbarItem) => boolean;
|
|
57
|
+
onClick: (e: MouseEvent, item: EditorToolbarItem) => void;
|
|
58
|
+
};
|
|
59
|
+
type SlotProps<T extends EditorToolbarItem> = (props: {
|
|
60
|
+
item: T;
|
|
61
|
+
} & SlotPropsProps) => any;
|
|
62
|
+
export type EditorToolbarSlots<A extends ArrayOrNested<EditorToolbarItem> = ArrayOrNested<EditorToolbarItem>, T extends NestedItem<A> = NestedItem<A>> = {
|
|
63
|
+
item: SlotProps<T>;
|
|
64
|
+
} & DynamicSlots<MergeTypes<T>, undefined, SlotPropsProps>;
|
|
65
|
+
declare const __VLS_export: <T extends ArrayOrNested<EditorToolbarItem>>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_expose?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
|
|
66
|
+
props: __VLS_PrettifyLocal<EditorToolbarProps<T>> & import("vue").PublicProps & (typeof globalThis extends {
|
|
67
|
+
__VLS_PROPS_FALLBACK: infer P;
|
|
68
|
+
} ? P : {});
|
|
69
|
+
expose: (exposed: {}) => void;
|
|
70
|
+
attrs: any;
|
|
71
|
+
slots: EditorToolbarSlots<T, NestedItem<T>>;
|
|
72
|
+
emit: {};
|
|
73
|
+
}>) => import("vue").VNode & {
|
|
74
|
+
__ctx?: Awaited<typeof __VLS_setup>;
|
|
75
|
+
};
|
|
76
|
+
declare const _default: typeof __VLS_export;
|
|
77
|
+
export default _default;
|
|
78
|
+
type __VLS_PrettifyLocal<T> = {
|
|
79
|
+
[K in keyof T as K]: T[K];
|
|
80
|
+
} & {};
|
|
@@ -16,7 +16,7 @@ const props = defineProps({
|
|
|
16
16
|
label: { type: String, required: false },
|
|
17
17
|
description: { type: String, required: false },
|
|
18
18
|
help: { type: String, required: false },
|
|
19
|
-
error: { type: [Boolean, String], required: false },
|
|
19
|
+
error: { type: [Boolean, String], required: false, default: void 0 },
|
|
20
20
|
hint: { type: String, required: false },
|
|
21
21
|
size: { type: null, required: false },
|
|
22
22
|
required: { type: Boolean, required: false },
|
|
@@ -83,7 +83,7 @@ provide(formFieldInjectionKey, computed(() => ({
|
|
|
83
83
|
<div data-slot="container" :class="[(label || !!slots.label || description || !!slots.description) && b24ui.container({ class: props.b24ui?.container })]">
|
|
84
84
|
<slot :error="error" />
|
|
85
85
|
|
|
86
|
-
<div v-if="typeof error === 'string' && error || !!slots.error" :id="`${ariaId}-error`" data-slot="error" :class="b24ui.error({ class: props.b24ui?.error })">
|
|
86
|
+
<div v-if="props.error !== false && (typeof error === 'string' && error || !!slots.error)" :id="`${ariaId}-error`" data-slot="error" :class="b24ui.error({ class: props.b24ui?.error })">
|
|
87
87
|
<slot name="error" :error="error">
|
|
88
88
|
<div data-slot="errorWrapper" :class="b24ui.errorWrapper({ class: props.b24ui?.errorWrapper })">
|
|
89
89
|
<WarningIcon data-slot="errorIcon" :class="b24ui.errorIcon()" />
|
|
@@ -3,6 +3,7 @@ import type { AppConfig } from '@nuxt/schema';
|
|
|
3
3
|
import theme from '#build/b24ui/input-menu';
|
|
4
4
|
import type { UseComponentIconsProps } from '../composables/useComponentIcons';
|
|
5
5
|
import type { AvatarProps, ChipProps, BadgeProps, IconComponent } from '../types';
|
|
6
|
+
import type { ModelModifiers } from '../types/input';
|
|
6
7
|
import type { InputHTMLAttributes } from '../types/html';
|
|
7
8
|
import type { AcceptableValue, ArrayOrNested, GetItemKeys, GetModelValue, GetModelValueEmits, NestedItem, EmitsToProps } from '../types/utils';
|
|
8
9
|
import type { ComponentConfig } from '../types/tv';
|
|
@@ -136,6 +137,7 @@ export interface InputMenuProps<T extends ArrayOrNested<InputMenuItem> = ArrayOr
|
|
|
136
137
|
defaultValue?: GetModelValue<T, VK, M>;
|
|
137
138
|
/** The controlled value of the InputMenu. Can be binded-with with `v-model`. */
|
|
138
139
|
modelValue?: GetModelValue<T, VK, M>;
|
|
140
|
+
modelModifiers?: Omit<ModelModifiers<GetModelValue<T, VK, M>>, 'lazy'>;
|
|
139
141
|
/** Whether multiple options can be selected or not. */
|
|
140
142
|
multiple?: M & boolean;
|
|
141
143
|
tag?: string;
|
|
@@ -14,7 +14,7 @@ import { useComponentIcons } from "../composables/useComponentIcons";
|
|
|
14
14
|
import { useFormField } from "../composables/useFormField";
|
|
15
15
|
import { useLocale } from "../composables/useLocale";
|
|
16
16
|
import { usePortal } from "../composables/usePortal";
|
|
17
|
-
import { compare, get, getDisplayValue, isArrayOfArray } from "../utils";
|
|
17
|
+
import { compare, get, getDisplayValue, isArrayOfArray, looseToNumber } from "../utils";
|
|
18
18
|
import { getEstimateSize } from "../utils/virtualizer";
|
|
19
19
|
import { tv } from "../utils/tv";
|
|
20
20
|
import icons from "../dictionary/icons";
|
|
@@ -48,6 +48,7 @@ const props = defineProps({
|
|
|
48
48
|
items: { type: null, required: false },
|
|
49
49
|
defaultValue: { type: null, required: false },
|
|
50
50
|
modelValue: { type: null, required: false },
|
|
51
|
+
modelModifiers: { type: Object, required: false },
|
|
51
52
|
multiple: { type: Boolean, required: false },
|
|
52
53
|
tag: { type: String, required: false },
|
|
53
54
|
tagColor: { type: null, required: false },
|
|
@@ -184,6 +185,18 @@ function onUpdate(value) {
|
|
|
184
185
|
if (toRaw(props.modelValue) === value) {
|
|
185
186
|
return;
|
|
186
187
|
}
|
|
188
|
+
if (props.modelModifiers?.trim) {
|
|
189
|
+
value = value?.trim() ?? null;
|
|
190
|
+
}
|
|
191
|
+
if (props.modelModifiers?.number) {
|
|
192
|
+
value = looseToNumber(value);
|
|
193
|
+
}
|
|
194
|
+
if (props.modelModifiers?.nullable) {
|
|
195
|
+
value ??= null;
|
|
196
|
+
}
|
|
197
|
+
if (props.modelModifiers?.optional) {
|
|
198
|
+
value ??= void 0;
|
|
199
|
+
}
|
|
187
200
|
const event = new Event("change", { target: { value } });
|
|
188
201
|
emits("change", event);
|
|
189
202
|
emitFormChange();
|
|
@@ -3,6 +3,7 @@ import type { AppConfig } from '@nuxt/schema';
|
|
|
3
3
|
import theme from '#build/b24ui/input-menu';
|
|
4
4
|
import type { UseComponentIconsProps } from '../composables/useComponentIcons';
|
|
5
5
|
import type { AvatarProps, ChipProps, BadgeProps, IconComponent } from '../types';
|
|
6
|
+
import type { ModelModifiers } from '../types/input';
|
|
6
7
|
import type { InputHTMLAttributes } from '../types/html';
|
|
7
8
|
import type { AcceptableValue, ArrayOrNested, GetItemKeys, GetModelValue, GetModelValueEmits, NestedItem, EmitsToProps } from '../types/utils';
|
|
8
9
|
import type { ComponentConfig } from '../types/tv';
|
|
@@ -136,6 +137,7 @@ export interface InputMenuProps<T extends ArrayOrNested<InputMenuItem> = ArrayOr
|
|
|
136
137
|
defaultValue?: GetModelValue<T, VK, M>;
|
|
137
138
|
/** The controlled value of the InputMenu. Can be binded-with with `v-model`. */
|
|
138
139
|
modelValue?: GetModelValue<T, VK, M>;
|
|
140
|
+
modelModifiers?: Omit<ModelModifiers<GetModelValue<T, VK, M>>, 'lazy'>;
|
|
139
141
|
/** Whether multiple options can be selected or not. */
|
|
140
142
|
multiple?: M & boolean;
|
|
141
143
|
tag?: string;
|
|
@@ -51,6 +51,7 @@ const ariaLabel = computed(() => {
|
|
|
51
51
|
:data-orientation="orientation"
|
|
52
52
|
data-slot="root"
|
|
53
53
|
:class="b24ui.root({ class: [props.b24ui?.root, props.class] })"
|
|
54
|
+
v-bind="$attrs"
|
|
54
55
|
@click="onClick"
|
|
55
56
|
>
|
|
56
57
|
<div data-slot="container" :class="b24ui.container({ class: props.b24ui?.container })">
|
|
@@ -92,7 +93,7 @@ const ariaLabel = computed(() => {
|
|
|
92
93
|
<B24Link
|
|
93
94
|
v-if="to"
|
|
94
95
|
:aria-label="ariaLabel"
|
|
95
|
-
v-bind="{ to, target
|
|
96
|
+
v-bind="{ to, target }"
|
|
96
97
|
class="focus:outline-none peer"
|
|
97
98
|
raw
|
|
98
99
|
>
|
|
@@ -3,6 +3,7 @@ import type { AppConfig } from '@nuxt/schema';
|
|
|
3
3
|
import theme from '#build/b24ui/select';
|
|
4
4
|
import type { UseComponentIconsProps } from '../composables/useComponentIcons';
|
|
5
5
|
import type { AvatarProps, ChipProps, BadgeProps, IconComponent } from '../types';
|
|
6
|
+
import type { ModelModifiers } from '../types/input';
|
|
6
7
|
import type { ButtonHTMLAttributes } from '../types/html';
|
|
7
8
|
import type { AcceptableValue, ArrayOrNested, GetItemKeys, GetModelValue, GetModelValueEmits, NestedItem, EmitsToProps } from '../types/utils';
|
|
8
9
|
import type { ComponentConfig } from '../types/tv';
|
|
@@ -115,6 +116,7 @@ export interface SelectProps<T extends ArrayOrNested<SelectItem> = ArrayOrNested
|
|
|
115
116
|
defaultValue?: GetModelValue<T, VK, M>;
|
|
116
117
|
/** The controlled value of the Select. Can be bind as `v-model`. */
|
|
117
118
|
modelValue?: GetModelValue<T, VK, M>;
|
|
119
|
+
modelModifiers?: Omit<ModelModifiers<GetModelValue<T, VK, M>>, 'lazy'>;
|
|
118
120
|
/** Whether multiple options can be selected or not. */
|
|
119
121
|
multiple?: M & boolean;
|
|
120
122
|
/** Highlight the ring color like a focus state. */
|
|
@@ -12,7 +12,7 @@ import { useFieldGroup } from "../composables/useFieldGroup";
|
|
|
12
12
|
import { useComponentIcons } from "../composables/useComponentIcons";
|
|
13
13
|
import { useFormField } from "../composables/useFormField";
|
|
14
14
|
import { usePortal } from "../composables/usePortal";
|
|
15
|
-
import { get, getDisplayValue, isArrayOfArray } from "../utils";
|
|
15
|
+
import { get, getDisplayValue, isArrayOfArray, looseToNumber } from "../utils";
|
|
16
16
|
import { tv } from "../utils/tv";
|
|
17
17
|
import icons from "../dictionary/icons";
|
|
18
18
|
import B24Badge from "./Badge.vue";
|
|
@@ -41,6 +41,7 @@ const props = defineProps({
|
|
|
41
41
|
items: { type: null, required: false },
|
|
42
42
|
defaultValue: { type: null, required: false },
|
|
43
43
|
modelValue: { type: null, required: false },
|
|
44
|
+
modelModifiers: { type: Object, required: false },
|
|
44
45
|
multiple: { type: Boolean, required: false },
|
|
45
46
|
highlight: { type: Boolean, required: false },
|
|
46
47
|
autofocus: { type: Boolean, required: false },
|
|
@@ -119,6 +120,18 @@ onMounted(() => {
|
|
|
119
120
|
}, props.autofocusDelay);
|
|
120
121
|
});
|
|
121
122
|
function onUpdate(value) {
|
|
123
|
+
if (props.modelModifiers?.trim) {
|
|
124
|
+
value = value?.trim() ?? null;
|
|
125
|
+
}
|
|
126
|
+
if (props.modelModifiers?.number) {
|
|
127
|
+
value = looseToNumber(value);
|
|
128
|
+
}
|
|
129
|
+
if (props.modelModifiers?.nullable) {
|
|
130
|
+
value ??= null;
|
|
131
|
+
}
|
|
132
|
+
if (props.modelModifiers?.optional) {
|
|
133
|
+
value ??= void 0;
|
|
134
|
+
}
|
|
122
135
|
const event = new Event("change", { target: { value } });
|
|
123
136
|
emits("change", event);
|
|
124
137
|
emitFormChange();
|
|
@@ -3,6 +3,7 @@ import type { AppConfig } from '@nuxt/schema';
|
|
|
3
3
|
import theme from '#build/b24ui/select';
|
|
4
4
|
import type { UseComponentIconsProps } from '../composables/useComponentIcons';
|
|
5
5
|
import type { AvatarProps, ChipProps, BadgeProps, IconComponent } from '../types';
|
|
6
|
+
import type { ModelModifiers } from '../types/input';
|
|
6
7
|
import type { ButtonHTMLAttributes } from '../types/html';
|
|
7
8
|
import type { AcceptableValue, ArrayOrNested, GetItemKeys, GetModelValue, GetModelValueEmits, NestedItem, EmitsToProps } from '../types/utils';
|
|
8
9
|
import type { ComponentConfig } from '../types/tv';
|
|
@@ -115,6 +116,7 @@ export interface SelectProps<T extends ArrayOrNested<SelectItem> = ArrayOrNested
|
|
|
115
116
|
defaultValue?: GetModelValue<T, VK, M>;
|
|
116
117
|
/** The controlled value of the Select. Can be bind as `v-model`. */
|
|
117
118
|
modelValue?: GetModelValue<T, VK, M>;
|
|
119
|
+
modelModifiers?: Omit<ModelModifiers<GetModelValue<T, VK, M>>, 'lazy'>;
|
|
118
120
|
/** Whether multiple options can be selected or not. */
|
|
119
121
|
multiple?: M & boolean;
|
|
120
122
|
/** Highlight the ring color like a focus state. */
|
|
@@ -3,6 +3,7 @@ import type { AppConfig } from '@nuxt/schema';
|
|
|
3
3
|
import theme from '#build/b24ui/select-menu';
|
|
4
4
|
import type { UseComponentIconsProps } from '../composables/useComponentIcons';
|
|
5
5
|
import type { AvatarProps, ChipProps, InputProps, BadgeProps, IconComponent } from '../types';
|
|
6
|
+
import type { ModelModifiers } from '../types/input';
|
|
6
7
|
import type { ButtonHTMLAttributes } from '../types/html';
|
|
7
8
|
import type { AcceptableValue, ArrayOrNested, GetItemKeys, GetModelValue, GetModelValueEmits, NestedItem, EmitsToProps } from '../types/utils';
|
|
8
9
|
import type { ComponentConfig } from '../types/tv';
|
|
@@ -142,6 +143,7 @@ export interface SelectMenuProps<T extends ArrayOrNested<SelectMenuItem> = Array
|
|
|
142
143
|
defaultValue?: GetModelValue<T, VK, M>;
|
|
143
144
|
/** The controlled value of the SelectMenu. Can be binded-with with `v-model`. */
|
|
144
145
|
modelValue?: GetModelValue<T, VK, M>;
|
|
146
|
+
modelModifiers?: Omit<ModelModifiers<GetModelValue<T, VK, M>>, 'lazy'>;
|
|
145
147
|
/** Whether multiple options can be selected or not. */
|
|
146
148
|
multiple?: M & boolean;
|
|
147
149
|
/** Highlight the ring color like a focus state. */
|
|
@@ -13,7 +13,7 @@ import { useComponentIcons } from "../composables/useComponentIcons";
|
|
|
13
13
|
import { useFormField } from "../composables/useFormField";
|
|
14
14
|
import { useLocale } from "../composables/useLocale";
|
|
15
15
|
import { usePortal } from "../composables/usePortal";
|
|
16
|
-
import { compare, get, getDisplayValue, isArrayOfArray } from "../utils";
|
|
16
|
+
import { compare, get, getDisplayValue, isArrayOfArray, looseToNumber } from "../utils";
|
|
17
17
|
import { getEstimateSize } from "../utils/virtualizer";
|
|
18
18
|
import { tv } from "../utils/tv";
|
|
19
19
|
import icons from "../dictionary/icons";
|
|
@@ -47,6 +47,7 @@ const props = defineProps({
|
|
|
47
47
|
items: { type: null, required: false },
|
|
48
48
|
defaultValue: { type: null, required: false },
|
|
49
49
|
modelValue: { type: null, required: false },
|
|
50
|
+
modelModifiers: { type: Object, required: false },
|
|
50
51
|
multiple: { type: Boolean, required: false },
|
|
51
52
|
highlight: { type: Boolean, required: false },
|
|
52
53
|
createItem: { type: [Boolean, String, Object], required: false },
|
|
@@ -188,6 +189,18 @@ function onUpdate(value) {
|
|
|
188
189
|
if (toRaw(props.modelValue) === value) {
|
|
189
190
|
return;
|
|
190
191
|
}
|
|
192
|
+
if (props.modelModifiers?.trim) {
|
|
193
|
+
value = value?.trim() ?? null;
|
|
194
|
+
}
|
|
195
|
+
if (props.modelModifiers?.number) {
|
|
196
|
+
value = looseToNumber(value);
|
|
197
|
+
}
|
|
198
|
+
if (props.modelModifiers?.nullable) {
|
|
199
|
+
value ??= null;
|
|
200
|
+
}
|
|
201
|
+
if (props.modelModifiers?.optional) {
|
|
202
|
+
value ??= void 0;
|
|
203
|
+
}
|
|
191
204
|
const event = new Event("change", { target: { value } });
|
|
192
205
|
emits("change", event);
|
|
193
206
|
emitFormChange();
|
|
@@ -3,6 +3,7 @@ import type { AppConfig } from '@nuxt/schema';
|
|
|
3
3
|
import theme from '#build/b24ui/select-menu';
|
|
4
4
|
import type { UseComponentIconsProps } from '../composables/useComponentIcons';
|
|
5
5
|
import type { AvatarProps, ChipProps, InputProps, BadgeProps, IconComponent } from '../types';
|
|
6
|
+
import type { ModelModifiers } from '../types/input';
|
|
6
7
|
import type { ButtonHTMLAttributes } from '../types/html';
|
|
7
8
|
import type { AcceptableValue, ArrayOrNested, GetItemKeys, GetModelValue, GetModelValueEmits, NestedItem, EmitsToProps } from '../types/utils';
|
|
8
9
|
import type { ComponentConfig } from '../types/tv';
|
|
@@ -142,6 +143,7 @@ export interface SelectMenuProps<T extends ArrayOrNested<SelectMenuItem> = Array
|
|
|
142
143
|
defaultValue?: GetModelValue<T, VK, M>;
|
|
143
144
|
/** The controlled value of the SelectMenu. Can be binded-with with `v-model`. */
|
|
144
145
|
modelValue?: GetModelValue<T, VK, M>;
|
|
146
|
+
modelModifiers?: Omit<ModelModifiers<GetModelValue<T, VK, M>>, 'lazy'>;
|
|
145
147
|
/** Whether multiple options can be selected or not. */
|
|
146
148
|
multiple?: M & boolean;
|
|
147
149
|
/** Highlight the ring color like a focus state. */
|
|
@@ -33,6 +33,7 @@ const props = defineProps({
|
|
|
33
33
|
labelKey: { type: null, required: false },
|
|
34
34
|
descriptionKey: { type: null, required: false },
|
|
35
35
|
defaultValue: { type: null, required: false },
|
|
36
|
+
modelModifiers: { type: Object, required: false },
|
|
36
37
|
multiple: { type: Boolean, required: false },
|
|
37
38
|
highlight: { type: Boolean, required: false },
|
|
38
39
|
createItem: { type: [Boolean, String, Object], required: false },
|
|
@@ -31,6 +31,7 @@ const props = defineProps({
|
|
|
31
31
|
labelKey: { type: null, required: false, default: "name" },
|
|
32
32
|
descriptionKey: { type: null, required: false },
|
|
33
33
|
defaultValue: { type: null, required: false },
|
|
34
|
+
modelModifiers: { type: Object, required: false },
|
|
34
35
|
multiple: { type: Boolean, required: false },
|
|
35
36
|
highlight: { type: Boolean, required: false },
|
|
36
37
|
createItem: { type: [Boolean, String, Object], required: false },
|
|
@@ -60,7 +61,7 @@ function getEmojiFlag(locale) {
|
|
|
60
61
|
// English -> USA
|
|
61
62
|
de: "de",
|
|
62
63
|
// Deutsch
|
|
63
|
-
|
|
64
|
+
es: "es",
|
|
64
65
|
// Catalan -> Spain
|
|
65
66
|
br: "br",
|
|
66
67
|
// Português
|
|
@@ -92,8 +93,10 @@ function getEmojiFlag(locale) {
|
|
|
92
93
|
// ภาษาไทย
|
|
93
94
|
ar: "sa",
|
|
94
95
|
// Arabic -> Saudi Arabia
|
|
95
|
-
|
|
96
|
+
kk: "kz",
|
|
96
97
|
// Kazakh -> Kazakhstan
|
|
98
|
+
hi: "in"
|
|
99
|
+
// Indian (हिन्दी)
|
|
97
100
|
};
|
|
98
101
|
const baseLanguage = locale.split("-")[0]?.toLowerCase() || locale;
|
|
99
102
|
const countryCode = languageToCountry[baseLanguage] || locale.replace(/^.*-/, "").slice(0, 2);
|
|
@@ -115,7 +118,7 @@ function getEmojiFlag(locale) {
|
|
|
115
118
|
|
|
116
119
|
<template #item-leading="{ item }">
|
|
117
120
|
<span class="size-5 text-center">
|
|
118
|
-
{{ getEmojiFlag(item.
|
|
121
|
+
{{ getEmojiFlag(item.locale) }}
|
|
119
122
|
</span>
|
|
120
123
|
</template>
|
|
121
124
|
</B24SelectMenu>
|
|
@@ -37,7 +37,7 @@ onBeforeUpdate(() => rerenderCount.value++);
|
|
|
37
37
|
</script>
|
|
38
38
|
|
|
39
39
|
<template>
|
|
40
|
-
<B24Accordion :type="type" :items="items" :unmount-on-hide="false" :class="props.class" :
|
|
40
|
+
<B24Accordion :type="type" :items="items" :unmount-on-hide="false" :class="props.class" :b24ui="transformUI(b24ui(), props.b24ui)">
|
|
41
41
|
<template #content="{ item }">
|
|
42
42
|
<component :is="item.component" />
|
|
43
43
|
</template>
|
|
@@ -9,7 +9,8 @@ export interface ShortcutsConfig {
|
|
|
9
9
|
}
|
|
10
10
|
export interface ShortcutsOptions {
|
|
11
11
|
chainDelay?: number;
|
|
12
|
+
layoutIndependent?: boolean;
|
|
12
13
|
}
|
|
13
|
-
export declare function extractShortcuts(items: any[] | any[][]): Record<string, Handler>;
|
|
14
|
+
export declare function extractShortcuts(items: any[] | any[][], separator?: '_' | '-'): Record<string, Handler>;
|
|
14
15
|
export declare function defineShortcuts(config: MaybeRef<ShortcutsConfig>, options?: ShortcutsOptions): import("@vueuse/shared").Fn;
|
|
15
16
|
export {};
|
|
@@ -4,12 +4,36 @@ import { useKbd } from "./useKbd.js";
|
|
|
4
4
|
const chainedShortcutRegex = /^[^-]+.*-.*[^-]+$/;
|
|
5
5
|
const combinedShortcutRegex = /^[^_]+.*_.*[^_]+$/;
|
|
6
6
|
const shiftableKeys = ["arrowleft", "arrowright", "arrowup", "arrowright", "tab", "escape", "enter", "backspace"];
|
|
7
|
-
|
|
7
|
+
function convertKeyToCode(key) {
|
|
8
|
+
if (/^[a-z]$/i.test(key)) {
|
|
9
|
+
return `Key${key.toUpperCase()}`;
|
|
10
|
+
}
|
|
11
|
+
if (/^\d$/.test(key)) {
|
|
12
|
+
return `Digit${key}`;
|
|
13
|
+
}
|
|
14
|
+
if (/^f\d+$/i.test(key)) {
|
|
15
|
+
return key.toUpperCase();
|
|
16
|
+
}
|
|
17
|
+
const specialKeys = {
|
|
18
|
+
space: "Space",
|
|
19
|
+
enter: "Enter",
|
|
20
|
+
escape: "Escape",
|
|
21
|
+
tab: "Tab",
|
|
22
|
+
backspace: "Backspace",
|
|
23
|
+
delete: "Delete",
|
|
24
|
+
arrowup: "ArrowUp",
|
|
25
|
+
arrowdown: "ArrowDown",
|
|
26
|
+
arrowleft: "ArrowLeft",
|
|
27
|
+
arrowright: "ArrowRight"
|
|
28
|
+
};
|
|
29
|
+
return specialKeys[key.toLowerCase()] || key;
|
|
30
|
+
}
|
|
31
|
+
export function extractShortcuts(items, separator = "_") {
|
|
8
32
|
const shortcuts = {};
|
|
9
33
|
function traverse(items2) {
|
|
10
34
|
items2.forEach((item) => {
|
|
11
35
|
if (item.kbds?.length && (item.onSelect || item.onClick)) {
|
|
12
|
-
const shortcutKey = item.kbds.join(
|
|
36
|
+
const shortcutKey = item.kbds.join(separator);
|
|
13
37
|
shortcuts[shortcutKey] = item.onSelect || item.onClick;
|
|
14
38
|
}
|
|
15
39
|
if (item.children) {
|
|
@@ -31,14 +55,16 @@ export function defineShortcuts(config, options = {}) {
|
|
|
31
55
|
const debouncedClearChainedInput = useDebounceFn(clearChainedInput, options.chainDelay ?? 800);
|
|
32
56
|
const { macOS } = useKbd();
|
|
33
57
|
const activeElement = useActiveElement();
|
|
58
|
+
const layoutIndependent = options.layoutIndependent ?? false;
|
|
59
|
+
const shiftableCodes = shiftableKeys.map((k) => convertKeyToCode(k));
|
|
34
60
|
const onKeyDown = (e) => {
|
|
35
61
|
if (!e.key) {
|
|
36
62
|
return;
|
|
37
63
|
}
|
|
38
|
-
const alphabetKey = /^[a-z]{1}$/i.test(e.key);
|
|
39
|
-
const shiftableKey = shiftableKeys.includes(e.key.toLowerCase());
|
|
64
|
+
const alphabetKey = layoutIndependent ? /^Key[A-Z]$/i.test(e.code) : /^[a-z]{1}$/i.test(e.key);
|
|
65
|
+
const shiftableKey = layoutIndependent ? shiftableCodes.includes(e.code) : shiftableKeys.includes(e.key.toLowerCase());
|
|
40
66
|
let chainedKey;
|
|
41
|
-
chainedInputs.value.push(e.key);
|
|
67
|
+
chainedInputs.value.push(layoutIndependent ? e.code : e.key);
|
|
42
68
|
if (chainedInputs.value.length >= 2) {
|
|
43
69
|
chainedKey = chainedInputs.value.slice(-2).join("-");
|
|
44
70
|
for (const shortcut of shortcuts.value.filter((s) => s.chained)) {
|
|
@@ -54,8 +80,14 @@ export function defineShortcuts(config, options = {}) {
|
|
|
54
80
|
}
|
|
55
81
|
}
|
|
56
82
|
for (const shortcut of shortcuts.value.filter((s) => !s.chained)) {
|
|
57
|
-
if (
|
|
58
|
-
|
|
83
|
+
if (layoutIndependent) {
|
|
84
|
+
if (e.code !== shortcut.key) {
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
} else {
|
|
88
|
+
if (e.key.toLowerCase() !== shortcut.key) {
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
59
91
|
}
|
|
60
92
|
if (e.metaKey !== shortcut.metaKey) {
|
|
61
93
|
continue;
|
|
@@ -98,17 +130,32 @@ export function defineShortcuts(config, options = {}) {
|
|
|
98
130
|
}
|
|
99
131
|
const chained = key.includes("-") && key !== "-" && !key.includes("_");
|
|
100
132
|
if (chained) {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
133
|
+
if (layoutIndependent) {
|
|
134
|
+
const parts = key.split("-").map((p) => convertKeyToCode(p));
|
|
135
|
+
shortcut = {
|
|
136
|
+
key: parts.join("-"),
|
|
137
|
+
metaKey: false,
|
|
138
|
+
ctrlKey: false,
|
|
139
|
+
shiftKey: false,
|
|
140
|
+
altKey: false
|
|
141
|
+
};
|
|
142
|
+
} else {
|
|
143
|
+
shortcut = {
|
|
144
|
+
key: key.toLowerCase(),
|
|
145
|
+
metaKey: false,
|
|
146
|
+
ctrlKey: false,
|
|
147
|
+
shiftKey: false,
|
|
148
|
+
altKey: false
|
|
149
|
+
};
|
|
150
|
+
}
|
|
108
151
|
} else {
|
|
109
152
|
const keySplit = key.toLowerCase().split("_").map((k) => k);
|
|
153
|
+
let baseKey = keySplit.filter((k) => !["meta", "command", "ctrl", "shift", "alt", "option"].includes(k)).join("_");
|
|
154
|
+
if (layoutIndependent) {
|
|
155
|
+
baseKey = convertKeyToCode(baseKey);
|
|
156
|
+
}
|
|
110
157
|
shortcut = {
|
|
111
|
-
key:
|
|
158
|
+
key: baseKey,
|
|
112
159
|
metaKey: keySplit.includes("meta") || keySplit.includes("command"),
|
|
113
160
|
ctrlKey: keySplit.includes("ctrl"),
|
|
114
161
|
shiftKey: keySplit.includes("shift"),
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { Ref, ComputedRef, MaybeRef } from 'vue';
|
|
2
|
+
import type { Editor } from '@tiptap/vue-3';
|
|
3
|
+
import type { FloatingUIOptions } from '../types/editor';
|
|
4
|
+
export interface EditorMenuOptions<T = any> {
|
|
5
|
+
editor: Editor;
|
|
6
|
+
/**
|
|
7
|
+
* The trigger character (e.g., '/', '@', ':')
|
|
8
|
+
*/
|
|
9
|
+
char: string;
|
|
10
|
+
/**
|
|
11
|
+
* Plugin key to identify this menu
|
|
12
|
+
*/
|
|
13
|
+
pluginKey: string;
|
|
14
|
+
/**
|
|
15
|
+
* The items to display (can be a flat array or grouped)
|
|
16
|
+
*/
|
|
17
|
+
items?: MaybeRef<T[] | T[][] | undefined>;
|
|
18
|
+
/**
|
|
19
|
+
* Fields to filter items by.
|
|
20
|
+
* @defaultValue ['label']
|
|
21
|
+
*/
|
|
22
|
+
filterFields?: string[];
|
|
23
|
+
/**
|
|
24
|
+
* Function to filter items based on query
|
|
25
|
+
*/
|
|
26
|
+
filter?: (items: T[], query: string) => T[];
|
|
27
|
+
/**
|
|
28
|
+
* Maximum number of items to display
|
|
29
|
+
* @defaultValue 42
|
|
30
|
+
*/
|
|
31
|
+
limit?: number;
|
|
32
|
+
/**
|
|
33
|
+
* Function to execute when an item is selected
|
|
34
|
+
*/
|
|
35
|
+
onSelect: (editor: Editor, range: any, item: T) => void;
|
|
36
|
+
/**
|
|
37
|
+
* Function to render each menu item
|
|
38
|
+
*/
|
|
39
|
+
renderItem: (item: T, b24ui: ComputedRef<any>) => any;
|
|
40
|
+
/**
|
|
41
|
+
* The options for positioning the menu. Those are passed to Floating UI and include options for the placement, offset, flip, shift, size, autoPlacement, hide, and inline middleware.
|
|
42
|
+
* @defaultValue { strategy: 'absolute', placement: 'bottom-start', offset: 8, shift: { padding: 8 } }
|
|
43
|
+
* @see https://floating-ui.com/docs/computePosition#options
|
|
44
|
+
*/
|
|
45
|
+
options?: FloatingUIOptions;
|
|
46
|
+
/**
|
|
47
|
+
* The DOM element to append the menu to. Default is the editor's parent element.
|
|
48
|
+
*
|
|
49
|
+
* Sometimes the menu needs to be appended to a different DOM context due to accessibility, clipping, or z-index issues.
|
|
50
|
+
*
|
|
51
|
+
* @type {HTMLElement}
|
|
52
|
+
* @default editor.view.dom.parentElement
|
|
53
|
+
*/
|
|
54
|
+
appendTo?: HTMLElement | (() => HTMLElement);
|
|
55
|
+
/**
|
|
56
|
+
* UI styles computed ref
|
|
57
|
+
*/
|
|
58
|
+
b24ui: ComputedRef<any>;
|
|
59
|
+
}
|
|
60
|
+
export declare function useEditorMenu<T = any>(options: EditorMenuOptions<T>): {
|
|
61
|
+
plugin: import("prosemirror-state").Plugin<any>;
|
|
62
|
+
destroy: () => void;
|
|
63
|
+
filteredItems: Ref<T[], T[]>;
|
|
64
|
+
};
|