@alveole/components 0.42.2 → 0.43.0

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 (75) hide show
  1. package/dist/core/Form/Form.d.ts +7 -0
  2. package/dist/core/Form/Form.d.ts.map +1 -0
  3. package/dist/core/Form/Form.js +30 -0
  4. package/dist/core/Form/Form.stories.d.ts +21 -0
  5. package/dist/core/Form/Form.stories.d.ts.map +1 -0
  6. package/dist/core/Form/Form.stories.js +18 -0
  7. package/dist/core/Form/Form.stories.sources.d.ts +8 -0
  8. package/dist/core/Form/Form.stories.sources.d.ts.map +1 -0
  9. package/dist/core/Form/Form.stories.sources.js +8 -0
  10. package/dist/core/Form/Form.styles.d.ts +10 -0
  11. package/dist/core/Form/Form.styles.d.ts.map +1 -0
  12. package/dist/core/Form/Form.styles.js +10 -0
  13. package/dist/core/Form/Form.web.d.ts +4 -0
  14. package/dist/core/Form/Form.web.d.ts.map +1 -0
  15. package/dist/core/Form/Form.web.js +18 -0
  16. package/dist/core/Form/index.d.ts +2 -0
  17. package/dist/core/Form/index.d.ts.map +1 -0
  18. package/dist/core/Form/index.js +1 -0
  19. package/dist/core/index.d.ts +1 -0
  20. package/dist/core/index.d.ts.map +1 -1
  21. package/dist/core/index.js +1 -0
  22. package/dist/generated/version.d.ts +1 -1
  23. package/dist/generated/version.js +1 -1
  24. package/dist/stories/index.d.ts +2 -0
  25. package/dist/stories/index.d.ts.map +1 -1
  26. package/dist/stories/index.js +2 -0
  27. package/dist/ui/FormControl/FormControl.d.ts +12 -0
  28. package/dist/ui/FormControl/FormControl.d.ts.map +1 -0
  29. package/dist/ui/FormControl/FormControl.js +9 -0
  30. package/dist/ui/FormControl/FormControl.stories.d.ts +225 -0
  31. package/dist/ui/FormControl/FormControl.stories.d.ts.map +1 -0
  32. package/dist/ui/FormControl/FormControl.stories.js +57 -0
  33. package/dist/ui/FormControl/FormControl.stories.sources.d.ts +30 -0
  34. package/dist/ui/FormControl/FormControl.stories.sources.d.ts.map +1 -0
  35. package/dist/ui/FormControl/FormControl.stories.sources.js +30 -0
  36. package/dist/ui/FormControl/FormControl.styles.d.ts +199 -0
  37. package/dist/ui/FormControl/FormControl.styles.d.ts.map +1 -0
  38. package/dist/ui/FormControl/FormControl.styles.js +185 -0
  39. package/dist/ui/FormControl/FormControlCaption.d.ts +6 -0
  40. package/dist/ui/FormControl/FormControlCaption.d.ts.map +1 -0
  41. package/dist/ui/FormControl/FormControlCaption.js +10 -0
  42. package/dist/ui/FormControl/FormControlDateInput.d.ts +11 -0
  43. package/dist/ui/FormControl/FormControlDateInput.d.ts.map +1 -0
  44. package/dist/ui/FormControl/FormControlDateInput.js +46 -0
  45. package/dist/ui/FormControl/FormControlFileInput.d.ts +20 -0
  46. package/dist/ui/FormControl/FormControlFileInput.d.ts.map +1 -0
  47. package/dist/ui/FormControl/FormControlFileInput.js +54 -0
  48. package/dist/ui/FormControl/FormControlFileInput.styles.d.ts +45 -0
  49. package/dist/ui/FormControl/FormControlFileInput.styles.d.ts.map +1 -0
  50. package/dist/ui/FormControl/FormControlFileInput.styles.js +37 -0
  51. package/dist/ui/FormControl/FormControlHint.d.ts +6 -0
  52. package/dist/ui/FormControl/FormControlHint.d.ts.map +1 -0
  53. package/dist/ui/FormControl/FormControlHint.js +8 -0
  54. package/dist/ui/FormControl/FormControlLabel.d.ts +8 -0
  55. package/dist/ui/FormControl/FormControlLabel.d.ts.map +1 -0
  56. package/dist/ui/FormControl/FormControlLabel.js +13 -0
  57. package/dist/ui/FormControl/FormControlModal.d.ts +12 -0
  58. package/dist/ui/FormControl/FormControlModal.d.ts.map +1 -0
  59. package/dist/ui/FormControl/FormControlModal.js +12 -0
  60. package/dist/ui/FormControl/FormControlNumberInput.d.ts +17 -0
  61. package/dist/ui/FormControl/FormControlNumberInput.d.ts.map +1 -0
  62. package/dist/ui/FormControl/FormControlNumberInput.js +22 -0
  63. package/dist/ui/FormControl/FormControlOtpInput.d.ts +10 -0
  64. package/dist/ui/FormControl/FormControlOtpInput.d.ts.map +1 -0
  65. package/dist/ui/FormControl/FormControlOtpInput.js +8 -0
  66. package/dist/ui/FormControl/TextInput.d.ts +20 -0
  67. package/dist/ui/FormControl/TextInput.d.ts.map +1 -0
  68. package/dist/ui/FormControl/TextInput.js +118 -0
  69. package/dist/ui/FormControl/index.d.ts +11 -0
  70. package/dist/ui/FormControl/index.d.ts.map +1 -0
  71. package/dist/ui/FormControl/index.js +10 -0
  72. package/dist/ui/index.d.ts +1 -0
  73. package/dist/ui/index.d.ts.map +1 -1
  74. package/dist/ui/index.js +1 -0
  75. package/package.json +5 -1
