@peng_kai/kit 0.2.0-beta.3 → 0.2.0-beta.30

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 (64) hide show
  1. package/admin/adminPlugin.ts +11 -1
  2. package/admin/components/filter/src/FilterDrawer.vue +153 -153
  3. package/admin/components/filter/src/FilterParam.vue +1 -1
  4. package/admin/components/filter/src/FilterReset.vue +12 -9
  5. package/admin/components/rich-text/index.ts +1 -1
  6. package/admin/components/rich-text/src/RichText.new.vue +164 -0
  7. package/admin/components/rich-text/src/RichText.vue +3 -6
  8. package/admin/components/rich-text/src/editorConfig.ts +126 -0
  9. package/admin/components/rich-text/src/imageUploader.ts +20 -18
  10. package/admin/components/scroll-nav/index.ts +1 -1
  11. package/admin/components/scroll-nav/src/ScrollNav.vue +1 -1
  12. package/admin/components/settings/index.ts +1 -0
  13. package/admin/components/settings/src/Settings.vue +333 -0
  14. package/admin/components/text/index.ts +13 -13
  15. package/admin/components/text/src/Amount.vue +121 -121
  16. package/admin/components/text/src/Datetime.vue +1 -1
  17. package/admin/components/text/src/Duration.vue +26 -26
  18. package/admin/components/text/src/Hash.vue +51 -51
  19. package/admin/components/text/src/createTagGetter.ts +13 -13
  20. package/admin/components/upload/index.ts +1 -0
  21. package/admin/components/upload/src/PictureCardUpload.vue +1 -1
  22. package/admin/components/upload/src/helpers.ts +37 -0
  23. package/admin/defines/route/defineRoute.ts +2 -4
  24. package/admin/defines/route/getRoutes.ts +4 -4
  25. package/admin/defines/route/index.ts +1 -1
  26. package/admin/defines/route-guard/defineRouteGuard.ts +1 -4
  27. package/admin/defines/route-guard/getRouteGuards.ts +5 -7
  28. package/admin/defines/startup/defineStartup.ts +1 -3
  29. package/admin/defines/startup/runStartup.ts +4 -6
  30. package/admin/layout/large/Breadcrumb.vue +2 -2
  31. package/admin/layout/large/Content.vue +2 -2
  32. package/admin/layout/large/Menu.vue +2 -2
  33. package/admin/layout/large/PageTab.vue +2 -2
  34. package/admin/permission/routerGuard.ts +1 -1
  35. package/admin/permission/vuePlugin.ts +1 -0
  36. package/admin/route-guards/index.ts +3 -3
  37. package/admin/route-guards/pageProgress.ts +27 -27
  38. package/admin/stores/createUsePageStore.ts +1 -3
  39. package/admin/styles/classCover.scss +107 -0
  40. package/admin/styles/globalCover.scss +54 -54
  41. package/admin/styles/index.scss +14 -12
  42. package/antd/components/InputNumberRange.vue +59 -59
  43. package/antd/directives/formLabelAlign.ts +36 -36
  44. package/antd/hooks/useAntdDrawer.ts +73 -73
  45. package/antd/hooks/useAntdForm.ts +1 -1
  46. package/antd/hooks/useAntdModal.ts +4 -1
  47. package/antd/hooks/useAntdTable.ts +2 -1
  48. package/libs/dayjs.ts +7 -0
  49. package/libs/echarts.ts +1 -1
  50. package/libs/vue-i18n.ts +21 -0
  51. package/package.json +36 -35
  52. package/request/helpers.ts +68 -68
  53. package/request/interceptors/returnResultType.ts +3 -3
  54. package/request/interceptors/toLogin.ts +43 -26
  55. package/request/request.ts +0 -3
  56. package/request/type.d.ts +92 -92
  57. package/stylelint.config.cjs +7 -7
  58. package/tsconfig.json +50 -50
  59. package/utils/LocaleManager.ts +125 -0
  60. package/utils/date.ts +1 -9
  61. package/vite/index.mjs +34 -8
  62. package/vue/components/infinite-query/index.ts +1 -1
  63. package/vue/components/infinite-query/src/InfiniteQuery.vue +199 -199
  64. package/vue/components/infinite-query/src/useCreateTrigger.ts +39 -39
