@grupalia/rn-ui-kit 0.2.0 → 0.3.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/lib/commonjs/components/BaseBottomSheetModal.js +46 -0
- package/lib/commonjs/components/BaseBottomSheetModal.js.map +1 -0
- package/lib/commonjs/components/BaseHorizontalTabs.js +138 -0
- package/lib/commonjs/components/BaseHorizontalTabs.js.map +1 -0
- package/lib/commonjs/components/BaseSelect.js +115 -0
- package/lib/commonjs/components/BaseSelect.js.map +1 -0
- package/lib/commonjs/components/BaseStackedList.js +6 -3
- package/lib/commonjs/components/BaseStackedList.js.map +1 -1
- package/lib/commonjs/components/FormikSelect.js +36 -0
- package/lib/commonjs/components/FormikSelect.js.map +1 -0
- package/lib/commonjs/components/index.js +28 -0
- package/lib/commonjs/components/index.js.map +1 -1
- package/lib/commonjs/styles/text-colors.js +4 -16
- package/lib/commonjs/styles/text-colors.js.map +1 -1
- package/lib/module/components/BaseBottomSheetModal.js +42 -0
- package/lib/module/components/BaseBottomSheetModal.js.map +1 -0
- package/lib/module/components/BaseHorizontalTabs.js +132 -0
- package/lib/module/components/BaseHorizontalTabs.js.map +1 -0
- package/lib/module/components/BaseSelect.js +109 -0
- package/lib/module/components/BaseSelect.js.map +1 -0
- package/lib/module/components/BaseStackedList.js +6 -3
- package/lib/module/components/BaseStackedList.js.map +1 -1
- package/lib/module/components/FormikSelect.js +31 -0
- package/lib/module/components/FormikSelect.js.map +1 -0
- package/lib/module/components/index.js +3 -0
- package/lib/module/components/index.js.map +1 -1
- package/lib/module/styles/text-colors.js +4 -16
- package/lib/module/styles/text-colors.js.map +1 -1
- package/lib/typescript/commonjs/components/BaseBottomSheetModal.d.ts +8 -0
- package/lib/typescript/commonjs/components/BaseBottomSheetModal.d.ts.map +1 -0
- package/lib/typescript/commonjs/components/BaseHorizontalTabs.d.ts +27 -0
- package/lib/typescript/commonjs/components/BaseHorizontalTabs.d.ts.map +1 -0
- package/lib/typescript/commonjs/components/BaseSelect.d.ts +28 -0
- package/lib/typescript/commonjs/components/BaseSelect.d.ts.map +1 -0
- package/lib/typescript/commonjs/components/BaseStackedList.d.ts +5 -8
- package/lib/typescript/commonjs/components/BaseStackedList.d.ts.map +1 -1
- package/lib/typescript/commonjs/components/FormikSelect.d.ts +20 -0
- package/lib/typescript/commonjs/components/FormikSelect.d.ts.map +1 -0
- package/lib/typescript/commonjs/components/index.d.ts +3 -0
- package/lib/typescript/commonjs/components/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/styles/text-colors.d.ts.map +1 -1
- package/lib/typescript/module/components/BaseBottomSheetModal.d.ts +8 -0
- package/lib/typescript/module/components/BaseBottomSheetModal.d.ts.map +1 -0
- package/lib/typescript/module/components/BaseHorizontalTabs.d.ts +27 -0
- package/lib/typescript/module/components/BaseHorizontalTabs.d.ts.map +1 -0
- package/lib/typescript/module/components/BaseSelect.d.ts +28 -0
- package/lib/typescript/module/components/BaseSelect.d.ts.map +1 -0
- package/lib/typescript/module/components/BaseStackedList.d.ts +5 -8
- package/lib/typescript/module/components/BaseStackedList.d.ts.map +1 -1
- package/lib/typescript/module/components/FormikSelect.d.ts +20 -0
- package/lib/typescript/module/components/FormikSelect.d.ts.map +1 -0
- package/lib/typescript/module/components/index.d.ts +3 -0
- package/lib/typescript/module/components/index.d.ts.map +1 -1
- package/lib/typescript/module/styles/text-colors.d.ts.map +1 -1
- package/package.json +9 -5
- package/src/components/BaseBottomSheetModal.tsx +51 -0
- package/src/components/BaseHorizontalTabs.tsx +221 -0
- package/src/components/BaseSelect.tsx +165 -0
- package/src/components/BaseStackedList.tsx +14 -6
- package/src/components/FormikSelect.tsx +45 -0
- package/src/components/index.ts +3 -0
- package/src/styles/text-colors.ts +4 -16
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BaseHorizontalTabs.d.ts","sourceRoot":"","sources":["../../../../src/components/BaseHorizontalTabs.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAWxC,MAAM,MAAM,OAAO,GAAG,cAAc,GAAG,WAAW,GAAG,aAAa,GAAG,eAAe,GAAG,gBAAgB,CAAC;AAExG,MAAM,WAAW,GAAG;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC;CAC1B;AAED,UAAU,uBAAuB;IAC/B,IAAI,EAAE,GAAG,EAAE,CAAC;IACZ,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;;;;;;;AA4LD,wBAA0C"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ViewStyle } from 'react-native';
|
|
3
|
+
export interface SelectOption {
|
|
4
|
+
value: string;
|
|
5
|
+
label: string;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
}
|
|
8
|
+
interface BaseSelectProps {
|
|
9
|
+
options: SelectOption[];
|
|
10
|
+
value?: string;
|
|
11
|
+
onChange?: (value: string) => void;
|
|
12
|
+
placeholder?: string;
|
|
13
|
+
label?: string;
|
|
14
|
+
helpText?: string;
|
|
15
|
+
error?: string;
|
|
16
|
+
touched?: boolean;
|
|
17
|
+
disabled?: boolean;
|
|
18
|
+
className?: string;
|
|
19
|
+
style?: ViewStyle;
|
|
20
|
+
}
|
|
21
|
+
declare const _default: React.ForwardRefExoticComponent<BaseSelectProps & {
|
|
22
|
+
className?: string | undefined;
|
|
23
|
+
tw?: string | undefined;
|
|
24
|
+
baseClassName?: string | undefined;
|
|
25
|
+
baseTw?: string | undefined;
|
|
26
|
+
} & React.RefAttributes<unknown>>;
|
|
27
|
+
export default _default;
|
|
28
|
+
//# sourceMappingURL=BaseSelect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BaseSelect.d.ts","sourceRoot":"","sources":["../../../../src/components/BaseSelect.tsx"],"names":[],"mappings":"AAGA,OAAO,KAA2B,MAAM,OAAO,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAYzC,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,UAAU,eAAe;IACvB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB;;;;;;;AAkID,wBAAkC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React, { ReactNode } from 'react';
|
|
2
|
-
|
|
2
|
+
import { ViewProps } from 'react-native';
|
|
3
|
+
export interface BaseStackedListProps<T> extends ViewProps {
|
|
3
4
|
itemsCount: number;
|
|
4
5
|
items: T[];
|
|
5
6
|
renderItem: (item: T, index: number) => ReactNode;
|
|
@@ -13,11 +14,7 @@ export interface BaseStackedListProps<T> {
|
|
|
13
14
|
emptyStateDescription?: string;
|
|
14
15
|
minHeight?: number;
|
|
15
16
|
}
|
|
16
|
-
declare
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
baseClassName?: string | undefined;
|
|
20
|
-
baseTw?: string | undefined;
|
|
21
|
-
} & React.RefAttributes<unknown>>;
|
|
22
|
-
export default _default;
|
|
17
|
+
declare function BaseStackedList<T>({ itemsCount, items, renderItem, onNextPage, onPrevPage, header, pageSize, loading, currentPage, keyExtractor, emptyStateDescription, minHeight, ...props }: BaseStackedListProps<T>): React.JSX.Element;
|
|
18
|
+
declare const StackedList: typeof BaseStackedList;
|
|
19
|
+
export default StackedList;
|
|
23
20
|
//# sourceMappingURL=BaseStackedList.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseStackedList.d.ts","sourceRoot":"","sources":["../../../../src/components/BaseStackedList.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,SAAS,EAAW,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"BaseStackedList.d.ts","sourceRoot":"","sources":["../../../../src/components/BaseStackedList.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,SAAS,EAAW,MAAM,OAAO,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AASzC,MAAM,WAAW,oBAAoB,CAAC,CAAC,CAAE,SAAQ,SAAS;IACxD,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,UAAU,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,SAAS,CAAC;IAClD,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAClD,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAuBD,iBAAS,eAAe,CAAC,CAAC,EAAE,EAC1B,UAAU,EACV,KAAK,EACL,UAAU,EACV,UAAU,EACV,UAAU,EACV,MAAM,EACN,QAAQ,EACR,OAAO,EACP,WAAe,EACf,YAAY,EACZ,qBAAqB,EACrB,SAAa,EACb,GAAG,KAAK,EACT,EAAE,oBAAoB,CAAC,CAAC,CAAC,qBA+EzB;AAED,QAAA,MAAM,WAAW,wBAAoD,CAAC;AAEtE,eAAe,WAAW,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { SelectOption } from './BaseSelect';
|
|
3
|
+
export type { SelectOption } from './BaseSelect';
|
|
4
|
+
interface FormikSelectProps {
|
|
5
|
+
name: string;
|
|
6
|
+
options: SelectOption[];
|
|
7
|
+
placeholder?: string;
|
|
8
|
+
label?: string;
|
|
9
|
+
helpText?: string;
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
className?: string;
|
|
12
|
+
}
|
|
13
|
+
declare const _default: import("react").ForwardRefExoticComponent<FormikSelectProps & {
|
|
14
|
+
className?: string | undefined;
|
|
15
|
+
tw?: string | undefined;
|
|
16
|
+
baseClassName?: string | undefined;
|
|
17
|
+
baseTw?: string | undefined;
|
|
18
|
+
} & import("react").RefAttributes<unknown>>;
|
|
19
|
+
export default _default;
|
|
20
|
+
//# sourceMappingURL=FormikSelect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FormikSelect.d.ts","sourceRoot":"","sources":["../../../../src/components/FormikSelect.tsx"],"names":[],"mappings":";AAGA,OAAmB,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAExD,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,UAAU,iBAAiB;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;;;;;;;AA6BD,wBAAoC"}
|
|
@@ -4,4 +4,7 @@ export { default as BaseSpinner } from './BaseSpinner';
|
|
|
4
4
|
export { default as BaseStackedList } from './BaseStackedList';
|
|
5
5
|
export { default as BaseIcon } from './BaseIcon';
|
|
6
6
|
export { default as BaseAlert } from './BaseAlert';
|
|
7
|
+
export { default as BaseSelect, SelectOption } from './BaseSelect';
|
|
8
|
+
export { default as FormikSelect } from './FormikSelect';
|
|
9
|
+
export { default as BaseHorizontalTabs } from './BaseHorizontalTabs';
|
|
7
10
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACnE,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,sBAAsB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text-colors.d.ts","sourceRoot":"","sources":["../../../../src/styles/text-colors.ts"],"names":[],"mappings":"AAGA,KAAK,WAAW,GAAG;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,KAAK,cAAc,GAAG;IACpB,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CAAC;CAC5B,CAAC;AAEF,QAAA,MAAM,UAAU,EAAE,
|
|
1
|
+
{"version":3,"file":"text-colors.d.ts","sourceRoot":"","sources":["../../../../src/styles/text-colors.ts"],"names":[],"mappings":"AAGA,KAAK,WAAW,GAAG;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,KAAK,cAAc,GAAG;IACpB,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CAAC;CAC5B,CAAC;AAEF,QAAA,MAAM,UAAU,EAAE,cA6FjB,CAAC;AASF,eAAe,UAAU,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@grupalia/rn-ui-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Grupalia React Native UI Kit",
|
|
5
5
|
"main": "./lib/module/index.js",
|
|
6
6
|
"types": "./lib/typescript/module/index.d.ts",
|
|
@@ -19,16 +19,19 @@
|
|
|
19
19
|
"publish-local": "npx yalc publish"
|
|
20
20
|
},
|
|
21
21
|
"peerDependencies": {
|
|
22
|
+
"@gorhom/bottom-sheet": "^5",
|
|
22
23
|
"clsx": "^2.1.1",
|
|
24
|
+
"formik": "^2",
|
|
23
25
|
"nativewind": "^2.0.11",
|
|
24
26
|
"react": "*",
|
|
25
27
|
"react-native": "*",
|
|
26
|
-
"tailwindcss": "3.3.2",
|
|
27
28
|
"react-native-heroicons": "^4.0.0",
|
|
28
|
-
"react-native-svg": "*"
|
|
29
|
+
"react-native-svg": "*",
|
|
30
|
+
"tailwindcss": "3.3.2"
|
|
29
31
|
},
|
|
30
32
|
"devDependencies": {
|
|
31
33
|
"@babel/core": "^7.20.0",
|
|
34
|
+
"@gorhom/bottom-sheet": "^5",
|
|
32
35
|
"@types/react": "~18.2.45",
|
|
33
36
|
"@typescript-eslint/eslint-plugin": "^7.10.0",
|
|
34
37
|
"@typescript-eslint/parser": "^7.10.0",
|
|
@@ -41,14 +44,15 @@
|
|
|
41
44
|
"eslint-plugin-react": "^7.34.1",
|
|
42
45
|
"eslint-plugin-react-hooks": "^4.6.2",
|
|
43
46
|
"eslint-plugin-tailwindcss": "^3.17.4",
|
|
47
|
+
"formik": "^2",
|
|
44
48
|
"nativewind": "^2.0.11",
|
|
45
49
|
"react": "18.2.0",
|
|
46
50
|
"react-native": "0.74.5",
|
|
47
51
|
"react-native-builder-bob": "^0.40.6",
|
|
52
|
+
"react-native-heroicons": "^4.0.0",
|
|
48
53
|
"react-native-svg": "^15.11.2",
|
|
49
54
|
"tailwindcss": "3.3.2",
|
|
50
|
-
"typescript": "~5.3.3"
|
|
51
|
-
"react-native-heroicons": "^4.0.0"
|
|
55
|
+
"typescript": "~5.3.3"
|
|
52
56
|
},
|
|
53
57
|
"exports": {
|
|
54
58
|
".": {
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BottomSheetModal,
|
|
3
|
+
BottomSheetBackdrop,
|
|
4
|
+
BottomSheetBackdropProps,
|
|
5
|
+
BottomSheetModalProps,
|
|
6
|
+
BottomSheetView,
|
|
7
|
+
} from '@gorhom/bottom-sheet';
|
|
8
|
+
import { styled } from 'nativewind';
|
|
9
|
+
import { forwardRef, ReactNode } from 'react';
|
|
10
|
+
import { StyleSheet } from 'react-native';
|
|
11
|
+
|
|
12
|
+
function BackdropComponent(props: BottomSheetBackdropProps) {
|
|
13
|
+
return (
|
|
14
|
+
<BottomSheetBackdrop
|
|
15
|
+
{...props}
|
|
16
|
+
opacity={0.5}
|
|
17
|
+
enableTouchThrough={false}
|
|
18
|
+
appearsOnIndex={0}
|
|
19
|
+
disappearsOnIndex={-1}
|
|
20
|
+
style={[{ backgroundColor: 'rgba(0, 0, 0, 1)' }, StyleSheet.absoluteFillObject]}
|
|
21
|
+
/>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
interface BaseBottomSheetModalProps extends BottomSheetModalProps {
|
|
26
|
+
children: ReactNode;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const BaseBottomSheetModal = forwardRef<
|
|
30
|
+
BottomSheetModal,
|
|
31
|
+
BaseBottomSheetModalProps
|
|
32
|
+
>(({ children, ...props }, ref) => (
|
|
33
|
+
<BottomSheetModal
|
|
34
|
+
ref={ref}
|
|
35
|
+
backdropComponent={BackdropComponent}
|
|
36
|
+
style={{
|
|
37
|
+
shadowColor: 'black',
|
|
38
|
+
shadowOffset: { width: 0, height: 10 },
|
|
39
|
+
shadowOpacity: 0.53,
|
|
40
|
+
shadowRadius: 13.97,
|
|
41
|
+
elevation: 21,
|
|
42
|
+
}}
|
|
43
|
+
{...props}
|
|
44
|
+
>
|
|
45
|
+
<BottomSheetView>
|
|
46
|
+
{children}
|
|
47
|
+
</BottomSheetView>
|
|
48
|
+
</BottomSheetModal>
|
|
49
|
+
));
|
|
50
|
+
|
|
51
|
+
export default styled(BaseBottomSheetModal);
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import clsx from 'clsx';
|
|
2
|
+
import { styled } from 'nativewind';
|
|
3
|
+
import React, { useState } from 'react';
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
View,
|
|
7
|
+
Text,
|
|
8
|
+
ScrollView,
|
|
9
|
+
Pressable,
|
|
10
|
+
} from '../hoc-components';
|
|
11
|
+
import BaseBadge from './BaseBadge';
|
|
12
|
+
import BaseSelect, { SelectOption } from './BaseSelect';
|
|
13
|
+
|
|
14
|
+
export type Variant = 'button-brand' | 'underline' | 'button-gray' | 'button-border' | 'button-minimal';
|
|
15
|
+
|
|
16
|
+
export interface Tab {
|
|
17
|
+
id: string;
|
|
18
|
+
label: string;
|
|
19
|
+
badge?: string | number;
|
|
20
|
+
content: React.ReactNode;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface BaseHorizontalTabsProps {
|
|
24
|
+
tabs: Tab[];
|
|
25
|
+
defaultTab?: string;
|
|
26
|
+
selectedTab?: string;
|
|
27
|
+
onTabChange?: (tabId: string) => void;
|
|
28
|
+
variant?: Variant;
|
|
29
|
+
fullWidth?: boolean;
|
|
30
|
+
select?: boolean;
|
|
31
|
+
unmountHiddenTabs?: boolean;
|
|
32
|
+
className?: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function BaseHorizontalTabs({
|
|
36
|
+
tabs,
|
|
37
|
+
defaultTab,
|
|
38
|
+
selectedTab: controlledSelectedTab,
|
|
39
|
+
onTabChange,
|
|
40
|
+
variant = 'button-brand',
|
|
41
|
+
fullWidth = false,
|
|
42
|
+
select = false,
|
|
43
|
+
unmountHiddenTabs = false,
|
|
44
|
+
className,
|
|
45
|
+
}: BaseHorizontalTabsProps) {
|
|
46
|
+
const [internalSelectedTab, setInternalSelectedTab] = useState(defaultTab || tabs[0]?.id);
|
|
47
|
+
const selectedTab = controlledSelectedTab || internalSelectedTab;
|
|
48
|
+
|
|
49
|
+
const handleTabSelect = (tabId: string) => {
|
|
50
|
+
if (controlledSelectedTab === undefined) {
|
|
51
|
+
setInternalSelectedTab(tabId);
|
|
52
|
+
}
|
|
53
|
+
onTabChange?.(tabId);
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const selectedTabContent = tabs.find((tab) => tab.id === selectedTab)?.content;
|
|
57
|
+
|
|
58
|
+
const getTabStyles = (isActive: boolean) => {
|
|
59
|
+
const baseStyles = 'rounded-md px-3 py-2';
|
|
60
|
+
|
|
61
|
+
switch (variant) {
|
|
62
|
+
case 'button-brand':
|
|
63
|
+
return clsx(
|
|
64
|
+
baseStyles,
|
|
65
|
+
isActive ? 'bg-brand-primary_alt' : 'bg-transparent',
|
|
66
|
+
);
|
|
67
|
+
case 'underline':
|
|
68
|
+
return clsx(
|
|
69
|
+
'px-1 pb-3',
|
|
70
|
+
isActive ? 'border-b-2 border-brand-primary' : 'border-b-2 border-transparent',
|
|
71
|
+
);
|
|
72
|
+
case 'button-gray':
|
|
73
|
+
return clsx(
|
|
74
|
+
baseStyles,
|
|
75
|
+
isActive ? 'bg-active' : 'bg-transparent',
|
|
76
|
+
);
|
|
77
|
+
case 'button-border':
|
|
78
|
+
return clsx(
|
|
79
|
+
baseStyles,
|
|
80
|
+
isActive ? 'bg-primary shadow-sm' : 'bg-transparent',
|
|
81
|
+
);
|
|
82
|
+
case 'button-minimal':
|
|
83
|
+
return clsx(
|
|
84
|
+
baseStyles,
|
|
85
|
+
'border',
|
|
86
|
+
isActive ? 'border-secondary bg-primary shadow-sm' : 'border-transparent bg-transparent',
|
|
87
|
+
);
|
|
88
|
+
default:
|
|
89
|
+
return baseStyles;
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const getTextStyles = (isActive: boolean) => {
|
|
94
|
+
const baseStyles = 'text-sm font-semibold';
|
|
95
|
+
|
|
96
|
+
switch (variant) {
|
|
97
|
+
case 'button-brand':
|
|
98
|
+
return clsx(
|
|
99
|
+
baseStyles,
|
|
100
|
+
isActive ? 'text-brand-secondary' : 'text-quaternary',
|
|
101
|
+
);
|
|
102
|
+
case 'underline':
|
|
103
|
+
return clsx(
|
|
104
|
+
baseStyles,
|
|
105
|
+
isActive ? 'text-brand-secondary' : 'text-quaternary',
|
|
106
|
+
);
|
|
107
|
+
case 'button-gray':
|
|
108
|
+
case 'button-border':
|
|
109
|
+
case 'button-minimal':
|
|
110
|
+
return clsx(
|
|
111
|
+
baseStyles,
|
|
112
|
+
isActive ? 'text-secondary' : 'text-quaternary',
|
|
113
|
+
);
|
|
114
|
+
default:
|
|
115
|
+
return baseStyles;
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const getContainerStyles = () => {
|
|
120
|
+
switch (variant) {
|
|
121
|
+
case 'button-brand':
|
|
122
|
+
case 'button-gray':
|
|
123
|
+
return fullWidth ? 'flex-row space-x-1 p-0' : 'flex-row space-x-1';
|
|
124
|
+
case 'underline':
|
|
125
|
+
return fullWidth ? 'flex-row space-x-3 border-b border-tertiary' : 'flex-row space-x-3 border-b border-tertiary';
|
|
126
|
+
case 'button-border':
|
|
127
|
+
return 'flex-row space-x-0.5 bg-secondary_alt p-1 rounded-lg border border-secondary';
|
|
128
|
+
case 'button-minimal':
|
|
129
|
+
return 'flex-row space-x-0.5 bg-secondary_alt rounded-lg border border-secondary';
|
|
130
|
+
default:
|
|
131
|
+
return 'flex-row space-x-1';
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
if (select) {
|
|
136
|
+
const selectOptions: SelectOption[] = tabs.map((tab) => ({
|
|
137
|
+
label: tab.badge ? `${tab.label} (${tab.badge})` : tab.label,
|
|
138
|
+
value: tab.id,
|
|
139
|
+
}));
|
|
140
|
+
|
|
141
|
+
return (
|
|
142
|
+
<View className={className}>
|
|
143
|
+
<BaseSelect
|
|
144
|
+
value={selectedTab}
|
|
145
|
+
onChange={handleTabSelect}
|
|
146
|
+
options={selectOptions}
|
|
147
|
+
placeholder="Select a tab"
|
|
148
|
+
/>
|
|
149
|
+
<View className="mt-4">
|
|
150
|
+
{unmountHiddenTabs ? (
|
|
151
|
+
selectedTabContent
|
|
152
|
+
) : (
|
|
153
|
+
tabs.map((tab) => (
|
|
154
|
+
<View
|
|
155
|
+
key={tab.id}
|
|
156
|
+
className={clsx(tab.id === selectedTab ? 'flex' : 'hidden')}
|
|
157
|
+
>
|
|
158
|
+
{tab.content}
|
|
159
|
+
</View>
|
|
160
|
+
))
|
|
161
|
+
)}
|
|
162
|
+
</View>
|
|
163
|
+
</View>
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return (
|
|
168
|
+
<View className={className}>
|
|
169
|
+
<ScrollView
|
|
170
|
+
horizontal
|
|
171
|
+
showsHorizontalScrollIndicator={false}
|
|
172
|
+
className={clsx(
|
|
173
|
+
'p-0.5',
|
|
174
|
+
fullWidth && 'w-full',
|
|
175
|
+
)}
|
|
176
|
+
>
|
|
177
|
+
<View className={getContainerStyles()}>
|
|
178
|
+
{tabs.map((tab) => (
|
|
179
|
+
<Pressable
|
|
180
|
+
key={tab.id}
|
|
181
|
+
onPress={() => handleTabSelect(tab.id)}
|
|
182
|
+
className={clsx(
|
|
183
|
+
getTabStyles(tab.id === selectedTab),
|
|
184
|
+
fullWidth && 'flex-1',
|
|
185
|
+
)}
|
|
186
|
+
>
|
|
187
|
+
<View className="flex-row items-center space-x-2">
|
|
188
|
+
<Text className={getTextStyles(tab.id === selectedTab)}>
|
|
189
|
+
{tab.label}
|
|
190
|
+
</Text>
|
|
191
|
+
{tab.badge && (
|
|
192
|
+
<BaseBadge
|
|
193
|
+
text={String(tab.badge)}
|
|
194
|
+
variant="gray"
|
|
195
|
+
size="sm"
|
|
196
|
+
/>
|
|
197
|
+
)}
|
|
198
|
+
</View>
|
|
199
|
+
</Pressable>
|
|
200
|
+
))}
|
|
201
|
+
</View>
|
|
202
|
+
</ScrollView>
|
|
203
|
+
<View className="mt-4">
|
|
204
|
+
{unmountHiddenTabs ? (
|
|
205
|
+
selectedTabContent
|
|
206
|
+
) : (
|
|
207
|
+
tabs.map((tab) => (
|
|
208
|
+
<View
|
|
209
|
+
key={tab.id}
|
|
210
|
+
className={clsx(tab.id === selectedTab ? 'flex' : 'hidden')}
|
|
211
|
+
>
|
|
212
|
+
{tab.content}
|
|
213
|
+
</View>
|
|
214
|
+
))
|
|
215
|
+
)}
|
|
216
|
+
</View>
|
|
217
|
+
</View>
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
export default styled(BaseHorizontalTabs);
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { BottomSheetModal } from '@gorhom/bottom-sheet';
|
|
2
|
+
import clsx from 'clsx';
|
|
3
|
+
import { styled } from 'nativewind';
|
|
4
|
+
import React, { useRef, useState } from 'react';
|
|
5
|
+
import { ViewStyle } from 'react-native';
|
|
6
|
+
import { ChevronDownIcon, CheckIcon } from 'react-native-heroicons/outline';
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
View,
|
|
10
|
+
Text,
|
|
11
|
+
Pressable,
|
|
12
|
+
TouchableOpacity,
|
|
13
|
+
} from '../hoc-components';
|
|
14
|
+
import BaseBottomSheetModal from './BaseBottomSheetModal';
|
|
15
|
+
import BaseIcon from './BaseIcon';
|
|
16
|
+
|
|
17
|
+
export interface SelectOption {
|
|
18
|
+
value: string;
|
|
19
|
+
label: string;
|
|
20
|
+
disabled?: boolean;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface BaseSelectProps {
|
|
24
|
+
options: SelectOption[];
|
|
25
|
+
value?: string;
|
|
26
|
+
onChange?: (value: string) => void;
|
|
27
|
+
placeholder?: string;
|
|
28
|
+
label?: string;
|
|
29
|
+
helpText?: string;
|
|
30
|
+
error?: string;
|
|
31
|
+
touched?: boolean;
|
|
32
|
+
disabled?: boolean;
|
|
33
|
+
className?: string;
|
|
34
|
+
style?: ViewStyle;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function BaseSelect({
|
|
38
|
+
options,
|
|
39
|
+
value = '',
|
|
40
|
+
onChange,
|
|
41
|
+
placeholder = 'Select option',
|
|
42
|
+
label,
|
|
43
|
+
helpText,
|
|
44
|
+
error,
|
|
45
|
+
touched = false,
|
|
46
|
+
disabled = false,
|
|
47
|
+
className,
|
|
48
|
+
style,
|
|
49
|
+
}: BaseSelectProps) {
|
|
50
|
+
const bottomSheetRef = useRef<BottomSheetModal>(null);
|
|
51
|
+
const [isFocused, setIsFocused] = useState(false);
|
|
52
|
+
|
|
53
|
+
const selectedOption = options.find((opt) => opt.value === value);
|
|
54
|
+
|
|
55
|
+
const handlePress = () => {
|
|
56
|
+
if (disabled) return;
|
|
57
|
+
setIsFocused(true);
|
|
58
|
+
bottomSheetRef.current?.present();
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const handleOptionPress = (optionValue: string) => {
|
|
62
|
+
onChange?.(optionValue);
|
|
63
|
+
bottomSheetRef.current?.dismiss();
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const hasError = touched && error;
|
|
67
|
+
|
|
68
|
+
const selectClasses = clsx(
|
|
69
|
+
'flex-row items-center justify-between rounded-lg border px-3.5 py-2.5',
|
|
70
|
+
{
|
|
71
|
+
'border-gray-300 bg-white': !hasError && !disabled,
|
|
72
|
+
'border-gray-300 bg-gray-50': disabled,
|
|
73
|
+
'border-red-300 bg-white': hasError && !disabled,
|
|
74
|
+
'shadow-sm': !disabled,
|
|
75
|
+
},
|
|
76
|
+
className,
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
const textClasses = clsx('text-base', {
|
|
80
|
+
'text-gray-900': selectedOption && !disabled,
|
|
81
|
+
'text-gray-500': (!selectedOption && !disabled) || disabled,
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
return (
|
|
85
|
+
<View style={style}>
|
|
86
|
+
{label && (
|
|
87
|
+
<Text className="mb-1.5 text-sm font-medium text-gray-700">{label}</Text>
|
|
88
|
+
)}
|
|
89
|
+
|
|
90
|
+
<Pressable
|
|
91
|
+
onPress={handlePress}
|
|
92
|
+
disabled={disabled}
|
|
93
|
+
className={selectClasses}
|
|
94
|
+
>
|
|
95
|
+
<Text
|
|
96
|
+
className={textClasses}
|
|
97
|
+
numberOfLines={1}
|
|
98
|
+
>
|
|
99
|
+
{selectedOption?.label || placeholder}
|
|
100
|
+
</Text>
|
|
101
|
+
<BaseIcon
|
|
102
|
+
icon={ChevronDownIcon}
|
|
103
|
+
size={20}
|
|
104
|
+
color="fg-quaternary"
|
|
105
|
+
className={clsx('ml-2', isFocused && 'rotate-180')}
|
|
106
|
+
/>
|
|
107
|
+
</Pressable>
|
|
108
|
+
|
|
109
|
+
{helpText && !hasError && (
|
|
110
|
+
<Text className="mt-1.5 text-sm text-gray-500">{helpText}</Text>
|
|
111
|
+
)}
|
|
112
|
+
|
|
113
|
+
{hasError && (
|
|
114
|
+
<Text className="mt-1.5 text-sm text-red-600">{error}</Text>
|
|
115
|
+
)}
|
|
116
|
+
|
|
117
|
+
<BaseBottomSheetModal
|
|
118
|
+
ref={bottomSheetRef}
|
|
119
|
+
enableDynamicSizing
|
|
120
|
+
maxDynamicContentSize={400}
|
|
121
|
+
onDismiss={() => setIsFocused(false)}
|
|
122
|
+
>
|
|
123
|
+
<View className="px-4 pb-8 pt-4">
|
|
124
|
+
<Text className="mb-4 text-center text-lg font-semibold text-gray-900">
|
|
125
|
+
{label || 'Select an option'}
|
|
126
|
+
</Text>
|
|
127
|
+
<View className="mx-2">
|
|
128
|
+
{options.map((option, index) => (
|
|
129
|
+
<TouchableOpacity
|
|
130
|
+
key={option.value}
|
|
131
|
+
onPress={() => handleOptionPress(option.value)}
|
|
132
|
+
disabled={option.disabled}
|
|
133
|
+
className={clsx(
|
|
134
|
+
'flex-row items-center justify-between py-4',
|
|
135
|
+
{
|
|
136
|
+
'border-t border-gray-200': index > 0,
|
|
137
|
+
'opacity-50': option.disabled,
|
|
138
|
+
},
|
|
139
|
+
)}
|
|
140
|
+
>
|
|
141
|
+
<Text
|
|
142
|
+
className={clsx('flex-1 text-base', {
|
|
143
|
+
'text-gray-900': !option.disabled,
|
|
144
|
+
'text-gray-400': option.disabled,
|
|
145
|
+
'font-medium': option.value === value,
|
|
146
|
+
})}
|
|
147
|
+
>
|
|
148
|
+
{option.label}
|
|
149
|
+
</Text>
|
|
150
|
+
{option.value === value && (
|
|
151
|
+
<CheckIcon
|
|
152
|
+
size={20}
|
|
153
|
+
className="ml-2 text-brand-primary"
|
|
154
|
+
/>
|
|
155
|
+
)}
|
|
156
|
+
</TouchableOpacity>
|
|
157
|
+
))}
|
|
158
|
+
</View>
|
|
159
|
+
</View>
|
|
160
|
+
</BaseBottomSheetModal>
|
|
161
|
+
</View>
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export default styled(BaseSelect);
|
|
@@ -9,7 +9,7 @@ import BaseButton from './BaseButton';
|
|
|
9
9
|
import BaseSpinner from './BaseSpinner';
|
|
10
10
|
import colors from '../styles/colors';
|
|
11
11
|
|
|
12
|
-
export interface BaseStackedListProps<T> {
|
|
12
|
+
export interface BaseStackedListProps<T> extends ViewProps {
|
|
13
13
|
itemsCount: number;
|
|
14
14
|
items: T[];
|
|
15
15
|
renderItem: (item: T, index: number) => ReactNode;
|
|
@@ -58,6 +58,7 @@ function BaseStackedList<T>({
|
|
|
58
58
|
keyExtractor,
|
|
59
59
|
emptyStateDescription,
|
|
60
60
|
minHeight = 0,
|
|
61
|
+
...props
|
|
61
62
|
}: BaseStackedListProps<T>) {
|
|
62
63
|
const totalPages = useMemo(() => Math.ceil(itemsCount / pageSize), [itemsCount, pageSize]);
|
|
63
64
|
const hasNextPage = currentPage < totalPages - 1;
|
|
@@ -73,10 +74,15 @@ function BaseStackedList<T>({
|
|
|
73
74
|
const hasItemsForCurrentPage = currentPageItems.length > pageSize * (currentPage + 1);
|
|
74
75
|
|
|
75
76
|
return (
|
|
76
|
-
<View
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
77
|
+
<View
|
|
78
|
+
className="flex flex-col rounded-xl border border-secondary bg-primary shadow-sm"
|
|
79
|
+
{...props}
|
|
80
|
+
>
|
|
81
|
+
{header && (
|
|
82
|
+
<View className="border-b border-secondary p-4">
|
|
83
|
+
{header}
|
|
84
|
+
</View>
|
|
85
|
+
)}
|
|
80
86
|
{loading && !hasItemsForCurrentPage && (
|
|
81
87
|
<View
|
|
82
88
|
className="flex items-center justify-center py-12"
|
|
@@ -134,4 +140,6 @@ function BaseStackedList<T>({
|
|
|
134
140
|
);
|
|
135
141
|
}
|
|
136
142
|
|
|
137
|
-
|
|
143
|
+
const StackedList = styled(BaseStackedList) as typeof BaseStackedList;
|
|
144
|
+
|
|
145
|
+
export default StackedList;
|