@vue-ui-kit/ant 1.7.1 → 1.7.3

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.
@@ -11,6 +11,7 @@ declare const _default: <F = Recordable<any>>(__VLS_props: NonNullable<Awaited<t
11
11
  activeKey: import('vue').ComputedRef<number>;
12
12
  setActiveKey: (key: number) => void;
13
13
  validateAll: () => Promise<any[]>;
14
+ validate: (__index: number) => any;
14
15
  }>): void;
15
16
  attrs: any;
16
17
  slots: ReturnType<() => {
@@ -49,7 +49,7 @@ declare const _default: <D = Recordable<any>, F = Recordable<any>>(__VLS_props:
49
49
  setBtnLoading: (code: string, value: boolean) => void;
50
50
  selectedRecords: import('vue').ComputedRef<D[]>;
51
51
  $form: import('vue').ComputedRef<any>;
52
- setLoadings: (value: boolean) => void;
52
+ setLoadings: (value: boolean | Record<string, boolean>) => void;
53
53
  resizeTable: () => void;
54
54
  }>): void;
55
55
  attrs: any;
@@ -1,5 +1,5 @@
1
1
  import { PropType } from 'vue';
2
- import { PGridProps } from '../../declarations/antProxy';
2
+ import { PGridInstance, PGridProps } from '../../declarations/antProxy';
3
3
  declare const _default: <D = Recordable<any>, F = Recordable<any>>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_Prettify<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_expose?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
4
4
  props: __VLS_Prettify<Pick<Partial<{
5
5
  title: string;
@@ -43,6 +43,8 @@ declare const _default: <D = Recordable<any>, F = Recordable<any>>(__VLS_props:
43
43
  row: D;
44
44
  field?: string;
45
45
  }>;
46
+ grid: import('vue').Ref<PGridInstance<D, Recordable<any>> | undefined, PGridInstance<D, Recordable<any>> | undefined>;
47
+ hide: () => void;
46
48
  }>): void;
47
49
  attrs: any;
48
50
  slots: ReturnType<() => {}>;