@@ -0,0 +1,37 @@
1
+ import { makeStyles } from '@alveole/theme';
2
+ export const useStyles = makeStyles(({ text, color, spacing }) => ({
3
+ fileInputContainer: {
4
+ display: 'flex',
5
+ flexDirection: 'row',
6
+ gap: spacing('050'),
7
+ alignItems: 'center',
8
+ },
9
+ fileInputButton: {
10
+ borderWidth: 1,
11
+ borderColor: color.border['default-grey'],
12
+ backgroundColor: color.background['alt-grey'],
13
+ transition: 'background-color 0.1s ease-in-out',
14
+ display: 'flex',
15
+ alignItems: 'center',
16
+ justifyContent: 'center',
17
+ paddingLeft: spacing('050'),
18
+ paddingRight: spacing('050'),
19
+ paddingTop: spacing('0375'),
20
+ paddingBottom: spacing('0375'),
21
+ },
22
+ fileInputButtonHovered: {
23
+ backgroundColor: color.background['contrast-grey'],
24
+ },
25
+ fileInputButtonDisabled: {
26
+ cursor: 'not-allowed',
27
+ backgroundColor: color.background['disabled-grey'],
28
+ },
29
+ inputFileText: {
30
+ ...text['Corps de texte'].XS.Regular,
31
+ color: color.text['default-grey'],
32
+ },
33
+ placeholderText: {
34
+ ...text['Corps de texte'].XS.Regular,
35
+ color: color.text['default-grey'],
36
+ },
37
+ }));
@@ -0,0 +1,6 @@
1
+ export type FormControlHintProps = {
2
+ hint?: string;
3
+ disabled?: boolean;
4
+ };
5
+ export declare const FormControlHint: (props: FormControlHintProps) => import("react").JSX.Element;
6
+ //# sourceMappingURL=FormControlHint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FormControlHint.d.ts","sourceRoot":"","sources":["../../../src/ui/FormControl/FormControlHint.tsx"],"names":[],"mappings":"AAGA,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,OAAO,oBAAoB,gCAU1D,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Box, Typography } from '../../core';
3
+ import { useStyles } from './FormControl.styles';
4
+ export const FormControlHint = (props) => {
5
+ const { hint, disabled } = props;
6
+ const styles = useStyles();
7
+ return (_jsx(Box, { style: styles.hintContainer, children: _jsx(Typography, { style: { ...styles.hint, ...(disabled ? styles.hintDisabled : {}) }, children: hint }) }));
8
+ };
@@ -0,0 +1,8 @@
1
+ import { FormControlCaptionProps } from './FormControlCaption';
2
+ export type FormControlLabelProps = {
3
+ label: string;
4
+ labelRight?: React.ReactNode;
5
+ disabled?: boolean;
6
+ } & FormControlCaptionProps;
7
+ export declare const FormControlLabel: (props: FormControlLabelProps) => import("react").JSX.Element;
8
+ //# sourceMappingURL=FormControlLabel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FormControlLabel.d.ts","sourceRoot":"","sources":["../../../src/ui/FormControl/FormControlLabel.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAE/D,MAAM,MAAM,qBAAqB,GAAG;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC7B,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,GAAG,uBAAuB,CAAC;AAE5B,eAAO,MAAM,gBAAgB,GAAI,OAAO,qBAAqB,gCAwB5D,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Box, Typography } from '../../core';
3
+ import { useStyles } from './FormControl.styles';
4
+ export const FormControlLabel = (props) => {
5
+ const { label, labelRight = false, disabled = false, error, success } = props;
6
+ const styles = useStyles();
7
+ return (_jsxs(Box, { style: styles.labelContainer, children: [_jsx(Typography, { style: {
8
+ ...styles.label,
9
+ ...(error ? styles.errorText : {}),
10
+ ...(success ? styles.successText : {}),
11
+ ...(disabled ? styles.labelDisabled : {}),
12
+ }, children: label }), label && (_jsx(Box, { mt: 'auto', mb: 'auto', ml: 'auto', children: labelRight }))] }));
13
+ };
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ export type FormControlModalProps = {
3
+ open: boolean;
4
+ onClose: () => void;
5
+ onShow?: () => void;
6
+ onDismiss?: () => void;
7
+ submitLabel?: string;
8
+ onSubmit?: () => void;
9
+ children: React.ReactNode;
10
+ };
11
+ export declare const FormControlModal: (props: FormControlModalProps) => React.JSX.Element;
12
+ //# sourceMappingURL=FormControlModal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FormControlModal.d.ts","sourceRoot":"","sources":["../../../src/ui/FormControl/FormControlModal.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAO1B,MAAM,MAAM,qBAAqB,GAAG;IAClC,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,OAAO,qBAAqB,sBAyC5D,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { KeyboardAvoidingView, Modal, Platform, Pressable } from 'react-native';
3
+ import { useSafeAreaInsets } from 'react-native-safe-area-context';
4
+ import { Box } from '../../core';
5
+ import { Button, ButtonIcon } from '../Button';
6
+ import { useStyles } from './FormControl.styles';
7
+ export const FormControlModal = (props) => {
8
+ const { open, onClose, onShow, onDismiss, submitLabel, onSubmit, children } = props;
9
+ const styles = useStyles();
10
+ const { top } = useSafeAreaInsets();
11
+ return (_jsx(Modal, { animationType: "slide", transparent: true, visible: open, onRequestClose: onClose, onShow: onShow, onDismiss: onDismiss, children: _jsx(Pressable, { style: styles.modalOverlay, onPress: onClose, children: _jsx(KeyboardAvoidingView, { behavior: Platform.OS === 'ios' ? 'padding' : undefined, keyboardVerticalOffset: Platform.OS === 'ios' ? -8 : 0, style: { ...styles.modalSheet, paddingTop: top }, children: _jsxs(Pressable, { style: styles.modalContent, onPress: () => null, children: [_jsxs(Box, { style: styles.modalHeader, children: [_jsx(Box, { style: styles.modalHeaderLeft }), _jsx(Box, { style: styles.modalHeaderRight, children: _jsx(ButtonIcon, { icon: "Check", variant: "primary", onPress: onClose }) })] }), children, submitLabel && onSubmit && (_jsx(Box, { style: styles.modalFooter, children: _jsx(Button, { size: "lg", variant: "primary", title: submitLabel, onPress: onSubmit }) }))] }) }) }) }));
12
+ };
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ export type FormControlNumberInputElement = HTMLInputElement;
3
+ export type FormControlNumberInputProps = {
4
+ value?: number | null;
5
+ placeholder?: string;
6
+ disabled?: boolean;
7
+ readOnly?: boolean;
8
+ min?: number;
9
+ max?: number;
10
+ step?: number;
11
+ startAdornment?: React.ReactNode;
12
+ endAdornment?: React.ReactNode;
13
+ onKeyDown?: React.KeyboardEventHandler<HTMLInputElement>;
14
+ onChange?: (value: number | null) => void;
15
+ };
16
+ export declare const FormControlNumberInput: React.ForwardRefExoticComponent<FormControlNumberInputProps & React.RefAttributes<HTMLInputElement>>;
17
+ //# sourceMappingURL=FormControlNumberInput.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FormControlNumberInput.d.ts","sourceRoot":"","sources":["../../../src/ui/FormControl/FormControlNumberInput.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,MAAM,MAAM,6BAA6B,GAAG,gBAAgB,CAAC;AAC7D,MAAM,MAAM,2BAA2B,GAAG;IACxC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,cAAc,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACjC,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC/B,SAAS,CAAC,EAAE,KAAK,CAAC,oBAAoB,CAAC,gBAAgB,CAAC,CAAC;IACzD,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;CAC3C,CAAC;AAEF,eAAO,MAAM,sBAAsB,sGAyClC,CAAC"}
@@ -0,0 +1,22 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import React from 'react';
3
+ import { Box } from '../../core';
4
+ import { useStyles } from './FormControl.styles';
5
+ export const FormControlNumberInput = React.forwardRef(function DateInput(props, ref) {
6
+ const { value, onChange, startAdornment, endAdornment, ...inputProps } = props;
7
+ const styles = useStyles();
8
+ return (_jsx(Box, { tag: "form-control-text-input", style: styles.inputContainer, children: _jsxs(Box, { tag: "form-control-text-input-inner", style: {
9
+ ...styles.inputInner,
10
+ ...(props.disabled ? styles.inputDisabled : {}),
11
+ ...(endAdornment ? { paddingRight: 0 } : {}),
12
+ ...(startAdornment ? { paddingLeft: 0 } : {}),
13
+ }, children: [startAdornment, _jsx("input", { ref: ref, value: value ?? '', onChange: e => {
14
+ const newValue = e.target.value;
15
+ onChange?.(newValue === '' ? null : Number(newValue));
16
+ }, type: "number", style: {
17
+ ...styles.input,
18
+ ...styles.inputWeb,
19
+ ...(endAdornment && startAdornment ? { textAlign: 'center' } : {}),
20
+ ...(endAdornment ? { minWidth: 0 } : {}),
21
+ }, ...inputProps }), endAdornment] }) }));
22
+ });
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import { OtpInputProps, OtpInputRef } from 'react-native-otp-entry';
3
+ export type FormControlOtpInputElement = OtpInputRef;
4
+ export type FormControlOtpInputProps = Omit<OtpInputProps, 'style'> & {
5
+ readOnly?: boolean;
6
+ };
7
+ export declare const FormControlOtpInput: React.ForwardRefExoticComponent<Omit<OtpInputProps, "style"> & {
8
+ readOnly?: boolean;
9
+ } & React.RefAttributes<OtpInputRef>>;
10
+ //# sourceMappingURL=FormControlOtpInput.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FormControlOtpInput.d.ts","sourceRoot":"","sources":["../../../src/ui/FormControl/FormControlOtpInput.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAY,aAAa,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAG9E,MAAM,MAAM,0BAA0B,GAAG,WAAW,CAAC;AACrD,MAAM,MAAM,wBAAwB,GAAG,IAAI,CAAC,aAAa,EAAE,OAAO,CAAC,GAAG;IACpE,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,eAAO,MAAM,mBAAmB;eAHnB,OAAO;qCAanB,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import React from 'react';
3
+ import { OtpInput } from 'react-native-otp-entry';
4
+ import { Box } from '../../core';
5
+ export const FormControlOtpInput = React.forwardRef(function FormControlOtpInput(props, ref) {
6
+ const { disabled, readOnly, ...inputProps } = props;
7
+ return (_jsx(Box, { tag: "form-control-otp-input", children: _jsx(OtpInput, { ref: ref, disabled: disabled || readOnly, ...inputProps }) }));
8
+ });
@@ -0,0 +1,20 @@
1
+ import React from 'react';
2
+ import { TextInput as ReactNativeTextInput, TextInputProps as ReactNativeTextInputProps } from 'react-native';
3
+ export type TextInputElement = ReactNativeTextInput;
4
+ export type TextInputProps = Omit<ReactNativeTextInputProps, 'style'> & {
5
+ disabled?: boolean;
6
+ startAdornment?: React.ReactNode;
7
+ endAdornment?: React.ReactNode;
8
+ openModal?: boolean;
9
+ modalSubmitLabel?: string;
10
+ onModalSubmit?: () => void;
11
+ };
12
+ export declare const TextInput: React.ForwardRefExoticComponent<Omit<ReactNativeTextInputProps, "style"> & {
13
+ disabled?: boolean;
14
+ startAdornment?: React.ReactNode;
15
+ endAdornment?: React.ReactNode;
16
+ openModal?: boolean;
17
+ modalSubmitLabel?: string;
18
+ onModalSubmit?: () => void;
19
+ } & React.RefAttributes<ReactNativeTextInput>>;
20
+ //# sourceMappingURL=TextInput.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TextInput.d.ts","sourceRoot":"","sources":["../../../src/ui/FormControl/TextInput.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAKL,SAAS,IAAI,oBAAoB,EACjC,cAAc,IAAI,yBAAyB,EAE5C,MAAM,cAAc,CAAC;AAQtB,MAAM,MAAM,gBAAgB,GAAG,oBAAoB,CAAC;AACpD,MAAM,MAAM,cAAc,GAAG,IAAI,CAAC,yBAAyB,EAAE,OAAO,CAAC,GAAG;IACtE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,cAAc,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACjC,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC/B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;CAC5B,CAAC;AAEF,eAAO,MAAM,SAAS;eART,OAAO;qBACD,KAAK,CAAC,SAAS;mBACjB,KAAK,CAAC,SAAS;gBAClB,OAAO;uBACA,MAAM;oBACT,MAAM,IAAI;8CAsN1B,CAAC"}
@@ -0,0 +1,118 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useTheme } from '@alveole/theme';
3
+ import React from 'react';
4
+ import { Keyboard, Platform, Pressable, TextInput as ReactNativeTextInput, } from 'react-native';
5
+ import { Box } from '../../core';
6
+ import { useStyles } from './FormControl.styles';
7
+ import { FormControlModal } from './FormControlModal';
8
+ export const TextInput = React.forwardRef(function TextInput(props, ref) {
9
+ const { disabled, readOnly, startAdornment, endAdornment, onFocus, onBlur, onPressIn, openModal, modalSubmitLabel, onModalSubmit, ...inputProps } = props;
10
+ const { color } = useTheme();
11
+ const styles = useStyles();
12
+ const shouldUseModal = Boolean(openModal && inputProps.multiline && Platform.OS !== 'web');
13
+ const [isModalOpen, setIsModalOpen] = React.useState(false);
14
+ const [isModalReady, setIsModalReady] = React.useState(false);
15
+ const [focus, setFocus] = React.useState(false);
16
+ const inputRef = React.useRef(null);
17
+ const modalInputRef = React.useRef(null);
18
+ const pendingFocusEventRef = React.useRef(null);
19
+ React.useImperativeHandle(ref, () => inputRef.current);
20
+ React.useEffect(() => {
21
+ if (!shouldUseModal)
22
+ return;
23
+ setFocus(isModalOpen);
24
+ }, [isModalOpen, shouldUseModal]);
25
+ // Appeler onFocus une fois que la modale est prête
26
+ React.useEffect(() => {
27
+ if (isModalReady && pendingFocusEventRef.current) {
28
+ const event = pendingFocusEventRef.current;
29
+ pendingFocusEventRef.current = null;
30
+ requestAnimationFrame(() => {
31
+ onFocus?.(event);
32
+ });
33
+ }
34
+ }, [isModalReady, onFocus]);
35
+ const focusModalInput = React.useCallback(() => {
36
+ if (!shouldUseModal)
37
+ return;
38
+ requestAnimationFrame(() => {
39
+ modalInputRef.current?.focus();
40
+ });
41
+ }, [shouldUseModal]);
42
+ const handleFocus = (e) => {
43
+ if (shouldUseModal) {
44
+ inputRef.current?.blur();
45
+ onFocus?.(e);
46
+ return;
47
+ }
48
+ if (!disabled && !readOnly)
49
+ setFocus(true);
50
+ onFocus?.(e);
51
+ };
52
+ const handleBlur = (e) => {
53
+ if (shouldUseModal) {
54
+ onBlur?.(e);
55
+ return;
56
+ }
57
+ if (!disabled && !readOnly)
58
+ setFocus(false);
59
+ onBlur?.(e);
60
+ };
61
+ const handleOpenModal = () => {
62
+ if (!shouldUseModal || disabled || readOnly || isModalOpen)
63
+ return;
64
+ setIsModalOpen(true);
65
+ };
66
+ const closeModal = () => {
67
+ if (!isModalReady)
68
+ return;
69
+ Keyboard.dismiss();
70
+ modalInputRef.current?.blur();
71
+ setIsModalOpen(false);
72
+ inputRef.current?.blur();
73
+ };
74
+ const handleModalSubmit = () => {
75
+ if (!isModalReady)
76
+ return;
77
+ onModalSubmit?.();
78
+ closeModal();
79
+ };
80
+ return (_jsxs(Box, { tag: "form-control-text-input", style: {
81
+ ...styles.inputContainer,
82
+ ...(inputProps.multiline ? { height: 'auto' } : {}),
83
+ }, children: [shouldUseModal ? (_jsxs(Pressable, { style: {
84
+ ...styles.inputInner,
85
+ ...(disabled ? styles.inputDisabled : {}),
86
+ ...(focus ? styles.inputFocused : {}),
87
+ ...(endAdornment ? { paddingRight: 0 } : {}),
88
+ ...(startAdornment ? { paddingLeft: 0 } : {}),
89
+ ...(inputProps.multiline ? { paddingTop: 8 } : {}),
90
+ }, onPress: handleOpenModal, children: [startAdornment, _jsx(ReactNativeTextInput, { ref: inputRef, style: {
91
+ ...styles.input,
92
+ ...(startAdornment && endAdornment ? { textAlign: 'center' } : {}),
93
+ }, readOnly: true, editable: false, focusable: false, pointerEvents: "none", showSoftInputOnFocus: false, caretHidden: true, selectTextOnFocus: false, contextMenuHidden: true, selectionColor: "transparent", placeholderTextColor: color.text.inverse.muted, ...inputProps }), endAdornment] })) : (_jsxs(Box, { tag: "form-control-text-input-inner", style: {
94
+ ...styles.inputInner,
95
+ ...(disabled ? styles.inputDisabled : {}),
96
+ ...(focus ? styles.inputFocused : {}),
97
+ ...(endAdornment ? { paddingRight: 0 } : {}),
98
+ ...(startAdornment ? { paddingLeft: 0 } : {}),
99
+ ...(inputProps.multiline ? { paddingTop: 8 } : {}),
100
+ }, children: [startAdornment, _jsx(ReactNativeTextInput, { ref: inputRef, style: {
101
+ ...styles.input,
102
+ ...(startAdornment && endAdornment ? { textAlign: 'center' } : {}),
103
+ }, readOnly: disabled === true || readOnly === true, editable: inputProps.editable, onFocus: handleFocus, onBlur: handleBlur, onPressIn: onPressIn, showSoftInputOnFocus: inputProps.showSoftInputOnFocus, caretHidden: inputProps.caretHidden, selectTextOnFocus: inputProps.selectTextOnFocus, contextMenuHidden: inputProps.contextMenuHidden, selectionColor: inputProps.selectionColor, placeholderTextColor: color.text.inverse.muted, ...inputProps }), endAdornment] })), shouldUseModal && (_jsx(FormControlModal, { open: isModalOpen, onClose: closeModal, onShow: () => {
104
+ setIsModalReady(true);
105
+ focusModalInput();
106
+ }, onDismiss: () => {
107
+ setIsModalReady(false);
108
+ pendingFocusEventRef.current = null;
109
+ Keyboard.dismiss();
110
+ }, submitLabel: modalSubmitLabel, onSubmit: onModalSubmit ? handleModalSubmit : undefined, children: _jsx(Box, { style: styles.modalInputContainer, children: _jsx(ReactNativeTextInput, { ref: modalInputRef, style: styles.modalInput, readOnly: disabled === true || readOnly === true, onFocus: e => {
111
+ if (!isModalReady) {
112
+ pendingFocusEventRef.current = e;
113
+ }
114
+ else {
115
+ onFocus?.(e);
116
+ }
117
+ }, onBlur: onBlur, placeholderTextColor: color.text.inverse.muted, ...inputProps, multiline: true, textAlignVertical: "top", autoFocus: true, showSoftInputOnFocus: true }) }) }))] }));
118
+ });
@@ -0,0 +1,11 @@
1
+ export * from './FormControl';
2
+ export * from './FormControlCaption';
3
+ export * from './FormControlDateInput';
4
+ export * from './FormControlFileInput';
5
+ export * from './FormControlHint';
6
+ export * from './FormControlLabel';
7
+ export * from './FormControlModal';
8
+ export * from './FormControlNumberInput';
9
+ export * from './FormControlOtpInput';
10
+ export * from './TextInput';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/FormControl/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;AACtC,cAAc,aAAa,CAAC"}
@@ -0,0 +1,10 @@
1
+ export * from './FormControl';
2
+ export * from './FormControlCaption';
3
+ export * from './FormControlDateInput';
4
+ export * from './FormControlFileInput';
5
+ export * from './FormControlHint';
6
+ export * from './FormControlLabel';
7
+ export * from './FormControlModal';
8
+ export * from './FormControlNumberInput';
9
+ export * from './FormControlOtpInput';
10
+ export * from './TextInput';
@@ -7,6 +7,7 @@ export * from './Card';
7
7
  export * from './Divider';
