Skip to content

Commit 7746038

Browse files
committed
add ConfirmationInput widget
1 parent 5b9f770 commit 7746038

File tree

7 files changed

+216
-3
lines changed

7 files changed

+216
-3
lines changed

apps/starter/src/ensemble/askEmbrace.yaml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,32 @@ View:
2222
# - Text:
2323
# id: he
2424
# text: hehe
25+
- ConfirmationInput:
26+
id: myConfirmationInput
27+
length: 4
28+
styles:
29+
inputType: "number"
30+
fieldWidth: 30
31+
fieldHeight: 30
32+
defaultFieldBorderColor: "green"
33+
defaultFieldBackgroundColor: "grey"
34+
activeFieldBorderColor: "black"
35+
activeFieldBackgroundColor: "yellow"
36+
filledFieldBorderColor: "blue"
37+
filledFieldBackgroundColor: "aqua"
38+
gap: 30px
39+
backgroundColor: "lightblue"
40+
padding: 20
41+
textStyle:
42+
fontSize: 15
43+
onChange:
44+
executeCode:
45+
body: |
46+
console.log(myConfirmationInput.text)
47+
onComplete:
48+
executeCode:
49+
body: |
50+
console.log("completed: "+myConfirmationInput.text)
2551
- Form:
2652
styles:
2753
labelPosition: start

packages/runtime/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
"@types/react": "^18.2.21",
3434
"@types/react-dom": "^18.2.0",
3535
"antd": "^5.9.0",
36+
"antd-input-otp": "^2.0.4",
3637
"chart.js": "^4.4.0",
3738
"eslint-config-custom": "workspace:*",
3839
"jest": "27.5.1",

packages/runtime/src/runtime/hooks/useEnsembleAction.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ export const useEnsembleAction = (
339339
(action.navigateScreen && navigateScreen) ||
340340
(action.showToast && showToast) ||
341341
(action.navigateModalScreen && navigateModalScreen) ||
342-
("closeAllDialogs" in action && closeAllDialogs) ||
342+
(!isString(action) && "closeAllDialogs" in action && closeAllDialogs) ||
343343
(action.pickFiles && pickFiles) ||
344344
(action.uploadFiles && uploadFiles)
345345
);

packages/runtime/src/util/types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import type { EnsembleWidget, Expression } from "@ensembleui/react-framework";
22