@@ -6,18 +6,20 @@ export declare const addRender: (name: string, { renderItemContent, renderDefaul
6
6
  declare const _default: {
7
7
  renders: {
8
8
  $button: {
9
- renderItemContent({ props, events }: RenderOptions, { data, field }: RenderFormParams, defaultHandler: {
9
+ renderItemContent({ props, events }: RenderOptions, { data, field, }: RenderFormParams, defaultHandler: {
10
10
  [key: string]: (...args: any[]) => any;
11
11
  }): import("vue/jsx-runtime").JSX.Element;
12
- renderDefault({ props, events }: RenderOptions, { row, field }: RenderTableParams, defaultHandler: {
12
+ renderDefault({ props, events }: RenderOptions, { row, field, }: RenderTableParams, defaultHandler: {
13
13
  [key: string]: (...args: any[]) => any;
14
14
  }): import("vue/jsx-runtime").JSX.Element;
15
15
  };
16
16
  $buttons: {
17
- renderItemContent({ props, children }: RenderOptions, { data, field }: RenderFormParams, defaultHandler: {
17
+ renderItemContent({ props, children }: RenderOptions, { data, field, }: RenderFormParams, defaultHandler: {
18
+ [key: string]: (...args: any[]) => any;
19
+ }): import("vue/jsx-runtime").JSX.Element;
20
+ renderDefault({ props, children }: RenderOptions, { data, row, field, }: RenderTableParams, defaultHandler: {
18
21
  [key: string]: (...args: any[]) => any;
19
22
  }): import("vue/jsx-runtime").JSX.Element;
20
- renderDefault({ props, children }: RenderOptions, { data, row, field }: RenderTableParams): import("vue/jsx-runtime").JSX.Element;
21
23
  };
22
24
  ButtonTree: {
23
25
  renderDefault({ children, props }: {
@@ -26,7 +28,7 @@ declare const _default: {
26
28
  }, params: RenderTableParams): import("vue/jsx-runtime").JSX.Element;
27
29
  };
28
30
  $radio: {
29
- renderItemContent({ props, options }: RenderOptions, { data, field }: RenderFormParams): import("vue/jsx-runtime").JSX.Element | null;
31
+ renderItemContent({ props, events, options }: RenderOptions, { data, field }: RenderFormParams): import("vue/jsx-runtime").JSX.Element | null;
30
32
  renderDefault({ props, options }: RenderOptions, { row, field }: RenderTableParams): import("vue/jsx-runtime").JSX.Element | null;
31
33
  };
32
34
  $autoComplete: {
package/dist/style.css CHANGED
@@ -1 +1 @@
1
- @charset "UTF-8";:root{--p-theme-bg: #fff}.p-pane{background-color:var(--p-theme-bg);padding:16px;border-radius:4px}.w-full{width:100%}.cursor-pointer{cursor:pointer}.py-4x{padding-top:4px;padding-bottom:4px}.px-2x{padding-left:2px;padding-right:2px}.h-0{height:0}.h-full{height:100%}.flex{display:flex}.flex-col{flex-direction:column}.flex-1{flex:1}.items-center{align-items:center}.justify-between{justify-content:space-between}.gap-4px{gap:4px}.gap-8px{gap:8px}.pt-8px{padding-top:8px}.px-16px{padding-left:16px;padding-right:16px}.mt-4px{margin-top:4px}.text-right{text-align:right}.overflow-y-auto{overflow-y:auto}.p-theme-bg{background-color:var(--p-theme-bg)}.p-wrapper .p-form-wrapper{z-index:4}.p-wrapper .p-toolbar-wrapper{box-shadow:0 8px #fff;border-radius:.5em .5em 0 0;margin-bottom:-.5em}.p-wrapper .ant-form .ant-form-item{margin-bottom:0}.p-wrapper .ant-form .ant-form-item.p-required .ant-form-item-label>label:before{display:inline-block;margin-inline-end:4px;color:#ff4d4f;font-size:14px;font-family:SimSun,sans-serif;line-height:1;content:"*"}.p-wrapper .ant-form .ant-form-item .ant-form-item-label{display:flex;align-items:start;justify-content:flex-end}.p-wrapper .ant-form .ant-form-item .ant-form-item-label>label{white-space:break-spaces;align-items:flex-start;height:fit-content;padding-top:.36em}.p-wrapper .ant-form .ant-form-item .ant-form-item-label>label:after{padding-left:4px;margin-inline-start:unset}.p-wrapper .ant-form.ant-form-vertical .ant-form-item .ant-form-item-label{justify-content:flex-start;font-weight:600}.p-wrapper .ant-table-sticky-scroll{visibility:hidden}.p-wrapper .ant-table-header.ant-table-sticky-holder:before{content:"";width:100%;position:absolute;height:22px;display:block;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);top:-16px}.p-wrapper .ant-table-wrapper .ant-table-pagination.ant-pagination{margin:unset;padding:16px 0}.p-wrapper .p-inner-scroll>.ant-table-wrapper{height:100%}.p-wrapper .p-inner-scroll>.ant-table-wrapper>.ant-spin-nested-loading{height:100%}.p-wrapper .p-inner-scroll>.ant-table-wrapper>.ant-spin-nested-loading>.ant-spin-container{height:100%;display:flex;flex-direction:column}.p-wrapper .p-inner-scroll>.ant-table-wrapper>.ant-spin-nested-loading>.ant-spin-container>.ant-table{border-radius:unset}.p-wrapper .ant-pagination-options .ant-select{width:100px}.p-content-align-right.ant-form-item .ant-form-item-control-input-content{display:flex;justify-content:flex-end;align-items:center;text-align:right}.p-content-align-center.ant-form-item .ant-form-item-control-input-content{display:flex;justify-content:center;align-items:center;text-align:center}
1
+ @charset "UTF-8";:root{--p-theme-bg: #fff}.p-pane{background-color:var(--p-theme-bg);padding:16px;border-radius:4px}.w-full{width:100%}.cursor-pointer{cursor:pointer}.py-4x{padding-top:4px;padding-bottom:4px}.px-2x{padding-left:2px;padding-right:2px}.pl-4x{padding-left:1em}.pl-8{padding-left:2em}.h-0{height:0}.h-full{height:100%}.flex{display:flex}.flex-col{flex-direction:column}.flex-1{flex:1}.items-center{align-items:center}.justify-between{justify-content:space-between}.gap-4px{gap:4px}.gap-8px{gap:8px}.pt-8px{padding-top:8px}.px-16px{padding-left:16px;padding-right:16px}.mt-4px{margin-top:4px}.text-right{text-align:right}.overflow-y-auto{overflow-y:auto}.p-theme-bg{background-color:var(--p-theme-bg)}.p-wrapper .p-form-wrapper{z-index:4}.p-wrapper .p-toolbar-wrapper{box-shadow:0 8px #fff;border-radius:.5em .5em 0 0;margin-bottom:-.5em}.p-wrapper .ant-form .ant-form-item{margin-bottom:0}.p-wrapper .ant-form .ant-form-item.p-required .ant-form-item-label>label:before{display:inline-block;margin-inline-end:4px;color:#ff4d4f;font-size:14px;font-family:SimSun,sans-serif;line-height:1;content:"*"}.p-wrapper .ant-form .ant-form-item .ant-form-item-label{display:flex;align-items:start;justify-content:flex-end}.p-wrapper .ant-form .ant-form-item .ant-form-item-label>label{white-space:break-spaces;align-items:flex-start;height:fit-content;padding-top:.36em}.p-wrapper .ant-form .ant-form-item .ant-form-item-label>label:after{padding-left:4px;margin-inline-start:unset}.p-wrapper .ant-form.ant-form-vertical .ant-form-item .ant-form-item-label{justify-content:flex-start;font-weight:600}.p-wrapper .ant-table-sticky-scroll{visibility:hidden}.p-wrapper .ant-table-header.ant-table-sticky-holder:before{content:"";width:100%;position:absolute;height:22px;display:block;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);top:-16px}.p-wrapper .ant-table-wrapper .ant-table-pagination.ant-pagination{margin:unset;padding:16px 0}.p-wrapper .p-inner-scroll>.ant-table-wrapper{height:100%}.p-wrapper .p-inner-scroll>.ant-table-wrapper>.ant-spin-nested-loading{height:100%}.p-wrapper .p-inner-scroll>.ant-table-wrapper>.ant-spin-nested-loading>.ant-spin-container{height:100%;display:flex;flex-direction:column}.p-wrapper .p-inner-scroll>.ant-table-wrapper>.ant-spin-nested-loading>.ant-spin-container>.ant-table{border-radius:unset}.p-wrapper .ant-pagination-options .ant-select{width:100px}.p-content-align-right.ant-form-item .ant-form-item-control-input-content{display:flex;justify-content:flex-end;align-items:center;text-align:right}.p-content-align-center.ant-form-item .ant-form-item-control-input-content{display:flex;justify-content:center;align-items:center;text-align:center}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vue-ui-kit/ant",
3
- "version": "1.7.1",
3
+ "version": "1.7.3",
4
4
  "description": "Vue3 UI Kit based on Ant Design",
5
5
  "type": "module",
6
6
  "types": "./dist/index.d.ts",
@@ -22,6 +22,7 @@ export interface ItemRender {
22
22
  name: string;
23
23
  defaultValue?: any;
24
24
  props?: Recordable;
25
+ attrs?: Recordable;
25
26
  options?: IOption[];
26
27
  children?: Recordable[];
27
28
  events?: { [key: string]: (...args: any[]) => any };
@@ -30,6 +31,7 @@ export interface ItemRender {
30
31
  export interface CellRender {
31
32
  name: string;
32
33
  props?: Recordable;
34
+ attrs?: Recordable;
33
35
  children?: Recordable[];
34
36
  }
35
37
 
@@ -106,8 +108,10 @@ export interface PFormGroupProps<F = Recordable> {
106
108
  tabLabel?: string;
107
109
  editAble?: boolean;
108
110
  showAdd?: boolean;
111
+ forceRender?: boolean;
109
112
  /* 是否保持连续编号 */
110
113
  keepSerial?: boolean;
114
+ loading?: boolean;
111
115
  itemMenus?: Array<GroupMenuItem<F>>;
112
116
  creatItem?: ({ list }: { list?: Partial<F>[] }) => Promise<Partial<F>>;
113
117
  max?: number;
@@ -142,7 +146,7 @@ export interface ToolbarButtonProps extends PButtonProps {
142
146
 
143
147
  export interface ToolbarConfig {
144
148
  buttons?: Array<ToolbarButtonProps>;
145
- tools?: Array<{ code: string; icon: string; type?: ButtonType; disabled?: boolean }>;
149
+ tools?: Array<{ code: string; icon: string; type?: ButtonType; disabled?: boolean; size?: 'small' | 'large' | 'middle' }>;
146
150
  disabled?: boolean;
147
151
  }
148
152
 
@@ -178,6 +182,7 @@ export interface PageConfig {
178
182
 
179
183
  export interface SelectConfig<D = Recordable> {
180
184
  multiple?: boolean;
185
+ showCount?: boolean;
181
186
  getCheckboxProps?: (record: D) => { disabled?: boolean };
182
187
  }
183
188
 
@@ -185,6 +190,7 @@ export type PGridProps<D = Recordable, F = Recordable> = {
185
190
  selectConfig?: SelectConfig<D>;
186
191
  rowKey?: string;
187
192
  manualFetch?: boolean;
193
+ align?: 'left' | 'right' | 'center'
188
194
  formConfig?: PFormProps<F>;
189
195
  columns?: ColumnProps<D>[];
190
196
  toolbarConfig?: ToolbarConfig;
@@ -275,6 +281,8 @@ export interface PFormInstance {
275
281
  export interface PromisePickerInstance<D = Recordable> {
276
282
  pick: () => Promise<{ row: D; field?: string }>;
277
283
  pickMultiple: () => Promise<D[]>;
284
+ grid: PGridInstance<D>;
285
+ hide: () => void;
278
286
  }
279
287
 
280
288
  export interface PFormBlockInstance {
@@ -285,4 +293,5 @@ export interface PFormGroupInstance<F = Recordable> {
285
293
  activeKey: number;
286
294
  setActiveKey: (activeKey: number) => void;
287
295
  validateAll: () => Promise<void>;
296
+ validate: (index: number) => Promise<void>;
288
297
  }
@@ -73,7 +73,7 @@
73
73
  </script>
74
74
  <template>
75
75
  <div
76
- v-if="items.some((s: PFormItemProps<F>) => s.field && s.itemRender)"
76
+ v-if="items.some((s: PFormItemProps<F>) => (s.field && s.itemRender) || s.slots?.default)"
77
77
  class="p-pane p-wrapper"
78
78
  >
79
79
  <a-form :key="renderFormKey" ref="formEl" :model="formData" v-bind="fc" @submit="handleSubmit">
@@ -2,6 +2,7 @@
2
2
  import { computed, nextTick, PropType, ref, watchEffect } from 'vue';
3
3
  import { PFormGroupProps, PFormBlockInstance } from '#/antProxy';
4
4
  import { MoreOutlined } from '@ant-design/icons-vue';
5
+ import { Form } from 'ant-design-vue'
5
6
  import { cloneDeep, toString, isFunction, omit, maxBy, debounce } from 'lodash-es';
6
7
  import PGroupBlock from '@/components/PGroupBlock.vue';
7
8
  import {
@@ -15,7 +16,9 @@
15
16
  } from 'ant-design-vue';
16
17
  import { valued } from '@/utils/is';
17
18
  import { MenuInfo } from 'ant-design-vue/es/menu/src/interface';
18
-
19
+ import { $warning } from '@/hooks/useMessage';
20
+
21
+ const useForm = Form.useForm
19
22
  const props = defineProps<PFormGroupProps<F>>();
20
23
  const model = defineModel({
21
24
  type: Array as PropType<Partial<F & { __index: number }>[]>,
@@ -44,6 +47,15 @@
44
47
  { content: '复制', code: 'copy' },
45
48
  { content: '删除', code: 'delete' },
46
49
  ];
50
+ // 实际是否强制渲染
51
+ const fr = computed(() => {
52
+ return props.forceRender || model.value.length <= 5
53
+ })
54
+ const handleTabChange = () => {
55
+ nextTick().then(() => {
56
+ blockInstance.value[activeKey.value]?.$form?.validate()
57
+ })
58
+ }
47
59
  watchEffect(() => {
48
60
  if (!props.keepSerial) {
49
61
  const unSortItems = model.value.filter((f) => !valued(f.__index));
@@ -70,6 +82,10 @@
70
82
  });
71
83
  break;
72
84
  case 'copy':
85
+ if (model.value.length >= maxLen.value) {
86
+ $warning('已达到最大数量')
87
+ return
88
+ }
73
89
  model.value = [
74
90
  ...model.value,
75
91
  cloneDeep({
@@ -93,15 +109,22 @@
93
109
  activeKey: computed(() => activeKey.value),
94
110
  setActiveKey,
95
111
  validateAll: () => {
96
- return Promise.all(
97
- blockInstance.value.map((block) => block.$form?.validate() ?? Promise.resolve()),
98
- );
112
+ return Promise.all(blockInstance.value.map((block, idx) =>
113
+ fr.value ? (block.$form?.validate() ?? Promise.resolve()) : (useForm(model.value[idx], props.getFormSetting(model.value[idx]).rules)?.validate() ?? Promise.resolve()),
114
+ ))
115
+ },
116
+ validate: (__index: number) => {
117
+ const index = model.value.findIndex(f => f.__index === __index)
118
+ return fr.value
119
+ ? (blockInstance.value[index]?.$form?.validate() ?? Promise.resolve())
120
+ : (useForm(model.value[index], props.getFormSetting(model.value[index]).rules)?.validate() ?? Promise.resolve())
99
121
  },
100
122
  });
101
123
  </script>
102
124
  <template>
103
125
  <a-card :title="title" size="small">
104
- <a-tabs type="editable-card" v-model:activeKey="activeKey" hide-add>
126
+ <a-spin v-if="loading" class="w-full" />
127
+ <a-tabs v-else type="editable-card" v-model:activeKey="activeKey" hide-add @change="handleTabChange">
105
128
  <template #rightExtra>
106
129
  <slot name="rightExtra">
107
130
  <a-button
@@ -117,7 +140,7 @@
117
140
  v-for="(item, idx) in model"
118
141
  :key="idx"
119
142
  :tab="`${tabLabel} ${keepSerial ? idx + 1 : (item.__index ?? 0) + 1}`"
120
- force-render
143
+ :force-render="fr"
121
144
  >
122
145
  <template #closeIcon>
123
146
  <a-dropdown v-if="editAble && itemMenus?.length">
@@ -11,7 +11,7 @@
11
11
  toRefs,
12
12
  onBeforeUnmount,
13
13
  } from 'vue';
14
- import { debounce, get, isArray, isFunction, isString, merge, omit, toNumber } from 'lodash-es';
14
+ import { debounce, get, isArray, isBoolean, isFunction, isObject, isString, merge, omit, toNumber } from 'lodash-es';
15
15
  import { eachTree } from '@/utils/treeHelper';
16
16
  import { message as $message } from 'ant-design-vue';
17
17
  import RenderAntItem from '@/components/RenderAntItem';
@@ -52,6 +52,17 @@
52
52
  toolbar: false,
53
53
  form: false,
54
54
  });
55
+ const setLoadings = (value: boolean|Record<string, boolean>) => {
56
+ if(isObject(value)) {
57
+ Object.keys(value).forEach(key => {
58
+ loading[key] = value[key];
59
+ });
60
+ } else if(isBoolean(value)) {
61
+ loading.form = value;
62
+ loading.table = value;
63
+ loading.toolbar = value;
64
+ }
65
+ };
55
66
  const submitOnReset = true;
56
67
  const boxEl = ref<HTMLDivElement>();
57
68
  const pFormWrapper = ref<HTMLDivElement>();
@@ -397,15 +408,12 @@
397
408
  ? window.getComputedStyle(pFormWrapper.value).height
398
409
  : '0px';
399
410
  const formHeight = formOriginHeight.includes('px')
400
- ? toNumber(window.getComputedStyle(pFormWrapper.value).height.replace('px', ''))
411
+ ? toNumber(formOriginHeight.replace('px', ''))
401
412
  : 0;
402
-
413
+ const showCountHeight = selectConfig.value?.showCount ? 22 : 0
403
414
  renderHeight.value =
404
415
  props.renderY ??
405
- toNumber(ph.replace('px', '')) -
406
- (props.fitHeight ?? 170) -
407
- (!!props.toolbarConfig ? 30 : 0) -
408
- formHeight;
416
+ toNumber(ph.replace('px', '')) -(props.fitHeight ?? 170) -(!!props.toolbarConfig ? 30 : 0) -formHeight- showCountHeight;
409
417
  enoughSpacing.value = toNumber(ph.replace('px', '')) > 600;
410
418
  };
411
419
  defineExpose({
@@ -420,11 +428,7 @@
420
428
  setBtnLoading,
421
429
  selectedRecords,
422
430
  $form: computed(() => formEl.value),
423
- setLoadings: (value: boolean) => {
424
- loading.form = value;
425
- loading.table = value;
426
- loading.toolbar = value;
427
- },
431
+ setLoadings,
428
432
  resizeTable,
429
433
  });
430
434
 
@@ -439,7 +443,7 @@
439
443
  const el = mutation.target as HTMLElement;
440
444
  const style = window.getComputedStyle(el);
441
445
  if (style.display !== 'none') {
442
- handlePageResize();
446
+ resizeTable();
443
447
  }
444
448
  }
445
449
  });
@@ -450,6 +454,13 @@
450
454
  }
451
455
  resetQueryFormData(props.manualFetch);
452
456
  });
457
+ const passFields = ['align']
458
+ const passDefaultColumnProps = (columns: ColumnProps<D>[]) => columns.map(c => ({
459
+ ...passFields.reduce((prev, cur) => ({
460
+ [cur]: props[cur],
461
+ }), {} as ColumnProps<D>),
462
+ ...c,
463
+ }))
453
464
  onBeforeUnmount(() => {
454
465
  window.removeEventListener('resize', resizeTable);
455
466
  observer.disconnect();
@@ -581,7 +592,7 @@
581
592
  v-for="(tool, idx) in toolbarConfig.tools"
582
593
  :key="idx"
583
594
  :type="tool.type"
584
- :size="btn.size ?? 'middle'"
595
+ :size="tool.size ?? 'middle'"
585
596
  :disabled="toolbarConfig.disabled || tool.disabled"
586
597
  @click="debounceToolToolClick(tool.code)"
587
598
  :loading="loading.toolbar || (!!tool.code && codeLoadings[tool.code])"
@@ -592,11 +603,14 @@
592
603
  </span>
593
604
  </div>
594
605
  <div :class="`p-pane flex-1 ${enoughSpacing ? 'h-0' : ''} p-${scrollMode ?? 'inner'}-scroll`">
606
+ <div v-if="selectConfig?.multiple && selectConfig.showCount" class="w-full text-slate-5 pl-4">
607
+ 已选:{{ selectedRowKeys.length }}
608
+ </div>
595
609
  <a-table
596
610
  :key="renderTableKey + '_table'"
597
611
  :row-key="rowKey ?? 'id'"
598
612
  ref="tableEl"
599
- :columns="(columns ?? []).map((c) => cleanCol(c as Recordable))"
613
+ :columns="passDefaultColumnProps(columns ?? []).map((c) => cleanCol(c as ColumnProps))"
600
614
  :data-source="tableData"
601
615
  :loading="loading.table"
602
616
  :pagination="pg"
@@ -619,7 +633,7 @@
619
633
  v-if="slotDefaultColumns.some((s) => column.key && s.field === column.key)"
620
634
  :key="renderTableKey + '_cell_' + dataSeed + '_slot_' + column.key"
621
635
  :column="slotDefaultColumns.find((f) => column.key && f.field === column.key)!"
622
- :default-handler="{ pick: pickRow }"
636
+ :default-handler="{ pick: pickRow, setLoadings }"
623
637
  :row="record"
624
638
  :row-index="index"
625
639
  :table-data="tableData as Recordable[]"
@@ -78,6 +78,10 @@
78
78
  rejectPromise = reject;
79
79
  visible.modal = true;
80
80
  }),
81
+ grid: gridEl,
82
+ hide: () => {
83
+ visible.modal = false;
84
+ }
81
85
  });
82
86
  </script>
83
87
  <template>