8
8
  export * from './DocumentViewer';
9
9
  export * from './EmptyState';
10
+ export * from './FormControl';
10
11
  export * from './Header';
11
12
  export * from './ListItem';
12
13
  export * from './LucideIcon';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ui/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC;AACvB,cAAc,WAAW,CAAC;AAC1B,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,QAAQ,CAAC;AACvB,cAAc,OAAO,CAAC;AACtB,cAAc,SAAS,CAAC;AACxB,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ui/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC;AACvB,cAAc,WAAW,CAAC;AAC1B,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,QAAQ,CAAC;AACvB,cAAc,OAAO,CAAC;AACtB,cAAc,SAAS,CAAC;AACxB,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC"}
package/dist/ui/index.js CHANGED
@@ -7,6 +7,7 @@ export * from './Card';
7
7
  export * from './Divider';
8
8
  export * from './DocumentViewer';
9
9
  export * from './EmptyState';
10
+ export * from './FormControl';
10
11
  export * from './Header';
11
12
  export * from './ListItem';
12
13
  export * from './LucideIcon';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alveole/components",
3
- "version": "0.42.2",
3
+ "version": "0.43.0",
4
4
  "description": "Shared UI components.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -40,6 +40,7 @@
40
40
  "@types/react-syntax-highlighter": "^15.5.13",
