Skip to content

Commit 16713f4

Browse files
liujupingJackLian
authored andcommitted
feat(skeleton): Add TS defs for modules & optimize Tabs display with array contents
1 parent 711a5f6 commit 16713f4

File tree

7 files changed

+78
-70
lines changed

7 files changed

+78
-70
lines changed

packages/editor-skeleton/src/components/widget-views/index.tsx

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -266,15 +266,28 @@ export class PanelView extends Component<{
266266
}
267267

268268
@observer
269-
export class TabsPanelView extends Component<{ container: WidgetContainer<Panel> }> {
269+
export class TabsPanelView extends Component<{
270+
container: WidgetContainer<Panel>;
271+
// shouldHideSingleTab: 一个布尔值,用于控制当 Tabs 组件只有一个标签时是否隐藏该标签。
272+
shouldHideSingleTab?: boolean;
273+
}> {
270274
render() {
271275
const { container } = this.props;
272276
const titles: ReactElement[] = [];
273277
const contents: ReactElement[] = [];
274-
container.items.forEach((item: any) => {
275-
titles.push(<PanelTitle key={item.id} panel={item} className="lc-tab-title" />);
276-
contents.push(<PanelView key={item.id} panel={item} hideOperationRow hideDragLine />);
277-
});
278+
// 如果只有一个标签且 shouldHideSingleTab 为 true,则不显示 Tabs
279+
if (this.props.shouldHideSingleTab && container.items.length === 1) {
280+
contents.push(<PanelView key={container.items[0].id} panel={container.items[0]} hideOperationRow hideDragLine />);
281+
} else {
282+
container.items.forEach((item: any) => {
283+
titles.push(<PanelTitle key={item.id} panel={item} className="lc-tab-title" />);
284+
contents.push(<PanelView key={item.id} panel={item} hideOperationRow hideDragLine />);
285+
});
286+
}
287+
288+
if (!titles.length) {
289+
return contents;
290+
}
278291

279292
return (
280293
<div className="lc-tabs">

packages/editor-skeleton/src/layouts/left-fixed-pane.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,16 @@ import { Component, Fragment } from 'react';
22
import classNames from 'classnames';
33
import { observer } from '@alilc/lowcode-editor-core';
44
import { Area } from '../area';
5-
import { PanelConfig } from '../types';
65
import { Panel } from '../widget/panel';
6+
import { IPublicTypePanelConfig } from '@alilc/lowcode-types';
77

88
@observer
9-
export default class LeftFixedPane extends Component<{ area: Area<PanelConfig, Panel> }> {
9+
export default class LeftFixedPane extends Component<{ area: Area<IPublicTypePanelConfig, Panel> }> {
1010
componentDidUpdate() {
1111
// FIXME: dirty fix, need deep think
1212
this.props.area.skeleton.editor.get('designer')?.touchOffsetObserver();
1313
}
1414

15-
1615
render() {
1716
const { area } = this.props;
1817
const width = area.current?.config.props?.width;
@@ -36,7 +35,7 @@ export default class LeftFixedPane extends Component<{ area: Area<PanelConfig, P
3635
}
3736

3837
@observer
39-
class Contents extends Component<{ area: Area<PanelConfig, Panel> }> {
38+
class Contents extends Component<{ area: Area<IPublicTypePanelConfig, Panel> }> {
4039
render() {
4140
const { area } = this.props;
4241
return <Fragment>{area.container.items.map((panel) => panel.content)}</Fragment>;

packages/editor-skeleton/src/layouts/left-float-pane.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,10 @@ import classNames from 'classnames';
33
import { observer, Focusable } from '@alilc/lowcode-editor-core';
44
import { Area } from '../area';
55
import { Panel } from '../widget/panel';
6-
import { PanelConfig } from '../types';
7-
import { IPublicApiProject } from '@alilc/lowcode-types';
6+
import { IPublicApiProject, IPublicTypePanelConfig } from '@alilc/lowcode-types';
87

98
@observer
10-
export default class LeftFloatPane extends Component<{ area: Area<PanelConfig, Panel> }> {
9+
export default class LeftFloatPane extends Component<{ area: Area<IPublicTypePanelConfig, Panel> }> {
1110
private dispose?: () => void;
1211

1312
private focusing?: Focusable;

packages/editor-skeleton/src/skeleton.ts

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { action, makeObservable, obx, engineConfig, IEditor, FocusTracker } from '@alilc/lowcode-editor-core';
22
import {
33
DockConfig,
4-
PanelConfig,
54
WidgetConfig,
65
PanelDockConfig,
76
DialogDockConfig,
@@ -29,6 +28,7 @@ import {
2928
IPublicTypeSkeletonConfig,
3029
IPublicApiSkeleton,
3130
IPublicTypeConfigTransducer,
31+
IPublicTypePanelConfig,
3232
} from '@alilc/lowcode-types';
3333

3434
const logger = new Logger({ level: 'warn', bizName: 'skeleton' });
@@ -70,15 +70,15 @@ export interface ISkeleton extends Omit<IPublicApiSkeleton,
7070

7171
readonly toolbar: Area<DockConfig | DividerConfig | PanelDockConfig | DialogDockConfig>;
7272

73-
readonly leftFixedArea: Area<PanelConfig, Panel>;
73+
readonly leftFixedArea: Area<IPublicTypePanelConfig, Panel>;
7474

75-
readonly leftFloatArea: Area<PanelConfig, Panel>;
75+
readonly leftFloatArea: Area<IPublicTypePanelConfig, Panel>;
7676

77-
readonly rightArea: Area<PanelConfig, Panel>;
77+
readonly rightArea: Area<IPublicTypePanelConfig, Panel>;
7878

79-
readonly mainArea: Area<WidgetConfig | PanelConfig, Widget | Panel>;
79+
readonly mainArea: Area<WidgetConfig | IPublicTypePanelConfig, Widget | Panel>;
8080

81-
readonly bottomArea: Area<PanelConfig, Panel>;
81+
readonly bottomArea: Area<IPublicTypePanelConfig, Panel>;
8282

8383
readonly stages: Area<StageConfig, Stage>;
8484

@@ -104,7 +104,7 @@ export interface ISkeleton extends Omit<IPublicApiSkeleton,
104104
defaultSetCurrent?: boolean,
105105
): WidgetContainer;
106106

107-
createPanel(config: PanelConfig): Panel;
107+
createPanel(config: IPublicTypePanelConfig): Panel;
108108

109109
add(config: IPublicTypeSkeletonConfig, extraConfig?: Record<string, any>): IWidget | Widget | Panel | Stage | Dock | PanelDock | undefined;
110110
}
@@ -124,15 +124,15 @@ export class Skeleton implements ISkeleton {
124124

125125
readonly toolbar: Area<DockConfig | DividerConfig | PanelDockConfig | DialogDockConfig>;
126126

127-
readonly leftFixedArea: Area<PanelConfig, Panel>;
127+
readonly leftFixedArea: Area<IPublicTypePanelConfig, Panel>;
128128

129-
readonly leftFloatArea: Area<PanelConfig, Panel>;
129+
readonly leftFloatArea: Area<IPublicTypePanelConfig, Panel>;
130130

131-
readonly rightArea: Area<PanelConfig, Panel>;
131+
readonly rightArea: Area<IPublicTypePanelConfig, Panel>;
132132

133-
@obx readonly mainArea: Area<WidgetConfig | PanelConfig, Widget | Panel>;
133+
@obx readonly mainArea: Area<WidgetConfig | IPublicTypePanelConfig, Widget | Panel>;
134134

135-
readonly bottomArea: Area<PanelConfig, Panel>;
135+
readonly bottomArea: Area<IPublicTypePanelConfig, Panel>;
136136

137137
readonly stages: Area<StageConfig, Stage>;
138138

@@ -388,9 +388,9 @@ export class Skeleton implements ISkeleton {
388388
return this.widgets.find(widget => widget.name === name);
389389
}
390390

391-
createPanel(config: PanelConfig) {
391+
createPanel(config: IPublicTypePanelConfig) {
392392
const parsedConfig = this.parseConfig(config);
393-
const panel = new Panel(this, parsedConfig as PanelConfig);
393+
const panel = new Panel(this, parsedConfig as IPublicTypePanelConfig);
394394
this.panels.set(panel.name, panel);
395395
logger.debug(`Panel created with name: ${panel.name} \nconfig:`, config, '\n current panels: ', this.panels);
396396
return panel;
@@ -496,7 +496,7 @@ export class Skeleton implements ISkeleton {
496496
return this.leftArea.add(parsedConfig as PanelDockConfig);
497497
case 'rightArea':
498498
case 'right':
499-
return this.rightArea.add(parsedConfig as PanelConfig);
499+
return this.rightArea.add(parsedConfig as IPublicTypePanelConfig);
500500
case 'topArea':
501501
case 'top':
502502
return this.topArea.add(parsedConfig as PanelDockConfig);
@@ -508,14 +508,14 @@ export class Skeleton implements ISkeleton {
508508
case 'main':
509509
case 'center':
510510
case 'centerArea':
511-
return this.mainArea.add(parsedConfig as PanelConfig);
511+
return this.mainArea.add(parsedConfig as IPublicTypePanelConfig);
512512
case 'bottomArea':
513513
case 'bottom':
514-
return this.bottomArea.add(parsedConfig as PanelConfig);
514+
return this.bottomArea.add(parsedConfig as IPublicTypePanelConfig);
515515
case 'leftFixedArea':
516-
return this.leftFixedArea.add(parsedConfig as PanelConfig);
516+
return this.leftFixedArea.add(parsedConfig as IPublicTypePanelConfig);
517517
case 'leftFloatArea':
518-
return this.leftFloatArea.add(parsedConfig as PanelConfig);
518+
return this.leftFloatArea.add(parsedConfig as IPublicTypePanelConfig);
519519
case 'stages':
520520
return this.stages.add(parsedConfig as StageConfig);
521521
default:

packages/editor-skeleton/src/types.ts

Lines changed: 5 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import { ReactElement, ComponentType } from 'react';
22
import {
33
IPublicTypeTitleContent,
4-
IPublicTypeI18nData,
54
IPublicTypeWidgetConfigArea,
65
IPublicTypeWidgetBaseConfig,
7-
IPublicTypePanelDockPanelProps,
86
IPublicTypePanelDockProps,
7+
IPublicTypePanelConfigProps,
8+
IPublicTypePanelConfig,
99
} from '@alilc/lowcode-types';
1010
import { IWidget } from './widget/widget';
1111

@@ -66,40 +66,17 @@ export function isDialogDockConfig(obj: any): obj is DialogDockConfig {
6666
return obj && obj.type === 'DialogDock';
6767
}
6868

69-
// 窗格扩展
70-
export interface PanelConfig extends IPublicTypeWidgetBaseConfig {
71-
type: 'Panel';
72-
content?: string | ReactElement | ComponentType<any> | PanelConfig[]; // as children
73-
props?: PanelProps;
74-
}
75-
76-
export function isPanelConfig(obj: any): obj is PanelConfig {
69+
export function isPanelConfig(obj: any): obj is IPublicTypePanelConfig {
7770
return obj && obj.type === 'Panel';
7871
}
7972

80-
export type HelpTipConfig = string | { url?: string; content?: string | ReactElement };
81-
82-
export interface PanelProps extends IPublicTypePanelDockPanelProps {
83-
title?: IPublicTypeTitleContent;
84-
icon?: any; // 冗余字段
85-
description?: string | IPublicTypeI18nData;
86-
help?: HelpTipConfig; // 显示问号帮助
87-
hiddenWhenInit?: boolean; // when this is true, by default will be hidden
88-
condition?: (widget: IWidget) => any;
89-
onInit?: (widget: IWidget) => any;
90-
onDestroy?: () => any;
91-
shortcut?: string; // 只有在特定位置,可触发 toggle show
92-
enableDrag?: boolean; // 是否开启通过 drag 调整 宽度
93-
keepVisibleWhileDragging?: boolean; // 是否在该 panel 范围内拖拽时保持 visible 状态
94-
}
95-
9673
export interface PanelDockConfig extends IDockBaseConfig {
9774
type: 'PanelDock';
9875
panelName?: string;
99-
panelProps?: PanelProps & {
76+
panelProps?: IPublicTypePanelConfigProps & {
10077
area?: IPublicTypeWidgetConfigArea;
10178
};
102-
content?: string | ReactElement | ComponentType<any> | PanelConfig[]; // content for pane
79+
content?: string | ReactElement | ComponentType<any> | IPublicTypePanelConfig[]; // content for pane
10380
}
10481

10582
export function isPanelDockConfig(obj: any): obj is PanelDockConfig {

packages/editor-skeleton/src/widget/panel.ts

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
import { createElement, ReactNode } from 'react';
22
import { obx, computed, makeObservable, IEventBus, createModuleEventBus } from '@alilc/lowcode-editor-core';
33
import { uniqueId, createContent } from '@alilc/lowcode-utils';
4-
import { IPublicTypeTitleContent } from '@alilc/lowcode-types';
4+
import { IPublicTypeHelpTipConfig, IPublicTypePanelConfig, IPublicTypeTitleContent } from '@alilc/lowcode-types';
55
import { WidgetContainer } from './widget-container';
66
import { getEvent } from '@alilc/lowcode-shell';
7-
import { PanelConfig, HelpTipConfig } from '../types';
87
import { TitledPanelView, TabsPanelView, PanelView } from '../components/widget-views';
98
import { ISkeleton } from '../skeleton';
109
import { composeTitle } from './utils';
@@ -45,6 +44,7 @@ export class Panel implements IWidget {
4544
if (this.container) {
4645
return createElement(TabsPanelView, {
4746
container: this.container,
47+
shouldHideSingleTab: true,
4848
});
4949
}
5050

@@ -72,15 +72,15 @@ export class Panel implements IWidget {
7272

7373
readonly title: IPublicTypeTitleContent;
7474

75-
readonly help?: HelpTipConfig;
75+
readonly help?: IPublicTypeHelpTipConfig;
7676

7777
private plain = false;
7878

79-
private container?: WidgetContainer<Panel, PanelConfig>;
79+
private container?: WidgetContainer<Panel, IPublicTypePanelConfig>;
8080

8181
@obx.ref public parent?: WidgetContainer;
8282

83-
constructor(readonly skeleton: ISkeleton, readonly config: PanelConfig) {
83+
constructor(readonly skeleton: ISkeleton, readonly config: IPublicTypePanelConfig) {
8484
makeObservable(this);
8585
const { name, content, props = {} } = config;
8686
const { hideTitleBar, title, icon, description, help } = props;
@@ -90,9 +90,6 @@ export class Panel implements IWidget {
9090
this.plain = hideTitleBar || !title;
9191
this.help = help;
9292
if (Array.isArray(content)) {
93-
if (content.length === 1) {
94-
// todo: not show tabs
95-
}
9693
this.container = this.skeleton.createContainer(
9794
name,
9895
(item) => {
@@ -127,7 +124,7 @@ export class Panel implements IWidget {
127124
this.parent = parent;
128125
}
129126

130-
add(item: Panel | PanelConfig) {
127+
add(item: Panel | IPublicTypePanelConfig) {
131128
return this.container?.add(item);
132129
}
133130

packages/types/src/shell/type/widget-base-config.ts

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,27 @@
1-
import { IPublicTypeIconType, IPublicTypeTitleContent, IPublicTypeWidgetConfigArea, TipContent } from './';
1+
import { ReactElement, ComponentType } from 'react';
2+
import { IPublicTypeI18nData, IPublicTypeIconType, IPublicTypeTitleContent, IPublicTypeWidgetConfigArea, TipContent } from './';
3+
4+
export type IPublicTypeHelpTipConfig = string | { url?: string; content?: string | ReactElement };
5+
6+
export interface IPublicTypePanelConfigProps extends IPublicTypePanelDockPanelProps {
7+
title?: IPublicTypeTitleContent;
8+
icon?: any; // 冗余字段
9+
description?: string | IPublicTypeI18nData;
10+
help?: IPublicTypeHelpTipConfig; // 显示问号帮助
11+
hiddenWhenInit?: boolean; // when this is true, by default will be hidden
12+
condition?: (widget: any) => any;
13+
onInit?: (widget: any) => any;
14+
onDestroy?: () => any;
15+
shortcut?: string; // 只有在特定位置,可触发 toggle show
16+
enableDrag?: boolean; // 是否开启通过 drag 调整 宽度
17+
keepVisibleWhileDragging?: boolean; // 是否在该 panel 范围内拖拽时保持 visible 状态
18+
}
19+
20+
export interface IPublicTypePanelConfig extends IPublicTypeWidgetBaseConfig {
21+
type: 'Panel';
22+
content?: string | ReactElement | ComponentType<any> | IPublicTypePanelConfig[]; // as children
23+
props?: IPublicTypePanelConfigProps;
24+
}
225

326
export interface IPublicTypeWidgetBaseConfig {
427
[extra: string]: any;
@@ -13,7 +36,7 @@ export interface IPublicTypeWidgetBaseConfig {
1336
*/
1437
area?: IPublicTypeWidgetConfigArea;
1538
props?: Record<string, any>;
16-
content?: any;
39+
content?: string | ReactElement | ComponentType<any> | IPublicTypePanelConfig[];
1740
contentProps?: Record<string, any>;
1841

1942
/**

0 commit comments

Comments
 (0)