@@ -0,0 +1,126 @@
1
+ export const defaultConfig: Record<string, any> = {
2
+ language: {
3
+ ui: 'zh-cn',
4
+ },
5
+ removePlugins: ['ImportWord', 'ExportWord', 'RevisionHistory', 'RealTimeCollaborativeEditing', 'RealTimeCollaborativeComments', 'RealTimeCollaborativeRevisionHistory', 'RealTimeCollaborativeTrackChanges', 'PresenceList', 'WProofreader', 'DocumentOutline', 'Comments', 'TrackChanges', 'TrackChangesData', 'TableOfContents', 'SlashCommand', 'PasteFromOfficeEnhanced', 'ContentTemplates', 'FormatPainter', 'Mentions', 'PageBreak', 'Pagination', 'AIAssistant', 'CaseChange', 'Template'],
6
+ toolbar: {
7
+ items: [
8
+ 'undo',
9
+ 'redo',
10
+ '|',
11
+ 'showBlocks',
12
+ 'selectAll',
13
+ '|',
14
+ 'heading',
15
+ '|',
16
+ 'fontSize',
17
+ 'fontFamily',
18
+ 'fontColor',
19
+ 'fontBackgroundColor',
20
+ '|',
21
+ 'bold',
22
+ 'italic',
23
+ 'underline',
24
+ {
25
+ label: 'Formatting',
26
+ icon: 'text',
27
+ items: ['strikethrough', 'subscript', 'superscript', 'code', 'horizontalLine', '|', 'removeFormat'],
28
+ },
29
+ '|',
30
+ 'link',
31
+ 'uploadImage',
32
+ 'insertTable',
33
+ {
34
+ label: 'Insert',
35
+ icon: 'plus',
36
+ items: ['highlight', 'blockQuote', 'mediaEmbed', 'codeBlock', 'htmlEmbed'],
37
+ },
38
+ '|',
39
+ 'alignment',
40
+ '|',
41
+ 'bulletedList',
42
+ 'numberedList',
43
+ 'todoList',
44
+ 'outdent',
45
+ 'indent',
46
+ '|',
47
+ 'sourceEditing',
48
+ ],
49
+ shouldNotGroupWhenFull: true,
50
+ },
51
+ htmlSupport: {
52
+ allow: [
53
+ {
54
+ name: /^.*$/,
55
+ styles: true,
56
+ attributes: true,
57
+ classes: true,
58
+ },
59
+ ],
60
+ },
61
+ fontSize: {
62
+ options: [10, 12, 14, 'default', 18, 20, 22],
63
+ supportAllValues: true,
64
+ },
65
+ image: {
66
+ styles: [
67
+ 'alignCenter',
68
+ 'alignLeft',
69
+ 'alignRight',
70
+ ],
71
+ resizeOptions: [
72
+ { name: 'resizeImage:original', label: 'Original', value: null },
73
+ { name: 'resizeImage:25', label: '25%', value: '25' },
74
+ { name: 'resizeImage:50', label: '50%', value: '50' },
75
+ { name: 'resizeImage:75', label: '75%', value: '75' },
76
+ ],
77
+ toolbar: [
78
+ 'imageTextAlternative',
79
+ 'toggleImageCaption',
80
+ '|',
81
+ 'imageStyle:inline',
82
+ 'imageStyle:wrapText',
83
+ 'imageStyle:breakText',
84
+ 'imageStyle:side',
85
+ '|',
86
+ 'resizeImage',
87
+ ],
88
+ resizeUnit: 'px',
89
+ },
90
+ list: {
91
+ properties: {
92
+ styles: true,
93
+ startIndex: true,
94
+ reversed: true,
95
+ },
96
+ },
97
+ link: {
98
+ addTargetToExternalLinks: true,
99
+ defaultProtocol: 'https://',
100
+ decorators: {
101
+ toggleDownloadable: {
102
+ mode: 'manual',
103
+ label: 'Downloadable',
104
+ attributes: {
105
+ download: 'file',
106
+ },
107
+ },
108
+ },
109
+ },
110
+ table: {
111
+ contentToolbar: [
112
+ 'tableColumn',
113
+ 'tableRow',
114
+ 'mergeTableCells',
115
+ 'tableProperties',
116
+ 'tableCellProperties',
117
+ 'toggleTableCaption',
118
+ ],
119
+ },
120
+ htmlEmbed: {
121
+ showPreviews: true,
122
+ },
123
+ wordCount: {
124
+ displayWords: true,
125
+ },
126
+ };
@@ -5,30 +5,32 @@ export { createImageUploaderForAws3 };
5
5
 
