@finema/core 2.14.0 → 2.15.0
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/dist/module.json +1 -1
- package/dist/module.mjs +1 -1
- package/dist/runtime/components/FlexDeck/Base.vue +1 -1
- package/dist/runtime/components/Form/Fields.vue +23 -15
- package/dist/runtime/components/Form/InputRadio/index.vue +56 -0
- package/dist/runtime/components/Form/InputRadio/index.vue.d.ts +11 -0
- package/dist/runtime/components/Form/InputRadio/types.d.ts +19 -0
- package/dist/runtime/components/Form/InputRadio/types.js +0 -0
- package/dist/runtime/components/Form/InputUploadDropzoneAuto/EmptyState.vue +1 -1
- package/dist/runtime/components/Form/InputUploadDropzoneAuto/FailedState.vue +1 -1
- package/dist/runtime/components/Form/InputUploadDropzoneAuto/useUploadState.js +8 -11
- package/dist/runtime/components/Form/InputWYSIWYG/UploadImageForm.vue +38 -0
- package/dist/runtime/components/Form/InputWYSIWYG/UploadImageForm.vue.d.ts +11 -0
- package/dist/runtime/components/Form/InputWYSIWYG/index.vue +281 -0
- package/dist/runtime/components/Form/InputWYSIWYG/index.vue.d.ts +6 -0
- package/dist/runtime/components/Form/InputWYSIWYG/types.d.ts +52 -0
- package/dist/runtime/components/Form/InputWYSIWYG/types.js +0 -0
- package/dist/runtime/components/Form/types.d.ts +3 -1
- package/dist/runtime/components/Image.vue +1 -1
- package/dist/runtime/components/Table/Base.vue +1 -1
- package/dist/runtime/components/Table/index.vue +1 -1
- package/dist/runtime/styles/main.css +1 -1
- package/dist/runtime/theme/index.d.ts +2 -0
- package/dist/runtime/theme/index.js +2 -0
- package/dist/runtime/theme/radioGroup.d.ts +6 -0
- package/dist/runtime/theme/radioGroup.js +6 -0
- package/dist/runtime/theme/uploadFileDropzone.js +4 -4
- package/dist/runtime/theme/wysiwyg.d.ts +53 -0
- package/dist/runtime/theme/wysiwyg.js +53 -0
- package/package.json +3 -2
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div
|
|
2
|
+
<div
|
|
3
3
|
:class="[theme.base({
|
|
4
4
|
class: [$props.class, ui?.base]
|
|
5
|
-
})]"
|
|
6
|
-
>
|
|
7
|
-
<component
|
|
8
|
-
:is="componentMap[option.type]?.component"
|
|
9
|
-
v-for="option in options.filter((item) => !item.isHide)"
|
|
10
|
-
:key="option.props.name"
|
|
11
|
-
:class="option.class"
|
|
12
|
-
:form="form"
|
|
13
|
-
v-bind="{ ...getFieldBinding(option), ...componentMap[option.type]?.props }"
|
|
14
|
-
v-on="option.on ?? {}"
|
|
15
|
-
/>
|
|
16
|
-
</div>
|
|
5
|
+
})]"
|
|
6
|
+
>
|
|
7
|
+
<component
|
|
8
|
+
:is="componentMap[option.type]?.component"
|
|
9
|
+
v-for="option in options.filter((item) => !item.isHide)"
|
|
10
|
+
:key="option.props.name"
|
|
11
|
+
:class="option.class"
|
|
12
|
+
:form="form"
|
|
13
|
+
v-bind="{ ...getFieldBinding(option), ...componentMap[option.type]?.props }"
|
|
14
|
+
v-on="option.on ?? {}"
|
|
15
|
+
/>
|
|
16
|
+
</div>
|
|
17
17
|
</template>
|
|
18
18
|
|
|
19
19
|
<script setup>
|
|
@@ -25,9 +25,11 @@ import FormInputToggle from "./InputToggle/index.vue";
|
|
|
25
25
|
import FormInputCheckbox from "./InputCheckbox/index.vue";
|
|
26
26
|
import FormInputSelect from "./InputSelect/index.vue";
|
|
27
27
|
import FormInputSelectMultiple from "./InputSelectMultiple/index.vue";
|
|
28
|
+
import FormInputRadio from "./InputRadio/index.vue";
|
|
28
29
|
import FormInputDateTime from "./InputDateTime/index.vue";
|
|
29
30
|
import FormInputDateTimeRange from "./InputDateTimeRange/index.vue";
|
|
30
31
|
import FormInputUploadDropzoneAuto from "./InputUploadDropzoneAuto/index.vue";
|
|
32
|
+
import FormInputWYSIWYG from "./InputWYSIWYG/index.vue";
|
|
31
33
|
import { INPUT_TYPES } from "#core/components/Form/types";
|
|
32
34
|
import { formTheme } from "#core/theme/form";
|
|
33
35
|
import { useUiConfig } from "#core/composables/useConfig";
|
|
@@ -84,7 +86,10 @@ const componentMap = {
|
|
|
84
86
|
}
|
|
85
87
|
},
|
|
86
88
|
[INPUT_TYPES.STATIC]: void 0,
|
|
87
|
-
[INPUT_TYPES.RADIO]:
|
|
89
|
+
[INPUT_TYPES.RADIO]: {
|
|
90
|
+
component: FormInputRadio,
|
|
91
|
+
props: {}
|
|
92
|
+
},
|
|
88
93
|
[INPUT_TYPES.DATE_TIME]: {
|
|
89
94
|
component: FormInputDateTime,
|
|
90
95
|
props: {}
|
|
@@ -115,7 +120,10 @@ const componentMap = {
|
|
|
115
120
|
},
|
|
116
121
|
[INPUT_TYPES.UPLOAD_DROPZONE_AUTO_MULTIPLE]: void 0,
|
|
117
122
|
[INPUT_TYPES.UPLOAD_DROPZONE_IMAGE_AUTO_MULTIPLE]: void 0,
|
|
118
|
-
[INPUT_TYPES.WYSIWYG]:
|
|
123
|
+
[INPUT_TYPES.WYSIWYG]: {
|
|
124
|
+
component: FormInputWYSIWYG,
|
|
125
|
+
props: {}
|
|
126
|
+
},
|
|
119
127
|
[INPUT_TYPES.TAGS]: void 0
|
|
120
128
|
};
|
|
121
129
|
const theme = computed(() => useUiConfig(formTheme, "form")({
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<FieldWrapper v-bind="wrapperProps">
|
|
3
|
+
<RadioGroup
|
|
4
|
+
:model-value="value"
|
|
5
|
+
:items="options"
|
|
6
|
+
:variant="variant"
|
|
7
|
+
:orientation="orientation"
|
|
8
|
+
:indicator="indicator"
|
|
9
|
+
:legend="legend"
|
|
10
|
+
:disabled="wrapperProps.disabled"
|
|
11
|
+
:required="wrapperProps.required"
|
|
12
|
+
:name="wrapperProps.name"
|
|
13
|
+
value-key="value"
|
|
14
|
+
label-key="label"
|
|
15
|
+
description-key="description"
|
|
16
|
+
:ui="ui"
|
|
17
|
+
@update:model-value="onChange"
|
|
18
|
+
/>
|
|
19
|
+
</FieldWrapper>
|
|
20
|
+
</template>
|
|
21
|
+
|
|
22
|
+
<script setup>
|
|
23
|
+
import FieldWrapper from "#core/components/Form/FieldWrapper.vue";
|
|
24
|
+
import { useFieldHOC } from "#core/composables/useForm";
|
|
25
|
+
const emits = defineEmits(["change"]);
|
|
26
|
+
const props = defineProps({
|
|
27
|
+
variant: { type: String, required: false, default: "list" },
|
|
28
|
+
orientation: { type: String, required: false, default: "vertical" },
|
|
29
|
+
indicator: { type: String, required: false, default: "start" },
|
|
30
|
+
options: { type: Array, required: true },
|
|
31
|
+
legend: { type: String, required: false },
|
|
32
|
+
form: { type: Object, required: false },
|
|
33
|
+
name: { type: String, required: true },
|
|
34
|
+
errorMessage: { type: String, required: false },
|
|
35
|
+
label: { type: null, required: false },
|
|
36
|
+
description: { type: String, required: false },
|
|
37
|
+
hint: { type: String, required: false },
|
|
38
|
+
rules: { type: null, required: false },
|
|
39
|
+
autoFocus: { type: Boolean, required: false },
|
|
40
|
+
placeholder: { type: String, required: false },
|
|
41
|
+
disabled: { type: Boolean, required: false },
|
|
42
|
+
readonly: { type: Boolean, required: false },
|
|
43
|
+
required: { type: Boolean, required: false },
|
|
44
|
+
help: { type: String, required: false },
|
|
45
|
+
ui: { type: null, required: false }
|
|
46
|
+
});
|
|
47
|
+
const {
|
|
48
|
+
value,
|
|
49
|
+
wrapperProps,
|
|
50
|
+
handleChange
|
|
51
|
+
} = useFieldHOC(props);
|
|
52
|
+
const onChange = (newValue) => {
|
|
53
|
+
handleChange(newValue);
|
|
54
|
+
emits("change", newValue);
|
|
55
|
+
};
|
|
56
|
+
</script>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { IRadioFieldProps } from '#core/components/Form/InputRadio/types';
|
|
2
|
+
declare const _default: import("vue").DefineComponent<IRadioFieldProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
3
|
+
change: (value: any) => any;
|
|
4
|
+
}, string, import("vue").PublicProps, Readonly<IRadioFieldProps> & Readonly<{
|
|
5
|
+
onChange?: ((value: any) => any) | undefined;
|
|
6
|
+
}>, {
|
|
7
|
+
orientation: "horizontal" | "vertical";
|
|
8
|
+
variant: "list" | "card" | "table";
|
|
9
|
+
indicator: "start" | "end" | "hidden";
|
|
10
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
11
|
+
export default _default;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { IFieldProps, IFormFieldBase, INPUT_TYPES } from '#core/components/Form/types';
|
|
2
|
+
import type { IOption } from '#core/types/common';
|
|
3
|
+
export type RadioOption = IOption & {
|
|
4
|
+
label?: string;
|
|
5
|
+
value?: any;
|
|
6
|
+
description?: string;
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
class?: any;
|
|
9
|
+
};
|
|
10
|
+
export interface IRadioFieldProps extends IFieldProps {
|
|
11
|
+
variant?: 'list' | 'card' | 'table';
|
|
12
|
+
orientation?: 'horizontal' | 'vertical';
|
|
13
|
+
indicator?: 'start' | 'end' | 'hidden';
|
|
14
|
+
options: RadioOption[];
|
|
15
|
+
legend?: string;
|
|
16
|
+
}
|
|
17
|
+
export type IRadioField = IFormFieldBase<INPUT_TYPES.RADIO, IRadioFieldProps, {
|
|
18
|
+
change?: (value: any) => void;
|
|
19
|
+
}>;
|
|
File without changes
|
|
@@ -32,8 +32,8 @@ export const useUploadState = (props, emits, onChange, setErrors, value, accepte
|
|
|
32
32
|
};
|
|
33
33
|
const upload = useUploadLoader(request);
|
|
34
34
|
const validateFile = (file) => {
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
if (props.accept && fileAllocate.acceptFile.value) {
|
|
36
|
+
const acceptedTypes = fileAllocate.acceptFile.value;
|
|
37
37
|
const acceptedTypesList = acceptedTypes.split(",").map((type) => type.trim());
|
|
38
38
|
const fileExtension = file.name.toLowerCase().split(".").pop();
|
|
39
39
|
const isValidFileType = acceptedTypesList.some((acceptedType) => {
|
|
@@ -113,6 +113,11 @@ export const useUploadState = (props, emits, onChange, setErrors, value, accepte
|
|
|
113
113
|
processFile(file);
|
|
114
114
|
}
|
|
115
115
|
};
|
|
116
|
+
fileDialog.onChange((files) => {
|
|
117
|
+
if (files?.length) {
|
|
118
|
+
processFile(files[0]);
|
|
119
|
+
}
|
|
120
|
+
});
|
|
116
121
|
const handleOpenFile = () => {
|
|
117
122
|
if (wrapperProps.value.disabled || wrapperProps.value.readonly) return;
|
|
118
123
|
fileDialog.open();
|
|
@@ -136,14 +141,6 @@ export const useUploadState = (props, emits, onChange, setErrors, value, accepte
|
|
|
136
141
|
value: value.value
|
|
137
142
|
});
|
|
138
143
|
};
|
|
139
|
-
watch(
|
|
140
|
-
() => fileDialog.files.value,
|
|
141
|
-
(files) => {
|
|
142
|
-
if (files?.length) {
|
|
143
|
-
processFile(files[0]);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
);
|
|
147
144
|
watch(
|
|
148
145
|
() => upload.status.value.isSuccess,
|
|
149
146
|
(isSuccess2) => {
|
|
@@ -163,7 +160,7 @@ export const useUploadState = (props, emits, onChange, setErrors, value, accepte
|
|
|
163
160
|
() => upload.status.value.isError,
|
|
164
161
|
(isError2) => {
|
|
165
162
|
if (isError2) {
|
|
166
|
-
setErrors(StringHelper.getError(upload.status.value.errorData));
|
|
163
|
+
setErrors("\u0E1E\u0E1A\u0E02\u0E49\u0E2D\u0E1C\u0E34\u0E14\u0E1E\u0E25\u0E32\u0E14: " + StringHelper.getError(upload.status.value.errorData));
|
|
167
164
|
}
|
|
168
165
|
}
|
|
169
166
|
);
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="upload-image-form">
|
|
3
|
+
<input
|
|
4
|
+
ref="fileInput"
|
|
5
|
+
type="file"
|
|
6
|
+
accept="image/*"
|
|
7
|
+
@change="handleFileSelect"
|
|
8
|
+
/>
|
|
9
|
+
<button
|
|
10
|
+
type="button"
|
|
11
|
+
@click="handleUpload"
|
|
12
|
+
>
|
|
13
|
+
Upload
|
|
14
|
+
</button>
|
|
15
|
+
</div>
|
|
16
|
+
</template>
|
|
17
|
+
|
|
18
|
+
<script setup>
|
|
19
|
+
import { ref } from "vue";
|
|
20
|
+
const props = defineProps({
|
|
21
|
+
options: { type: Object, required: false }
|
|
22
|
+
});
|
|
23
|
+
const emit = defineEmits(["submit"]);
|
|
24
|
+
const fileInput = ref();
|
|
25
|
+
const selectedFile = ref(null);
|
|
26
|
+
const handleFileSelect = (event) => {
|
|
27
|
+
const target = event.target;
|
|
28
|
+
const file = target.files?.[0];
|
|
29
|
+
if (file) {
|
|
30
|
+
selectedFile.value = file;
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
const handleUpload = async () => {
|
|
34
|
+
if (!selectedFile.value) return;
|
|
35
|
+
const url = URL.createObjectURL(selectedFile.value);
|
|
36
|
+
emit("submit", url);
|
|
37
|
+
};
|
|
38
|
+
</script>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
options?: {
|
|
3
|
+
requestOptions?: any;
|
|
4
|
+
};
|
|
5
|
+
}
|
|
6
|
+
declare const _default: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
7
|
+
submit: (url: string) => any;
|
|
8
|
+
}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{
|
|
9
|
+
onSubmit?: ((url: string) => any) | undefined;
|
|
10
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
11
|
+
export default _default;
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<FieldWrapper v-bind="wrapperProps">
|
|
3
|
+
<div :class="ui.container()">
|
|
4
|
+
<div
|
|
5
|
+
v-if="showToolbar"
|
|
6
|
+
:class="ui.toolbar()"
|
|
7
|
+
>
|
|
8
|
+
<div
|
|
9
|
+
v-for="(items, index) in menuItems"
|
|
10
|
+
:key="index"
|
|
11
|
+
:class="ui.toolbarGroup()"
|
|
12
|
+
>
|
|
13
|
+
<button
|
|
14
|
+
v-for="item in items"
|
|
15
|
+
:key="item.name"
|
|
16
|
+
:class="[ui.menuItem(), { [ui.menuItemActive()]: item.isActive?.() }]"
|
|
17
|
+
type="button"
|
|
18
|
+
:title="item.title"
|
|
19
|
+
@click="item.action"
|
|
20
|
+
>
|
|
21
|
+
<Icon
|
|
22
|
+
:name="item.icon"
|
|
23
|
+
:class="ui.icon()"
|
|
24
|
+
/>
|
|
25
|
+
</button>
|
|
26
|
+
</div>
|
|
27
|
+
</div>
|
|
28
|
+
<ClientOnly>
|
|
29
|
+
<EditorContent
|
|
30
|
+
:editor="editor"
|
|
31
|
+
:class="ui.editorContent()"
|
|
32
|
+
/>
|
|
33
|
+
<template #fallback>
|
|
34
|
+
<div
|
|
35
|
+
class="min-h-[200px]"
|
|
36
|
+
v-html="value"
|
|
37
|
+
/>
|
|
38
|
+
</template>
|
|
39
|
+
</ClientOnly>
|
|
40
|
+
</div>
|
|
41
|
+
</FieldWrapper>
|
|
42
|
+
</template>
|
|
43
|
+
|
|
44
|
+
<script setup>
|
|
45
|
+
import { computed, watch } from "vue";
|
|
46
|
+
import { EditorContent, useEditor } from "@tiptap/vue-3";
|
|
47
|
+
import StarterKit from "@tiptap/starter-kit";
|
|
48
|
+
import Underline from "@tiptap/extension-underline";
|
|
49
|
+
import TextAlign from "@tiptap/extension-text-align";
|
|
50
|
+
import Link from "@tiptap/extension-link";
|
|
51
|
+
import Image from "@tiptap/extension-image";
|
|
52
|
+
import Youtube from "@tiptap/extension-youtube";
|
|
53
|
+
import { useFieldHOC } from "#core/composables/useForm";
|
|
54
|
+
import FieldWrapper from "#core/components/Form/FieldWrapper.vue";
|
|
55
|
+
import { wysiwygTheme } from "#core/theme/wysiwyg";
|
|
56
|
+
import { useUiConfig } from "#core/composables/useConfig";
|
|
57
|
+
const props = defineProps({
|
|
58
|
+
editable: { type: Boolean, required: false },
|
|
59
|
+
autofocus: { type: Boolean, required: false },
|
|
60
|
+
content: { type: String, required: false },
|
|
61
|
+
toolbar: { type: Object, required: false },
|
|
62
|
+
minHeight: { type: [String, Number], required: false },
|
|
63
|
+
maxHeight: { type: [String, Number], required: false },
|
|
64
|
+
size: { type: String, required: false, default: "md" },
|
|
65
|
+
color: { type: String, required: false, default: "gray" },
|
|
66
|
+
imageUpload: { type: Object, required: false },
|
|
67
|
+
linkOptions: { type: Object, required: false },
|
|
68
|
+
containerUi: { type: null, required: false },
|
|
69
|
+
image: { type: Object, required: false },
|
|
70
|
+
form: { type: Object, required: false },
|
|
71
|
+
name: { type: String, required: true },
|
|
72
|
+
errorMessage: { type: String, required: false },
|
|
73
|
+
label: { type: null, required: false },
|
|
74
|
+
description: { type: String, required: false },
|
|
75
|
+
hint: { type: String, required: false },
|
|
76
|
+
rules: { type: null, required: false },
|
|
77
|
+
autoFocus: { type: Boolean, required: false },
|
|
78
|
+
placeholder: { type: String, required: false },
|
|
79
|
+
disabled: { type: Boolean, required: false },
|
|
80
|
+
readonly: { type: Boolean, required: false },
|
|
81
|
+
required: { type: Boolean, required: false },
|
|
82
|
+
help: { type: String, required: false },
|
|
83
|
+
ui: { type: null, required: false }
|
|
84
|
+
});
|
|
85
|
+
const {
|
|
86
|
+
value,
|
|
87
|
+
wrapperProps
|
|
88
|
+
} = useFieldHOC(props);
|
|
89
|
+
const ui = computed(() => useUiConfig(wysiwygTheme, "wysiwyg")({
|
|
90
|
+
size: props.size,
|
|
91
|
+
color: props.color
|
|
92
|
+
}));
|
|
93
|
+
const showToolbar = computed(() => {
|
|
94
|
+
if (!props.toolbar) return true;
|
|
95
|
+
return Object.values(props.toolbar).some(Boolean);
|
|
96
|
+
});
|
|
97
|
+
const editor = useEditor({
|
|
98
|
+
content: value.value,
|
|
99
|
+
extensions: [
|
|
100
|
+
StarterKit,
|
|
101
|
+
Underline,
|
|
102
|
+
TextAlign.configure({
|
|
103
|
+
types: ["heading", "paragraph"]
|
|
104
|
+
}),
|
|
105
|
+
Link.configure({
|
|
106
|
+
openOnClick: false
|
|
107
|
+
}),
|
|
108
|
+
Image,
|
|
109
|
+
Youtube
|
|
110
|
+
],
|
|
111
|
+
editorProps: {
|
|
112
|
+
attributes: {
|
|
113
|
+
class: "prose px-4 py-2 focus:outline-none min-h-[200px]"
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
onUpdate: ({
|
|
117
|
+
editor: editor2
|
|
118
|
+
}) => {
|
|
119
|
+
value.value = editor2.getHTML();
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
watch(value, (newValue) => {
|
|
123
|
+
if (editor.value && newValue !== editor.value.getHTML()) {
|
|
124
|
+
editor.value.commands.setContent(newValue);
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
const toolbarConfig = {
|
|
128
|
+
format: [
|
|
129
|
+
{
|
|
130
|
+
key: "bold",
|
|
131
|
+
name: "bold",
|
|
132
|
+
icon: "ph:text-b-bold",
|
|
133
|
+
action: () => editor.value?.chain().focus().toggleBold().run(),
|
|
134
|
+
isActive: () => editor.value?.isActive("bold") || false,
|
|
135
|
+
title: "\u0E15\u0E31\u0E27\u0E2B\u0E19\u0E32"
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
key: "italic",
|
|
139
|
+
name: "italic",
|
|
140
|
+
icon: "ph:text-italic",
|
|
141
|
+
action: () => editor.value?.chain().focus().toggleItalic().run(),
|
|
142
|
+
isActive: () => editor.value?.isActive("italic") || false,
|
|
143
|
+
title: "\u0E15\u0E31\u0E27\u0E40\u0E2D\u0E35\u0E22\u0E07"
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
key: "underline",
|
|
147
|
+
name: "underline",
|
|
148
|
+
icon: "ph:text-underline",
|
|
149
|
+
action: () => editor.value?.chain().focus().toggleUnderline().run(),
|
|
150
|
+
isActive: () => editor.value?.isActive("underline") || false,
|
|
151
|
+
title: "\u0E02\u0E35\u0E14\u0E40\u0E2A\u0E49\u0E19\u0E43\u0E15\u0E49"
|
|
152
|
+
}
|
|
153
|
+
],
|
|
154
|
+
list: [
|
|
155
|
+
{
|
|
156
|
+
key: "bulletList",
|
|
157
|
+
name: "bullet-list",
|
|
158
|
+
icon: "ph:list-bullets",
|
|
159
|
+
action: () => editor.value?.chain().focus().toggleBulletList().run(),
|
|
160
|
+
isActive: () => editor.value?.isActive("bulletList") || false,
|
|
161
|
+
title: "\u0E23\u0E32\u0E22\u0E01\u0E32\u0E23\u0E2A\u0E31\u0E0D\u0E25\u0E31\u0E01\u0E29\u0E13\u0E4C"
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
key: "orderedList",
|
|
165
|
+
name: "ordered-list",
|
|
166
|
+
icon: "ph:list-numbers",
|
|
167
|
+
action: () => editor.value?.chain().focus().toggleOrderedList().run(),
|
|
168
|
+
isActive: () => editor.value?.isActive("orderedList") || false,
|
|
169
|
+
title: "\u0E23\u0E32\u0E22\u0E01\u0E32\u0E23\u0E25\u0E33\u0E14\u0E31\u0E1A"
|
|
170
|
+
}
|
|
171
|
+
],
|
|
172
|
+
textAlign: [
|
|
173
|
+
{
|
|
174
|
+
key: "textAlign",
|
|
175
|
+
name: "align-left",
|
|
176
|
+
icon: "ph:text-align-left",
|
|
177
|
+
action: () => editor.value?.chain().focus().setTextAlign("left").run(),
|
|
178
|
+
isActive: () => editor.value?.isActive({
|
|
179
|
+
textAlign: "left"
|
|
180
|
+
}) || false,
|
|
181
|
+
title: "\u0E08\u0E31\u0E14\u0E0A\u0E34\u0E14\u0E0B\u0E49\u0E32\u0E22"
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
key: "textAlign",
|
|
185
|
+
name: "align-center",
|
|
186
|
+
icon: "ph:text-align-center",
|
|
187
|
+
action: () => editor.value?.chain().focus().setTextAlign("center").run(),
|
|
188
|
+
isActive: () => editor.value?.isActive({
|
|
189
|
+
textAlign: "center"
|
|
190
|
+
}) || false,
|
|
191
|
+
title: "\u0E08\u0E31\u0E14\u0E01\u0E36\u0E48\u0E07\u0E01\u0E25\u0E32\u0E07"
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
key: "textAlign",
|
|
195
|
+
name: "align-right",
|
|
196
|
+
icon: "ph:text-align-right",
|
|
197
|
+
action: () => editor.value?.chain().focus().setTextAlign("right").run(),
|
|
198
|
+
isActive: () => editor.value?.isActive({
|
|
199
|
+
textAlign: "right"
|
|
200
|
+
}) || false,
|
|
201
|
+
title: "\u0E08\u0E31\u0E14\u0E0A\u0E34\u0E14\u0E02\u0E27\u0E32"
|
|
202
|
+
}
|
|
203
|
+
],
|
|
204
|
+
media: [
|
|
205
|
+
{
|
|
206
|
+
key: "link",
|
|
207
|
+
name: "link",
|
|
208
|
+
icon: "ph:link-simple",
|
|
209
|
+
action: () => {
|
|
210
|
+
const url = window.prompt("URL");
|
|
211
|
+
if (url) {
|
|
212
|
+
editor.value?.chain().focus().setLink({
|
|
213
|
+
href: url
|
|
214
|
+
}).run();
|
|
215
|
+
}
|
|
216
|
+
},
|
|
217
|
+
isActive: () => editor.value?.isActive("link") || false,
|
|
218
|
+
title: "\u0E41\u0E17\u0E23\u0E01\u0E25\u0E34\u0E07\u0E01\u0E4C"
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
key: "image",
|
|
222
|
+
name: "image",
|
|
223
|
+
icon: "ph:image",
|
|
224
|
+
action: () => {
|
|
225
|
+
const url = window.prompt("URL \u0E23\u0E39\u0E1B\u0E20\u0E32\u0E1E");
|
|
226
|
+
if (url) {
|
|
227
|
+
editor.value?.chain().focus().setImage({
|
|
228
|
+
src: url
|
|
229
|
+
}).run();
|
|
230
|
+
}
|
|
231
|
+
},
|
|
232
|
+
title: "\u0E41\u0E17\u0E23\u0E01\u0E23\u0E39\u0E1B\u0E20\u0E32\u0E1E"
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
key: "youtube",
|
|
236
|
+
name: "video",
|
|
237
|
+
icon: "ph:video-camera",
|
|
238
|
+
action: () => {
|
|
239
|
+
const url = window.prompt("URL \u0E27\u0E34\u0E14\u0E35\u0E42\u0E2D");
|
|
240
|
+
if (url) {
|
|
241
|
+
editor.value?.chain().focus().setYoutubeVideo({
|
|
242
|
+
src: url
|
|
243
|
+
}).run();
|
|
244
|
+
}
|
|
245
|
+
},
|
|
246
|
+
title: "\u0E41\u0E17\u0E23\u0E01\u0E27\u0E34\u0E14\u0E35\u0E42\u0E2D"
|
|
247
|
+
}
|
|
248
|
+
],
|
|
249
|
+
history: [
|
|
250
|
+
{
|
|
251
|
+
key: "undo",
|
|
252
|
+
name: "undo",
|
|
253
|
+
icon: "ph:arrow-counter-clockwise",
|
|
254
|
+
action: () => editor.value?.chain().focus().undo().run(),
|
|
255
|
+
title: "\u0E40\u0E25\u0E34\u0E01\u0E17\u0E33"
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
key: "redo",
|
|
259
|
+
name: "redo",
|
|
260
|
+
icon: "ph:arrow-clockwise",
|
|
261
|
+
action: () => editor.value?.chain().focus().redo().run(),
|
|
262
|
+
title: "\u0E17\u0E33\u0E43\u0E2B\u0E21\u0E48"
|
|
263
|
+
}
|
|
264
|
+
]
|
|
265
|
+
};
|
|
266
|
+
const menuItems = computed(() => {
|
|
267
|
+
const items = [];
|
|
268
|
+
Object.entries(toolbarConfig).forEach(([groupKey, groupItems]) => {
|
|
269
|
+
const enabledItems = groupItems.filter((item) => {
|
|
270
|
+
if (groupKey === "textAlign") {
|
|
271
|
+
return props.toolbar?.textAlign;
|
|
272
|
+
}
|
|
273
|
+
return props.toolbar?.[item.key];
|
|
274
|
+
});
|
|
275
|
+
if (enabledItems.length > 0) {
|
|
276
|
+
items.push(enabledItems);
|
|
277
|
+
}
|
|
278
|
+
});
|
|
279
|
+
return items;
|
|
280
|
+
});
|
|
281
|
+
</script>
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { IWYSIWYGFieldProps } from '#core/components/Form/InputWYSIWYG/types';
|
|
2
|
+
declare const _default: import("vue").DefineComponent<IWYSIWYGFieldProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<IWYSIWYGFieldProps> & Readonly<{}>, {
|
|
3
|
+
size: "xs" | "sm" | "md" | "lg" | "xl";
|
|
4
|
+
color: "primary" | "gray";
|
|
5
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
6
|
+
export default _default;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { Editor } from '@tiptap/vue-3';
|
|
2
|
+
import type { IFieldProps, IFormFieldBase, INPUT_TYPES } from '#core/components/Form/types';
|
|
3
|
+
export interface IWYSIWYGFieldProps extends IFieldProps {
|
|
4
|
+
editable?: boolean;
|
|
5
|
+
autofocus?: boolean;
|
|
6
|
+
content?: string;
|
|
7
|
+
toolbar?: {
|
|
8
|
+
bold?: boolean;
|
|
9
|
+
italic?: boolean;
|
|
10
|
+
underline?: boolean;
|
|
11
|
+
strike?: boolean;
|
|
12
|
+
code?: boolean;
|
|
13
|
+
heading?: boolean | number[];
|
|
14
|
+
paragraph?: boolean;
|
|
15
|
+
bulletList?: boolean;
|
|
16
|
+
orderedList?: boolean;
|
|
17
|
+
blockquote?: boolean;
|
|
18
|
+
codeBlock?: boolean;
|
|
19
|
+
horizontalRule?: boolean;
|
|
20
|
+
link?: boolean;
|
|
21
|
+
image?: boolean;
|
|
22
|
+
youtube?: boolean;
|
|
23
|
+
textAlign?: boolean;
|
|
24
|
+
undo?: boolean;
|
|
25
|
+
redo?: boolean;
|
|
26
|
+
};
|
|
27
|
+
minHeight?: string | number;
|
|
28
|
+
maxHeight?: string | number;
|
|
29
|
+
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
30
|
+
color?: 'primary' | 'gray';
|
|
31
|
+
imageUpload?: {
|
|
32
|
+
enabled?: boolean;
|
|
33
|
+
uploadUrl?: string;
|
|
34
|
+
maxSize?: number;
|
|
35
|
+
accept?: string[];
|
|
36
|
+
headers?: Record<string, string>;
|
|
37
|
+
};
|
|
38
|
+
linkOptions?: {
|
|
39
|
+
openOnClick?: boolean;
|
|
40
|
+
HTMLAttributes?: Record<string, any>;
|
|
41
|
+
};
|
|
42
|
+
containerUi?: any;
|
|
43
|
+
image?: {
|
|
44
|
+
requestOptions?: any;
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
export type IWYSIWYGField = IFormFieldBase<INPUT_TYPES.WYSIWYG, IWYSIWYGFieldProps, {
|
|
48
|
+
change?: (content: string) => void;
|
|
49
|
+
update?: (content: string, editor: Editor) => void;
|
|
50
|
+
focus?: (editor: Editor) => void;
|
|
51
|
+
blur?: (editor: Editor) => void;
|
|
52
|
+
}>;
|
|
File without changes
|
|
@@ -10,6 +10,8 @@ import type { ICheckboxField } from '#core/components/Form/InputCheckbox/types';
|
|
|
10
10
|
import type { ISelectMultipleField } from '#core/components/Form/InputSelectMultiple/types';
|
|
11
11
|
import type { INumberField } from '#core/components/Form/InputNumber/types';
|
|
12
12
|
import type { IDateTimeField } from '#core/components/Form/InputDateTime/date_time_field.types';
|
|
13
|
+
import type { IRadioField } from '#core/components/Form/InputRadio/types';
|
|
14
|
+
import type { IWYSIWYGField } from '#core/components/Form/InputWYSIWYG/types';
|
|
13
15
|
export declare const enum INPUT_TYPES {
|
|
14
16
|
TEXT = "TEXT",
|
|
15
17
|
NUMBER = "NUMBER",
|
|
@@ -62,7 +64,7 @@ export interface IFormFieldBase<I extends INPUT_TYPES, P extends IFieldProps, O>
|
|
|
62
64
|
props: P;
|
|
63
65
|
on?: O;
|
|
64
66
|
}
|
|
65
|
-
export type IFormField = ITextField | INumberField | ITextareaField | IToggleField | ISelectField | ICheckboxField | ISelectMultipleField | IDateTimeField | IDateTimeRangeField | IUploadDropzoneAutoField | IFormFieldBase<INPUT_TYPES.COMPONENT, any, any>;
|
|
67
|
+
export type IFormField = ITextField | INumberField | ITextareaField | IToggleField | ISelectField | ICheckboxField | ISelectMultipleField | IRadioField | IDateTimeField | IDateTimeRangeField | IUploadDropzoneAutoField | IWYSIWYGField | IFormFieldBase<INPUT_TYPES.COMPONENT, any, any>;
|
|
66
68
|
export interface IFileValue {
|
|
67
69
|
url: string;
|
|
68
70
|
path?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
@import "tailwindcss";@import "@nuxt/ui";@theme static{--font-sans:"Noto Sans Thai","Noto Sans Thai Looped","Public Sans",sans-serif;--color-main:#232c5a;--color-main-50:#f4f4f7;--color-main-100:#e9eaef;--color-main-200:#c8cad6;--color-main-300:#a7abbd;--color-main-400:#656b8c;--color-main-500:#232c5a;--color-main-600:#202851;--color-main-700:#151a36;--color-main-800:#101429;--color-main-900:#0b0d1b;--color-main-950:#0b0d1b;--color-secondary:#ee8b36;--color-secondary-50:#fdf1e7;--color-secondary-100:#f9d6b8;--color-secondary-200:#f5bb89;--color-secondary-300:#f1a05a;--color-secondary-400:#ed852b;--color-secondary-500:#d46b12;--color-secondary-600:#a5540e;--color-secondary-700:#763c0a;--color-secondary-800:#472406;--color-secondary-900:#180c02;--color-info:#0d8cee;--color-info-50:#f3f9fe;--color-info-100:#e7f4fd;--color-info-200:#ebf6ff;--color-info-300:#9ed1f8;--color-info-400:#56aff3;--color-info-500:#0d8cee;--color-info-600:#0c7ed6;--color-info-700:#08548f;--color-info-800:#063f6b;--color-info-900:#042a47;--color-error:#f25555;--color-error-50:#fef7f7;--color-error-100:#feeeee;--color-error-200:#ffdfdf;--color-error-300:#fabbbb;--color-error-400:#f68888;--color-error-500:#f25555;--color-error-600:#da4d4d;--color-error-700:#913333;--color-error-800:#6d2626;--color-error-900:#491a1a;--color-success:#3fb061;--color-success-50:#f5fbf7;--color-success-100:#ecf7ef;--color-success-200:#daeee0;--color-success-300:#b2dfc0;--color-success-400:#79c890;--color-success-500:#3fb061;--color-success-600:#399e57;--color-success-700:#266a3a;--color-success-800:#1c4f2c;--color-success-900:#13351d;--color-warning:#ff9a35;--color-warning-50:#fffaf5;--color-warning-100:#fff5eb;--color-warning-200:#fef1cc;--color-warning-300:#ffd7ae;--color-warning-400:#ffb872;--color-warning-500:#ff9a35;--color-warning-600:#e68b30;--color-warning-700:#995c20;--color-warning-800:#734518;--color-warning-900:#4d2e10}::-webkit-scrollbar{-webkit-appearance:none;height:10px;width:10px}::-webkit-scrollbar-thumb{background-color:rgba(0,0,0,.3);border-radius:4px;box-shadow:0 0 1px hsla(0,0%,100%,.5)}:root{--dp-font-family:inherit!important}.dp__theme_light{--dp-primary-color:var(--color-main)!important;--dp-primary-disabled-color:var(--color-main-200)!important}#__nuxt,body,html{@apply w-full h-full}
|
|
1
|
+
@import "tailwindcss";@import "@nuxt/ui";@plugin "@tailwindcss/typography";@source inline("prose");@theme static{--font-sans:"Noto Sans Thai","Noto Sans Thai Looped","Public Sans",sans-serif;--color-main:#232c5a;--color-main-50:#f4f4f7;--color-main-100:#e9eaef;--color-main-200:#c8cad6;--color-main-300:#a7abbd;--color-main-400:#656b8c;--color-main-500:#232c5a;--color-main-600:#202851;--color-main-700:#151a36;--color-main-800:#101429;--color-main-900:#0b0d1b;--color-main-950:#0b0d1b;--color-secondary:#ee8b36;--color-secondary-50:#fdf1e7;--color-secondary-100:#f9d6b8;--color-secondary-200:#f5bb89;--color-secondary-300:#f1a05a;--color-secondary-400:#ed852b;--color-secondary-500:#d46b12;--color-secondary-600:#a5540e;--color-secondary-700:#763c0a;--color-secondary-800:#472406;--color-secondary-900:#180c02;--color-info:#0d8cee;--color-info-50:#f3f9fe;--color-info-100:#e7f4fd;--color-info-200:#ebf6ff;--color-info-300:#9ed1f8;--color-info-400:#56aff3;--color-info-500:#0d8cee;--color-info-600:#0c7ed6;--color-info-700:#08548f;--color-info-800:#063f6b;--color-info-900:#042a47;--color-error:#f25555;--color-error-50:#fef7f7;--color-error-100:#feeeee;--color-error-200:#ffdfdf;--color-error-300:#fabbbb;--color-error-400:#f68888;--color-error-500:#f25555;--color-error-600:#da4d4d;--color-error-700:#913333;--color-error-800:#6d2626;--color-error-900:#491a1a;--color-success:#3fb061;--color-success-50:#f5fbf7;--color-success-100:#ecf7ef;--color-success-200:#daeee0;--color-success-300:#b2dfc0;--color-success-400:#79c890;--color-success-500:#3fb061;--color-success-600:#399e57;--color-success-700:#266a3a;--color-success-800:#1c4f2c;--color-success-900:#13351d;--color-warning:#ff9a35;--color-warning-50:#fffaf5;--color-warning-100:#fff5eb;--color-warning-200:#fef1cc;--color-warning-300:#ffd7ae;--color-warning-400:#ffb872;--color-warning-500:#ff9a35;--color-warning-600:#e68b30;--color-warning-700:#995c20;--color-warning-800:#734518;--color-warning-900:#4d2e10}::-webkit-scrollbar{-webkit-appearance:none;height:10px;width:10px}::-webkit-scrollbar-thumb{background-color:rgba(0,0,0,.3);border-radius:4px;box-shadow:0 0 1px hsla(0,0%,100%,.5)}:root{--dp-font-family:inherit!important}.dp__theme_light{--dp-primary-color:var(--color-main)!important;--dp-primary-disabled-color:var(--color-main-200)!important}#__nuxt,body,html{@apply w-full h-full}
|
|
@@ -11,3 +11,5 @@ export { inputNumberTheme as inputNumber } from './inputNumber.js';
|
|
|
11
11
|
export { iconsTheme as icons } from './icons.js';
|
|
12
12
|
export { uploadFileDropzoneTheme as uploadFileDropzone } from './uploadFileDropzone.js';
|
|
13
13
|
export { dateTimeTheme as dateTime } from './dateTime.js';
|
|
14
|
+
export { radioGroupTheme as radioGroup } from './radioGroup.js';
|
|
15
|
+
export { wysiwygTheme as wysiwyg } from './wysiwyg.js';
|
|
@@ -11,3 +11,5 @@ export { inputNumberTheme as inputNumber } from "./inputNumber.js";
|
|
|
11
11
|
export { iconsTheme as icons } from "./icons.js";
|
|
12
12
|
export { uploadFileDropzoneTheme as uploadFileDropzone } from "./uploadFileDropzone.js";
|
|
13
13
|
export { dateTimeTheme as dateTime } from "./dateTime.js";
|
|
14
|
+
export { radioGroupTheme as radioGroup } from "./radioGroup.js";
|
|
15
|
+
export { wysiwygTheme as wysiwyg } from "./wysiwyg.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export const uploadFileDropzoneTheme = {
|
|
2
2
|
slots: {
|
|
3
|
-
base: "relative w-full text-base p-4 transition rounded-
|
|
3
|
+
base: "relative w-full text-base p-4 transition rounded-md flex items-center justify-center ring-1 bg-white ring-gray-300",
|
|
4
4
|
wrapper: "flex flex-col items-center w-full",
|
|
5
5
|
disabled: "bg-gray-100 border-none grayscale cursor-not-allowed",
|
|
6
6
|
failed: "border-error",
|
|
@@ -20,13 +20,13 @@ export const uploadFileDropzoneTheme = {
|
|
|
20
20
|
onLoadingTextWrapper: "flex-1 min-w-0 flex items-center justify-between",
|
|
21
21
|
onLoadingLoadingIconClass: "size-10 text-primary animate-spin",
|
|
22
22
|
// Preview state
|
|
23
|
-
onPreviewWrapper: "flex items-center space-x-4 rounded-
|
|
24
|
-
onPreviewPreviewImgWrapper: "flex-shrink-0 w-16 h-16 rounded-
|
|
23
|
+
onPreviewWrapper: "flex items-center space-x-4 rounded-md w-full",
|
|
24
|
+
onPreviewPreviewImgWrapper: "flex-shrink-0 w-16 h-16 rounded-md overflow-hidden bg-gray-100",
|
|
25
25
|
onPreviewPreviewImgClass: "w-full h-full object-cover",
|
|
26
26
|
onPreviewPreviewFileClass: "size-8 text-gray-400 m-auto mt-4",
|
|
27
27
|
onPreviewTextWrapper: "flex-1 min-w-0 flex items-center justify-between",
|
|
28
28
|
// Failed state
|
|
29
|
-
onFailedWrapper: "flex items-start space-x-4 w-full rounded-
|
|
29
|
+
onFailedWrapper: "flex items-start space-x-4 w-full rounded-md",
|
|
30
30
|
onFailedFailedImgWrapper: "flex-shrink-0",
|
|
31
31
|
onFailedFailedIconClass: "size-12",
|
|
32
32
|
onFailedTextWrapper: "flex-1 min-w-0 flex items-start justify-between",
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export declare const wysiwygTheme: {
|
|
2
|
+
slots: {
|
|
3
|
+
container: string;
|
|
4
|
+
toolbar: string;
|
|
5
|
+
toolbarGroup: string;
|
|
6
|
+
menuItem: string;
|
|
7
|
+
menuItemActive: string;
|
|
8
|
+
icon: string;
|
|
9
|
+
editorContent: string;
|
|
10
|
+
};
|
|
11
|
+
variants: {
|
|
12
|
+
size: {
|
|
13
|
+
xs: {
|
|
14
|
+
button: string;
|
|
15
|
+
icon: string;
|
|
16
|
+
select: string;
|
|
17
|
+
};
|
|
18
|
+
sm: {
|
|
19
|
+
button: string;
|
|
20
|
+
icon: string;
|
|
21
|
+
select: string;
|
|
22
|
+
};
|
|
23
|
+
md: {
|
|
24
|
+
button: string;
|
|
25
|
+
icon: string;
|
|
26
|
+
select: string;
|
|
27
|
+
};
|
|
28
|
+
lg: {
|
|
29
|
+
button: string;
|
|
30
|
+
icon: string;
|
|
31
|
+
select: string;
|
|
32
|
+
};
|
|
33
|
+
xl: {
|
|
34
|
+
button: string;
|
|
35
|
+
icon: string;
|
|
36
|
+
select: string;
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
color: {
|
|
40
|
+
primary: {
|
|
41
|
+
button: string;
|
|
42
|
+
};
|
|
43
|
+
gray: {
|
|
44
|
+
button: string;
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
compoundVariants: never[];
|
|
49
|
+
defaultVariants: {
|
|
50
|
+
size: string;
|
|
51
|
+
color: string;
|
|
52
|
+
};
|
|
53
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export const wysiwygTheme = {
|
|
2
|
+
slots: {
|
|
3
|
+
container: "border border-gray-200 rounded focus:ring-primary-500 relative block w-full resize-none rounded-md border-0 bg-white p-0 pb-3 text-sm text-gray-900 ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:outline-none focus:ring-2 disabled:cursor-not-allowed disabled:opacity-75",
|
|
4
|
+
toolbar: "flex flex-wrap border py-2 px-2 gap-1 border-gray-300 bg-white rounded-t-md",
|
|
5
|
+
toolbarGroup: "flex items-center border-r border-gray-200 pr-2",
|
|
6
|
+
menuItem: "px-1 py-1 rounded-md hover:bg-gray-100 transition-colors flex justify-center items-center cursor-pointer flex-wrap",
|
|
7
|
+
menuItemActive: "bg-primary-100 text-primary-600",
|
|
8
|
+
icon: "size-5",
|
|
9
|
+
editorContent: ""
|
|
10
|
+
},
|
|
11
|
+
variants: {
|
|
12
|
+
size: {
|
|
13
|
+
xs: {
|
|
14
|
+
button: "px-1.5 py-0.5 text-xs",
|
|
15
|
+
icon: "h-3 w-3",
|
|
16
|
+
select: "px-1.5 py-0.5 text-xs"
|
|
17
|
+
},
|
|
18
|
+
sm: {
|
|
19
|
+
button: "px-2 py-1 text-sm",
|
|
20
|
+
icon: "h-3.5 w-3.5",
|
|
21
|
+
select: "px-2 py-1 text-xs"
|
|
22
|
+
},
|
|
23
|
+
md: {
|
|
24
|
+
button: "px-2 py-1 text-sm",
|
|
25
|
+
icon: "h-4 w-4",
|
|
26
|
+
select: "px-2 py-1 text-xs"
|
|
27
|
+
},
|
|
28
|
+
lg: {
|
|
29
|
+
button: "px-3 py-1.5 text-base",
|
|
30
|
+
icon: "h-5 w-5",
|
|
31
|
+
select: "px-3 py-1.5 text-sm"
|
|
32
|
+
},
|
|
33
|
+
xl: {
|
|
34
|
+
button: "px-4 py-2 text-lg",
|
|
35
|
+
icon: "h-6 w-6",
|
|
36
|
+
select: "px-4 py-2 text-base"
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
color: {
|
|
40
|
+
primary: {
|
|
41
|
+
button: "hover:bg-blue-50 hover:border-blue-300"
|
|
42
|
+
},
|
|
43
|
+
gray: {
|
|
44
|
+
button: "hover:bg-gray-100 hover:border-gray-300"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
compoundVariants: [],
|
|
49
|
+
defaultVariants: {
|
|
50
|
+
size: "md",
|
|
51
|
+
color: "gray"
|
|
52
|
+
}
|
|
53
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@finema/core",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.15.0",
|
|
4
4
|
"repository": "https://gitlab.finema.co/finema/ui-kit",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Finema Dev Core Team",
|
|
@@ -67,13 +67,14 @@
|
|
|
67
67
|
"url-join": "^5.0.0"
|
|
68
68
|
},
|
|
69
69
|
"devDependencies": {
|
|
70
|
-
"@hyoban/eslint-plugin-tailwindcss": "^4.0.0-alpha.12",
|
|
71
70
|
"@eslint/js": "^9.26.0",
|
|
71
|
+
"@hyoban/eslint-plugin-tailwindcss": "^4.0.0-alpha.12",
|
|
72
72
|
"@nuxt/devtools": "^2.4.1",
|
|
73
73
|
"@nuxt/eslint-config": "^1.3.1",
|
|
74
74
|
"@nuxt/module-builder": "^1.0.1",
|
|
75
75
|
"@nuxt/schema": "^3.17.3",
|
|
76
76
|
"@nuxt/test-utils": "^3.19.0",
|
|
77
|
+
"@tailwindcss/typography": "^0.5.0-alpha.3",
|
|
77
78
|
"@types/node": "latest",
|
|
78
79
|
"changelogen": "^0.5.7",
|
|
79
80
|
"eslint": "^9.26.0",
|