3-
export interface EnsembleWidgetProps {
3+
export interface EnsembleWidgetProps<T = Record<string, string | number>> {
44
id?: string;
5+
styles?: T;
56
[key: string]: unknown;
6-
styles?: Record<string, string | number>;
77
}
88

99
export type BaseTextProps = {
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
import {
2+
type EnsembleAction,
3+
useRegisterBindings,
4+
} from "@ensembleui/react-framework";
5+
import { InputOTP } from "antd-input-otp";
6+
import { useState } from "react";
7+
import { Form } from "antd";
8+
import { useEnsembleAction } from "../runtime/hooks/useEnsembleAction";
9+
import { WidgetRegistry } from "../registry";
10+
import type { EnsembleWidgetProps } from "../util/utils";
11+
import type { TextStyles } from "./Text";
12+
13+
interface ConfirmationInputStyles {
14+
inputType?: "number" | "text";
15+
fieldWidth?: number | string;
16+
fieldHeight?: number | string;
17+
gap?: number;
18+
spaceEvenly?: boolean;
19+
defaultFieldBorderColor?: string;
20+
activeFieldBorderColor?: string;
21+
filledFieldBorderColor?: string;
22+
defaultFieldBackgroundColor?: string;
23+
activeFieldBackgroundColor?: string;
24+
filledFieldBackgroundColor?: string;
25+
textStyle?: TextStyles;
26+
27+
backgroundColor?: string;
28+
margin?: number | string;
29+
padding?: number | string;
30+
31+
[key: string]: unknown;
32+
}
33+
34+
const defaultStyles: ConfirmationInputStyles = {
35+
inputType: "number",
36+
fieldWidth: 50,
37+
fieldHeight: 50,
38+
gap: 10,
39+
spaceEvenly: true,
40+
defaultFieldBorderColor: "rgba(0, 0, 0, 0.451)",
41+
activeFieldBorderColor: "black",
42+
filledFieldBorderColor: "transparent",
43+
defaultFieldBackgroundColor: "transparent",
44+
activeFieldBackgroundColor: "transparent",
45+
filledFieldBackgroundColor: "transparent",
46+
textStyle: {
47+
color: "black",
48+
fontFamily: "inherit",
49+
fontSize: 25,
50+
fontWeight: "bold",
51+
backgroundColor: "transparent",
52+
},
53+
54+
backgroundColor: "transparent",
55+
margin: 0,
56+
padding: 0,
57+
};
58+
59+
type ConfirmationInputProps = {
60+
length?: number;
61+
onChange?: EnsembleAction;
62+
onComplete?: EnsembleAction;
63+
} & EnsembleWidgetProps<ConfirmationInputStyles>;
64+
65+
export const ConfirmationInput: React.FC<ConfirmationInputProps> = (props) => {
66+
const { id, length, onChange, onComplete, styles, ...otherProps } = props;
67+
68+
const [form] = Form.useForm();
69+
70+
const [text, setText] = useState("");
71+
72+
const onChangeAction = useEnsembleAction(onChange);
73+
const onCompleteAction = useEnsembleAction(onComplete);
74+
75+
useRegisterBindings({ text }, id, { setText });
76+
77+
const handleChange = (value: string[]): void => {
78+
setText(value.join(""));
79+
80+
onChangeAction?.callback({
81+
[id as string]: {
82+
text: value.join(""),
83+
setText,
84+
},
85+
});
86+
};
87+
88+
const handleComplete = (values: Record<string, string[]>): unknown =>
89+
onCompleteAction?.callback({
90+
[id as string]: {
91+
text: values["confirmationItem"].join(""),
92+
setText,
93+
},
94+
});
95+
96+
const customStyles = `
97+
.confirmationInput:focus {
98+
border-color: ${
99+
styles?.activeFieldBorderColor || defaultStyles.activeFieldBorderColor
100+
} !important;
101+
background-color: ${
102+
styles?.activeFieldBackgroundColor ||
103+
defaultStyles.activeFieldBackgroundColor
104+
} !important;
105+
}
106+
107+
.confirmationinput[value]:not([value=""]):not(.confirmationinput:where(.ant-input:focus), .confirmationinput:where(.ant-input-focused)) {
108+
border-color: ${
109+
styles?.filledFieldBorderColor || defaultStyles.filledFieldBorderColor
110+
} !important;
111+
background-color: ${
112+
styles?.filledFieldBackgroundColor ||
113+
defaultStyles.filledFieldBackgroundColor
114+
} !important;
115+
}
116+
`;
117+
118+
return (
119+
<>
120+
<style>{customStyles}</style>
121+
<Form form={form} onFinish={handleComplete}>
122+
<Form.Item name="confirmationItem">
123+
<InputOTP
124+
length={length || 4}
125+
onChange={handleChange}
126+
autoSubmit={form}
127+
inputType={styles?.inputType === "text" ? "all" : "numeric"}
128+
inputClassName="confirmationInput"
129+
wrapperStyle={{
130+
backgroundColor:
131+
styles?.backgroundColor || defaultStyles.backgroundColor,
132+
margin: styles?.margin || defaultStyles.margin,
133+
padding: styles?.padding || defaultStyles.padding,
134+
gap:
135+
styles?.gap && !styles?.spaceEvenly
136+
? styles?.gap
137+
: defaultStyles.gap,
138+
...(styles?.spaceEvenly && {
139+
flex: 1,
140+
alignItems: "center",
141+
justifyContent: "space-evenly",
142+
}),
143+
}}
144+
inputStyle={{
145+
padding: 0,
146+
margin: 0,
147+
width: styles?.fieldWidth || defaultStyles.fieldWidth,
148+
height: styles?.fieldHeight || defaultStyles.fieldHeight,
149+
borderColor:
150+
styles?.defaultFieldBorderColor ||
151+
defaultStyles.defaultFieldBorderColor,
152+
backgroundColor:
153+
styles?.defaultFieldBackgroundColor ||
154+
defaultStyles.defaultFieldBackgroundColor,
155+
fontFamily:
156+
styles?.textStyle?.fontFamily ||
157+
defaultStyles.textStyle?.fontFamily,
158+
fontSize:
159+
styles?.textStyle?.fontSize ||
160+
defaultStyles.textStyle?.fontSize,
161+
fontWeight:
162+
styles?.textStyle?.fontWeight ||
163+
defaultStyles.textStyle?.fontWeight,
164+
color: styles?.textStyle?.color || defaultStyles.textStyle?.color,
165+
}}
166+
{...otherProps}
167+
/>
168+
</Form.Item>
169+
</Form>
170+
</>
171+
);
172+
};
173+
174+
WidgetRegistry.register("ConfirmationInput", ConfirmationInput);

packages/runtime/src/widgets/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,4 @@ export * from "./Tag";
2323
export * from "./Carousel";
2424
export * from "./PopupMenu";
2525
export * from "./Dropdown";
26+
export * from "./ConfirmationInput";

pnpm-lock.yaml

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)