@12-apps/payments-frontend 3.34.3 → 3.34.4
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.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@12-apps/payments-frontend",
|
|
3
|
-
"version": "3.34.
|
|
3
|
+
"version": "3.34.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"description": "Browser half of the vendor-agnostic payments platform: plug-and-play MUI components for the per-provider settings page (credential form from each provider's schema, masked hints, verify/enable) and the checkout page (PIX QR + polling, card tokenization, hosted-checkout redirect), plus the headless hooks and fetch clients they build on. Talks only to the host's payments HTTP surface — never to a provider directly. Microfrontend-ready: no app coupling, host injects theme and auth.",
|
|
@@ -19,15 +19,21 @@ import {
|
|
|
19
19
|
CircularProgress,
|
|
20
20
|
FormControl,
|
|
21
21
|
FormControlLabel,
|
|
22
|
+
FormHelperText,
|
|
22
23
|
FormLabel,
|
|
24
|
+
InputLabel,
|
|
25
|
+
OutlinedInput,
|
|
23
26
|
Radio,
|
|
24
27
|
RadioGroup as MuiRadioGroup,
|
|
25
28
|
Step,
|
|
26
29
|
StepLabel,
|
|
27
30
|
Stepper as MuiStepper,
|
|
28
|
-
TextField,
|
|
29
31
|
Typography,
|
|
32
|
+
styled,
|
|
33
|
+
useThemeProps,
|
|
30
34
|
} from '@mui/material';
|
|
35
|
+
import type { TextFieldProps } from '@mui/material';
|
|
36
|
+
import { useId } from 'react';
|
|
31
37
|
import type { JSX } from 'react';
|
|
32
38
|
|
|
33
39
|
import type {
|
|
@@ -93,25 +99,170 @@ function DefaultButton({ variant = 'solid', color = 'primary', size = 'md', full
|
|
|
93
99
|
);
|
|
94
100
|
}
|
|
95
101
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
102
|
+
type OwnerState = Record<string, unknown>;
|
|
103
|
+
type SlotProps = Record<string, unknown> | ((ownerState: OwnerState) => Record<string, unknown>) | undefined;
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* `TextField`'s root, by name and with its `ownerState`: a theme's
|
|
107
|
+
* `components.MuiTextField` (`styleOverrides`, including functions reading
|
|
108
|
+
* `ownerState`, and `variants`) applies exactly as it did to `TextField`.
|
|
109
|
+
*/
|
|
110
|
+
const TextFieldRoot = styled(FormControl, {
|
|
111
|
+
name: 'MuiTextField',
|
|
112
|
+
slot: 'Root',
|
|
113
|
+
overridesResolver: (_props, styles) => styles.root,
|
|
114
|
+
})<{ ownerState: OwnerState }>({});
|
|
115
|
+
|
|
116
|
+
/** A theme's slot props may be a function of `ownerState`, as `useSlot` allows. */
|
|
117
|
+
function slotPropsOf(slotProps: SlotProps, ownerState: OwnerState): Record<string, unknown> {
|
|
118
|
+
return (typeof slotProps === 'function' ? slotProps(ownerState) : slotProps) ?? {};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/** `TextField`'s `ownerState`, for the outlined, non-select field this slot is. */
|
|
122
|
+
function ownerStateOf(props: TextFieldProps): OwnerState {
|
|
123
|
+
return {
|
|
124
|
+
...props,
|
|
125
|
+
autoFocus: false,
|
|
126
|
+
color: props.color ?? 'primary',
|
|
127
|
+
disabled: props.disabled ?? false,
|
|
128
|
+
error: props.error ?? false,
|
|
129
|
+
fullWidth: props.fullWidth ?? false,
|
|
130
|
+
multiline: false,
|
|
131
|
+
required: props.required ?? false,
|
|
132
|
+
select: false,
|
|
133
|
+
variant: 'outlined',
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* The slot's own props, run through the theme's `MuiTextField` defaults the way
|
|
139
|
+
* `TextField` runs them (`useDefaultProps` is `useThemeProps` by another name).
|
|
140
|
+
*/
|
|
141
|
+
function useTextFieldProps({ label, type = 'text', inputMode, fullWidth, required, autoComplete, placeholder, maxLength, value, error, helperText, endAdornment, onChange, onBlur, ...rest }: CheckoutInputProps): TextFieldProps {
|
|
142
|
+
return useThemeProps({
|
|
143
|
+
name: 'MuiTextField',
|
|
144
|
+
props: {
|
|
145
|
+
label,
|
|
146
|
+
type,
|
|
147
|
+
size: 'small',
|
|
148
|
+
fullWidth,
|
|
149
|
+
required,
|
|
150
|
+
placeholder,
|
|
151
|
+
value,
|
|
152
|
+
error,
|
|
153
|
+
helperText,
|
|
154
|
+
onChange,
|
|
155
|
+
onBlur,
|
|
156
|
+
slotProps: {
|
|
111
157
|
htmlInput: { inputMode, maxLength, autoComplete, 'data-testid': rest['data-testid'] },
|
|
112
158
|
input: { endAdornment },
|
|
113
|
-
}
|
|
114
|
-
|
|
159
|
+
},
|
|
160
|
+
} as TextFieldProps,
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* What `TextField` consumes by name rather than handing to its root. A key LIST
|
|
166
|
+
* rather than a destructure, which would bind every one of them only to drop it.
|
|
167
|
+
*/
|
|
168
|
+
const CONSUMED_BY_FIELD: ReadonlySet<string> = new Set([
|
|
169
|
+
'autoComplete', 'autoFocus', 'children', 'className', 'color', 'defaultValue', 'disabled', 'error',
|
|
170
|
+
'FormHelperTextProps', 'fullWidth', 'helperText', 'id', 'InputLabelProps', 'inputProps', 'InputProps',
|
|
171
|
+
'inputRef', 'label', 'maxRows', 'minRows', 'multiline', 'name', 'onBlur', 'onChange', 'onFocus',
|
|
172
|
+
'placeholder', 'required', 'rows', 'select', 'SelectProps', 'slotProps', 'slots', 'type', 'value',
|
|
173
|
+
'variant',
|
|
174
|
+
]);
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* The slot props as `TextField` resolves them: the legacy `InputProps`,
|
|
178
|
+
* `InputLabelProps`, `inputProps` and `FormHelperTextProps` first, then
|
|
179
|
+
* `slotProps` over them.
|
|
180
|
+
*/
|
|
181
|
+
function slotPropsFor(props: TextFieldProps): Record<string, SlotProps> {
|
|
182
|
+
return {
|
|
183
|
+
input: props.InputProps as SlotProps,
|
|
184
|
+
inputLabel: props.InputLabelProps as SlotProps,
|
|
185
|
+
htmlInput: props.inputProps as SlotProps,
|
|
186
|
+
formHelperText: props.FormHelperTextProps as SlotProps,
|
|
187
|
+
...((props.slotProps ?? {}) as Record<string, SlotProps>),
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/** The root: what `TextField` did not consume, then the props it hands the root by name. */
|
|
192
|
+
function rootPropsOf(props: TextFieldProps, ownerState: OwnerState): Record<string, unknown> {
|
|
193
|
+
return {
|
|
194
|
+
...Object.fromEntries(Object.entries(props).filter(([key]) => !CONSUMED_BY_FIELD.has(key))),
|
|
195
|
+
ownerState,
|
|
196
|
+
className: ['MuiTextField-root', (props.classes as { root?: string } | undefined)?.root, props.className]
|
|
197
|
+
.filter(Boolean)
|
|
198
|
+
.join(' '),
|
|
199
|
+
disabled: ownerState.disabled,
|
|
200
|
+
error: ownerState.error,
|
|
201
|
+
fullWidth: ownerState.fullWidth,
|
|
202
|
+
required: ownerState.required,
|
|
203
|
+
color: ownerState.color,
|
|
204
|
+
variant: 'outlined',
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/** The input: the props `TextField` names, then the theme's and the slot's `input` slot props. */
|
|
209
|
+
function inputPropsOf(props: TextFieldProps, ownerState: OwnerState, ids: { id: string; helperTextId?: string }): Record<string, unknown> {
|
|
210
|
+
const slots = slotPropsFor(props);
|
|
211
|
+
const shrink = slotPropsOf(slots.inputLabel, ownerState).shrink;
|
|
212
|
+
return {
|
|
213
|
+
'aria-describedby': ids.helperTextId,
|
|
214
|
+
autoComplete: props.autoComplete,
|
|
215
|
+
autoFocus: ownerState.autoFocus,
|
|
216
|
+
defaultValue: props.defaultValue,
|
|
217
|
+
fullWidth: ownerState.fullWidth,
|
|
218
|
+
name: props.name,
|
|
219
|
+
inputRef: props.inputRef,
|
|
220
|
+
onFocus: props.onFocus,
|
|
221
|
+
type: props.type,
|
|
222
|
+
value: props.value,
|
|
223
|
+
id: ids.id,
|
|
224
|
+
onBlur: props.onBlur,
|
|
225
|
+
onChange: props.onChange,
|
|
226
|
+
placeholder: props.placeholder,
|
|
227
|
+
inputProps: slotPropsOf(slots.htmlInput, ownerState),
|
|
228
|
+
label: props.label,
|
|
229
|
+
...(shrink === undefined ? {} : { notched: shrink }),
|
|
230
|
+
...slotPropsOf(slots.input, ownerState),
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* An outlined text field, composed from the parts MUI's `TextField` composes
|
|
236
|
+
* (FUT-3402). `TextField` itself imports `Select` unconditionally, and through
|
|
237
|
+
* it `Menu`, `MenuList`, `Popover` and `List`; this slot is in every host's
|
|
238
|
+
* checkout bundle whether or not the host fills it, so it paid for a dropdown
|
|
239
|
+
* it can never render.
|
|
240
|
+
*
|
|
241
|
+
* Same DOM and the same theme hooks — `defaultProps`, `styleOverrides`,
|
|
242
|
+
* `variants`, slot props — pinned by `default-input-parity.test.tsx`, with two
|
|
243
|
+
* deliberate exceptions: a theme default `variant` other than `outlined`, and
|
|
244
|
+
* `slots` replacing a part, are not honoured. Either would need the very
|
|
245
|
+
* components this slot exists to leave out; a host that wants them fills the
|
|
246
|
+
* `Input` slot.
|
|
247
|
+
*/
|
|
248
|
+
function DefaultInput(slotProps: CheckoutInputProps): JSX.Element {
|
|
249
|
+
const props = useTextFieldProps(slotProps);
|
|
250
|
+
const ownerState = ownerStateOf(props);
|
|
251
|
+
const generatedId = useId();
|
|
252
|
+
const id = props.id ?? generatedId;
|
|
253
|
+
const helperTextId = props.helperText ? `${id}-helper-text` : undefined;
|
|
254
|
+
const slots = slotPropsFor(props);
|
|
255
|
+
const { label, helperText } = props;
|
|
256
|
+
return (
|
|
257
|
+
<TextFieldRoot {...(rootPropsOf(props, ownerState) as { ownerState: OwnerState })}>
|
|
258
|
+
{label != null && label !== '' ? (
|
|
259
|
+
<InputLabel htmlFor={id} id={`${id}-label`} {...slotPropsOf(slots.inputLabel, ownerState)}>{label}</InputLabel>
|
|
260
|
+
) : null}
|
|
261
|
+
<OutlinedInput {...inputPropsOf(props, ownerState, { id, helperTextId })} />
|
|
262
|
+
{helperText ? (
|
|
263
|
+
<FormHelperText id={helperTextId} {...slotPropsOf(slots.formHelperText, ownerState)}>{helperText}</FormHelperText>
|
|
264
|
+
) : null}
|
|
265
|
+
</TextFieldRoot>
|
|
115
266
|
);
|
|
116
267
|
}
|
|
117
268
|
|