Skip to content

Commit 4741f03

Browse files
committed
refactor toast component + remove unnecessary code
1 parent 0983be1 commit 4741f03

File tree

8 files changed

+500
-504
lines changed

8 files changed

+500
-504
lines changed

client/packages/lowcoder/src/comps/hooks/toastComp.tsx

Lines changed: 0 additions & 504 deletions
This file was deleted.
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import React from "react";
2+
import { Section, sectionNames } from "lowcoder-design";
3+
import { trans } from "i18n";
4+
5+
/**
6+
* Property view for toast component configuration
7+
*/
8+
export const ToastPropertyView = React.memo((props: { comp: any }) => {
9+
const { comp } = props;
10+
11+
return (
12+
<>
13+
<Section name={sectionNames.basic}>
14+
{comp.children.title.propertyView({
15+
label: trans("toastComp.title"),
16+
placeholder: trans("toastComp.titlePlaceholder"),
17+
})}
18+
{comp.children.description.propertyView({
19+
label: trans("toastComp.description"),
20+
placeholder: trans("toastComp.descriptionPlaceholder"),
21+
})}
22+
{comp.children.type.propertyView({
23+
label: trans("toastComp.type"),
24+
})}
25+
</Section>
26+
27+
<Section name={trans("toastComp.behavior")}>
28+
{comp.children.duration.propertyView({
29+
label: trans("toastComp.duration"),
30+
tooltip: trans("toastComp.durationTooltip"),
31+
placeholder: "4.5",
32+
})}
33+
{comp.children.placement.propertyView({
34+
label: trans("toastComp.placement"),
35+
})}
36+
{comp.children.dismissible.propertyView({
37+
label: trans("toastComp.dismissible"),
38+
})}
39+
{comp.children.showProgress.propertyView({
40+
label: trans("toastComp.showProgress"),
41+
tooltip: trans("toastComp.showProgressTooltip"),
42+
})}
43+
{comp.children.pauseOnHover.propertyView({
44+
label: trans("toastComp.pauseOnHover"),
45+
})}
46+
</Section>
47+
48+
<Section name={sectionNames.layout}>
49+
{comp.children.width.propertyView({
50+
label: trans("toastComp.width"),
51+
tooltip: trans("toastComp.widthTooltip"),
52+
placeholder: "384px or 100vw",
53+
})}
54+
{comp.children.progressHeight.propertyView({
55+
label: trans("toastComp.progressHeight"),
56+
tooltip: trans("toastComp.progressHeightTooltip"),
57+
placeholder: "4px",
58+
})}
59+
</Section>
60+
61+
<Section name={sectionNames.interaction}>
62+
{comp.children.onEvent.getPropertyView()}
63+
</Section>
64+
65+
<Section name={sectionNames.style}>
66+
{comp.children.style.getPropertyView()}
67+
</Section>
68+
</>
69+
);
70+
});
71+
72+
ToastPropertyView.displayName = "ToastPropertyView";
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import React, { useEffect, useId } from "react";
2+
import { NotificationStyleType } from "comps/controls/styleControlConstants";
3+
import { ToastGlobalStyle } from "./toastStyles";
4+
5+
/**
6+
* Toast runtime view - injects global CSS styles for the notification.
7+
*/
8+
export const ToastRuntimeView = React.memo((props: { comp: any }) => {
9+
const { comp } = props;
10+
const style = comp.children.style.getView() as NotificationStyleType;
11+
const width = comp.children.width.getView() as string;
12+
const progressHeight = comp.children.progressHeight.getView() as string;
13+
const instanceId = useId().replace(/:/g, '-');
14+
15+
// Store instance ID so the show() method can use it for the notification className
16+
useEffect(() => {
17+
comp.children.instanceId.dispatchChangeValueAction(instanceId);
18+
}, [comp, instanceId]);
19+
20+
return (
21+
<ToastGlobalStyle
22+
$instanceId={instanceId}
23+
$background={style.background}
24+
$textColor={style.color}
25+
$closeIconColor={style.closeIconColor}
26+
$infoIconColor={style.infoIconColor}
27+
$successIconColor={style.successIconColor}
28+
$warningIconColor={style.warningIconColor}
29+
$errorIconColor={style.errorIconColor}
30+
$progressColor={style.progressColor}
31+
$progressBackground={style.progressBackground}
32+
$progressHeight={progressHeight || undefined}
33+
$border={style.border}
34+
$borderWidth={style.borderWidth}
35+
$borderStyle={style.borderStyle}
36+
$radius={style.radius}
37+
$margin={style.margin}
38+
$padding={style.padding || '20px'}
39+
$width={width || undefined}
40+
/>
41+
);
42+
});
43+
44+
ToastRuntimeView.displayName = "ToastRuntimeView";
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { ToastComp } from "./toastComp";
2+
export type { ToastType } from "./toastConstants";
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import { simpleMultiComp, withPropertyViewFn, withViewFn } from "comps/generators";
2+
import { withMethodExposing } from "comps/generators/withMethodExposing";
3+
import { withExposingConfigs } from "comps/generators/withExposing";
4+
import { notificationInstance } from "lowcoder-design";
5+
import { trans } from "i18n";
6+
import type { NotificationPlacement } from "antd/es/notification/interface";
7+
import React from "react";
8+
9+
import { childrenMap, showParams, closeParams, ToastType } from "./toastConstants";
10+
import { showNotificationWithEvents, showNotificationProgrammatic, ToastConfig } from "./toastUtils";
11+
import { ToastPropertyView } from "./ToastPropertyView";
12+
import { ToastRuntimeView } from "./ToastRuntimeView";
13+
14+
// Build the component
15+
let ToastCompBase = simpleMultiComp(childrenMap);
16+
17+
ToastCompBase = withViewFn(ToastCompBase, (comp) => <ToastRuntimeView comp={comp} />);
18+
19+
ToastCompBase = withPropertyViewFn(ToastCompBase, (comp) => (
20+
<ToastPropertyView comp={comp} />
21+
));
22+
23+
24+
let ToastCompWithExposing = withExposingConfigs(ToastCompBase, []);
25+
26+
// Add method exposing
27+
export let ToastComp = withMethodExposing(ToastCompWithExposing, [
28+
{
29+
method: {
30+
name: "show",
31+
description: trans("toastComp.showMethod"),
32+
params: [],
33+
},
34+
execute: (comp) => {
35+
const config: ToastConfig = {
36+
title: comp.children.title.getView(),
37+
description: comp.children.description.getView(),
38+
type: comp.children.type.getView() as ToastType,
39+
duration: comp.children.duration.getView(),
40+
placement: comp.children.placement.getView() as NotificationPlacement,
41+
dismissible: comp.children.dismissible.getView(),
42+
showProgress: comp.children.showProgress.getView(),
43+
pauseOnHover: comp.children.pauseOnHover.getView(),
44+
instanceId: comp.children.instanceId.getView() as string,
45+
};
46+
47+
const onEvent = comp.children.onEvent.getView();
48+
const setVisible = (visible: boolean) => {
49+
comp.children.visible.dispatchChangeValueAction(visible);
50+
};
51+
52+
showNotificationWithEvents(config, onEvent, setVisible);
53+
},
54+
},
55+
{
56+
method: {
57+
name: "info",
58+
description: trans("toastComp.info"),
59+
params: showParams,
60+
},
61+
execute: (comp, params) => showNotificationProgrammatic(params, "info", comp),
62+
},
63+
{
64+
method: {
65+
name: "success",
66+
description: trans("toastComp.success"),
67+
params: showParams,
68+
},
69+
execute: (comp, params) => showNotificationProgrammatic(params, "success", comp),
70+
},
71+
{
72+
method: {
73+
name: "warn",
74+
description: trans("toastComp.warn"),
75+
params: showParams,
76+
},
77+
execute: (comp, params) => showNotificationProgrammatic(params, "warning", comp),
78+
},
79+
{
80+
method: {
81+
name: "error",
82+
description: trans("toastComp.error"),
83+
params: showParams,
84+
},
85+
execute: (comp, params) => showNotificationProgrammatic(params, "error", comp),
86+
},
87+
{
88+
method: {
89+
name: "close",
90+
description: trans("toastComp.closeMethod"),
91+
params: closeParams,
92+
},
93+
execute: (comp, params) => {
94+
const key = params?.[0] as string;
95+
if (key) {
96+
notificationInstance.destroy(key);
97+
}
98+
comp.children.visible.dispatchChangeValueAction(false);
99+
comp.children.onEvent.getView()("close");
100+
},
101+
},
102+
// Legacy method for backwards compatibility
103+
{
104+
method: {
105+
name: "destroy",
106+
description: trans("toastComp.destroy"),
107+
params: closeParams,
108+
},
109+
execute: (comp, params) => {
110+
const key = params?.[0] as string;
111+
notificationInstance.destroy(key);
112+
},
113+
},
114+
{
115+
method: {
116+
name: "open",
117+
description: trans("toastComp.openMethod"),
118+
params: showParams,
119+
},
120+
execute: (comp, params) => showNotificationProgrammatic(params, "info", comp),
121+
},
122+
]);
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import { BoolControl } from "comps/controls/boolControl";
2+
import { NumberControl, StringControl } from "comps/controls/codeControl";
3+
import { dropdownControl } from "comps/controls/dropdownControl";
4+
import { eventHandlerControl } from "comps/controls/eventHandlerControl";
5+
import { styleControl } from "comps/controls/styleControl";
6+
import { NotificationStyle } from "comps/controls/styleControlConstants";
7+
import { withDefault } from "comps/generators";
8+
import { stateComp } from "comps/generators/simpleGenerators";
9+
import { ParamsConfig } from "comps/controls/actionSelector/executeCompTypes";
10+
import { trans } from "i18n";
11+
12+
// Toast type
13+
export type ToastType = "info" | "success" | "warning" | "error";
14+
15+
// Toast type options
16+
export const toastTypeOptions = [
17+
{ label: trans("toastComp.typeInfo"), value: "info" },
18+
{ label: trans("toastComp.typeSuccess"), value: "success" },
19+
{ label: trans("toastComp.typeWarning"), value: "warning" },
20+
{ label: trans("toastComp.typeError"), value: "error" },
21+
] as const;
22+
23+
// Placement options
24+
export const placementOptions = [
25+
{ label: trans("toastComp.placementTopLeft"), value: "topLeft" },
26+
{ label: trans("toastComp.placementTopRight"), value: "topRight" },
27+
{ label: trans("toastComp.placementBottomLeft"), value: "bottomLeft" },
28+
{ label: trans("toastComp.placementBottomRight"), value: "bottomRight" },
29+
] as const;
30+
31+
// Event options
32+
export const ToastEventOptions = [
33+
{ label: trans("toastComp.click"), value: "click", description: trans("toastComp.clickDesc") },
34+
{ label: trans("toastComp.close"), value: "close", description: trans("toastComp.closeDesc") },
35+
] as const;
36+
37+
// Method params
38+
export const showParams: ParamsConfig = [
39+
{ name: "text", type: "string" },
40+
{ name: "options", type: "JSON" },
41+
];
42+
43+
export const closeParams: ParamsConfig = [
44+
{ name: "key", type: "string" },
45+
];
46+
47+
// Children map for toast component configuration
48+
export const childrenMap = {
49+
// Basic configuration
50+
title: withDefault(StringControl, ""),
51+
description: withDefault(StringControl, ""),
52+
type: dropdownControl(toastTypeOptions, "info"),
53+
54+
// Timing
55+
duration: withDefault(NumberControl, 4.5),
56+
57+
// Position & Appearance
58+
placement: dropdownControl(placementOptions, "bottomRight"),
59+
dismissible: withDefault(BoolControl, true),
60+
showProgress: withDefault(BoolControl, false),
61+
pauseOnHover: withDefault(BoolControl, true),
62+
63+
// Layout
64+
width: withDefault(StringControl, ""),
65+
progressHeight: withDefault(StringControl, ""),
66+
67+
// Event handlers
68+
onEvent: eventHandlerControl(ToastEventOptions),
69+
70+
// Style (applied via global CSS in ToastRuntimeView)
71+
style: styleControl(NotificationStyle),
72+
73+
// Internal state for tracking visibility
74+
visible: stateComp<boolean>(false),
75+
76+
// Unique instance ID for scoped styling (set by ToastRuntimeView)
77+
instanceId: stateComp<string>(""),
78+
};

0 commit comments

Comments
 (0)