@kaushverse/pickify 1.2.6 → 1.2.7

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 CHANGED
@@ -2,7 +2,7 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import React$1 from 'react';
3
3
  import { TextStyle, ViewStyle, Animated } from 'react-native';
4
4
 
5
- type IconRenderer = (props: {
5
+ type IconRenderer$1 = (props: {
6
6
  name?: string;
7
7
  size?: number;
8
8
  color?: string;
@@ -37,7 +37,7 @@ type PickerStyles = {
37
37
  selectText?: TextStyle;
38
38
  error?: TextStyle;
39
39
  };
40
- type Props$1 = {
40
+ type Props = {
41
41
  labelStyle?: TextStyle;
42
42
  selectBoxStyle?: ViewStyle;
43
43
  selectTextStyle?: TextStyle;
@@ -52,12 +52,12 @@ type Props$1 = {
52
52
  renderTab?: (tab: Group, isActive: boolean, onPress: () => void) => React$1.ReactNode;
53
53
  renderItem?: (item: Option, isSelected: boolean) => React$1.ReactNode;
54
54
  renderContainer?: (children: React$1.ReactNode) => React$1.ReactNode;
55
- renderIcon?: IconRenderer;
55
+ renderIcon?: IconRenderer$1;
56
56
  onSelect: (value: string) => void;
57
57
  onClose: () => void;
58
58
  };
59
59
 
60
- declare function PickerModal({ visible, selectedValue, options, groups, styles, theme, renderTab, renderItem, renderContainer, onSelect, onClose, renderIcon, label, placeholder, error, labelStyle, selectBoxStyle, selectTextStyle, errorStyle, setVisible }: Props$1 & {
60
+ declare function PickerModal({ visible, selectedValue, options, groups, styles, theme, renderTab, renderItem, renderContainer, onSelect, onClose, renderIcon, label, placeholder, error, labelStyle, selectBoxStyle, selectTextStyle, errorStyle, setVisible }: Props & {
61
61
  label?: string;
62
62
  placeholder?: string;
63
63
  error?: string;
@@ -82,7 +82,7 @@ type MultiPickerItemProps = {
82
82
  label: string;
83
83
  selected: boolean;
84
84
  onPress: () => void;
85
- renderItemIcon?: IconRenderer;
85
+ renderItemIcon?: IconRenderer$1;
86
86
  styles?: MultiPickerItemStyles;
87
87
  };
88
88
  type MultiPickerGroupStyles = {
@@ -95,7 +95,7 @@ type MultiPickerGroupStyles = {
95
95
  type MultiPickerGroupProps = {
96
96
  label: string;
97
97
  children: React.ReactNode;
98
- renderGroupIcon?: IconRenderer;
98
+ renderGroupIcon?: IconRenderer$1;
99
99
  styles?: MultiPickerGroupStyles;
100
100
  defaultOpen: boolean;
101
101
  };
@@ -121,14 +121,19 @@ type MultiPickerProps = {
121
121
  label?: string;
122
122
  placeholder?: string;
123
123
  error?: string;
124
- renderInputIcon?: IconRenderer;
125
- renderGroupIcon?: IconRenderer;
126
- renderItemIcon?: IconRenderer;
124
+ renderInputIcon?: IconRenderer$1;
125
+ renderGroupIcon?: IconRenderer$1;
126
+ renderItemIcon?: IconRenderer$1;
127
127
  styles?: MultiPickerStyles;
128
128
  };
129
129
 
130
130
  declare function MultiPickerModal({ visible, setVisible, selectedValues, options, groups, onChange, label, placeholder, error, renderInputIcon, renderGroupIcon, renderItemIcon, styles, }: MultiPickerProps): react_jsx_runtime.JSX.Element;
131
131
 
132
+ type IconRenderer = (props: {
133
+ name: string;
134
+ size: number;
135
+ color: string;
136
+ }) => React$1.ReactNode;
132
137
  type Action = {
133
138
  icon: string;
134
139
  onPress?: () => void;
@@ -142,23 +147,36 @@ type FloatingButtonStyles = {
142
147
  secondaryButton?: ViewStyle;
143
148
  circleContainer?: ViewStyle;
144
149
  };
145
- type Props = {
150
+ type FloatingButtonProps = {
151
+ /** List of actions to display when menu is open */
146
152
  actions: Action[];
153
+ /** Layout direction: vertical, horizontal, or circle */
147
154
  mode?: "vertical" | "horizontal" | "circle";
155
+ /** Radius for circle mode (distance from main button) */
148
156
  radius?: number;
157
+ /** Custom renderer for the main icon */
149
158
  renderMainIcon?: IconRenderer;
159
+ /** Custom renderer for action icons */
150
160
  renderItemIcon?: IconRenderer;
161
+ /** Custom styles for different parts */
151
162
  styles?: FloatingButtonStyles;
163
+ /** Additional style for the container */
152
164
  style?: ViewStyle;
165
+ /** Name of the main icon (default: 'add') */
153
166
  mainIconName?: string;
154
- };
155
- declare class FloatingButton extends React$1.Component<Props> {
156
- animation: Animated.Value;
157
- open: boolean;
167
+ /** Controls menu open state (optional, for controlled mode) */
168
+ open?: boolean;
169
+ /** Callback when menu opens/closes */
170
+ onToggle?: (isOpen: boolean) => void;
171
+ /** Animation configuration (optional) */
172
+ animationConfig?: Partial<Animated.SpringAnimationConfig>;
173
+ };
174
+ type FloatingButtonRef = {
175
+ openMenu: () => void;
176
+ closeMenu: () => void;
158
177
  toggleMenu: () => void;
159
- renderAction: (action: Action, index: number) => react_jsx_runtime.JSX.Element;
160
- render(): react_jsx_runtime.JSX.Element;
161
- }
178
+ };
179
+ declare const FloatingButton: React$1.ForwardRefExoticComponent<FloatingButtonProps & React$1.RefAttributes<FloatingButtonRef>>;
162
180
 
163
181
  declare function MultiPickerItem({ label, selected, onPress, renderItemIcon, styles: customStyles, }: MultiPickerItemProps): react_jsx_runtime.JSX.Element;
164
182
 
@@ -168,4 +186,4 @@ declare const toggleValue: (arr: string[], value: string) => string[];
168
186
 
169
187
  declare const groupOptions: (options: Option[], config: Record<string, string[]>) => Group[];
170
188
 
171
- export { FloatingButton, type Group, type MultiGroup, type MultiOption, MultiPickerGroup, type MultiPickerGroupProps, type MultiPickerGroupStyles, MultiPickerItem, type MultiPickerItemProps, type MultiPickerItemStyles, MultiPickerModal, type MultiPickerProps, type MultiPickerStyles, type Option, PickerModal, type PickerStyles, type Props$1 as Props, type Theme, groupOptions, toggleValue };
189
+ export { FloatingButton, type Group, type MultiGroup, type MultiOption, MultiPickerGroup, type MultiPickerGroupProps, type MultiPickerGroupStyles, MultiPickerItem, type MultiPickerItemProps, type MultiPickerItemStyles, MultiPickerModal, type MultiPickerProps, type MultiPickerStyles, type Option, PickerModal, type PickerStyles, type Props, type Theme, groupOptions, toggleValue };
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import React$1 from 'react';
3
3
  import { TextStyle, ViewStyle, Animated } from 'react-native';
4
4
 
5
- type IconRenderer = (props: {
5
+ type IconRenderer$1 = (props: {
6
6
  name?: string;
7
7
  size?: number;
8
8
  color?: string;
@@ -37,7 +37,7 @@ type PickerStyles = {
37
37
  selectText?: TextStyle;
38
38
  error?: TextStyle;
39
39
  };
40
- type Props$1 = {
40
+ type Props = {
41
41
  labelStyle?: TextStyle;
42
42
  selectBoxStyle?: ViewStyle;
43
43
  selectTextStyle?: TextStyle;
@@ -52,12 +52,12 @@ type Props$1 = {
52
52
  renderTab?: (tab: Group, isActive: boolean, onPress: () => void) => React$1.ReactNode;
53
53
  renderItem?: (item: Option, isSelected: boolean) => React$1.ReactNode;
54
54
  renderContainer?: (children: React$1.ReactNode) => React$1.ReactNode;
55
- renderIcon?: IconRenderer;
55
+ renderIcon?: IconRenderer$1;
56
56
  onSelect: (value: string) => void;
57
57
  onClose: () => void;
58
58
  };
59
59
 
60
- declare function PickerModal({ visible, selectedValue, options, groups, styles, theme, renderTab, renderItem, renderContainer, onSelect, onClose, renderIcon, label, placeholder, error, labelStyle, selectBoxStyle, selectTextStyle, errorStyle, setVisible }: Props$1 & {
60
+ declare function PickerModal({ visible, selectedValue, options, groups, styles, theme, renderTab, renderItem, renderContainer, onSelect, onClose, renderIcon, label, placeholder, error, labelStyle, selectBoxStyle, selectTextStyle, errorStyle, setVisible }: Props & {
61
61
  label?: string;
62
62
  placeholder?: string;
63
63
  error?: string;
@@ -82,7 +82,7 @@ type MultiPickerItemProps = {
82
82
  label: string;
83
83
  selected: boolean;
84
84
  onPress: () => void;
85
- renderItemIcon?: IconRenderer;
85
+ renderItemIcon?: IconRenderer$1;
86
86
  styles?: MultiPickerItemStyles;
87
87
  };
88
88
  type MultiPickerGroupStyles = {
@@ -95,7 +95,7 @@ type MultiPickerGroupStyles = {
95
95
  type MultiPickerGroupProps = {
96
96
  label: string;
97
97
  children: React.ReactNode;
98
- renderGroupIcon?: IconRenderer;
98
+ renderGroupIcon?: IconRenderer$1;
99
99
  styles?: MultiPickerGroupStyles;
100
100
  defaultOpen: boolean;
101
101
  };
@@ -121,14 +121,19 @@ type MultiPickerProps = {
121
121
  label?: string;
122
122
  placeholder?: string;
123
123
  error?: string;
124
- renderInputIcon?: IconRenderer;
125
- renderGroupIcon?: IconRenderer;
126
- renderItemIcon?: IconRenderer;
124
+ renderInputIcon?: IconRenderer$1;
125
+ renderGroupIcon?: IconRenderer$1;
126
+ renderItemIcon?: IconRenderer$1;
127
127
  styles?: MultiPickerStyles;
128
128
  };
129
129
 
130
130
  declare function MultiPickerModal({ visible, setVisible, selectedValues, options, groups, onChange, label, placeholder, error, renderInputIcon, renderGroupIcon, renderItemIcon, styles, }: MultiPickerProps): react_jsx_runtime.JSX.Element;
131
131
 
132
+ type IconRenderer = (props: {
133
+ name: string;
134
+ size: number;
135
+ color: string;
136
+ }) => React$1.ReactNode;
132
137
  type Action = {
133
138
  icon: string;
134
139
  onPress?: () => void;
@@ -142,23 +147,36 @@ type FloatingButtonStyles = {
142
147
  secondaryButton?: ViewStyle;
143
148
  circleContainer?: ViewStyle;
144
149
  };
145
- type Props = {
150
+ type FloatingButtonProps = {
151
+ /** List of actions to display when menu is open */
146
152
  actions: Action[];
153
+ /** Layout direction: vertical, horizontal, or circle */
147
154
  mode?: "vertical" | "horizontal" | "circle";
155
+ /** Radius for circle mode (distance from main button) */
148
156
  radius?: number;
157
+ /** Custom renderer for the main icon */
149
158
  renderMainIcon?: IconRenderer;
159
+ /** Custom renderer for action icons */
150
160
  renderItemIcon?: IconRenderer;
161
+ /** Custom styles for different parts */
151
162
  styles?: FloatingButtonStyles;
163
+ /** Additional style for the container */
152
164
  style?: ViewStyle;
165
+ /** Name of the main icon (default: 'add') */
153
166
  mainIconName?: string;
154
- };
155
- declare class FloatingButton extends React$1.Component<Props> {
156
- animation: Animated.Value;
157
- open: boolean;
167
+ /** Controls menu open state (optional, for controlled mode) */
168
+ open?: boolean;
169
+ /** Callback when menu opens/closes */
170
+ onToggle?: (isOpen: boolean) => void;
171
+ /** Animation configuration (optional) */
172
+ animationConfig?: Partial<Animated.SpringAnimationConfig>;
173
+ };
174
+ type FloatingButtonRef = {
175
+ openMenu: () => void;
176
+ closeMenu: () => void;
158
177
  toggleMenu: () => void;
159
- renderAction: (action: Action, index: number) => react_jsx_runtime.JSX.Element;
160
- render(): react_jsx_runtime.JSX.Element;
161
- }
178
+ };
179
+ declare const FloatingButton: React$1.ForwardRefExoticComponent<FloatingButtonProps & React$1.RefAttributes<FloatingButtonRef>>;
162
180
 
163
181
  declare function MultiPickerItem({ label, selected, onPress, renderItemIcon, styles: customStyles, }: MultiPickerItemProps): react_jsx_runtime.JSX.Element;
164
182
 
@@ -168,4 +186,4 @@ declare const toggleValue: (arr: string[], value: string) => string[];
168
186
 
169
187
  declare const groupOptions: (options: Option[], config: Record<string, string[]>) => Group[];
170
188
 
171
- export { FloatingButton, type Group, type MultiGroup, type MultiOption, MultiPickerGroup, type MultiPickerGroupProps, type MultiPickerGroupStyles, MultiPickerItem, type MultiPickerItemProps, type MultiPickerItemStyles, MultiPickerModal, type MultiPickerProps, type MultiPickerStyles, type Option, PickerModal, type PickerStyles, type Props$1 as Props, type Theme, groupOptions, toggleValue };
189
+ export { FloatingButton, type Group, type MultiGroup, type MultiOption, MultiPickerGroup, type MultiPickerGroupProps, type MultiPickerGroupStyles, MultiPickerItem, type MultiPickerItemProps, type MultiPickerItemStyles, MultiPickerModal, type MultiPickerProps, type MultiPickerStyles, type Option, PickerModal, type PickerStyles, type Props, type Theme, groupOptions, toggleValue };
package/dist/index.js CHANGED
@@ -1,9 +1,7 @@
1
1
  "use strict";
2
- var __create = Object.create;
3
2
  var __defProp = Object.defineProperty;
4
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
6
  var __export = (target, all) => {
9
7
  for (var name in all)
@@ -17,20 +15,12 @@ var __copyProps = (to, from, except, desc) => {
17
15
  }
18
16
  return to;
19
17
  };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
19
 
30
20
  // src/index.ts
31
21
  var index_exports = {};
32
22
  __export(index_exports, {
33
- FloatingButton: () => FloatingButton,
23
+ FloatingButton: () => FloatingButton_default,
34
24
  MultiPickerGroup: () => MultiPickerGroup,
35
25
  MultiPickerItem: () => MultiPickerItem,
36
26
  MultiPickerModal: () => MultiPickerModal,
@@ -718,107 +708,131 @@ var defaultStyles3 = import_react_native4.StyleSheet.create({
718
708
  });
719
709
 
720
710
  // src/core/FloatingButton.tsx
721
- var import_react4 = __toESM(require("react"));
711
+ var import_react4 = require("react");
722
712
  var import_react_native5 = require("react-native");
723
713
  var import_jsx_runtime5 = require("react/jsx-runtime");
724
- var FloatingButton = class extends import_react4.default.Component {
725
- animation = new import_react_native5.Animated.Value(0);
726
- open = false;
727
- toggleMenu = () => {
728
- import_react_native5.Animated.spring(this.animation, {
729
- toValue: this.open ? 0 : 1,
730
- useNativeDriver: true,
731
- damping: 12,
732
- mass: 0.6,
733
- stiffness: 180
734
- }).start();
735
- this.open = !this.open;
736
- };
737
- renderAction = (action, index) => {
714
+ var FloatingButton = (0, import_react4.forwardRef)(
715
+ (props, ref) => {
738
716
  const {
717
+ actions,
739
718
  mode = "vertical",
740
719
  radius = 100,
741
- actions,
720
+ renderMainIcon,
742
721
  renderItemIcon,
743
- styles: styles2
744
- } = this.props;
745
- let translateX = 0;
746
- let translateY = 0;
747
- if (mode === "vertical") {
748
- translateY = -60 * (index + 1);
749
- translateX = 0;
750
- }
751
- if (mode === "horizontal") {
752
- translateX = -60 * (index + 1);
753
- translateY = 0;
754
- }
755
- if (mode === "circle") {
756
- const totalActions = actions.length;
757
- const startAngle = -Math.PI / 3;
758
- const endAngle = -Math.PI * 0.8;
759
- const angle = startAngle + index / (totalActions - 1 || 1) * (endAngle - startAngle);
760
- const baseRadius = radius * 0.65;
761
- const adjustedRadius = index === actions.length - 1 ? baseRadius * 0.8 : baseRadius;
762
- translateX = adjustedRadius * Math.cos(angle);
763
- translateY = adjustedRadius * Math.sin(angle);
764
- }
765
- const animStyle = {
766
- transform: [
767
- {
768
- translateX: this.animation.interpolate({
769
- inputRange: [0, 1],
770
- outputRange: [0, translateX]
771
- })
772
- },
773
- {
774
- translateY: this.animation.interpolate({
775
- inputRange: [0, 1],
776
- outputRange: [0, translateY]
777
- })
778
- },
779
- {
780
- scale: this.animation.interpolate({
781
- inputRange: [0, 0.5, 1],
782
- outputRange: [0, 1.2, 1]
783
- })
784
- }
785
- ],
786
- opacity: this.animation
722
+ styles: customStyles,
723
+ style,
724
+ mainIconName = "add",
725
+ open: controlledOpen,
726
+ onToggle,
727
+ animationConfig = {}
728
+ } = props;
729
+ const animation = (0, import_react4.useRef)(new import_react_native5.Animated.Value(0)).current;
730
+ const [internalOpen, setInternalOpen] = (0, import_react4.useState)(false);
731
+ const isOpen = controlledOpen !== void 0 ? controlledOpen : internalOpen;
732
+ (0, import_react4.useEffect)(() => {
733
+ import_react_native5.Animated.spring(animation, {
734
+ toValue: isOpen ? 1 : 0,
735
+ useNativeDriver: true,
736
+ damping: 12,
737
+ mass: 0.6,
738
+ stiffness: 180,
739
+ ...animationConfig
740
+ }).start();
741
+ }, [isOpen, animation, animationConfig]);
742
+ (0, import_react4.useImperativeHandle)(ref, () => ({
743
+ openMenu: () => {
744
+ if (controlledOpen === void 0) setInternalOpen(true);
745
+ onToggle?.(true);
746
+ },
747
+ closeMenu: () => {
748
+ if (controlledOpen === void 0) setInternalOpen(false);
749
+ onToggle?.(false);
750
+ },
751
+ toggleMenu: () => {
752
+ const newState = !isOpen;
753
+ if (controlledOpen === void 0) setInternalOpen(newState);
754
+ onToggle?.(newState);
755
+ }
756
+ }));
757
+ const toggleMenu = () => {
758
+ const newState = !isOpen;
759
+ if (controlledOpen === void 0) setInternalOpen(newState);
760
+ onToggle?.(newState);
787
761
  };
788
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
789
- import_react_native5.TouchableWithoutFeedback,
790
- {
791
- onPress: () => {
792
- this.toggleMenu();
793
- action.onPress?.();
794
- action.navigateTo?.();
795
- },
796
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
797
- import_react_native5.Animated.View,
762
+ const renderAction = (action, index) => {
763
+ let translateX = 0;
764
+ let translateY = 0;
765
+ if (mode === "vertical") {
766
+ translateY = -60 * (index + 1);
767
+ translateX = 0;
768
+ } else if (mode === "horizontal") {
769
+ translateX = -60 * (index + 1);
770
+ translateY = 0;
771
+ } else if (mode === "circle") {
772
+ const totalActions = actions.length;
773
+ const startAngle = -Math.PI / 3;
774
+ const endAngle = -Math.PI * 0.8;
775
+ const angle = startAngle + index / (totalActions - 1 || 1) * (endAngle - startAngle);
776
+ const baseRadius = radius * 0.65;
777
+ const adjustedRadius = index === actions.length - 1 ? baseRadius * 0.8 : baseRadius;
778
+ translateX = adjustedRadius * Math.cos(angle);
779
+ translateY = adjustedRadius * Math.sin(angle);
780
+ }
781
+ const animStyle = {
782
+ transform: [
798
783
  {
799
- style: [
800
- defaultStyles4.secondary,
801
- styles2?.secondaryButton,
802
- { backgroundColor: action.color || "#F02A4B" },
803
- animStyle
804
- ],
805
- children: renderItemIcon?.({
806
- name: action.icon,
807
- size: 20,
808
- color: action.iconColor || "#FFF"
784
+ translateX: animation.interpolate({
785
+ inputRange: [0, 1],
786
+ outputRange: [0, translateX]
787
+ })
788
+ },
789
+ {
790
+ translateY: animation.interpolate({
791
+ inputRange: [0, 1],
792
+ outputRange: [0, translateY]
793
+ })
794
+ },
795
+ {
796
+ scale: animation.interpolate({
797
+ inputRange: [0, 0.5, 1],
798
+ outputRange: [0, 1.2, 1]
809
799
  })
810
800
  }
811
- )
812
- },
813
- index
814
- );
815
- };
816
- render() {
817
- const { actions, renderMainIcon, styles: styles2, style, mainIconName } = this.props;
801
+ ],
802
+ opacity: animation
803
+ };
804
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
805
+ import_react_native5.TouchableWithoutFeedback,
806
+ {
807
+ onPress: () => {
808
+ toggleMenu();
809
+ action.onPress?.();
810
+ action.navigateTo?.();
811
+ },
812
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
813
+ import_react_native5.Animated.View,
814
+ {
815
+ style: [
816
+ defaultStyles4.secondary,
817
+ customStyles?.secondaryButton,
818
+ { backgroundColor: action.color || "#F02A4B" },
819
+ animStyle
820
+ ],
821
+ children: renderItemIcon?.({
822
+ name: action.icon,
823
+ size: 20,
824
+ color: action.iconColor || "#FFF"
825
+ })
826
+ }
827
+ )
828
+ },
829
+ index
830
+ );
831
+ };
818
832
  const rotation = {
819
833
  transform: [
820
834
  {
821
- rotate: this.animation.interpolate({
835
+ rotate: animation.interpolate({
822
836
  inputRange: [0, 1],
823
837
  outputRange: ["0deg", "45deg"]
824
838
  })
@@ -828,42 +842,41 @@ var FloatingButton = class extends import_react4.default.Component {
828
842
  const scale = {
829
843
  transform: [
830
844
  {
831
- scale: this.animation.interpolate({
845
+ scale: animation.interpolate({
832
846
  inputRange: [0, 0.5, 1],
833
847
  outputRange: [1, 1.1, 1]
834
848
  })
835
849
  }
836
850
  ]
837
851
  };
838
- const mainIcon = mainIconName || "add";
839
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native5.View, { style: [defaultStyles4.container, styles2?.container, style], children: [
852
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native5.View, { style: [defaultStyles4.container, customStyles?.container, style], children: [
840
853
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
841
854
  import_react_native5.Animated.View,
842
855
  {
843
856
  style: [
844
857
  defaultStyles4.circleContainer,
845
- styles2?.circleContainer,
858
+ customStyles?.circleContainer,
846
859
  {
847
860
  transform: [
848
861
  {
849
- scale: this.animation.interpolate({
862
+ scale: animation.interpolate({
850
863
  inputRange: [0, 1],
851
864
  outputRange: [0, 1]
852
865
  })
853
866
  }
854
867
  ],
855
- opacity: this.animation
868
+ opacity: animation
856
869
  }
857
870
  ],
858
- children: actions.map(this.renderAction)
871
+ children: actions.map(renderAction)
859
872
  }
860
873
  ),
861
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native5.TouchableWithoutFeedback, { onPress: this.toggleMenu, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
874
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native5.TouchableWithoutFeedback, { onPress: toggleMenu, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
862
875
  import_react_native5.Animated.View,
863
876
  {
864
877
  style: [defaultStyles4.mainButtonWrapper, rotation, scale],
865
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native5.View, { style: [defaultStyles4.button, styles2?.mainButton], children: renderMainIcon?.({
866
- name: mainIcon,
878
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native5.View, { style: [defaultStyles4.button, customStyles?.mainButton], children: renderMainIcon?.({
879
+ name: mainIconName,
867
880
  size: 26,
868
881
  color: "#FFF"
869
882
  }) })
@@ -871,7 +884,7 @@ var FloatingButton = class extends import_react4.default.Component {
871
884
  ) })
872
885
  ] });
873
886
  }
874
- };
887
+ );
875
888
  var defaultStyles4 = import_react_native5.StyleSheet.create({
876
889
  container: {
877
890
  position: "absolute",
@@ -888,10 +901,7 @@ var defaultStyles4 = import_react_native5.StyleSheet.create({
888
901
  alignItems: "center",
889
902
  justifyContent: "center",
890
903
  shadowColor: "#000",
891
- shadowOffset: {
892
- width: 0,
893
- height: 2
894
- },
904
+ shadowOffset: { width: 0, height: 2 },
895
905
  shadowOpacity: 0.25,
896
906
  shadowRadius: 3.84,
897
907
  elevation: 5
@@ -922,15 +932,13 @@ var defaultStyles4 = import_react_native5.StyleSheet.create({
922
932
  alignItems: "center",
923
933
  justifyContent: "center",
924
934
  shadowColor: "#000",
925
- shadowOffset: {
926
- width: 0,
927
- height: 2
928
- },
935
+ shadowOffset: { width: 0, height: 2 },
929
936
  shadowOpacity: 0.25,
930
937
  shadowRadius: 3.84,
931
938
  elevation: 5
932
939
  }
933
940
  });
941
+ var FloatingButton_default = FloatingButton;
934
942
 
935
943
  // src/utils/groupOptions.ts
936
944
  var groupOptions = (options, config) => {
package/dist/index.mjs CHANGED
@@ -697,7 +697,13 @@ var defaultStyles3 = StyleSheet4.create({
697
697
  });
698
698
 
699
699
  // src/core/FloatingButton.tsx
700
- import React4 from "react";
700
+ import {
701
+ forwardRef,
702
+ useImperativeHandle,
703
+ useRef as useRef3,
704
+ useState as useState4,
705
+ useEffect as useEffect4
706
+ } from "react";
701
707
  import {
702
708
  Animated as Animated3,
703
709
  StyleSheet as StyleSheet5,
@@ -705,104 +711,128 @@ import {
705
711
  View as View5
706
712
  } from "react-native";
707
713
  import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
708
- var FloatingButton = class extends React4.Component {
709
- animation = new Animated3.Value(0);
710
- open = false;
711
- toggleMenu = () => {
712
- Animated3.spring(this.animation, {
713
- toValue: this.open ? 0 : 1,
714
- useNativeDriver: true,
715
- damping: 12,
716
- mass: 0.6,
717
- stiffness: 180
718
- }).start();
719
- this.open = !this.open;
720
- };
721
- renderAction = (action, index) => {
714
+ var FloatingButton = forwardRef(
715
+ (props, ref) => {
722
716
  const {
717
+ actions,
723
718
  mode = "vertical",
724
719
  radius = 100,
725
- actions,
720
+ renderMainIcon,
726
721
  renderItemIcon,
727
- styles: styles2
728
- } = this.props;
729
- let translateX = 0;
730
- let translateY = 0;
731
- if (mode === "vertical") {
732
- translateY = -60 * (index + 1);
733
- translateX = 0;
734
- }
735
- if (mode === "horizontal") {
736
- translateX = -60 * (index + 1);
737
- translateY = 0;
738
- }
739
- if (mode === "circle") {
740
- const totalActions = actions.length;
741
- const startAngle = -Math.PI / 3;
742
- const endAngle = -Math.PI * 0.8;
743
- const angle = startAngle + index / (totalActions - 1 || 1) * (endAngle - startAngle);
744
- const baseRadius = radius * 0.65;
745
- const adjustedRadius = index === actions.length - 1 ? baseRadius * 0.8 : baseRadius;
746
- translateX = adjustedRadius * Math.cos(angle);
747
- translateY = adjustedRadius * Math.sin(angle);
748
- }
749
- const animStyle = {
750
- transform: [
751
- {
752
- translateX: this.animation.interpolate({
753
- inputRange: [0, 1],
754
- outputRange: [0, translateX]
755
- })
756
- },
757
- {
758
- translateY: this.animation.interpolate({
759
- inputRange: [0, 1],
760
- outputRange: [0, translateY]
761
- })
762
- },
763
- {
764
- scale: this.animation.interpolate({
765
- inputRange: [0, 0.5, 1],
766
- outputRange: [0, 1.2, 1]
767
- })
768
- }
769
- ],
770
- opacity: this.animation
722
+ styles: customStyles,
723
+ style,
724
+ mainIconName = "add",
725
+ open: controlledOpen,
726
+ onToggle,
727
+ animationConfig = {}
728
+ } = props;
729
+ const animation = useRef3(new Animated3.Value(0)).current;
730
+ const [internalOpen, setInternalOpen] = useState4(false);
731
+ const isOpen = controlledOpen !== void 0 ? controlledOpen : internalOpen;
732
+ useEffect4(() => {
733
+ Animated3.spring(animation, {
734
+ toValue: isOpen ? 1 : 0,
735
+ useNativeDriver: true,
736
+ damping: 12,
737
+ mass: 0.6,
738
+ stiffness: 180,
739
+ ...animationConfig
740
+ }).start();
741
+ }, [isOpen, animation, animationConfig]);
742
+ useImperativeHandle(ref, () => ({
743
+ openMenu: () => {
744
+ if (controlledOpen === void 0) setInternalOpen(true);
745
+ onToggle?.(true);
746
+ },
747
+ closeMenu: () => {
748
+ if (controlledOpen === void 0) setInternalOpen(false);
749
+ onToggle?.(false);
750
+ },
751
+ toggleMenu: () => {
752
+ const newState = !isOpen;
753
+ if (controlledOpen === void 0) setInternalOpen(newState);
754
+ onToggle?.(newState);
755
+ }
756
+ }));
757
+ const toggleMenu = () => {
758
+ const newState = !isOpen;
759
+ if (controlledOpen === void 0) setInternalOpen(newState);
760
+ onToggle?.(newState);
771
761
  };
772
- return /* @__PURE__ */ jsx5(
773
- TouchableWithoutFeedback,
774
- {
775
- onPress: () => {
776
- this.toggleMenu();
777
- action.onPress?.();
778
- action.navigateTo?.();
779
- },
780
- children: /* @__PURE__ */ jsx5(
781
- Animated3.View,
762
+ const renderAction = (action, index) => {
763
+ let translateX = 0;
764
+ let translateY = 0;
765
+ if (mode === "vertical") {
766
+ translateY = -60 * (index + 1);
767
+ translateX = 0;
768
+ } else if (mode === "horizontal") {
769
+ translateX = -60 * (index + 1);
770
+ translateY = 0;
771
+ } else if (mode === "circle") {
772
+ const totalActions = actions.length;
773
+ const startAngle = -Math.PI / 3;
774
+ const endAngle = -Math.PI * 0.8;
775
+ const angle = startAngle + index / (totalActions - 1 || 1) * (endAngle - startAngle);
776
+ const baseRadius = radius * 0.65;
777
+ const adjustedRadius = index === actions.length - 1 ? baseRadius * 0.8 : baseRadius;
778
+ translateX = adjustedRadius * Math.cos(angle);
779
+ translateY = adjustedRadius * Math.sin(angle);
780
+ }
781
+ const animStyle = {
782
+ transform: [
782
783
  {
783
- style: [
784
- defaultStyles4.secondary,
785
- styles2?.secondaryButton,
786
- { backgroundColor: action.color || "#F02A4B" },
787
- animStyle
788
- ],
789
- children: renderItemIcon?.({
790
- name: action.icon,
791
- size: 20,
792
- color: action.iconColor || "#FFF"
784
+ translateX: animation.interpolate({
785
+ inputRange: [0, 1],
786
+ outputRange: [0, translateX]
787
+ })
788
+ },
789
+ {
790
+ translateY: animation.interpolate({
791
+ inputRange: [0, 1],
792
+ outputRange: [0, translateY]
793
+ })
794
+ },
795
+ {
796
+ scale: animation.interpolate({
797
+ inputRange: [0, 0.5, 1],
798
+ outputRange: [0, 1.2, 1]
793
799
  })
794
800
  }
795
- )
796
- },
797
- index
798
- );
799
- };
800
- render() {
801
- const { actions, renderMainIcon, styles: styles2, style, mainIconName } = this.props;
801
+ ],
802
+ opacity: animation
803
+ };
804
+ return /* @__PURE__ */ jsx5(
805
+ TouchableWithoutFeedback,
806
+ {
807
+ onPress: () => {
808
+ toggleMenu();
809
+ action.onPress?.();
810
+ action.navigateTo?.();
811
+ },
812
+ children: /* @__PURE__ */ jsx5(
813
+ Animated3.View,
814
+ {
815
+ style: [
816
+ defaultStyles4.secondary,
817
+ customStyles?.secondaryButton,
818
+ { backgroundColor: action.color || "#F02A4B" },
819
+ animStyle
820
+ ],
821
+ children: renderItemIcon?.({
822
+ name: action.icon,
823
+ size: 20,
824
+ color: action.iconColor || "#FFF"
825
+ })
826
+ }
827
+ )
828
+ },
829
+ index
830
+ );
831
+ };
802
832
  const rotation = {
803
833
  transform: [
804
834
  {
805
- rotate: this.animation.interpolate({
835
+ rotate: animation.interpolate({
806
836
  inputRange: [0, 1],
807
837
  outputRange: ["0deg", "45deg"]
808
838
  })
@@ -812,42 +842,41 @@ var FloatingButton = class extends React4.Component {
812
842
  const scale = {
813
843
  transform: [
814
844
  {
815
- scale: this.animation.interpolate({
845
+ scale: animation.interpolate({
816
846
  inputRange: [0, 0.5, 1],
817
847
  outputRange: [1, 1.1, 1]
818
848
  })
819
849
  }
820
850
  ]
821
851
  };
822
- const mainIcon = mainIconName || "add";
823
- return /* @__PURE__ */ jsxs5(View5, { style: [defaultStyles4.container, styles2?.container, style], children: [
852
+ return /* @__PURE__ */ jsxs5(View5, { style: [defaultStyles4.container, customStyles?.container, style], children: [
824
853
  /* @__PURE__ */ jsx5(
825
854
  Animated3.View,
826
855
  {
827
856
  style: [
828
857
  defaultStyles4.circleContainer,
829
- styles2?.circleContainer,
858
+ customStyles?.circleContainer,
830
859
  {
831
860
  transform: [
832
861
  {
833
- scale: this.animation.interpolate({
862
+ scale: animation.interpolate({
834
863
  inputRange: [0, 1],
835
864
  outputRange: [0, 1]
836
865
  })
837
866
  }
838
867
  ],
839
- opacity: this.animation
868
+ opacity: animation
840
869
  }
841
870
  ],
842
- children: actions.map(this.renderAction)
871
+ children: actions.map(renderAction)
843
872
  }
844
873
  ),
845
- /* @__PURE__ */ jsx5(TouchableWithoutFeedback, { onPress: this.toggleMenu, children: /* @__PURE__ */ jsx5(
874
+ /* @__PURE__ */ jsx5(TouchableWithoutFeedback, { onPress: toggleMenu, children: /* @__PURE__ */ jsx5(
846
875
  Animated3.View,
847
876
  {
848
877
  style: [defaultStyles4.mainButtonWrapper, rotation, scale],
849
- children: /* @__PURE__ */ jsx5(View5, { style: [defaultStyles4.button, styles2?.mainButton], children: renderMainIcon?.({
850
- name: mainIcon,
878
+ children: /* @__PURE__ */ jsx5(View5, { style: [defaultStyles4.button, customStyles?.mainButton], children: renderMainIcon?.({
879
+ name: mainIconName,
851
880
  size: 26,
852
881
  color: "#FFF"
853
882
  }) })
@@ -855,7 +884,7 @@ var FloatingButton = class extends React4.Component {
855
884
  ) })
856
885
  ] });
857
886
  }
858
- };
887
+ );
859
888
  var defaultStyles4 = StyleSheet5.create({
860
889
  container: {
861
890
  position: "absolute",
@@ -872,10 +901,7 @@ var defaultStyles4 = StyleSheet5.create({
872
901
  alignItems: "center",
873
902
  justifyContent: "center",
874
903
  shadowColor: "#000",
875
- shadowOffset: {
876
- width: 0,
877
- height: 2
878
- },
904
+ shadowOffset: { width: 0, height: 2 },
879
905
  shadowOpacity: 0.25,
880
906
  shadowRadius: 3.84,
881
907
  elevation: 5
@@ -906,15 +932,13 @@ var defaultStyles4 = StyleSheet5.create({
906
932
  alignItems: "center",
907
933
  justifyContent: "center",
908
934
  shadowColor: "#000",
909
- shadowOffset: {
910
- width: 0,
911
- height: 2
912
- },
935
+ shadowOffset: { width: 0, height: 2 },
913
936
  shadowOpacity: 0.25,
914
937
  shadowRadius: 3.84,
915
938
  elevation: 5
916
939
  }
917
940
  });
941
+ var FloatingButton_default = FloatingButton;
918
942
 
919
943
  // src/utils/groupOptions.ts
920
944
  var groupOptions = (options, config) => {
@@ -924,7 +948,7 @@ var groupOptions = (options, config) => {
924
948
  })).filter((g) => g.data.length > 0);
925
949
  };
926
950
  export {
927
- FloatingButton,
951
+ FloatingButton_default as FloatingButton,
928
952
  MultiPickerGroup,
929
953
  MultiPickerItem,
930
954
  MultiPickerModal,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kaushverse/pickify",
3
- "version": "1.2.6",
3
+ "version": "1.2.7",
4
4
  "description": "A fully customizable React Native picker with search, multi-select, grouping, and async support.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",