@kaushverse/pickify 1.2.5 → 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,106 +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 adjustedRadius = radius * 0.65;
761
- translateX = adjustedRadius * Math.cos(angle);
762
- translateY = adjustedRadius * Math.sin(angle);
763
- }
764
- const animStyle = {
765
- transform: [
766
- {
767
- translateX: this.animation.interpolate({
768
- inputRange: [0, 1],
769
- outputRange: [0, translateX]
770
- })
771
- },
772
- {
773
- translateY: this.animation.interpolate({
774
- inputRange: [0, 1],
775
- outputRange: [0, translateY]
776
- })
777
- },
778
- {
779
- scale: this.animation.interpolate({
780
- inputRange: [0, 0.5, 1],
781
- outputRange: [0, 1.2, 1]
782
- })
783
- }
784
- ],
785
- 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);
786
761
  };
787
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
788
- import_react_native5.TouchableWithoutFeedback,
789
- {
790
- onPress: () => {
791
- this.toggleMenu();
792
- action.onPress?.();
793
- action.navigateTo?.();
794
- },
795
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
796
- 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: [
797
783
  {
798
- style: [
799
- defaultStyles4.secondary,
800
- styles2?.secondaryButton,
801
- { backgroundColor: action.color || "#F02A4B" },
802
- animStyle
803
- ],
804
- children: renderItemIcon?.({
805
- name: action.icon,
806
- size: 20,
807
- 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]
808
799
  })
809
800
  }
810
- )
811
- },
812
- index
813
- );
814
- };
815
- render() {
816
- 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
+ };
817
832
  const rotation = {
818
833
  transform: [
819
834
  {
820
- rotate: this.animation.interpolate({
835
+ rotate: animation.interpolate({
821
836
  inputRange: [0, 1],
822
837
  outputRange: ["0deg", "45deg"]
823
838
  })
@@ -827,42 +842,41 @@ var FloatingButton = class extends import_react4.default.Component {
827
842
  const scale = {
828
843
  transform: [
829
844
  {
830
- scale: this.animation.interpolate({
845
+ scale: animation.interpolate({
831
846
  inputRange: [0, 0.5, 1],
832
847
  outputRange: [1, 1.1, 1]
833
848
  })
834
849
  }
835
850
  ]
836
851
  };
837
- const mainIcon = mainIconName || "add";
838
- 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: [
839
853
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
840
854
  import_react_native5.Animated.View,
841
855
  {
842
856
  style: [
843
857
  defaultStyles4.circleContainer,
844
- styles2?.circleContainer,
858
+ customStyles?.circleContainer,
845
859
  {
846
860
  transform: [
847
861
  {
848
- scale: this.animation.interpolate({
862
+ scale: animation.interpolate({
849
863
  inputRange: [0, 1],
850
864
  outputRange: [0, 1]
851
865
  })
852
866
  }
853
867
  ],
854
- opacity: this.animation
868
+ opacity: animation
855
869
  }
856
870
  ],
857
- children: actions.map(this.renderAction)
871
+ children: actions.map(renderAction)
858
872
  }
859
873
  ),
860
- /* @__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)(
861
875
  import_react_native5.Animated.View,
862
876
  {
863
877
  style: [defaultStyles4.mainButtonWrapper, rotation, scale],
864
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native5.View, { style: [defaultStyles4.button, styles2?.mainButton], children: renderMainIcon?.({
865
- name: mainIcon,
878
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native5.View, { style: [defaultStyles4.button, customStyles?.mainButton], children: renderMainIcon?.({
879
+ name: mainIconName,
866
880
  size: 26,
867
881
  color: "#FFF"
868
882
  }) })
@@ -870,7 +884,7 @@ var FloatingButton = class extends import_react4.default.Component {
870
884
  ) })
871
885
  ] });
872
886
  }
873
- };
887
+ );
874
888
  var defaultStyles4 = import_react_native5.StyleSheet.create({
875
889
  container: {
876
890
  position: "absolute",
@@ -887,10 +901,7 @@ var defaultStyles4 = import_react_native5.StyleSheet.create({
887
901
  alignItems: "center",
888
902
  justifyContent: "center",
889
903
  shadowColor: "#000",
890
- shadowOffset: {
891
- width: 0,
892
- height: 2
893
- },
904
+ shadowOffset: { width: 0, height: 2 },
894
905
  shadowOpacity: 0.25,
895
906
  shadowRadius: 3.84,
896
907
  elevation: 5
@@ -921,15 +932,13 @@ var defaultStyles4 = import_react_native5.StyleSheet.create({
921
932
  alignItems: "center",
922
933
  justifyContent: "center",
923
934
  shadowColor: "#000",
924
- shadowOffset: {
925
- width: 0,
926
- height: 2
927
- },
935
+ shadowOffset: { width: 0, height: 2 },
928
936
  shadowOpacity: 0.25,
929
937
  shadowRadius: 3.84,
930
938
  elevation: 5
931
939
  }
932
940
  });
941
+ var FloatingButton_default = FloatingButton;
933
942
 
934
943
  // src/utils/groupOptions.ts
935
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,103 +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 adjustedRadius = radius * 0.65;
745
- translateX = adjustedRadius * Math.cos(angle);
746
- translateY = adjustedRadius * Math.sin(angle);
747
- }
748
- const animStyle = {
749
- transform: [
750
- {
751
- translateX: this.animation.interpolate({
752
- inputRange: [0, 1],
753
- outputRange: [0, translateX]
754
- })
755
- },
756
- {
757
- translateY: this.animation.interpolate({
758
- inputRange: [0, 1],
759
- outputRange: [0, translateY]
760
- })
761
- },
762
- {
763
- scale: this.animation.interpolate({
764
- inputRange: [0, 0.5, 1],
765
- outputRange: [0, 1.2, 1]
766
- })
767
- }
768
- ],
769
- 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);
770
761
  };
771
- return /* @__PURE__ */ jsx5(
772
- TouchableWithoutFeedback,
773
- {
774
- onPress: () => {
775
- this.toggleMenu();
776
- action.onPress?.();
777
- action.navigateTo?.();
778
- },
779
- children: /* @__PURE__ */ jsx5(
780
- 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: [
781
783
  {
782
- style: [
783
- defaultStyles4.secondary,
784
- styles2?.secondaryButton,
785
- { backgroundColor: action.color || "#F02A4B" },
786
- animStyle
787
- ],
788
- children: renderItemIcon?.({
789
- name: action.icon,
790
- size: 20,
791
- 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]
792
799
  })
793
800
  }
794
- )
795
- },
796
- index
797
- );
798
- };
799
- render() {
800
- 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
+ };
801
832
  const rotation = {
802
833
  transform: [
803
834
  {
804
- rotate: this.animation.interpolate({
835
+ rotate: animation.interpolate({
805
836
  inputRange: [0, 1],
806
837
  outputRange: ["0deg", "45deg"]
807
838
  })
@@ -811,42 +842,41 @@ var FloatingButton = class extends React4.Component {
811
842
  const scale = {
812
843
  transform: [
813
844
  {
814
- scale: this.animation.interpolate({
845
+ scale: animation.interpolate({
815
846
  inputRange: [0, 0.5, 1],
816
847
  outputRange: [1, 1.1, 1]
817
848
  })
818
849
  }
819
850
  ]
820
851
  };
821
- const mainIcon = mainIconName || "add";
822
- return /* @__PURE__ */ jsxs5(View5, { style: [defaultStyles4.container, styles2?.container, style], children: [
852
+ return /* @__PURE__ */ jsxs5(View5, { style: [defaultStyles4.container, customStyles?.container, style], children: [
823
853
  /* @__PURE__ */ jsx5(
824
854
  Animated3.View,
825
855
  {
826
856
  style: [
827
857
  defaultStyles4.circleContainer,
828
- styles2?.circleContainer,
858
+ customStyles?.circleContainer,
829
859
  {
830
860
  transform: [
831
861
  {
832
- scale: this.animation.interpolate({
862
+ scale: animation.interpolate({
833
863
  inputRange: [0, 1],
834
864
  outputRange: [0, 1]
835
865
  })
836
866
  }
837
867
  ],
838
- opacity: this.animation
868
+ opacity: animation
839
869
  }
840
870
  ],
841
- children: actions.map(this.renderAction)
871
+ children: actions.map(renderAction)
842
872
  }
843
873
  ),
844
- /* @__PURE__ */ jsx5(TouchableWithoutFeedback, { onPress: this.toggleMenu, children: /* @__PURE__ */ jsx5(
874
+ /* @__PURE__ */ jsx5(TouchableWithoutFeedback, { onPress: toggleMenu, children: /* @__PURE__ */ jsx5(
845
875
  Animated3.View,
846
876
  {
847
877
  style: [defaultStyles4.mainButtonWrapper, rotation, scale],
848
- children: /* @__PURE__ */ jsx5(View5, { style: [defaultStyles4.button, styles2?.mainButton], children: renderMainIcon?.({
849
- name: mainIcon,
878
+ children: /* @__PURE__ */ jsx5(View5, { style: [defaultStyles4.button, customStyles?.mainButton], children: renderMainIcon?.({
879
+ name: mainIconName,
850
880
  size: 26,
851
881
  color: "#FFF"
852
882
  }) })
@@ -854,7 +884,7 @@ var FloatingButton = class extends React4.Component {
854
884
  ) })
855
885
  ] });
856
886
  }
857
- };
887
+ );
858
888
  var defaultStyles4 = StyleSheet5.create({
859
889
  container: {
860
890
  position: "absolute",
@@ -871,10 +901,7 @@ var defaultStyles4 = StyleSheet5.create({
871
901
  alignItems: "center",
872
902
  justifyContent: "center",
873
903
  shadowColor: "#000",
874
- shadowOffset: {
875
- width: 0,
876
- height: 2
877
- },
904
+ shadowOffset: { width: 0, height: 2 },
878
905
  shadowOpacity: 0.25,
879
906
  shadowRadius: 3.84,
880
907
  elevation: 5
@@ -905,15 +932,13 @@ var defaultStyles4 = StyleSheet5.create({
905
932
  alignItems: "center",
906
933
  justifyContent: "center",
907
934
  shadowColor: "#000",
908
- shadowOffset: {
909
- width: 0,
910
- height: 2
911
- },
935
+ shadowOffset: { width: 0, height: 2 },
912
936
  shadowOpacity: 0.25,
913
937
  shadowRadius: 3.84,
914
938
  elevation: 5
915
939
  }
916
940
  });
941
+ var FloatingButton_default = FloatingButton;
917
942
 
918
943
  // src/utils/groupOptions.ts
919
944
  var groupOptions = (options, config) => {
@@ -923,7 +948,7 @@ var groupOptions = (options, config) => {
923
948
  })).filter((g) => g.data.length > 0);
924
949
  };
925
950
  export {
926
- FloatingButton,
951
+ FloatingButton_default as FloatingButton,
927
952
  MultiPickerGroup,
928
953
  MultiPickerItem,
929
954
  MultiPickerModal,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kaushverse/pickify",
3
- "version": "1.2.5",
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",