cabloy 5.1.246 → 5.1.247

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 (24) hide show
  1. package/.cabloy-version +1 -1
  2. package/CHANGELOG.md +6 -0
  3. package/package.json +1 -1
  4. package/repo-docs/frontend/column-configuration-guide.md +2 -0
  5. package/repo-docs/frontend/table-guide.md +24 -0
  6. package/repo-e2e/specs/cabloy-basic.spec.ts +350 -28
  7. package/zova/packages-zova/zova/package.json +2 -2
  8. package/zova/src/suite/cabloy-basic/modules/basic-date/src/component/dateRange/controller.tsx +4 -3
  9. package/zova/src/suite/cabloy-basic/modules/basic-date/src/component/formFieldDateRange/controller.tsx +13 -1
  10. package/zova/src/suite/cabloy-basic/modules/basic-details/src/component/blockTable/controller.tsx +1 -1
  11. package/zova/src/suite/cabloy-basic/modules/basic-page/src/component/blockTable/controller.tsx +1 -1
  12. package/zova/src/suite/cabloy-basic/modules/basic-table/src/.metadata/component/rowOperations.ts +31 -0
  13. package/zova/src/suite/cabloy-basic/modules/basic-table/src/.metadata/index.ts +13 -0
  14. package/zova/src/suite/cabloy-basic/modules/basic-table/src/bean/tableCell.actionDelete.tsx +6 -2
  15. package/zova/src/suite/cabloy-basic/modules/basic-table/src/bean/tableCell.actionOperationsRow.tsx +32 -4
  16. package/zova/src/suite/cabloy-basic/modules/basic-table/src/bean/tableCell.actionUpdate.tsx +6 -2
  17. package/zova/src/suite/cabloy-basic/modules/basic-table/src/component/rowOperations/controller.tsx +233 -0
  18. package/zova/src/suite/cabloy-basic/modules/basic-table/src/component/table/controller.tsx +75 -2
  19. package/zova/src/suite/cabloy-basic/modules/basic-table/src/component/table/render.tsx +40 -22
  20. package/zova/src/suite/cabloy-basic/modules/basic-table/src/config/locale/en-us.ts +4 -0
  21. package/zova/src/suite/cabloy-basic/modules/basic-table/src/config/locale/zh-cn.ts +4 -0
  22. package/zova/src/suite-vendor/a-zova/modules/a-table/package.json +1 -1
  23. package/zova/src/suite-vendor/a-zova/modules/a-table/src/component/table/controller.tsx +19 -11
  24. package/zova/src/suite-vendor/a-zova/package.json +2 -2
@@ -4,6 +4,7 @@ export * from '../component/actionColumnConfig/controller.tsx';
4
4
  export * from '../component/actionCreate/controller.tsx';
5
5
  export * from '../component/actionDeleteBulk/controller.tsx';
6
6
  export * from '../component/actionRefresh/controller.tsx';
7
+ export * from '../component/rowOperations/controller.tsx';
7
8
  export * from '../component/table/controller.tsx';
8
9
 
9
10
  import 'zova';
@@ -33,6 +34,11 @@ declare module 'zova-module-basic-table' {
33
34
  get scope(): ScopeModuleBasicTable;
34
35
  }
35
36
 
