@particle-network/ui-native 0.0.11 → 0.0.12
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/components/UXListBox/UXListBox.d.ts +12 -0
- package/dist/components/UXListBox/UXListBox.js +61 -0
- package/dist/components/UXListBox/UXListBoxItem.d.ts +3 -0
- package/dist/components/UXListBox/UXListBoxItem.js +56 -0
- package/dist/components/UXListBox/UXListBoxSection.d.ts +3 -0
- package/dist/components/UXListBox/UXListBoxSection.js +15 -0
- package/dist/components/UXListBox/index.d.ts +4 -0
- package/dist/components/UXListBox/index.js +4 -0
- package/dist/components/UXListBox/types.d.ts +25 -0
- package/dist/components/UXListBox/types.js +0 -0
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.js +1 -0
- package/dist/icons/CheckIcon.d.ts +4 -0
- package/dist/icons/CheckIcon.js +20 -0
- package/package.json +4 -3
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type Item, type UXListBoxProps } from './types';
|
|
3
|
+
interface ListBoxContextValue {
|
|
4
|
+
selectedValues: Set<string>;
|
|
5
|
+
selectionMode?: 'single' | 'multiple';
|
|
6
|
+
disabledKeys?: Set<string>;
|
|
7
|
+
onItemPress: (key: string) => void;
|
|
8
|
+
onAction?: (key: string) => void;
|
|
9
|
+
}
|
|
10
|
+
export declare const ListBoxContext: React.Context<ListBoxContextValue>;
|
|
11
|
+
export declare function UXListBox<T = Item>({ items, selectionMode, selectedValues: controlledselectedValues, disabledKeys, defaultselectedValues, onSelectionChange, onAction, disallowEmptySelection, 'aria-label': ariaLabel, children, }: UXListBoxProps<T>): React.JSX.Element;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import react, { useState } from "react";
|
|
3
|
+
import { ScrollView } from "react-native";
|
|
4
|
+
const ListBoxContext = /*#__PURE__*/ react.createContext({
|
|
5
|
+
selectedValues: new Set(),
|
|
6
|
+
onItemPress: ()=>null
|
|
7
|
+
});
|
|
8
|
+
function UXListBox({ items, selectionMode, selectedValues: controlledselectedValues, disabledKeys, defaultselectedValues, onSelectionChange, onAction, disallowEmptySelection = false, 'aria-label': ariaLabel, children }) {
|
|
9
|
+
const [internalselectedValues, setInternalselectedValues] = useState(()=>{
|
|
10
|
+
if ('all' === defaultselectedValues) return new Set();
|
|
11
|
+
return defaultselectedValues || new Set();
|
|
12
|
+
});
|
|
13
|
+
const selectedValues = void 0 !== controlledselectedValues ? controlledselectedValues : internalselectedValues;
|
|
14
|
+
const isControlled = void 0 !== controlledselectedValues;
|
|
15
|
+
const handleItemPress = (key)=>{
|
|
16
|
+
if (onAction && !selectionMode) return void onAction(key);
|
|
17
|
+
if (selectionMode) {
|
|
18
|
+
const newselectedValues = new Set('all' === selectedValues ? [] : selectedValues);
|
|
19
|
+
if ('single' === selectionMode) if (newselectedValues.has(key)) {
|
|
20
|
+
if (!disallowEmptySelection) newselectedValues.clear();
|
|
21
|
+
} else {
|
|
22
|
+
newselectedValues.clear();
|
|
23
|
+
newselectedValues.add(key);
|
|
24
|
+
}
|
|
25
|
+
else if ('multiple' === selectionMode) if (newselectedValues.has(key)) {
|
|
26
|
+
if (!disallowEmptySelection || newselectedValues.size > 1) newselectedValues.delete(key);
|
|
27
|
+
} else newselectedValues.add(key);
|
|
28
|
+
if (!isControlled) setInternalselectedValues(newselectedValues);
|
|
29
|
+
onSelectionChange?.(newselectedValues);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
const renderChildren = ()=>{
|
|
33
|
+
if (items && 'function' == typeof children) {
|
|
34
|
+
const itemsArray = Array.from(items);
|
|
35
|
+
return itemsArray.map((item)=>{
|
|
36
|
+
const child = children(item);
|
|
37
|
+
return /*#__PURE__*/ react.cloneElement(child, {
|
|
38
|
+
key: child.key || item.key || item.value
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
return children;
|
|
43
|
+
};
|
|
44
|
+
const contextValue = {
|
|
45
|
+
selectedValues: 'all' === selectedValues ? new Set() : selectedValues,
|
|
46
|
+
selectionMode,
|
|
47
|
+
disabledKeys,
|
|
48
|
+
onItemPress: handleItemPress,
|
|
49
|
+
onAction
|
|
50
|
+
};
|
|
51
|
+
return /*#__PURE__*/ jsx(ListBoxContext.Provider, {
|
|
52
|
+
value: contextValue,
|
|
53
|
+
children: /*#__PURE__*/ jsx(ScrollView, {
|
|
54
|
+
showsVerticalScrollIndicator: false,
|
|
55
|
+
accessibilityRole: 'list',
|
|
56
|
+
accessibilityLabel: ariaLabel,
|
|
57
|
+
children: renderChildren()
|
|
58
|
+
})
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
export { ListBoxContext, UXListBox };
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useContext } from "react";
|
|
3
|
+
import { ms } from "react-native-size-matters";
|
|
4
|
+
import CheckIcon from "../../icons/CheckIcon.js";
|
|
5
|
+
import { HStack } from "../layout/HStack.js";
|
|
6
|
+
import { Text } from "../Text/index.js";
|
|
7
|
+
import { UXTouchableOpacity } from "../UXTouchableOpacity/index.js";
|
|
8
|
+
import { ListBoxContext } from "./UXListBox.js";
|
|
9
|
+
const disabledOpacity = 0.4;
|
|
10
|
+
const UXListBoxItem = ({ value = '', startContent, isDisabled = false, onPress, children })=>{
|
|
11
|
+
const context = useContext(ListBoxContext);
|
|
12
|
+
const { selectedValues, selectionMode, disabledKeys, onItemPress } = context;
|
|
13
|
+
const isSelected = selectedValues.has(value);
|
|
14
|
+
const isItemDisabled = isDisabled || disabledKeys?.has(value);
|
|
15
|
+
const handlePress = ()=>{
|
|
16
|
+
if (isItemDisabled) return;
|
|
17
|
+
if (onPress) onPress();
|
|
18
|
+
else onItemPress(value);
|
|
19
|
+
};
|
|
20
|
+
return /*#__PURE__*/ jsxs(UXTouchableOpacity, {
|
|
21
|
+
radius: "sm",
|
|
22
|
+
ph: "md",
|
|
23
|
+
pv: "sm",
|
|
24
|
+
gap: 4,
|
|
25
|
+
items: "center",
|
|
26
|
+
justify: "between",
|
|
27
|
+
minH: 40,
|
|
28
|
+
disabled: isItemDisabled,
|
|
29
|
+
activeOpacity: 0.7,
|
|
30
|
+
accessibilityRole: "button",
|
|
31
|
+
accessibilityState: {
|
|
32
|
+
selected: isSelected,
|
|
33
|
+
disabled: isItemDisabled
|
|
34
|
+
},
|
|
35
|
+
onPress: handlePress,
|
|
36
|
+
children: [
|
|
37
|
+
/*#__PURE__*/ jsxs(HStack, {
|
|
38
|
+
gap: 4,
|
|
39
|
+
children: [
|
|
40
|
+
startContent,
|
|
41
|
+
/*#__PURE__*/ jsx(Text, {
|
|
42
|
+
body1Bold: true,
|
|
43
|
+
opacity: isItemDisabled ? disabledOpacity : 1,
|
|
44
|
+
color: isSelected ? 'foreground' : 'secondary',
|
|
45
|
+
children: children
|
|
46
|
+
})
|
|
47
|
+
]
|
|
48
|
+
}),
|
|
49
|
+
selectionMode && isSelected ? /*#__PURE__*/ jsx(CheckIcon, {
|
|
50
|
+
size: ms(16),
|
|
51
|
+
color: "foreground"
|
|
52
|
+
}) : null
|
|
53
|
+
]
|
|
54
|
+
});
|
|
55
|
+
};
|
|
56
|
+
export { UXListBoxItem };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import "react";
|
|
3
|
+
import { VStack } from "../layout/VStack.js";
|
|
4
|
+
import { Text } from "../Text/index.js";
|
|
5
|
+
const UXListBoxSection = ({ title, children })=>/*#__PURE__*/ jsxs(VStack, {
|
|
6
|
+
children: [
|
|
7
|
+
/*#__PURE__*/ jsx(Text, {
|
|
8
|
+
body1Bold: true,
|
|
9
|
+
mt: "md",
|
|
10
|
+
children: title
|
|
11
|
+
}),
|
|
12
|
+
children
|
|
13
|
+
]
|
|
14
|
+
});
|
|
15
|
+
export { UXListBoxSection };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
export type Item = Record<string, unknown>;
|
|
3
|
+
export interface UXListBoxProps<T = Item> {
|
|
4
|
+
items?: Iterable<T>;
|
|
5
|
+
selectionMode?: 'single' | 'multiple';
|
|
6
|
+
selectedValues?: Set<string> | 'all';
|
|
7
|
+
disabledKeys?: Set<string>;
|
|
8
|
+
defaultselectedValues?: Set<string> | 'all';
|
|
9
|
+
onSelectionChange?: (keys: Set<string>) => void;
|
|
10
|
+
onAction?: (key: string) => void;
|
|
11
|
+
disallowEmptySelection?: boolean;
|
|
12
|
+
'aria-label'?: string;
|
|
13
|
+
children?: ReactNode | ((item: T) => ReactNode);
|
|
14
|
+
}
|
|
15
|
+
export interface UXListBoxSectionProps {
|
|
16
|
+
title: string;
|
|
17
|
+
children?: ReactNode;
|
|
18
|
+
}
|
|
19
|
+
export interface UXListBoxItemProps {
|
|
20
|
+
value?: string;
|
|
21
|
+
startContent?: ReactNode;
|
|
22
|
+
isDisabled?: boolean;
|
|
23
|
+
onPress?: () => void;
|
|
24
|
+
children?: ReactNode;
|
|
25
|
+
}
|
|
File without changes
|
package/dist/components/index.js
CHANGED
|
@@ -13,6 +13,7 @@ export * from "./UXCheckbox/index.js";
|
|
|
13
13
|
export * from "./UXChip/index.js";
|
|
14
14
|
export * from "./UXDivider/index.js";
|
|
15
15
|
export * from "./UXHint/index.js";
|
|
16
|
+
export * from "./UXListBox/index.js";
|
|
16
17
|
export * from "./UXModal/index.js";
|
|
17
18
|
export * from "./UXPressable/index.js";
|
|
18
19
|
export * from "./UXRadio/index.js";
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import "react";
|
|
3
|
+
import react_native_svg, { Path } from "react-native-svg";
|
|
4
|
+
import { useColors } from "../hooks/index.js";
|
|
5
|
+
const CheckIcon_CheckIcon = ({ size = 16, color = 'default', ...props })=>{
|
|
6
|
+
const { getColor } = useColors();
|
|
7
|
+
return /*#__PURE__*/ jsx(react_native_svg, {
|
|
8
|
+
width: size,
|
|
9
|
+
height: size,
|
|
10
|
+
viewBox: "0 0 24 24",
|
|
11
|
+
fill: "none",
|
|
12
|
+
...props,
|
|
13
|
+
children: /*#__PURE__*/ jsx(Path, {
|
|
14
|
+
d: "M19.3281 6.28711C19.7108 5.90439 20.3302 5.9044 20.7129 6.28711C21.0956 6.66983 21.0956 7.28916 20.7129 7.67188L10.042 18.3389C10.0336 18.3479 10.0264 18.3584 10.0176 18.3672C9.82525 18.5574 9.57459 18.6514 9.32422 18.6514C9.07383 18.6513 8.82312 18.5555 8.63281 18.3652L3.28711 13.0186C2.90448 12.6358 2.90442 12.0165 3.28711 11.6338C3.66982 11.2513 4.28923 11.2512 4.67188 11.6338L9.32422 16.2891L19.3281 6.28711Z",
|
|
15
|
+
fill: getColor(color)
|
|
16
|
+
})
|
|
17
|
+
});
|
|
18
|
+
};
|
|
19
|
+
const CheckIcon = CheckIcon_CheckIcon;
|
|
20
|
+
export { CheckIcon as default };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@particle-network/ui-native",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.12",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": "./entry.js",
|
|
6
6
|
"react-native": "./dist/index.js",
|
|
@@ -29,7 +29,8 @@
|
|
|
29
29
|
"build": "rslib build",
|
|
30
30
|
"lint": "eslint . --no-error-on-unmatched-pattern --quiet",
|
|
31
31
|
"lint:fix": "eslint . --fix --no-error-on-unmatched-pattern --quiet",
|
|
32
|
-
"clean": "rm -rf .turbo node_modules dist"
|
|
32
|
+
"clean": "rm -rf .turbo node_modules dist",
|
|
33
|
+
"deploy:dev": "sh ./scripts/deploy-dev.sh"
|
|
33
34
|
},
|
|
34
35
|
"files": [
|
|
35
36
|
"dist",
|
|
@@ -53,6 +54,7 @@
|
|
|
53
54
|
"@particle-network/ui-shared": "*",
|
|
54
55
|
"ahooks": "^3.9.4",
|
|
55
56
|
"expo-haptics": "^14.1.4",
|
|
57
|
+
"react-native-paper": "^5.14.5",
|
|
56
58
|
"react-native-size-matters": "^0.4.2"
|
|
57
59
|
},
|
|
58
60
|
"devDependencies": {
|
|
@@ -88,7 +90,6 @@
|
|
|
88
90
|
"react-dom": "19.0.0",
|
|
89
91
|
"react-native": "0.79.5",
|
|
90
92
|
"react-native-gesture-handler": "~2.24.0",
|
|
91
|
-
"react-native-paper": "^5.14.5",
|
|
92
93
|
"react-native-reanimated": "~3.17.4",
|
|
93
94
|
"react-native-safe-area-context": "5.4.0",
|
|
94
95
|
"react-native-svg": "15.11.2",
|