41
41
  "eslint": "^9.39.2",
42
42
  "expo": "~53.0.0",
43
+ "expo-document-picker": "~56.0.4",
43
44
  "expo-router": "~4.0.0",
44
45
  "jest": "^29.7.0",
45
46
  "jest-expo": "~53.0.0",
@@ -49,6 +50,7 @@
49
50
  "react-dom": "^19.2.5",
50
51
  "react-native": "^0.80.0",
51
52
  "react-native-code-highlighter": "1.3.0",
53
+ "react-native-otp-entry": "1.8.6",
52
54
  "react-syntax-highlighter": "16.1.1",
53
55
  "react-test-renderer": "^19.2.5",
54
56
  "tamagui": "^1.144.4"
@@ -77,6 +79,7 @@
77
79
  "@tamagui/toast": "^1.129.0 <2.0.0",
78
80
  "@uiw/react-signature": "*",
79
81
  "expo-application": "*",
82
+ "expo-document-picker": "*",
80
83
  "expo-constants": "*",
81
84
  "expo-image": "*",
82
85
  "expo-linear-gradient": "*",
@@ -87,6 +90,7 @@
87
90
  "react": "*",
88
91
  "react-native": "*",
89
92
  "react-native-code-highlighter": "*",
93
+ "react-native-otp-entry": "*",
90
94
  "react-native-safe-area-context": "*",
91
95
  "react-native-signature-canvas": "*",
92
96
  "react-native-svg": "^15.0.0",