37
+ export interface ControllerRowOperations {
38
+ /** @internal */
39
+ get scope(): ScopeModuleBasicTable;
40
+ }
41
+
36
42
  export interface ControllerTable {
37
43
  /** @internal */
38
44
  get scope(): ScopeModuleBasicTable;
@@ -44,6 +50,7 @@ import type { ControllerActionColumnConfig } from '../component/actionColumnConf
44
50
  import type { ControllerActionCreate } from '../component/actionCreate/controller.tsx';
45
51
  import type { ControllerActionDeleteBulk } from '../component/actionDeleteBulk/controller.tsx';
46
52
  import type { ControllerActionRefresh } from '../component/actionRefresh/controller.tsx';
53
+ import type { ControllerRowOperations } from '../component/rowOperations/controller.tsx';
47
54
  import type { ControllerTable } from '../component/table/controller.tsx';
48
55
  import 'zova';
49
56
  declare module 'zova' {
@@ -52,6 +59,7 @@ declare module 'zova' {
52
59
  'basic-table.controller.actionCreate': ControllerActionCreate;
53
60
  'basic-table.controller.actionDeleteBulk': ControllerActionDeleteBulk;
54
61
  'basic-table.controller.actionRefresh': ControllerActionRefresh;
62
+ 'basic-table.controller.rowOperations': ControllerRowOperations;
55
63
  'basic-table.controller.table': ControllerTable;
56
64
  }
57
65
  }
@@ -66,6 +74,8 @@ export * from './component/actionDeleteBulk.ts';
66
74
  import { ZActionDeleteBulk } from './component/actionDeleteBulk.ts';
67
75
  export * from './component/actionRefresh.ts';
68
76
  import { ZActionRefresh } from './component/actionRefresh.ts';
77
+ export * from './component/rowOperations.ts';
78
+ import { ZRowOperations } from './component/rowOperations.ts';
69
79
  export * from './component/table.ts';
70
80
  import { ZTable } from './component/table.ts';
71
81
  export const components = {
@@ -73,6 +83,7 @@ export const components = {
73
83
  'actionCreate': ZActionCreate,
74
84
  'actionDeleteBulk': ZActionDeleteBulk,
75
85
  'actionRefresh': ZActionRefresh,
86
+ 'rowOperations': ZRowOperations,
76
87
  'table': ZTable,
77
88
  };
78
89
  import 'zova';
@@ -82,6 +93,7 @@ export interface IComponentRecord {
82
93
  'basic-table:actionCreate': ControllerActionCreate;
83
94
  'basic-table:actionDeleteBulk': ControllerActionDeleteBulk;
84
95
  'basic-table:actionRefresh': ControllerActionRefresh;
96
+ 'basic-table:rowOperations': ControllerRowOperations;
85
97
  'basic-table:table': ControllerTable;
86
98
  }
87
99
  export interface IZovaComponentRecord {
@@ -89,6 +101,7 @@ export interface IZovaComponentRecord {
89
101
  'basic-table:actionCreate': typeof ZActionCreate;
90
102
  'basic-table:actionDeleteBulk': typeof ZActionDeleteBulk;
91
103
  'basic-table:actionRefresh': typeof ZActionRefresh;
104
+ 'basic-table:rowOperations': typeof ZRowOperations;
92
105
  'basic-table:table': typeof ZTable;
93
106
  }
94
107
  }
@@ -16,7 +16,9 @@ declare module 'zova-module-a-openapi' {
16
16
  }
17
17
  }
18
18
 
19
- export interface ITableCellOptionsActionDelete extends IResourceTableActionRowOptionsBase {}
19
+ export interface ITableCellOptionsActionDelete extends IResourceTableActionRowOptionsBase {
20
+ showLabel?: boolean;
21
+ }
20
22
 
21
23
  @TableCell<ITableCellOptionsActionDelete>({
22
24
  class: 'btn btn-outline btn-error join-item',
@@ -31,6 +33,7 @@ export class TableCellActionDelete extends BeanBase implements ITableCellRender
31
33
  return (
32
34
  <ZButton
33
35
  class={options.class}
36
+ aria-label={this.scope.locale.Delete()}
34
37
  onPerform={async () => {
35
38
  const confirmed = await $host.$performCommand('basic-commands:confirm', {
36
39
  text: this.scope.locale.DeleteConfirm(),
@@ -39,7 +42,8 @@ export class TableCellActionDelete extends BeanBase implements ITableCellRender
39
42
  await $host.$performCommand('basic-commands:delete', options, renderContext);
40
43
  }}
41
44
  >
42
- <ZIcon name="::delete" width={24}></ZIcon>
45
+ <ZIcon name="::delete" width={24} aria-hidden="true"></ZIcon>
46
+ {options.showLabel && this.scope.locale.Delete()}
43
47
  </ZButton>
44
48
  );
45
49
  }
@@ -1,3 +1,4 @@
1
+ import type { VNode } from 'vue';
1
2
  import type {
2
3
  IResourceRenderTableActionRowOptionsAction,
3
4
  IResourceTableActionRowOptionsBase,
@@ -9,10 +10,12 @@ import type {
9
10
  NextTableCellRender,
10
11
  } from 'zova-module-a-table';
11
12
 
12
- import { VNode } from 'vue';
13
+ import { Comment, Fragment, isVNode, Text } from 'vue';
13
14
  import { BeanBase } from 'zova';
14
15
  import { IJsxRenderContextTableColumn, TableCell } from 'zova-module-a-table';
15
16
 
17
+ import { ZRowOperations } from '../.metadata/component/rowOperations.ts';
18
+
16
19
  declare module 'zova-module-a-openapi' {
17
20
  export interface IResourceTableActionRowRecord {
18
21
  'basic-table:actionOperationsRow'?: ITableCellOptionsActionOperationsRow;
@@ -65,10 +68,35 @@ export class TableCellActionOperationsRow extends BeanBase implements ITableCell
65
68
  const actionName = action.name;
66
69
  const permissionHint = action.options?.permission;
67
70
  if (!$host.$passport.checkPermission(permissions, actionName, permissionHint, data)) return;
68
- const options2 = Object.assign({ key: index }, action.options);
69
- domActions.push($$table.cellRender(action.render!, options2, renderContext));
71
+ const builtInLabel =
72
+ action.render === 'basic-table:actionUpdate' ||
73
+ action.render === 'basic-table:actionDelete';
74
+ const options2 = Object.assign(
75
+ { key: index },
76
+ action.options,
77
+ builtInLabel ? { showLabel: $$table.compact } : undefined,
78
+ );
79
+ const domAction = $$table.cellRender(action.render!, options2, renderContext);
80
+ if (this._hasContent(domAction)) domActions.push(domAction);
70
81
  });
71
82
  if (domActions.length === 0) return;
72
- return <div class={options.class}>{domActions}</div>;
83
+ return (
84
+ <ZRowOperations
85
+ compact={$$table.compact}
86
+ class={options.class}
87
+ slotDefault={() => <>{domActions}</>}
88
+ />
89
+ );
90
+ }
91
+
92
+ private _hasContent(value: unknown): boolean {
93
+ if (value === undefined || value === null || typeof value === 'boolean') return false;
94
+ if (typeof value === 'string') return value.trim().length > 0;
95
+ if (Array.isArray(value)) return value.some(item => this._hasContent(item));
96
+ if (!isVNode(value)) return true;
97
+ if (value.type === Comment) return false;
98
+ if (value.type === Text || value.type === Fragment) return this._hasContent(value.children);
99
+ // Component renderers stay opaque: preserve their VNode and runtime ownership.
100
+ return true;
73
101
  }
74
102
  }
@@ -16,7 +16,9 @@ declare module 'zova-module-a-openapi' {
16
16
  }
17
17
  }
18
18
 
19
- export interface ITableCellOptionsActionUpdate extends IResourceTableActionRowOptionsBase {}
19
+ export interface ITableCellOptionsActionUpdate extends IResourceTableActionRowOptionsBase {
20
+ showLabel?: boolean;
21
+ }
20
22
 
21
23
  @TableCell<ITableCellOptionsActionUpdate>({
22
24
  class: 'btn btn-outline btn-primary join-item',
@@ -31,11 +33,13 @@ export class TableCellActionUpdate extends BeanBase implements ITableCellRender
31
33
  return (
32
34
  <ZButton
33
35
  class={options.class}
36
+ aria-label={this.scope.locale.Edit()}
34
37
  onPerform={async () => {
35
38
  await $host.$performCommand('basic-commands:edit', options, renderContext);
36
39
  }}
37
40
  >
38
- <ZIcon name="::draft" width={24}></ZIcon>
41
+ <ZIcon name="::draft" width={24} aria-hidden="true"></ZIcon>
42
+ {options.showLabel && this.scope.locale.Edit()}
39
43
  </ZButton>
40
44
  );
41
45
  }
@@ -0,0 +1,233 @@
1
+ import type { IComponentOptions, ISlot } from 'zova';
2
+
3
+ import { useId } from 'vue';
4
+ import { BeanControllerBase } from 'zova';
5
+ import { Controller } from 'zova-module-a-bean';
6
+ import { ZIcon } from 'zova-module-a-icon';
7
+ import { ZButton } from 'zova-module-basic-button';
8
+
9
+ export interface ControllerRowOperationsProps {
10
+ compact?: boolean;
11
+ class?: unknown;
12
+ slotDefault?: ISlot;
13
+ }
14
+
15
+ @Controller()
16
+ export class ControllerRowOperations extends BeanControllerBase {
17
+ static $propsDefault = { compact: false };
18
+ static $componentOptions: IComponentOptions = { inheritAttrs: false };
19
+
20
+ private _id: string;
21
+ private _actionsRef?: HTMLDivElement;
22
+ private _open = false;
23
+ private _positionFrame?: number;
24
+ private _cPopover: string;
25
+ private _onBeforeToggle: (event: ToggleEvent) => void;
26
+ private _onViewportChange: (event: Event) => void;
27
+ private _onKeydown: (event: KeyboardEvent) => void;
28
+ private _onActionClick: (event: MouseEvent) => void;
29
+
30
+ protected async __init__() {
31
+ this._onActionClick = event => this._handleActionClick(event);
32
+ this._onBeforeToggle = event => this._handleBeforeToggle(event);
33
+ this._onKeydown = event => this._handleKeydown(event);
34
+ this._onViewportChange = event => {
35
+ if (event.target instanceof Node && this._actionsRef?.contains(event.target)) return;
36
+ this._close();
37
+ };
38
+ this._id = this.$composable(useId);
39
+ this._cPopover = this.$style({
40
+ position: 'fixed',
41
+ inset: 'auto',
42
+ margin: 0,
43
+ minWidth: '10rem',
44
+ maxWidth: 'calc(100vw - 16px)',
45
+ maxHeight: 'calc(100vh - 16px)',
46
+ overflowY: 'auto',
47
+ $nest: {
48
+ '&:popover-open': {
49
+ display: 'flex',
50
+ flexDirection: 'column',
51
+ alignItems: 'stretch',
52
+ gap: '0.25rem',
53
+ },
54
+ '& > .btn': {
55
+ justifyContent: 'flex-start',
56
+ },
57
+ },
58
+ });
59
+ this.$watch(
60
+ () => this.$props.compact,
61
+ () => this._close(),
62
+ { flush: 'sync' },
63
+ );
64
+ }
65
+
66
+ protected __dispose__() {
67
+ this._close();
68
+ this._setActionsRef(undefined);
69
+ }
70
+
71
+ private _setActionsRef(element?: HTMLDivElement) {
72
+ if (element === this._actionsRef) return;
73
+ this._actionsRef?.removeEventListener('beforetoggle', this._onBeforeToggle);
74
+ this._actionsRef?.removeEventListener('click', this._onActionClick, true);
75
+ this._actionsRef = element;
76
+ element?.addEventListener('beforetoggle', this._onBeforeToggle);
77
+ element?.addEventListener('click', this._onActionClick, true);
78
+ }
79
+
80
+ private _handleBeforeToggle(event: ToggleEvent) {
81
+ if (event.target !== this._actionsRef) return;
82
+ this._open = event.newState === 'open';
83
+ if (this._open) {
84
+ // beforetoggle precedes display; measure in the first frame after native opening.
85
+ this._actionsRef!.style.visibility = 'hidden';
86
+ this._positionFrame = window.requestAnimationFrame(() => {
87
+ this._positionFrame = undefined;
88
+ if (!this._open) return;
89
+ this._position();
90
+ const element = this._actionsRef;
91
+ element?.style.removeProperty('visibility');
92
+ const document = element?.ownerDocument;
93
+ if (
94
+ document &&
95
+ (document.activeElement?.id === `${this._id}-trigger` ||
96
+ document.activeElement === document.body)
97
+ ) {
98
+ element
99
+ ?.querySelector<HTMLElement>('button:not(:disabled), a[href], [tabindex="0"]')
100
+ ?.focus({ preventScroll: true });
101
+ }
102
+ // Opening can follow scroll-into-view with its scroll event still queued.
103
+ // Arm dismissal only after measuring the settled anchor and revealing the popup.
104
+ window.addEventListener('scroll', this._onViewportChange, true);
105
+ });
106
+ window.addEventListener('resize', this._onViewportChange);
107
+ this._actionsRef!.ownerDocument.addEventListener('keydown', this._onKeydown);
108
+ } else {
109
+ this._clearOpenState();
110
+ }
111
+ }
112
+
113
+ private _clearOpenState() {
114
+ this._open = false;
115
+ if (this._positionFrame !== undefined) {
116
+ window.cancelAnimationFrame(this._positionFrame);
117
+ this._positionFrame = undefined;
118
+ }
119
+ window.removeEventListener('scroll', this._onViewportChange, true);
120
+ window.removeEventListener('resize', this._onViewportChange);
121
+ this._actionsRef?.ownerDocument.removeEventListener('keydown', this._onKeydown);
122
+ this._actionsRef?.style.removeProperty('visibility');
123
+ this._actionsRef?.style.removeProperty('left');
124
+ this._actionsRef?.style.removeProperty('top');
125
+ }
126
+
127
+ private _close() {
128
+ if (!this._open) return;
129
+ const element = this._actionsRef;
130
+ if (element?.isConnected && element.popover === 'auto') element.hidePopover();
131
+ this._clearOpenState();
132
+ }
133
+
134
+ private _handleActionClick(event: MouseEvent) {
135
+ if (!this.$props.compact || !this._open || !(event.target instanceof Element)) return;
136
+ const action = event.target.closest('button, a[href], [role="button"]');
137
+ if (
138
+ !action ||
139
+ !this._actionsRef?.contains(action) ||
140
+ action.matches(':disabled, [aria-disabled="true"]')
141
+ ) {
142
+ return;
143
+ }
144
+ this._close();
145
+ }
146
+
147
+ private _handleKeydown(event: KeyboardEvent) {
148
+ if (event.key !== 'Escape' || event.defaultPrevented || !this._open) return;
149
+ if (event.target instanceof Element && event.target.closest('dialog[open], [role="dialog"]'))
150
+ return;
151
+ const element = this._actionsRef;
152
+ const document = element?.ownerDocument;
153
+ const activeElement = document?.activeElement;
154
+ const trigger = document?.getElementById(`${this._id}-trigger`);
155
+ if (!document || !activeElement) return;
156
+ if (activeElement.closest('dialog[open], [role="dialog"]')) return;
157
+ if (
158
+ activeElement !== document.body &&
159
+ activeElement !== trigger &&
160
+ !element?.contains(activeElement)
161
+ ) {
162
+ return;
163
+ }
164
+ if (activeElement === document.body && document.querySelector('dialog:modal')) return;
165
+ // A disabled action can leave focus on body; never claim unrelated focused controls.
166
+ event.preventDefault();
167
+ event.stopPropagation();
168
+ this._close();
169
+ if (trigger?.isConnected) trigger.focus({ preventScroll: true });
170
+ }
171
+
172
+ private _position() {
173
+ const element = this._actionsRef;
174
+ const trigger = element?.ownerDocument.getElementById(`${this._id}-trigger`);
175
+ if (!element || !trigger) return;
176
+ const anchor = trigger.getBoundingClientRect();
177
+ const popup = element.getBoundingClientRect();
178
+ const viewport = element.ownerDocument.documentElement;
179
+ const margin = 8;
180
+ const gap = 4;
181
+ const left = Math.max(
182
+ margin,
183
+ Math.min(anchor.right - popup.width, viewport.clientWidth - popup.width - margin),
184
+ );
185
+ const below = anchor.bottom + gap;
186
+ const above = anchor.top - gap - popup.height;
187
+ const preferredTop =
188
+ below + popup.height > viewport.clientHeight - margin && above >= margin ? above : below;
189
+ const top = Math.max(
190
+ margin,
191
+ Math.min(preferredTop, viewport.clientHeight - popup.height - margin),
192
+ );
193
+ element.style.left = `${left}px`;
194
+ element.style.top = `${top}px`;
195
+ }
196
+
197
+ protected render() {
198
+ const { compact } = this.$props;
199
+ const label = this.scope.locale.MoreActions();
200
+ return (
201
+ <div class="inline-flex items-center">
202
+ {compact && (
203
+ <ZButton
204
+ key="trigger"
205
+ id={`${this._id}-trigger`}
206
+ class="btn btn-ghost btn-square"
207
+ aria-label={label}
208
+ aria-controls={this._id}
209
+ aria-expanded={this._open}
210
+ {...{ popovertarget: this._id }}
211
+ >
212
+ <ZIcon name="::more-horiz" width={24} aria-hidden="true" />
213
+ </ZButton>
214
+ )}
215
+ <div
216
+ key="actions"
217
+ ref={ref => this._setActionsRef((ref as HTMLDivElement | null) ?? undefined)}
218
+ id={this._id}
219
+ class={
220
+ compact
221
+ ? [this._cPopover, 'bg-base-100 border border-base-300 rounded-box shadow-lg p-2']
222
+ : this.$props.class
223
+ }
224
+ {...{ popover: compact ? 'auto' : undefined }}
225
+ role="group"
226
+ aria-label={this.scope.locale.RowActions()}
227
+ >
228
+ {this.$slotDefault?.()}
229
+ </div>
230
+ </div>
231
+ );
232
+ }
233
+ }
@@ -1,5 +1,6 @@
1
1
  import type {
2
2
  BeanControllerTableBase,
3
+ ControllerTable as ControllerTableInner,
3
4
  ControllerTableProps as ControllerTablePropsSuper,
4
5
  } from 'zova-module-a-table';
5
6
 
@@ -9,12 +10,84 @@ import { Controller } from 'zova-module-a-bean';
9
10
  export interface ControllerTableProps<
10
11
  TData extends {} = {},
11
12
  > extends ControllerTablePropsSuper<TData> {
13
+ compactBreakpoint?: number | false;
12
14
  tableRef?: (ref: BeanControllerTableBase<TData>) => void;
13
15
  }
14
16
 
15
17
  @Controller()
16
18
  export class ControllerTable extends BeanControllerBase {
17
- static $propsDefault = {};
19
+ static $propsDefault = { compactBreakpoint: 768 };
18
20
 
19
- protected async __init__() {}
21
+ innerTable?: ControllerTableInner<any>;
22
+ containerWidth: number = 0;
23
+ popoverSupported: boolean = false;
24
+ private _container?: HTMLElement;
25
+ private _observer?: ResizeObserver;
26
+ private _mounted: boolean = false;
27
+ private _disposed: boolean = false;
28
+
29
+ protected async __init__() {
30
+ this.$controllerMounted(() => {
31
+ this.$ssr.handleDirectOrOnHydrated(() => {
32
+ if (this._disposed) return;
33
+ this._mounted = true;
34
+ this.popoverSupported = typeof HTMLElement.prototype.showPopover === 'function';
35
+ this._observeContainer();
36
+ });
37
+ });
38
+ }
39
+
40
+ public get compact() {
41
+ const breakpoint = this.$props.compactBreakpoint;
42
+ return (
43
+ this.popoverSupported &&
44
+ breakpoint !== false &&
45
+ this.containerWidth > 0 &&
46
+ this.containerWidth < (breakpoint ?? 768)
47
+ );
48
+ }
49
+
50
+ public get columnSizing() {
51
+ const sizing = { ...this.$props.columnSizing };
52
+ if (this.compact) {
53
+ for (const property of this.innerTable?.tableMeta?.properties ?? []) {
54
+ if (this.isOperationsColumn(property.key!)) sizing[property.key!] = 80;
55
+ }
56
+ }
57
+ return sizing;
58
+ }
59
+
60
+ public isOperationsColumn(key: string) {
61
+ const table = this.innerTable;
62
+ if (!table) return false;
63
+ const scope = table.getColumnScope(key);
64
+ const { render } = table.getColumnComponentPropsTop(key, scope, {});
65
+ return table.getRenderProvider(render) === 'basic-table.tableCell.actionOperationsRow';
66
+ }
67
+
68
+ public setContainer(element: HTMLElement | undefined) {
69
+ if (element === this._container) return;
70
+ this._observer?.disconnect();
71
+ this._container = element;
72
+ this._observeContainer();
73
+ }
74
+
75
+ private _observeContainer() {
76
+ const container = this._container;
77
+ if (!this._mounted || this._disposed || !container) return;
78
+ this._observer?.disconnect();
79
+ const measure = () => {
80
+ if (this._disposed || container !== this._container) return;
81
+ this.containerWidth = container.clientWidth;
82
+ };
83
+ measure();
84
+ this._observer = new ResizeObserver(measure);
85
+ this._observer.observe(container);
86
+ }
87
+
88
+ protected __dispose__() {
89
+ this._disposed = true;
90
+ this._observer?.disconnect();
91
+ this._container = undefined;
92
+ }
20
93
  }
@@ -1,4 +1,4 @@
1
- import type { AriaAttributes, CSSProperties } from 'vue';
1
+ import type { AriaAttributes, CSSProperties, ComponentPublicInstance } from 'vue';
2
2
 
3
3
  import { FlexRender } from '@tanstack/vue-table';
4
4
  import { BeanRenderBase } from 'zova';
@@ -9,27 +9,39 @@ import { ControllerTable, TableColumnIdSelection, ZTable } from 'zova-module-a-t
9
9
  export class RenderTable<TData extends {} = {}> extends BeanRenderBase {
10
10
  public render() {
11
11
  return (
12
- <ZTable
13
- data={this.$props.data}
14
- schema={this.$props.schema}
15
- schemaOrder={this.$props.schemaOrder}
16
- sorting={this.$props.sorting}
17
- onSortingChange={this.$props.onSortingChange}
18
- enableRowSelection={this.$props.enableRowSelection}
19
- selectionMode={this.$props.selectionMode}
20
- rowSelection={this.$props.rowSelection}
21
- onRowSelectionChange={this.$props.onRowSelectionChange}
22
- tableScope={this.$props.tableScope}
23
- getColumns={this.$props.getColumns}
24
- getRowId={this.$props.getRowId}
25
- layout={this.$props.layout}
26
- controllerRef={ref => {
27
- this.$props?.tableRef?.(ref);
12
+ <div
13
+ class="min-w-0 max-w-full overflow-x-auto"
14
+ data-table-compact={this.compact ? 'true' : 'false'}
15
+ ref={(element: Element | ComponentPublicInstance | null) => {
16
+ if (this.ctx.disposed) return;
17
+ this.setContainer?.((element as HTMLElement | null) ?? undefined);
28
18
  }}
29
- slotDefault={$$table => {
30
- return this._renderTable($$table);
31
- }}
32
- ></ZTable>
19
+ >
20
+ <ZTable
21
+ data={this.$props.data}
22
+ schema={this.$props.schema}
23
+ schemaOrder={this.$props.schemaOrder}
24
+ sorting={this.$props.sorting}
25
+ onSortingChange={this.$props.onSortingChange}
26
+ enableRowSelection={this.$props.enableRowSelection}
27
+ selectionMode={this.$props.selectionMode}
28
+ rowSelection={this.$props.rowSelection}
29
+ onRowSelectionChange={this.$props.onRowSelectionChange}
30
+ tableScope={this.$props.tableScope}
31
+ getColumns={this.$props.getColumns}
32
+ getRowId={this.$props.getRowId}
33
+ layout={this.$props.layout}
34
+ compact={this.compact}
35
+ columnSizing={this.columnSizing}
36
+ controllerRef={ref => {
37
+ this.innerTable = ref;
38
+ this.$props?.tableRef?.(ref);
39
+ }}
40
+ slotDefault={$$table => {
41
+ return this._renderTable($$table);
42
+ }}
43
+ ></ZTable>
44
+ </div>
33
45
  );
34
46
  }
35
47
 
@@ -38,7 +50,9 @@ export class RenderTable<TData extends {} = {}> extends BeanRenderBase {
38
50
  const fixed = column.getIsPinned();
39
51
  const width = column.getSize();
40
52
  return {
41
- ...(typeof rest?.width === 'number' ? { width: `${width}px`, minWidth: `${width}px` } : {}),
53
+ ...(typeof rest?.width === 'number' || typeof this.columnSizing[column.id] === 'number'
54
+ ? { width: `${width}px`, minWidth: `${width}px` }
55
+ : {}),
42
56
  textAlign: rest?.align,
43
57
  position: fixed ? ('sticky' as const) : undefined,
44
58
  left: fixed === 'left' ? `${column.getStart('left')}px` : undefined,
@@ -75,6 +89,10 @@ export class RenderTable<TData extends {} = {}> extends BeanRenderBase {
75
89
  onChange={table.getToggleAllPageRowsSelectedHandler()}
76
90
  />
77
91
  )
92
+ ) : this.compact && this.isOperationsColumn(column.id) ? (
93
+ <span class="sr-only">
94
+ <FlexRender render={headerDefinition} props={header.getContext()}></FlexRender>
95
+ </span>
78
96
  ) : (
79
97
  <FlexRender render={headerDefinition} props={header.getContext()}></FlexRender>
80
98
  );
@@ -1,5 +1,9 @@
1
1
  export default {
2
2
  Create: 'Create',
3
+ Edit: 'Edit',
4
+ Delete: 'Delete',
5
+ MoreActions: 'More actions',
6
+ RowActions: 'Row actions',
3
7
  DeleteConfirm: 'Are you sure you want to delete this item?',
4
8
  SelectAllPageRows: 'Select all rows on this page',
5
9
  SelectRow: 'Select row %s',
@@ -1,5 +1,9 @@
1
1
  export default {
2
2
  Create: '创建',
3
+ Edit: '编辑',
4
+ Delete: '删除',
5
+ MoreActions: '更多操作',
6
+ RowActions: '行操作',
3
7
  DeleteConfirm: '您确认要删除本数据吗?',
4
8
  SelectAllPageRows: '选择本页所有行',
5
9
  SelectRow: '选择行 %s',
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zova-module-a-table",
3
- "version": "5.1.45",
3
+ "version": "5.1.46",
4
4
  "gitHead": "09d901d17140a80ee0764211b441cda72fd94663",
5
5
  "description": "",
6
6
  "keywords": [