jp-composter 0.1.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.
- package/dist/index.d.mts +997 -0
- package/dist/index.d.ts +997 -0
- package/dist/index.js +36837 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +36778 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +66 -0
- package/src/SliceUI/IconMoon.tsx +33 -0
- package/src/SliceUI/assets/Anatomy diagram copy.svg +19 -0
- package/src/SliceUI/assets/Anatomy diagram.svg +19 -0
- package/src/SliceUI/assets/Anatomycheck.svg +15 -0
- package/src/SliceUI/assets/Anatomyinput.svg +32 -0
- package/src/SliceUI/assets/Checkbox.jpg +0 -0
- package/src/SliceUI/assets/Diagram copy.svg +15 -0
- package/src/SliceUI/assets/Diagram.jpg +0 -0
- package/src/SliceUI/assets/Diagram.svg +15 -0
- package/src/SliceUI/assets/Frame 5 copy.png +0 -0
- package/src/SliceUI/assets/Frame 5.png +0 -0
- package/src/SliceUI/assets/Frame 65.png +0 -0
- package/src/SliceUI/assets/Frame_65.png +0 -0
- package/src/SliceUI/assets/Icon copy.svg +3 -0
- package/src/SliceUI/assets/Icon.svg +3 -0
- package/src/SliceUI/assets/Icon_Bridging copy.svg +39 -0
- package/src/SliceUI/assets/Icon_Bridging.svg +39 -0
- package/src/SliceUI/assets/Icon_Consistent copy.svg +39 -0
- package/src/SliceUI/assets/Icon_Consistent.svg +39 -0
- package/src/SliceUI/assets/Icon_Plug copy.svg +38 -0
- package/src/SliceUI/assets/Icon_Plug.svg +38 -0
- package/src/SliceUI/assets/Icon_Reusable copy.svg +39 -0
- package/src/SliceUI/assets/Icon_Reusable.svg +39 -0
- package/src/SliceUI/assets/Layer_1.png +0 -0
- package/src/SliceUI/assets/accessibility.png +0 -0
- package/src/SliceUI/assets/accessibility.svg +1 -0
- package/src/SliceUI/assets/addon-library.png +0 -0
- package/src/SliceUI/assets/assets.png +0 -0
- package/src/SliceUI/assets/avif-test-image.avif +0 -0
- package/src/SliceUI/assets/bridging.svg +13 -0
- package/src/SliceUI/assets/consistent.svg +11 -0
- package/src/SliceUI/assets/context.png +0 -0
- package/src/SliceUI/assets/discord.svg +1 -0
- package/src/SliceUI/assets/docs.png +0 -0
- package/src/SliceUI/assets/figma-plugin.png +0 -0
- package/src/SliceUI/assets/github.svg +1 -0
- package/src/SliceUI/assets/resources/Anatomy diagram.svg +19 -0
- package/src/SliceUI/assets/resources/Anatomycheck.svg +15 -0
- package/src/SliceUI/assets/resources/Anatomyinput.svg +32 -0
- package/src/SliceUI/assets/resources/Diagram.svg +15 -0
- package/src/SliceUI/assets/resources/Frame 5.png +0 -0
- package/src/SliceUI/assets/resources/Frame 65.png +0 -0
- package/src/SliceUI/assets/resources/Icon.svg +3 -0
- package/src/SliceUI/assets/resources/Icon_Bridging.svg +39 -0
- package/src/SliceUI/assets/resources/Icon_Consistent.svg +39 -0
- package/src/SliceUI/assets/resources/Icon_Plug.svg +38 -0
- package/src/SliceUI/assets/resources/Icon_Reusable.svg +39 -0
- package/src/SliceUI/assets/resources/fonts/FontIcon.json +150 -0
- package/src/SliceUI/assets/resources/fonts/Lato-Black.ttf +0 -0
- package/src/SliceUI/assets/resources/fonts/Lato-Bold.ttf +0 -0
- package/src/SliceUI/assets/resources/fonts/Lato-Heavy.ttf +0 -0
- package/src/SliceUI/assets/resources/fonts/Lato-Medium.ttf +0 -0
- package/src/SliceUI/assets/resources/fonts/Lato-Regular.ttf +0 -0
- package/src/SliceUI/assets/resources/fonts/Lato.woff2 +0 -0
- package/src/SliceUI/assets/resources/fonts/icomoon.eot +0 -0
- package/src/SliceUI/assets/resources/fonts/icomoon.svg +601 -0
- package/src/SliceUI/assets/resources/fonts/icomoon.ttf +0 -0
- package/src/SliceUI/assets/resources/fonts/icomoon.woff +0 -0
- package/src/SliceUI/assets/resources/fonts/selection.json +1 -0
- package/src/SliceUI/assets/share.png +0 -0
- package/src/SliceUI/assets/styling.png +0 -0
- package/src/SliceUI/assets/testing.png +0 -0
- package/src/SliceUI/assets/theming.png +0 -0
- package/src/SliceUI/assets/tutorials.svg +1 -0
- package/src/SliceUI/assets/youtube.svg +1 -0
- package/src/SliceUI/automation/helper.ts +29 -0
- package/src/SliceUI/avatar/Avatar.tsx +237 -0
- package/src/SliceUI/avatar/Token.ts +116 -0
- package/src/SliceUI/avatar/Type.ts +36 -0
- package/src/SliceUI/avatar/helper.ts +53 -0
- package/src/SliceUI/badge/Badge.tsx +308 -0
- package/src/SliceUI/badge/Token.ts +202 -0
- package/src/SliceUI/badge/Type.ts +46 -0
- package/src/SliceUI/badge/helper.ts +39 -0
- package/src/SliceUI/button/Button.tsx +243 -0
- package/src/SliceUI/button/Token.ts +138 -0
- package/src/SliceUI/button/Type.ts +34 -0
- package/src/SliceUI/button/helper.ts +125 -0
- package/src/SliceUI/checkbox/Checkbox.tsx +176 -0
- package/src/SliceUI/checkbox/Token.ts +128 -0
- package/src/SliceUI/checkbox/Type.ts +35 -0
- package/src/SliceUI/chip/Chip.tsx +290 -0
- package/src/SliceUI/chip/Token.ts +151 -0
- package/src/SliceUI/chip/Type.ts +43 -0
- package/src/SliceUI/chip/helper.ts +40 -0
- package/src/SliceUI/colors/Pallete.ts +151 -0
- package/src/SliceUI/colors/Token.ts +110 -0
- package/src/SliceUI/colors/Type.ts +56 -0
- package/src/SliceUI/contextProvider/context.tsx +108 -0
- package/src/SliceUI/divider/Divider.tsx +109 -0
- package/src/SliceUI/divider/Token.ts +18 -0
- package/src/SliceUI/divider/Type.ts +26 -0
- package/src/SliceUI/icon/CustomIcon.ts +4 -0
- package/src/SliceUI/icon/IcoMoonIcon.tsx +11 -0
- package/src/SliceUI/icon/Icon.tsx +38 -0
- package/src/SliceUI/icon/Token.ts +14 -0
- package/src/SliceUI/icon/Type.ts +13 -0
- package/src/SliceUI/icon/selection.json +1 -0
- package/src/SliceUI/input/Input.tsx +573 -0
- package/src/SliceUI/input/ToDo.md +99 -0
- package/src/SliceUI/input/Token.ts +372 -0
- package/src/SliceUI/input/Type.ts +109 -0
- package/src/SliceUI/input/components/InputPortal.tsx +211 -0
- package/src/SliceUI/input/components/NativeBottomSheet.tsx +296 -0
- package/src/SliceUI/input/components/SelectChip.tsx +185 -0
- package/src/SliceUI/input/components/SelectList.tsx +173 -0
- package/src/SliceUI/input/components/SelectListItem.tsx +377 -0
- package/src/SliceUI/input/components/SelectScrollbarStyle.ts +44 -0
- package/src/SliceUI/input/hooks/useCustomScrollbar.ts +17 -0
- package/src/SliceUI/input/hooks/useInputState.ts +41 -0
- package/src/SliceUI/input/hooks/useLabelAnimation.ts +132 -0
- package/src/SliceUI/input/hooks/useOutsideClick.ts +38 -0
- package/src/SliceUI/input/hooks/useSelectLogic.ts +338 -0
- package/src/SliceUI/input/utils/inputUtils.ts +120 -0
- package/src/SliceUI/input/utils/selectUtils.ts +85 -0
- package/src/SliceUI/input/utils/styleUtils.ts +50 -0
- package/src/SliceUI/input/variants/CurrencyInput/CurrencyInput.tsx +16 -0
- package/src/SliceUI/input/variants/CurrencyInput/NativeCurrencyInput.tsx +181 -0
- package/src/SliceUI/input/variants/CurrencyInput/WebCurrencyInput.tsx +163 -0
- package/src/SliceUI/input/variants/CurrencyInput/types.ts +17 -0
- package/src/SliceUI/input/variants/PhoneInput/NativePhoneInput.tsx +189 -0
- package/src/SliceUI/input/variants/PhoneInput/PhoneInput.tsx +16 -0
- package/src/SliceUI/input/variants/PhoneInput/WebPhoneInput.tsx +291 -0
- package/src/SliceUI/input/variants/PhoneInput/types.ts +22 -0
- package/src/SliceUI/input/variants/SelectInput/SelectInput.tsx +407 -0
- package/src/SliceUI/input/variants/SelectInput/types.ts +34 -0
- package/src/SliceUI/input/variants/TextInput.tsx +68 -0
- package/src/SliceUI/layout/Box.tsx +38 -0
- package/src/SliceUI/layout/Center.tsx +38 -0
- package/src/SliceUI/layout/Divider.tsx +37 -0
- package/src/SliceUI/layout/Grid.tsx +75 -0
- package/src/SliceUI/layout/PageContainer.tsx +60 -0
- package/src/SliceUI/layout/ScrollContainer.tsx +72 -0
- package/src/SliceUI/layout/Spacer.tsx +54 -0
- package/src/SliceUI/layout/Stack.tsx +97 -0
- package/src/SliceUI/layout/StickyHeader.tsx +71 -0
- package/src/SliceUI/radio/RadioButton.tsx +130 -0
- package/src/SliceUI/radio/Token.ts +197 -0
- package/src/SliceUI/radio/Type.ts +35 -0
- package/src/SliceUI/react-native.config.js +3 -0
- package/src/SliceUI/responsive/Type.ts +7 -0
- package/src/SliceUI/responsive/helper.ts +53 -0
- package/src/SliceUI/switch/Switch.tsx +119 -0
- package/src/SliceUI/switch/Token.ts +205 -0
- package/src/SliceUI/switch/Type.ts +26 -0
- package/src/SliceUI/tab/TabItem.tsx +204 -0
- package/src/SliceUI/tab/Tabs.tsx +110 -0
- package/src/SliceUI/tab/Token.ts +282 -0
- package/src/SliceUI/tab/Type.ts +66 -0
- package/src/SliceUI/tab/helper.ts +53 -0
- package/src/SliceUI/table/Table.tsx +388 -0
- package/src/SliceUI/table/TableCell.tsx +158 -0
- package/src/SliceUI/table/TableFooter.tsx +353 -0
- package/src/SliceUI/table/TableHeader.tsx +247 -0
- package/src/SliceUI/table/TableRow.tsx +218 -0
- package/src/SliceUI/table/Token.ts +252 -0
- package/src/SliceUI/table/Type.ts +213 -0
- package/src/SliceUI/table/helper.ts +376 -0
- package/src/SliceUI/table/index.ts +53 -0
- package/src/SliceUI/theme/dummyColors.tsx +7 -0
- package/src/SliceUI/theme/theme.ts +107 -0
- package/src/SliceUI/typography/BaseTypographyToken.ts +62 -0
- package/src/SliceUI/typography/FoundationToken.ts +48 -0
- package/src/SliceUI/typography/Token.ts +228 -0
- package/src/SliceUI/typography/Type.ts +20 -0
- package/src/SliceUI/typography/Typography.tsx +99 -0
- package/src/SliceUI/values/BorderRadius.ts +17 -0
- package/src/SliceUI/values/BorderWidth.ts +7 -0
- package/src/SliceUI/values/Dimension.ts +35 -0
- package/src/SliceUI/values/IconSizes.ts +13 -0
- package/src/SliceUI/values/Spacing.ts +22 -0
- package/src/declarations.d.ts +8 -0
- package/src/index.tsx +119 -0
- package/src/stories/Colors.mdx +1418 -0
- package/src/stories/Dimensions.mdx +60 -0
- package/src/stories/GetStarted.mdx +90 -0
- package/src/stories/Introduction.mdx +136 -0
- package/src/stories/Shape.mdx +126 -0
- package/src/stories/Spacing.mdx +104 -0
- package/src/stories/Typography.mdx +454 -0
- package/src/stories/Utils.mdx +277 -0
- package/src/stories/story-components/AddIcon.js +13 -0
- package/src/stories/story-components/RectangleWithBox.jsx +51 -0
- package/src/stories/story-components/RoundedRectangle.jsx +18 -0
- package/src/stories/story-components/RoundedWithWhiteInside.jsx +33 -0
- package/src/stories/story-components/WhiteRoundedRectangle.jsx +107 -0
- package/src/stories/story-components/svgPaths.js +126 -0
|
@@ -0,0 +1,573 @@
|
|
|
1
|
+
import React, {forwardRef, useMemo, useRef, useState, useCallback} from 'react';
|
|
2
|
+
import {View, Text, StyleSheet, Animated} from 'react-native';
|
|
3
|
+
|
|
4
|
+
import {useSliceTheme} from '../contextProvider/context';
|
|
5
|
+
import {useGetColors} from '../theme/dummyColors';
|
|
6
|
+
import {resolveVariant} from '../responsive/helper';
|
|
7
|
+
import {spacing} from '../values/Spacing';
|
|
8
|
+
|
|
9
|
+
import type {ExtendedInputProps, InputSizeType} from './Type';
|
|
10
|
+
|
|
11
|
+
import {
|
|
12
|
+
isWeb,
|
|
13
|
+
getNormalizedVariant,
|
|
14
|
+
getNormalizedMultiple,
|
|
15
|
+
getNormalizedListType,
|
|
16
|
+
isSelectVariant,
|
|
17
|
+
getDisplayValue,
|
|
18
|
+
} from './utils/inputUtils';
|
|
19
|
+
|
|
20
|
+
import {useInputState} from './hooks/useInputState';
|
|
21
|
+
import {useLabelAnimation} from './hooks/useLabelAnimation';
|
|
22
|
+
import {useSelectLogic} from './hooks/useSelectLogic';
|
|
23
|
+
import {useOutsideClick} from './hooks/useOutsideClick';
|
|
24
|
+
import IconMoon from '../IconMoon';
|
|
25
|
+
import FONT_ICON from '../assets/resources/fonts/FontIcon.json';
|
|
26
|
+
import Icon from '../icon/Icon';
|
|
27
|
+
|
|
28
|
+
import TextInputVariant from './variants/TextInput';
|
|
29
|
+
import CurrencyInput from './variants/CurrencyInput/CurrencyInput';
|
|
30
|
+
import PhoneInput from './variants/PhoneInput/PhoneInput';
|
|
31
|
+
import SelectInput from './variants/SelectInput/SelectInput';
|
|
32
|
+
import SelectList from './components/SelectList';
|
|
33
|
+
|
|
34
|
+
import {getCountryCallingCode} from 'react-phone-number-input';
|
|
35
|
+
import type {CountryCode} from 'libphonenumber-js';
|
|
36
|
+
import {colors} from '../colors/Pallete';
|
|
37
|
+
|
|
38
|
+
const labelTopBySize: Record<InputSizeType, number> = {
|
|
39
|
+
small: 14,
|
|
40
|
+
medium: 16,
|
|
41
|
+
large: 18,
|
|
42
|
+
xlarge: 17,
|
|
43
|
+
xxlarge: 19,
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const Input = forwardRef<any, ExtendedInputProps>((props, ref) => {
|
|
47
|
+
const {
|
|
48
|
+
variant = 'outlined',
|
|
49
|
+
size = 'medium',
|
|
50
|
+
labelText,
|
|
51
|
+
error,
|
|
52
|
+
helperText,
|
|
53
|
+
containerStyle,
|
|
54
|
+
inputStyle,
|
|
55
|
+
labelStyle,
|
|
56
|
+
helperTextStyle,
|
|
57
|
+
value,
|
|
58
|
+
onChangeText,
|
|
59
|
+
onFocus,
|
|
60
|
+
onBlur,
|
|
61
|
+
placeholder,
|
|
62
|
+
prefixIcon,
|
|
63
|
+
suffixIcon,
|
|
64
|
+
disabled,
|
|
65
|
+
hover = false,
|
|
66
|
+
multiple,
|
|
67
|
+
listType = 'default',
|
|
68
|
+
searchable = false,
|
|
69
|
+
options = [],
|
|
70
|
+
noItemText,
|
|
71
|
+
maxVisibleItems,
|
|
72
|
+
selectedIcon,
|
|
73
|
+
...rest
|
|
74
|
+
} = props;
|
|
75
|
+
const inputRef = useRef<HTMLInputElement | null>(null);
|
|
76
|
+
const webInputContainerRef = useRef<any>(null);
|
|
77
|
+
|
|
78
|
+
const normalizedVariant = getNormalizedVariant(variant);
|
|
79
|
+
const normalizedMultiple = getNormalizedMultiple(variant, multiple);
|
|
80
|
+
const normalizedListType = getNormalizedListType(variant, listType);
|
|
81
|
+
|
|
82
|
+
const [currency, setCurrency] = React.useState('CAD');
|
|
83
|
+
const [currencyDropdownOpen, setCurrencyDropdownOpen] = React.useState(false);
|
|
84
|
+
const [country, setCountry] = useState<CountryCode>('CA');
|
|
85
|
+
const [number, setNumber] = useState('');
|
|
86
|
+
const [dropdownOpen, setDropdownOpen] = useState(false);
|
|
87
|
+
|
|
88
|
+
const onNumberChange = (val: string) => {
|
|
89
|
+
setNumber(val);
|
|
90
|
+
const fullNumber = `+${getCountryCallingCode(country)}${val.replace(
|
|
91
|
+
/\D/g,
|
|
92
|
+
'',
|
|
93
|
+
)}`;
|
|
94
|
+
(onChangeText as any)?.(fullNumber);
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const rawTheme = useGetColors();
|
|
98
|
+
const colorTheme = useMemo(() => rawTheme, [rawTheme]);
|
|
99
|
+
|
|
100
|
+
const {theme, deviceBreakpoint} = useSliceTheme();
|
|
101
|
+
const isWebMobile =
|
|
102
|
+
isWeb && (deviceBreakpoint === 'xs' || deviceBreakpoint === 'sm');
|
|
103
|
+
const responsiveSize = useMemo(
|
|
104
|
+
() => resolveVariant(size, deviceBreakpoint) as InputSizeType,
|
|
105
|
+
[size, deviceBreakpoint],
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
const selectLogic = useSelectLogic({
|
|
109
|
+
variant: normalizedVariant,
|
|
110
|
+
value,
|
|
111
|
+
options,
|
|
112
|
+
searchable,
|
|
113
|
+
normalizedMultiple,
|
|
114
|
+
onChangeText,
|
|
115
|
+
disabled,
|
|
116
|
+
maxAllowed: rest.maxAllowed,
|
|
117
|
+
focusInput: () => {
|
|
118
|
+
requestAnimationFrame(() => {
|
|
119
|
+
inputRef.current?.focus();
|
|
120
|
+
});
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
const {registerOptionRef} = selectLogic;
|
|
124
|
+
|
|
125
|
+
const focusSearchInput = useCallback(() => {
|
|
126
|
+
if (!isWeb || normalizedVariant !== 'select' || !searchable) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
requestAnimationFrame(() => {
|
|
131
|
+
inputRef.current?.focus?.();
|
|
132
|
+
});
|
|
133
|
+
}, [normalizedVariant, searchable]);
|
|
134
|
+
|
|
135
|
+
const handleSelectOpen = useCallback(() => {
|
|
136
|
+
if (!disabled) {
|
|
137
|
+
if (selectLogic.suppressNextOpenRef.current) {
|
|
138
|
+
selectLogic.suppressNextOpenRef.current = false;
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
selectLogic.setSelectDropdownOpen(true);
|
|
142
|
+
focusSearchInput();
|
|
143
|
+
}
|
|
144
|
+
}, [disabled, selectLogic, focusSearchInput]);
|
|
145
|
+
|
|
146
|
+
const handleSelectClose = useCallback(() => {
|
|
147
|
+
selectLogic.setSelectDropdownOpen(false);
|
|
148
|
+
}, [selectLogic]);
|
|
149
|
+
|
|
150
|
+
const handleSelectContainerClick = useCallback(
|
|
151
|
+
(e: any) => {
|
|
152
|
+
const clickTarget = e?.target as HTMLElement | null;
|
|
153
|
+
|
|
154
|
+
if (clickTarget?.closest?.('.select-dropdown')) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
handleSelectOpen();
|
|
159
|
+
},
|
|
160
|
+
[handleSelectOpen],
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
const {isFocused, setIsFocused, hasValue} = useInputState({
|
|
164
|
+
value,
|
|
165
|
+
hover,
|
|
166
|
+
normalizedMultiple,
|
|
167
|
+
variant: normalizedVariant,
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
const handleInputFocus = useCallback(
|
|
171
|
+
(e: any) => {
|
|
172
|
+
setIsFocused(true);
|
|
173
|
+
onFocus?.(e);
|
|
174
|
+
},
|
|
175
|
+
[onFocus, setIsFocused],
|
|
176
|
+
);
|
|
177
|
+
|
|
178
|
+
const handleInputBlur = useCallback(
|
|
179
|
+
(e: any) => {
|
|
180
|
+
setIsFocused(false);
|
|
181
|
+
onBlur?.(e);
|
|
182
|
+
},
|
|
183
|
+
[onBlur, setIsFocused],
|
|
184
|
+
);
|
|
185
|
+
|
|
186
|
+
const {animatedStyle} = useLabelAnimation({
|
|
187
|
+
value,
|
|
188
|
+
hasValue,
|
|
189
|
+
isFocused,
|
|
190
|
+
variant: normalizedVariant,
|
|
191
|
+
size: responsiveSize,
|
|
192
|
+
prefixIcon: !!prefixIcon,
|
|
193
|
+
selectDropdownOpen: selectLogic.selectDropdownOpen,
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
useOutsideClick({
|
|
197
|
+
enabled: isWeb && !isWebMobile && selectLogic.selectDropdownOpen,
|
|
198
|
+
onOutsideClick: handleSelectClose,
|
|
199
|
+
ignoredClassNames: [
|
|
200
|
+
'select-dropdown',
|
|
201
|
+
'select-button',
|
|
202
|
+
'slice-input-container',
|
|
203
|
+
],
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
const displayValue = useMemo(
|
|
207
|
+
() =>
|
|
208
|
+
getDisplayValue({
|
|
209
|
+
variant: normalizedVariant,
|
|
210
|
+
value,
|
|
211
|
+
options,
|
|
212
|
+
selectedValues: selectLogic.selectedValues,
|
|
213
|
+
labelText,
|
|
214
|
+
placeholder,
|
|
215
|
+
normalizedMultiple,
|
|
216
|
+
}),
|
|
217
|
+
[
|
|
218
|
+
normalizedVariant,
|
|
219
|
+
value,
|
|
220
|
+
options,
|
|
221
|
+
selectLogic.selectedValues,
|
|
222
|
+
labelText,
|
|
223
|
+
placeholder,
|
|
224
|
+
normalizedMultiple,
|
|
225
|
+
],
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
const variantForTokens = isSelectVariant(normalizedVariant)
|
|
229
|
+
? 'outlined'
|
|
230
|
+
: normalizedVariant;
|
|
231
|
+
const inputTheme =
|
|
232
|
+
theme.inputStyles[responsiveSize as keyof typeof theme.inputStyles]?.[
|
|
233
|
+
variantForTokens as keyof typeof theme.inputStyles.medium
|
|
234
|
+
] ?? theme.inputStyles.medium.outlined;
|
|
235
|
+
|
|
236
|
+
const defaultSelectedIcon = useMemo(() => {
|
|
237
|
+
return (
|
|
238
|
+
<Icon
|
|
239
|
+
component={<IconMoon icon={FONT_ICON.TICK} />}
|
|
240
|
+
variant="small"
|
|
241
|
+
color={colors.black[1000]}
|
|
242
|
+
/>
|
|
243
|
+
);
|
|
244
|
+
}, []);
|
|
245
|
+
|
|
246
|
+
const labelTop = useMemo(() => {
|
|
247
|
+
return labelTopBySize[responsiveSize] ?? 14;
|
|
248
|
+
}, [responsiveSize]);
|
|
249
|
+
|
|
250
|
+
const labelPositionStyle = useMemo(
|
|
251
|
+
() => ({
|
|
252
|
+
top: labelTop,
|
|
253
|
+
zIndex: 10,
|
|
254
|
+
}),
|
|
255
|
+
[labelTop],
|
|
256
|
+
);
|
|
257
|
+
|
|
258
|
+
const webContainerFocusResetStyle = useMemo(
|
|
259
|
+
() =>
|
|
260
|
+
isWeb && normalizedVariant === 'select'
|
|
261
|
+
? {
|
|
262
|
+
['outlineStyle' as any]: 'none',
|
|
263
|
+
['outlineWidth' as any]: 0,
|
|
264
|
+
['outlineColor' as any]: 'transparent',
|
|
265
|
+
['boxShadow' as any]: 'none',
|
|
266
|
+
}
|
|
267
|
+
: null,
|
|
268
|
+
[normalizedVariant],
|
|
269
|
+
);
|
|
270
|
+
|
|
271
|
+
const combinedContainerStyle = [
|
|
272
|
+
styles.baseContainer,
|
|
273
|
+
inputTheme.container,
|
|
274
|
+
{
|
|
275
|
+
borderColor: error
|
|
276
|
+
? colorTheme.colors.colorBorderNegative
|
|
277
|
+
: isFocused
|
|
278
|
+
? colorTheme.colors.colorBorderStrong
|
|
279
|
+
: `var(--slice-input-border-color, ${colorTheme.colors.colorBorderSubtle})`,
|
|
280
|
+
borderWidth: isFocused ? 1.2 : 1,
|
|
281
|
+
borderRadius: theme.dimensions.dimension06,
|
|
282
|
+
['--slice-input-font-size' as any]: inputTheme.input.fontSize,
|
|
283
|
+
['--slice-input-line-height' as any]: inputTheme.input.lineHeight,
|
|
284
|
+
['--slice-input-min-height' as any]: inputTheme.container.minHeight,
|
|
285
|
+
},
|
|
286
|
+
webContainerFocusResetStyle,
|
|
287
|
+
containerStyle,
|
|
288
|
+
];
|
|
289
|
+
|
|
290
|
+
const combinedInputStyle = [
|
|
291
|
+
styles.baseInput,
|
|
292
|
+
inputTheme.input,
|
|
293
|
+
{
|
|
294
|
+
color: colorTheme.colors.colorForegroundPrimary,
|
|
295
|
+
paddingHorizontal: spacing.space200,
|
|
296
|
+
},
|
|
297
|
+
inputStyle,
|
|
298
|
+
];
|
|
299
|
+
|
|
300
|
+
const combinedLabelStyle = [
|
|
301
|
+
styles.baseLabel,
|
|
302
|
+
inputTheme.label,
|
|
303
|
+
{
|
|
304
|
+
color: error
|
|
305
|
+
? colorTheme.colors.colorForegroundNegative
|
|
306
|
+
: colorTheme.colors.colorForegroundLight,
|
|
307
|
+
backgroundColor: colorTheme.colors.colorBackgroundPrimary,
|
|
308
|
+
},
|
|
309
|
+
labelStyle,
|
|
310
|
+
];
|
|
311
|
+
|
|
312
|
+
const combinedHelperTextStyle = [
|
|
313
|
+
styles.baseHelperText,
|
|
314
|
+
inputTheme.helperText,
|
|
315
|
+
{
|
|
316
|
+
color: error
|
|
317
|
+
? colorTheme.colors.colorForegroundNegative
|
|
318
|
+
: colorTheme.colors.colorForegroundSecondary,
|
|
319
|
+
},
|
|
320
|
+
helperTextStyle,
|
|
321
|
+
];
|
|
322
|
+
|
|
323
|
+
const isFullWidthVariant =
|
|
324
|
+
normalizedVariant === 'currency' ||
|
|
325
|
+
normalizedVariant === 'phoneWithFlag' ||
|
|
326
|
+
normalizedVariant === 'phoneWithCodeOnly';
|
|
327
|
+
|
|
328
|
+
const renderInput = () => {
|
|
329
|
+
switch (normalizedVariant) {
|
|
330
|
+
case 'currency':
|
|
331
|
+
return (
|
|
332
|
+
<CurrencyInput
|
|
333
|
+
value={typeof value === 'string' ? value : ''}
|
|
334
|
+
currency={currency}
|
|
335
|
+
currencyDropdownOpen={currencyDropdownOpen}
|
|
336
|
+
onToggleDropdown={() => setCurrencyDropdownOpen(v => !v)}
|
|
337
|
+
onCloseDropdown={() => setCurrencyDropdownOpen(false)}
|
|
338
|
+
onSelectCurrency={c => {
|
|
339
|
+
setCurrency(c);
|
|
340
|
+
setCurrencyDropdownOpen(false);
|
|
341
|
+
}}
|
|
342
|
+
disabled={disabled}
|
|
343
|
+
labelText={labelText}
|
|
344
|
+
placeholder={placeholder}
|
|
345
|
+
onChangeText={
|
|
346
|
+
onChangeText
|
|
347
|
+
? (val: string) => (onChangeText as any)(val)
|
|
348
|
+
: undefined
|
|
349
|
+
}
|
|
350
|
+
colorTheme={colorTheme}
|
|
351
|
+
portalAnchorRef={webInputContainerRef}
|
|
352
|
+
/>
|
|
353
|
+
);
|
|
354
|
+
|
|
355
|
+
case 'phoneWithFlag':
|
|
356
|
+
case 'phoneWithCodeOnly':
|
|
357
|
+
return (
|
|
358
|
+
<PhoneInput
|
|
359
|
+
mode={normalizedVariant === 'phoneWithFlag' ? 'flag' : 'code'}
|
|
360
|
+
country={country}
|
|
361
|
+
number={number}
|
|
362
|
+
dropdownOpen={dropdownOpen}
|
|
363
|
+
disabled={disabled}
|
|
364
|
+
labelText={labelText}
|
|
365
|
+
placeholder={placeholder}
|
|
366
|
+
onToggleDropdown={() => setDropdownOpen(v => !v)}
|
|
367
|
+
onCloseDropdown={() => setDropdownOpen(false)}
|
|
368
|
+
onSelectCountry={c => {
|
|
369
|
+
setCountry(c);
|
|
370
|
+
setDropdownOpen(false);
|
|
371
|
+
if (onChangeText) {
|
|
372
|
+
(onChangeText as any)(
|
|
373
|
+
`+${getCountryCallingCode(c)}${number.replace(/\D/g, '')}`,
|
|
374
|
+
);
|
|
375
|
+
}
|
|
376
|
+
}}
|
|
377
|
+
onNumberChange={onNumberChange}
|
|
378
|
+
onFocus={handleInputFocus}
|
|
379
|
+
onBlur={handleInputBlur}
|
|
380
|
+
colorTheme={colorTheme}
|
|
381
|
+
size={size}
|
|
382
|
+
portalAnchorRef={webInputContainerRef}
|
|
383
|
+
/>
|
|
384
|
+
);
|
|
385
|
+
|
|
386
|
+
case 'select':
|
|
387
|
+
return (
|
|
388
|
+
<SelectInput
|
|
389
|
+
value={value}
|
|
390
|
+
displayValue={displayValue}
|
|
391
|
+
options={options}
|
|
392
|
+
searchable={searchable}
|
|
393
|
+
normalizedMultiple={normalizedMultiple}
|
|
394
|
+
normalizedListType={normalizedListType}
|
|
395
|
+
selectDropdownOpen={selectLogic.selectDropdownOpen}
|
|
396
|
+
filteredOptions={selectLogic.filteredOptions}
|
|
397
|
+
searchValue={selectLogic.searchValue}
|
|
398
|
+
setSearchValue={selectLogic.setSearchValue}
|
|
399
|
+
onOpen={handleSelectOpen}
|
|
400
|
+
onClose={handleSelectClose}
|
|
401
|
+
onKeyDown={selectLogic.handleSelectKeyDown}
|
|
402
|
+
onOptionSelect={selectLogic.handleOptionSelect}
|
|
403
|
+
onCheckboxToggle={selectLogic.handleCheckboxToggle}
|
|
404
|
+
colorTheme={colorTheme}
|
|
405
|
+
placeholder={placeholder}
|
|
406
|
+
noItemText={noItemText}
|
|
407
|
+
maxAllowed={rest.maxAllowed}
|
|
408
|
+
maxVisibleItems={maxVisibleItems}
|
|
409
|
+
selectedIcon={selectedIcon ?? defaultSelectedIcon}
|
|
410
|
+
selectedValues={selectLogic.selectedValues}
|
|
411
|
+
disabled={disabled}
|
|
412
|
+
registerOptionRef={registerOptionRef}
|
|
413
|
+
inputRef={inputRef}
|
|
414
|
+
size={responsiveSize}
|
|
415
|
+
expandChips={rest.expandChips}
|
|
416
|
+
/>
|
|
417
|
+
);
|
|
418
|
+
|
|
419
|
+
default:
|
|
420
|
+
return (
|
|
421
|
+
<TextInputVariant
|
|
422
|
+
inputRef={inputRef}
|
|
423
|
+
value={typeof value === 'string' ? value : ''}
|
|
424
|
+
onChangeText={
|
|
425
|
+
onChangeText
|
|
426
|
+
? (val: string | string[]) => {
|
|
427
|
+
const stringVal = typeof val === 'string' ? val : '';
|
|
428
|
+
(onChangeText as any)(stringVal);
|
|
429
|
+
}
|
|
430
|
+
: undefined
|
|
431
|
+
}
|
|
432
|
+
onFocus={handleInputFocus}
|
|
433
|
+
onBlur={handleInputBlur}
|
|
434
|
+
placeholder={!labelText ? placeholder : undefined}
|
|
435
|
+
disabled={disabled}
|
|
436
|
+
style={combinedInputStyle}
|
|
437
|
+
placeholderTextColor={colorTheme.colors.colorForegroundTertiary}
|
|
438
|
+
restProps={rest}
|
|
439
|
+
/>
|
|
440
|
+
);
|
|
441
|
+
}
|
|
442
|
+
};
|
|
443
|
+
|
|
444
|
+
return (
|
|
445
|
+
<View style={styles.wrapper}>
|
|
446
|
+
<View
|
|
447
|
+
ref={webInputContainerRef}
|
|
448
|
+
style={combinedContainerStyle}
|
|
449
|
+
{...(isWeb && {
|
|
450
|
+
tabIndex: 0,
|
|
451
|
+
onFocus: () => setIsFocused(true),
|
|
452
|
+
onBlur: () => setIsFocused(false),
|
|
453
|
+
className: disabled
|
|
454
|
+
? 'slice-input-container slice-input-container--disabled'
|
|
455
|
+
: 'slice-input-container',
|
|
456
|
+
onKeyDown:
|
|
457
|
+
normalizedVariant === 'select'
|
|
458
|
+
? selectLogic.handleSelectKeyDown
|
|
459
|
+
: undefined,
|
|
460
|
+
onClick:
|
|
461
|
+
normalizedVariant === 'select' && !disabled
|
|
462
|
+
? handleSelectContainerClick
|
|
463
|
+
: undefined,
|
|
464
|
+
})}>
|
|
465
|
+
{labelText && (
|
|
466
|
+
<Animated.Text
|
|
467
|
+
style={[combinedLabelStyle, animatedStyle, labelPositionStyle]}>
|
|
468
|
+
{labelText}
|
|
469
|
+
</Animated.Text>
|
|
470
|
+
)}
|
|
471
|
+
|
|
472
|
+
<View style={styles.inputWrapper}>
|
|
473
|
+
{isFullWidthVariant ? (
|
|
474
|
+
<View style={styles.fullWidthInputContainer}>{renderInput()}</View>
|
|
475
|
+
) : (
|
|
476
|
+
<>
|
|
477
|
+
{prefixIcon && (
|
|
478
|
+
<View style={styles.prefixSlot}>{prefixIcon}</View>
|
|
479
|
+
)}
|
|
480
|
+
|
|
481
|
+
<View style={styles.inputSlot}>{renderInput()}</View>
|
|
482
|
+
|
|
483
|
+
{suffixIcon && (
|
|
484
|
+
<View style={styles.suffixSlot}>{suffixIcon}</View>
|
|
485
|
+
)}
|
|
486
|
+
</>
|
|
487
|
+
)}
|
|
488
|
+
</View>
|
|
489
|
+
|
|
490
|
+
{normalizedVariant === 'select' &&
|
|
491
|
+
isWeb &&
|
|
492
|
+
!isWebMobile &&
|
|
493
|
+
selectLogic.selectDropdownOpen &&
|
|
494
|
+
!disabled && (
|
|
495
|
+
<SelectList
|
|
496
|
+
options={selectLogic.filteredOptions}
|
|
497
|
+
value={value}
|
|
498
|
+
normalizedMultiple={normalizedMultiple}
|
|
499
|
+
normalizedListType={normalizedListType}
|
|
500
|
+
onOptionSelect={selectLogic.handleOptionSelect}
|
|
501
|
+
onCheckboxToggle={selectLogic.handleCheckboxToggle}
|
|
502
|
+
onKeyDown={selectLogic.handleSelectKeyDown}
|
|
503
|
+
colorTheme={colorTheme}
|
|
504
|
+
noItemText={noItemText ?? 'No items'}
|
|
505
|
+
maxVisibleItems={maxVisibleItems}
|
|
506
|
+
selectedIcon={selectedIcon ?? defaultSelectedIcon}
|
|
507
|
+
disabled={disabled}
|
|
508
|
+
registerOptionRef={registerOptionRef}
|
|
509
|
+
size={responsiveSize}
|
|
510
|
+
/>
|
|
511
|
+
)}
|
|
512
|
+
</View>
|
|
513
|
+
|
|
514
|
+
{(error || helperText) && (
|
|
515
|
+
<Text style={combinedHelperTextStyle}>{error || helperText}</Text>
|
|
516
|
+
)}
|
|
517
|
+
</View>
|
|
518
|
+
);
|
|
519
|
+
});
|
|
520
|
+
|
|
521
|
+
const styles = StyleSheet.create({
|
|
522
|
+
wrapper: {
|
|
523
|
+
marginVertical: 8,
|
|
524
|
+
},
|
|
525
|
+
baseContainer: {
|
|
526
|
+
position: 'relative',
|
|
527
|
+
backgroundColor: 'transparent',
|
|
528
|
+
},
|
|
529
|
+
baseInput: {
|
|
530
|
+
flex: 1,
|
|
531
|
+
minHeight: 24,
|
|
532
|
+
fontSize: 16,
|
|
533
|
+
},
|
|
534
|
+
baseLabel: {
|
|
535
|
+
position: 'absolute',
|
|
536
|
+
left: 12,
|
|
537
|
+
paddingHorizontal: 4,
|
|
538
|
+
includeFontPadding: false,
|
|
539
|
+
pointerEvents: 'none',
|
|
540
|
+
},
|
|
541
|
+
baseHelperText: {
|
|
542
|
+
marginTop: 4,
|
|
543
|
+
fontSize: 12,
|
|
544
|
+
paddingHorizontal: 12,
|
|
545
|
+
},
|
|
546
|
+
inputWrapper: {
|
|
547
|
+
flexDirection: 'row',
|
|
548
|
+
alignItems: 'center',
|
|
549
|
+
minHeight: 24,
|
|
550
|
+
position: 'relative',
|
|
551
|
+
},
|
|
552
|
+
prefixSlot: {
|
|
553
|
+
justifyContent: 'center',
|
|
554
|
+
alignItems: 'center',
|
|
555
|
+
marginLeft: spacing.space100,
|
|
556
|
+
},
|
|
557
|
+
|
|
558
|
+
suffixSlot: {
|
|
559
|
+
justifyContent: 'center',
|
|
560
|
+
alignItems: 'center',
|
|
561
|
+
marginRight: spacing.space100,
|
|
562
|
+
},
|
|
563
|
+
|
|
564
|
+
inputSlot: {
|
|
565
|
+
flex: 1,
|
|
566
|
+
justifyContent: 'center',
|
|
567
|
+
},
|
|
568
|
+
fullWidthInputContainer: {
|
|
569
|
+
flex: 1,
|
|
570
|
+
},
|
|
571
|
+
});
|
|
572
|
+
|
|
573
|
+
export default Input;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
## Input Dropdown
|
|
2
|
+
## Day 1 To Do
|
|
3
|
+
- [x] Add select and checkbox variant support with dropdown functionality
|
|
4
|
+
- [x] Add Multi-select Variant by adding Select-Checkbox as a variant
|
|
5
|
+
- [x] Display selected values with smart formatting (single, two, or "first +N" format)
|
|
6
|
+
- [x] Add click-outside handler to close dropdown
|
|
7
|
+
- [x] Update label animation to work with dropdown open state
|
|
8
|
+
- [x] Import and integrate Checkbox component
|
|
9
|
+
|
|
10
|
+
## Day 2 To Do
|
|
11
|
+
- [x] Match Logic to Country & Currency Code Dropdown
|
|
12
|
+
- [x] Add Keyboard Accessibility
|
|
13
|
+
- [x] Add Searchable prop
|
|
14
|
+
- [x] Type Check the Implementation
|
|
15
|
+
|
|
16
|
+
## Day 3 To Do
|
|
17
|
+
- [x] Split Files as proposed
|
|
18
|
+
- [x] Bug Fixes
|
|
19
|
+
- [x] Hover Colors
|
|
20
|
+
- [x] Final Type Check
|
|
21
|
+
- [x] Add Ability to backspace selected items for select variant
|
|
22
|
+
- [x] Add an No Items found Item
|
|
23
|
+
|
|
24
|
+
## Day 4 To Do
|
|
25
|
+
- [x] Add Disabled State
|
|
26
|
+
- [x] Add Icon Support for ListItem (selected Item Icon (tick,X or anything) on right & Each item can have its own icon on left)
|
|
27
|
+
- [x] Add Custom Scrollbar
|
|
28
|
+
- [x] Add Selected Item Chip for Multi-select.
|
|
29
|
+
- [x] Add a Prop to Show only Max of x Items
|
|
30
|
+
- [x] Add sole/exact word enter in searchable
|
|
31
|
+
- [x] Bug fix
|
|
32
|
+
- [x] Keyboard Hover and Mouse Hover are independently working.Need them to work as 1 so that there isn’t 2 hover at 1 time
|
|
33
|
+
|
|
34
|
+
## Day 5 To Do
|
|
35
|
+
- [x] Stablize Elements
|
|
36
|
+
|
|
37
|
+
## Day 6 To Do
|
|
38
|
+
- [x] Optimize
|
|
39
|
+
|
|
40
|
+
### Result
|
|
41
|
+
|
|
42
|
+
#### Single Select Dropdown
|
|
43
|
+
| Metric | Pre-Optimization | Post-Optimization | Δ (Pre → Post) |
|
|
44
|
+
| ---------------------------------- | ---------------- | ----------------- | -------------- |
|
|
45
|
+
| Total commits | 23 | 7 | -16 |
|
|
46
|
+
| Total render duration (ms) | 72 | 36 | -36 |
|
|
47
|
+
| Average commit duration (ms) | 3.13 | 5.14 | +2.01 |
|
|
48
|
+
| Max single commit duration (ms) | 8 | 15 | +7 |
|
|
49
|
+
| Total effect duration (ms) | 1 | 0 | -1 |
|
|
50
|
+
| Total passive effect duration (ms) | 6 | 1 | -5 |
|
|
51
|
+
|
|
52
|
+
#### Multi-Select Dropdown
|
|
53
|
+
| Metric | Pre-Optimization | Post-Optimization | Δ (Pre → Post) |
|
|
54
|
+
| ---------------------------------- | ---------------- | ----------------- | -------------- |
|
|
55
|
+
| Total commits | 24 | 18 | -6 |
|
|
56
|
+
| Total render duration (ms) | 84 | 49 | -35 |
|
|
57
|
+
| Average commit duration (ms) | 3.50 | 2.72 | -0.78 |
|
|
58
|
+
| Max single commit duration (ms) | 10 | 15 | +5 |
|
|
59
|
+
| Total effect duration (ms) | 2 | 1 | -1 |
|
|
60
|
+
| Total passive effect duration (ms) | 4 | 5 | +1 |
|
|
61
|
+
|
|
62
|
+
## Day 7 To Do
|
|
63
|
+
- [x] Match Label to Design
|
|
64
|
+
- [x] Add Default Icon to selected Icon
|
|
65
|
+
- [x] Make size variants work for input based on the Tokens
|
|
66
|
+
|
|
67
|
+
## Day 8 To Do
|
|
68
|
+
- [x] Add Sizes Based on design using the token styling from Chips Component
|
|
69
|
+
- [x] Replace Normal Text With Typography code calls
|
|
70
|
+
- [x] Add Size Based Animation for Labels
|
|
71
|
+
- [x] Match Text Styles to the design
|
|
72
|
+
- [x] Check Android Working
|
|
73
|
+
|
|
74
|
+
## Day 9 To Do
|
|
75
|
+
- [x] Remake the Details page for Showcase
|
|
76
|
+
- [x] Select-Input Fixes
|
|
77
|
+
- [x] Move Icon to be below Animated Labels and Aligns with Item Icon
|
|
78
|
+
- [x] Select-Chip Icon Size Controls
|
|
79
|
+
- [x] Dropdown Width Matching the Parent
|
|
80
|
+
- [x] Align Size Based Labels Properly
|
|
81
|
+
- [x] Click outside to lose focus
|
|
82
|
+
- [x] Prepare a Documentation of what work is done
|
|
83
|
+
- [x] Add Native Support using bottom Sheet
|
|
84
|
+
|
|
85
|
+
## Day 10 To Do
|
|
86
|
+
- [x] Edit Testscreen to support Mobile view
|
|
87
|
+
- [x] Mimic Input-Dropdown Web on Mobile
|
|
88
|
+
- [x] Features
|
|
89
|
+
- [x] Searchable
|
|
90
|
+
- [x] Max Allowed
|
|
91
|
+
- [x] Max Visible Items
|
|
92
|
+
- [x] Checkbox Support
|
|
93
|
+
- [x] Empty State
|
|
94
|
+
- [x] Styles
|
|
95
|
+
- [x] Add Expanded Chips for Mobile
|
|
96
|
+
|
|
97
|
+
## Day 11 To Do
|
|
98
|
+
- [x] Move inline styles into Internal Stylesheet/Memonized style component (If rendered dynamically/web specific)
|
|
99
|
+
- []
|