6
6
  function createImageUploaderForAws3(awsS3: AwsS3, rootDir?: string): PluginConstructor {
7
7
  return function (editor) {
8
- editor.plugins.get('FileRepository').createUploadAdapter = (loader) => {
9
- return {
10
- async upload() {
11
- const file = await loader.file;
8
+ setTimeout(() => {
9
+ editor.plugins.get('FileRepository').createUploadAdapter = (loader) => {
10
+ return {
11
+ async upload() {
12
+ const file = await loader.file;
12
13
 
13
- if (file) {
14
- const { uploader, fileURL } = await awsS3.upload(file, rootDir);
14
+ if (file) {
15
+ const { uploader, fileURL } = await awsS3.upload(file, rootDir);
15
16
 
16
- uploader.on('httpUploadProgress', (progress) => {
17
- loader.uploadTotal = progress.total ?? null;
18
- loader.uploaded = progress.loaded ?? 0;
19
- });
17
+ uploader.on('httpUploadProgress', (progress) => {
18
+ loader.uploadTotal = progress.total ?? null;
19
+ loader.uploaded = progress.loaded ?? 0;
20
+ });
20
21
 
21
- await uploader.done();
22
+ await uploader.done();
22
23
 
23
- return { default: fileURL };
24
- }
24
+ return { default: fileURL };
25
+ }
25
26
 
26
- return {};
27
- },
28
- abort() {
27
+ return {};
28
+ },
29
+ abort() {
29
30
 
30
- },
31
+ },
32
+ };
31
33
  };
32
- };
34
+ });
33
35
  };
34
36
  }
@@ -1 +1 @@
1
- export { default as ScrollNav } from './src/ScrollNav.vue';
1
+ export { default as ScrollNav } from './src/ScrollNav.vue';
@@ -10,7 +10,7 @@ const $content = document.querySelector(props.selector) as HTMLElement;
10
10
  const $contentParent = $content.parentElement;
11
11
  const { height: contentParentH } = useElementSize($contentParent);
12
12
  const { height: contentH } = useElementSize($content);
13
- const visible = computed(() => contentParentH.value * 2 < contentH.value);
13
+ const visible = computed(() => contentParentH.value * 1.5 < contentH.value);
14
14
 
15
15
  function scrollTo(top: number) {
16
16
  $contentParent?.scrollTo({ top });
@@ -0,0 +1 @@
1
+ export { default as Settings } from './src/Settings.vue';
@@ -0,0 +1,333 @@
1
+ <script lang="ts">
2
+ import { reactiveComputed } from '@vueuse/core';
3
+ import { cloneDeep, mapKeys, mapValues } from 'lodash-es';
4
+ import dayjs from 'dayjs';
5
+ import { Button, Card, CheckboxGroup, DatePicker, type DatePickerProps, Form, FormItem, Input, InputNumber, RadioGroup, RangePicker, Select, Textarea } from 'ant-design-vue';
6
+ import { computed, ref, toRef } from 'vue';
7
+ import { useMutation, useQuery, useQueryClient } from '@tanstack/vue-query';
8
+ import { type ItemSchema, useAntdForm } from '../../../../antd';
9
+
10
+ interface IConfigDetail {
11
+ category_id: number
12
+ data_type: string
13
+ form_type: number
14
+ key: string
15
+ label: string
16
+ options: any
17
+ required: number
18
+ sort: number
19
+ status: number
20
+ summary: string
21
+ value: any
22
+ }
23
+
24
+ enum FormTypes {
25
+ /** 数字输入框 */
26
+ NUMBER_INPUT = 0,
27
+ /** 文本输入框 */
28
+ TEXT_INPUT = 1,
29
+ /** 多行文本输入框 */
30
+ TEXTAREA = 2,
31
+ /** 开关 */
32
+ SWITCH = 3,
33
+ /** 单选框 */
34
+ RADIO = 4,
35
+ /** 多选框 */
36
+ CHECKBOX = 5,
37
+ /** 单选下拉选择器 */
38
+ SINGLE_SELECT = 6,
39
+ /** 多选下拉选择器 */
40
+ MULTIPLE_SELECT = 7,
41
+ /** 单一日期选择器 */
42
+ SINGLE_DATE_PICKER = 13,
43
+ /** 日期范围选择器 */
44
+ RANGE_DATE_PICKER = 14,
45
+ }
46
+
47
+ const antdPropsResolvers: Record<number, (config: IConfigDetail) => IConfigDetail> = {
48
+ [FormTypes.SWITCH](config) {
49
+ const props: any = {};
50
+
51
+ if (config.options) {
52
+ props.options = config.options.split(',').map((item: any) => {
53
+ const [label, value] = item.split(':');
54
+ return { value, label };
55
+ });
56
+ }
57
+ else {
58
+ props.options = [{ value: '1', label: '是' }, { value: '0', label: '否' }];
59
+ }
60
+
61
+ config.options = props;
62
+
63
+ return config;
64
+ },
65
+ [FormTypes.RADIO](config) {
66
+ return this[FormTypes.SWITCH](config);
67
+ },
68
+ [FormTypes.CHECKBOX](config) {
69
+ const props: any = {};
70
+ props.options = config.options.split(',').map((item: any) => {
71
+ const [label, value] = item.split(':');
72
+ return { value, label };
73
+ });
74
+
75
+ config.value = config.value.split(',');
76
+ config.options = props;
77
+
78
+ return config;
79
+ },
80
+ [FormTypes.SINGLE_SELECT](config) {
81
+ return this[FormTypes.SWITCH](config);
82
+ },
83
+ [FormTypes.MULTIPLE_SELECT](config) {
84
+ return this[FormTypes.CHECKBOX](config);
85
+ },
86
+ [FormTypes.SINGLE_DATE_PICKER](config) {
87
+ const props: DatePickerProps = {};
88
+
89
+ if (config.options) {
90
+ const [minDate, maxDate] = (config.options || '/').split('/').map(dayjs);
91
+ props.disabledDate = (current) => {
92
+ return current.isBefore(minDate) || current.isAfter(maxDate);
93
+ };
94
+ }
95
+
96
+ config.value = config.value === '' ? undefined : dayjs(config.value);
97
+ config.options = props;
98
+
99
+ return config;
100
+ },
101
+ [FormTypes.RANGE_DATE_PICKER](config) {
102
+ const props: DatePickerProps = {};
103
+
104
+ if (config.options) {
105
+ const [minDate, maxDate] = (config.options || '/').split('/').map(dayjs);
106
+ props.disabledDate = (current) => {
107
+ return current.isBefore(minDate) || current.isAfter(maxDate);
108
+ };
109
+ }
110
+
111
+ if (config.value === '')
112
+ config.value = [undefined, undefined];
113
+ else
114
+ config.value = (config.value || '/').split('/').map(dayjs);
115
+
116
+ config.options = props;
117
+
118
+ return config;
119
+ },
120
+ };
121
+ const antdValueResolvers: Record<number, (value: any) => any> = {
122
+ [FormTypes.NUMBER_INPUT](value) {
123
+ return String(value);
124
+ },
125
+ [FormTypes.CHECKBOX](value) {
126
+ if (Array.isArray(value))
127
+ return value.join(',');
128
+
129
+ return value;
130
+ },
131
+ [FormTypes.MULTIPLE_SELECT](value) {
132
+ if (Array.isArray(value))
133
+ return value.join(',');
134
+
135
+ return value;
136
+ },
137
+ [FormTypes.SINGLE_DATE_PICKER](value) {
138
+ if (dayjs.isDayjs(value))
139
+ return value.format('YYYY-MM-DD');
140
+
141
+ return value;
142
+ },
143
+ [FormTypes.RANGE_DATE_PICKER](value) {
144
+ if (dayjs.isDayjs(value[0]) && dayjs.isDayjs(value[1]))
145
+ return [value[0].format('YYYY-MM-DD'), value[1].format('YYYY-MM-DD')].join('/');
146
+
147
+ return value;
148
+ },
149
+ };
150
+ </script>
151
+
152
+ <script setup lang="ts">
153
+ const props = defineProps<{
154
+ categoryApi: Api.Request
155
+ configApi: Api.Request
156
+ updateApi: Api.Request
157
+ }>();
158
+
159
+ const queryClient = useQueryClient();
160
+
161
+ /* 配置分类 */
162
+ const categoryId = ref(1);
163
+ const categoryQuerier = useQuery({
164
+ queryKey: [props.categoryApi.id],
165
+ queryFn: () => props.categoryApi(undefined),
166
+ });
167
+ const categoryList = computed(() => categoryQuerier.data.value?.map((item: any) => ({ key: String(item.type), tab: item.label })));
168
+
169
+ /* 当前分类下的配置 */
170
+ const configQuerier = useQuery<IConfigDetail[] | undefined>({
171
+ enabled: computed(() => !!categoryQuerier.data.value),
172
+ queryKey: [props.configApi.id, categoryId],
173
+ queryFn: () => props.configApi({ category_id: categoryId.value }),
174
+ });
175
+ const configList = computed(() => {
176
+ const list = cloneDeep(configQuerier.data.value);
177
+
178
+ if (!list?.length)
179
+ return;
180
+
181
+ for (let i = 0; i < list.length; i++) {
182
+ const config = { ...list[i] };
183
+ list[i] = antdPropsResolvers[config.form_type]?.(config) ?? config;
184
+ }
185
+
186
+ return list;
187
+ });
188
+ const configMap = computed(() => mapKeys(cloneDeep(configQuerier.data.value ?? []), 'key'));
189
+
190
+ /* 配置表单 */
191
+ const settingMutator = useMutation({
192
+ mutationKey: [props.updateApi.id],
193
+ mutationFn: props.updateApi.setDefaultConfig({ successMessage: '更新成功' }),
194
+ onSuccess() {
195
+ configQuerier.refetch();
196
+ queryClient.invalidateQueries({ queryKey: [props.configApi.id], exact: false });
197
+ },
198
+ });
199
+ const formSchema = reactiveComputed(() => {
200
+ const _configList = configList.value ?? [];
201
+ const entries = _configList.map(config => [
202
+ config.key,
203
+ {
204
+ value: cloneDeep(config.value),
205
+ rules: config.required ? [{ required: true }] : undefined,
206
+ },
207
+ ] as [string, ItemSchema]);
208
+ const schema = Object.fromEntries(entries);
209
+
210
+ return schema;
211
+ });
212
+ const settingForm = useAntdForm(formSchema, {
213
+ transform(state) {
214
+ return mapValues(state, (v, k) => {
215
+ const formType = configMap.value[k].form_type;
216
+ const resolver = antdValueResolvers[formType];
217
+
218
+ return resolver ? resolver(v) : v;
219
+ });
220
+ },
221
+ });
222
+
223
+ /** 提交表单内容 */
224
+ async function submitSetting() {
225
+ const body = await settingForm.$form.validate?.().catch(() => {});
226
+
227
+ if (body)
228
+ await settingMutator.mutateAsync({ requestBody: settingForm.stateTF });
229
+ }
230
+
231
+ /** 重置表单内容 */
232
+ function resetSetting() {
233
+ configList.value?.forEach(config => settingForm.state[config.key] = cloneDeep(config.value));
234
+ settingForm.$form.clearValidate?.();
235
+ }
236
+ </script>
237
+
238
+ <template>
239
+ <Card
240
+ class="antd-cover__actions-right-align"
241
+ :activeTabKey="String(categoryId)"
242
+ :tabList="categoryList"
243
+ :loading="configQuerier.isPending.value"
244
+ @tabChange="key => categoryId = Number(key)"
245
+ >
246
+ <Form
247
+ v-bind="settingForm.props"
248
+ class="ant-cover__col2-form"
249
+ layout="vertical"
250
+ :disabled="settingMutator.isPending.value"
251
+ >
252
+ <template v-for="item of configList" :key="item.key">
253
+ <FormItem v-bind="settingForm.itemProps[item.key]" :label="item.label" :extra="item.summary">
254
+ <slot
255
+ v-if="$slots[item.key]"
256
+ :name="item.key"
257
+ :state="toRef(settingForm.state, item.key)"
258
+ :config="item"
259
+ :orginConfig="configMap[item.key]"
260
+ />
261
+ <template v-else>
262
+ <slot v-if="item.form_type === FormTypes.NUMBER_INPUT" :name="FormTypes.NUMBER_INPUT">
263
+ <InputNumber v-model:value="settingForm.state[item.key]" class="w-full" />
264
+ </slot>
265
+
266
+ <slot v-else-if="item.form_type === FormTypes.TEXT_INPUT" :name="FormTypes.TEXT_INPUT">
267
+ <Input v-model:value="settingForm.state[item.key]" allowClear />
268
+ </slot>
269
+
270
+ <slot v-else-if="item.form_type === FormTypes.TEXTAREA" :name="FormTypes.TEXTAREA">
271
+ <Textarea v-model:value="settingForm.state[item.key]" :rows="4" />
272
+ </slot>
273
+
274
+ <slot v-else-if="item.form_type === FormTypes.SWITCH" :name="FormTypes.SWITCH">
275
+ <RadioGroup
276
+ v-model:value="settingForm.state[item.key]"
277
+ v-bind="item.options"
278
+ buttonStyle="solid"
279
+ optionType="button"
280
+ />
281
+ </slot>
282
+
283
+ <slot v-else-if="item.form_type === FormTypes.RADIO" :name="FormTypes.RADIO">
284
+ <RadioGroup
285
+ v-model:value="settingForm.state[item.key]"
286
+ buttonStyle="solid"
287
+ v-bind="item.options"
288
+ />
289
+ </slot>
290
+
291
+ <slot v-else-if="item.form_type === FormTypes.CHECKBOX" :name="FormTypes.CHECKBOX">
292
+ <CheckboxGroup v-model:value="settingForm.state[item.key]" v-bind="item.options" />
293
+ </slot>
294
+
295
+ <slot v-else-if="item.form_type === FormTypes.SINGLE_SELECT" :name="FormTypes.SINGLE_SELECT">
296
+ <Select v-model:value="settingForm.state[item.key]" v-bind="item.options" />
297
+ </slot>
298
+
299
+ <slot v-else-if="item.form_type === FormTypes.MULTIPLE_SELECT" :name="FormTypes.MULTIPLE_SELECT">
300
+ <Select v-model:value="settingForm.state[item.key]" v-bind="item.options" mode="multiple" />
301
+ </slot>
302
+
303
+ <slot v-else-if="item.form_type === FormTypes.SINGLE_DATE_PICKER" :name="FormTypes.SINGLE_DATE_PICKER">
304
+ <DatePicker v-model:value="settingForm.state[item.key]" v-bind="item.options" />
305
+ </slot>
306
+
307
+ <slot v-else-if="item.form_type === FormTypes.RANGE_DATE_PICKER" :name="FormTypes.RANGE_DATE_PICKER">
308
+ <RangePicker v-model:value="settingForm.state[item.key]" v-bind="item.options" />
309
+ </slot>
310
+
311
+ <span v-else class="text-red">没有找到预设 form_type:{{ item.form_type }},可以通过 {{ item.key }} 插槽自定义</span>
312
+ </template>
313
+ </FormItem>
314
+ </template>
315
+ </Form>
316
+
317
+ <template #actions>
318
+ <Button :disabled="settingMutator.isPending.value" @click="resetSetting()">
319
+ 重置
320
+ </Button>
321
+ <Button type="primary" :loading="settingMutator.isPending.value" @click="submitSetting()">
322
+ 提交
323
+ </Button>
324
+ </template>
325
+ </Card>
326
+ </template>
327
+
328
+ <style lang="scss" scoped>
329
+ .ant-cover__col2-form :deep(.ant-form-item-label > label) {
330
+ // padding-left: 0.5em;
331
+ // border-left: 2px solid #2361d0;
332
+ }
333
+ </style>
@@ -1,13 +1,13 @@
1
- import Hash from './src/Hash.vue';
2
- import Amount from './src/Amount.vue';
3
- import Datetime from './src/Datetime.vue';
4
- import Duration from './src/Duration.vue';
5
-
6
- export { createTagGetter } from './src/createTagGetter';
7
-
8
- export const Text = {
9
- Hash,
10
- Amount,
11
- Datetime,
12
- Duration,
13
- };
1
+ import Hash from './src/Hash.vue';
2
+ import Amount from './src/Amount.vue';
3
+ import Datetime from './src/Datetime.vue';
4
+ import Duration from './src/Duration.vue';
5
+
6
+ export { createTagGetter } from './src/createTagGetter';
7
+
8
+ export const Text = {
9
+ Hash,
10
+ Amount,
11
+ Datetime,
12
+ Duration,
13
+ };