@korsolutions/ui 0.0.19 → 0.0.21
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/index.d.mts +73 -4
- package/dist/components/index.mjs +156 -8
- package/dist/hooks/index.d.mts +32 -2
- package/dist/hooks/index.mjs +79 -2
- package/dist/{index-BLsiF42Z.d.mts → index-pCM7YTs1.d.mts} +165 -9
- package/dist/index.d.mts +3 -3
- package/dist/index.mjs +3 -2
- package/dist/primitives/index.d.mts +3 -2
- package/dist/primitives/index.mjs +3 -2
- package/dist/{primitives-CyDqzNcp.mjs → primitives-DNeYBN-3.mjs} +330 -12
- package/dist/{toast-manager-BOORCQn8.mjs → toast-manager-BfoJ-_dB.mjs} +1 -1
- package/dist/use-numeric-mask-B9WZG25o.d.mts +33 -0
- package/dist/use-numeric-mask-BQlz1Pus.mjs +113 -0
- package/dist/use-relative-position-BTKEyT1F.mjs +106 -0
- package/dist/use-relative-position-DBzhrBU7.d.mts +61 -0
- package/package.json +1 -1
- package/src/components/button/button.tsx +7 -4
- package/src/components/dropdown-menu/dropdown-menu.tsx +49 -0
- package/src/components/dropdown-menu/variants/default.tsx +40 -0
- package/src/components/dropdown-menu/variants/index.ts +5 -0
- package/src/components/index.ts +3 -1
- package/src/components/input/index.ts +2 -0
- package/src/components/input/numeric-input.tsx +73 -0
- package/src/components/popover/popover.tsx +51 -0
- package/src/components/popover/variants/default.tsx +26 -0
- package/src/components/popover/variants/index.ts +5 -0
- package/src/hooks/index.ts +4 -1
- package/src/hooks/use-currency-mask.ts +141 -0
- package/src/hooks/use-numeric-mask.ts +202 -0
- package/src/hooks/use-relative-position.ts +188 -0
- package/src/primitives/button/button-root.tsx +2 -4
- package/src/primitives/dropdown-menu/context.ts +25 -0
- package/src/primitives/dropdown-menu/dropdown-menu-button.tsx +47 -0
- package/src/primitives/dropdown-menu/dropdown-menu-content.tsx +39 -0
- package/src/primitives/dropdown-menu/dropdown-menu-divider.tsx +18 -0
- package/src/primitives/dropdown-menu/dropdown-menu-overlay.tsx +29 -0
- package/src/primitives/dropdown-menu/dropdown-menu-portal.tsx +21 -0
- package/src/primitives/dropdown-menu/dropdown-menu-root.tsx +35 -0
- package/src/primitives/dropdown-menu/dropdown-menu-trigger.tsx +47 -0
- package/src/primitives/dropdown-menu/index.ts +26 -0
- package/src/primitives/dropdown-menu/types.ts +13 -0
- package/src/primitives/index.ts +2 -0
- package/src/primitives/popover/context.ts +25 -0
- package/src/primitives/popover/index.ts +24 -0
- package/src/primitives/popover/popover-close.tsx +29 -0
- package/src/primitives/popover/popover-content.tsx +39 -0
- package/src/primitives/popover/popover-overlay.tsx +37 -0
- package/src/primitives/popover/popover-portal.tsx +21 -0
- package/src/primitives/popover/popover-root.tsx +35 -0
- package/src/primitives/popover/popover-trigger.tsx +47 -0
- package/src/primitives/popover/types.ts +7 -0
- package/src/utils/get-ref-layout.ts +16 -0
- /package/src/hooks/{useScreenSize.ts → use-screen-size.ts} +0 -0
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
import { $ as
|
|
2
|
-
|
|
1
|
+
import { $ as SelectPortalProps, A as ToastRootProps, B as EmptyRootProps, C as TextareaPrimitiveProps, D as BadgeStyles, E as BadgeRootProps, F as AvatarRootProps, G as CardPrimitive, H as EmptyTitleProps, I as AvatarStyles, J as CardFooterProps, K as CardRootProps, L as AvatarImageProps, M as ToastDescriptionProps, N as ToastTitleProps, O as BadgeLabelProps, P as AvatarPrimitive, Q as SelectPrimitive, R as AvatarFallbackProps, S as TextareaPrimitiveBaseProps, St as FieldLabelProps, T as BadgePrimitive, U as EmptyMediaProps, V as EmptyStyles, W as EmptyDescriptionProps, X as CardTitleProps, Y as CardBodyProps, Z as CardHeaderProps, _ as DropdownMenuDividerProps, _t as FieldPrimitive, a as PopoverPortalProps, at as SelectOverlayProps, b as DropdownMenuTriggerProps, bt as FieldErrorProps, c as PopoverOverlayProps, ct as ButtonPrimitive, d as PopoverTriggerRef, dt as ButtonStyles, et as SelectRootBaseProps, f as DropdownMenuPrimitive, ft as ButtonPrimitiveLabelProps, g as DropdownMenuOverlayProps, gt as InputStyles, h as DropdownMenuStyles, ht as InputPrimitiveProps, i as PopoverCloseProps, it as SelectContentProps, j as ToastStyles, k as ToastPrimitive, l as PopoverContentProps, lt as ButtonPrimitiveRootProps, m as DropdownMenuRootProps, mt as InputPrimitiveBaseProps, n as PopoverContext, nt as SelectStyles, o as PopoverRootProps, ot as SelectValueProps, p as DropdownMenuPortalProps, pt as InputPrimitive, q as CardStyles, r as usePopover, rt as SelectOptionProps, st as SelectTriggerProps, t as PopoverPrimitive, tt as SelectRootProps, u as PopoverTriggerProps, ut as ButtonState, v as DropdownMenuButtonProps, vt as FieldPrimitiveRootProps, w as TextareaStyles, x as TextareaPrimitive, xt as FieldDescriptionProps, y as DropdownMenuContentProps, yt as FieldStyles, z as EmptyPrimitive } from "../index-pCM7YTs1.mjs";
|
|
2
|
+
import "../use-relative-position-DBzhrBU7.mjs";
|
|
3
|
+
export { AvatarFallbackProps, AvatarImageProps, AvatarPrimitive, AvatarRootProps, AvatarStyles, BadgeLabelProps, BadgePrimitive, BadgeRootProps, BadgeStyles, ButtonPrimitive, ButtonPrimitiveLabelProps, ButtonPrimitiveRootProps, ButtonState, ButtonStyles, CardBodyProps, CardFooterProps, CardHeaderProps, CardPrimitive, CardRootProps, CardStyles, CardTitleProps, DropdownMenuButtonProps, DropdownMenuContentProps, DropdownMenuDividerProps, DropdownMenuOverlayProps, DropdownMenuPortalProps, DropdownMenuPrimitive, DropdownMenuRootProps, DropdownMenuStyles, DropdownMenuTriggerProps, EmptyDescriptionProps, EmptyMediaProps, EmptyPrimitive, EmptyRootProps, EmptyStyles, EmptyTitleProps, FieldDescriptionProps, FieldErrorProps, FieldLabelProps, FieldPrimitive, FieldPrimitiveRootProps, FieldStyles, InputPrimitive, InputPrimitiveBaseProps, InputPrimitiveProps, InputStyles, PopoverCloseProps, PopoverContentProps, PopoverContext, PopoverOverlayProps, PopoverPortalProps, PopoverPrimitive, PopoverRootProps, PopoverTriggerProps, PopoverTriggerRef, SelectContentProps, SelectOptionProps, SelectOverlayProps, SelectPortalProps, SelectPrimitive, SelectRootBaseProps, SelectRootProps, SelectStyles, SelectTriggerProps, SelectValueProps, TextareaPrimitive, TextareaPrimitiveBaseProps, TextareaPrimitiveProps, TextareaStyles, ToastDescriptionProps, ToastPrimitive, ToastRootProps, ToastStyles, ToastTitleProps, usePopover };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { a as BadgePrimitive, c as EmptyPrimitive, d as ButtonPrimitive, f as InputPrimitive, i as TextareaPrimitive, l as CardPrimitive, n as usePopover, o as ToastPrimitive, p as FieldPrimitive, r as DropdownMenuPrimitive, s as AvatarPrimitive, t as PopoverPrimitive, u as SelectPrimitive } from "../primitives-DNeYBN-3.mjs";
|
|
2
|
+
import "../use-relative-position-BTKEyT1F.mjs";
|
|
2
3
|
|
|
3
|
-
export { AvatarPrimitive, BadgePrimitive, ButtonPrimitive, CardPrimitive, EmptyPrimitive, FieldPrimitive, InputPrimitive, SelectPrimitive, TextareaPrimitive, ToastPrimitive };
|
|
4
|
+
export { AvatarPrimitive, BadgePrimitive, ButtonPrimitive, CardPrimitive, DropdownMenuPrimitive, EmptyPrimitive, FieldPrimitive, InputPrimitive, PopoverPrimitive, SelectPrimitive, TextareaPrimitive, ToastPrimitive, usePopover };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { n as DEFAULT_POSITION, r as useRelativePosition, t as DEFAULT_LAYOUT } from "./use-relative-position-BTKEyT1F.mjs";
|
|
2
|
+
import React, { createContext, forwardRef, useCallback, useContext, useEffect, useImperativeHandle, useRef, useState, useSyncExternalStore } from "react";
|
|
2
3
|
import { ActivityIndicator, Image, Pressable, StyleSheet, Text, TextInput, View } from "react-native";
|
|
3
4
|
import { Fragment, jsx } from "react/jsx-runtime";
|
|
4
5
|
|
|
@@ -122,14 +123,14 @@ const FieldPrimitive = {
|
|
|
122
123
|
|
|
123
124
|
//#endregion
|
|
124
125
|
//#region src/primitives/input/input.tsx
|
|
125
|
-
const calculateState$
|
|
126
|
+
const calculateState$5 = (props, isFocused) => {
|
|
126
127
|
if (props.isDisabled) return "disabled";
|
|
127
128
|
if (isFocused) return "focused";
|
|
128
129
|
return "default";
|
|
129
130
|
};
|
|
130
131
|
function InputPrimitive(props) {
|
|
131
132
|
const [isFocused, setIsFocused] = useState(false);
|
|
132
|
-
const state = calculateState$
|
|
133
|
+
const state = calculateState$5(props, isFocused);
|
|
133
134
|
const composedStyles = [
|
|
134
135
|
props.styles?.default?.style,
|
|
135
136
|
props.styles?.[state]?.style,
|
|
@@ -168,7 +169,7 @@ const useButtonPrimitive = () => {
|
|
|
168
169
|
|
|
169
170
|
//#endregion
|
|
170
171
|
//#region src/primitives/button/button-root.tsx
|
|
171
|
-
const calculateState$
|
|
172
|
+
const calculateState$4 = (props, isHovered) => {
|
|
172
173
|
if (props.isDisabled) return "disabled";
|
|
173
174
|
if (props.isLoading) return "loading";
|
|
174
175
|
if (isHovered) return "hovered";
|
|
@@ -176,7 +177,7 @@ const calculateState$3 = (props, isHovered) => {
|
|
|
176
177
|
};
|
|
177
178
|
function ButtonRoot(props) {
|
|
178
179
|
const [isHovered, setIsHovered] = useState(false);
|
|
179
|
-
const state = calculateState$
|
|
180
|
+
const state = calculateState$4(props, isHovered);
|
|
180
181
|
const calculatedStyle = [
|
|
181
182
|
props.styles?.root?.default,
|
|
182
183
|
props.styles?.root?.[state],
|
|
@@ -246,7 +247,7 @@ const useSelect = () => {
|
|
|
246
247
|
|
|
247
248
|
//#endregion
|
|
248
249
|
//#region src/primitives/select/select-root.tsx
|
|
249
|
-
const calculateState$
|
|
250
|
+
const calculateState$3 = (props) => {
|
|
250
251
|
if (props.isDisabled) return "disabled";
|
|
251
252
|
return "default";
|
|
252
253
|
};
|
|
@@ -254,7 +255,7 @@ function SelectRoot(props) {
|
|
|
254
255
|
const [isOpen, setIsOpen] = useState(false);
|
|
255
256
|
const [triggerLayout, setTriggerLayout] = useState(null);
|
|
256
257
|
const [options, setOptions] = useState([]);
|
|
257
|
-
const state = calculateState$
|
|
258
|
+
const state = calculateState$3(props);
|
|
258
259
|
const composedStyles = calculateComposedStyles(props.styles, state, "root", props.style);
|
|
259
260
|
const Component = props.render ?? View;
|
|
260
261
|
return /* @__PURE__ */ jsx(SelectContext.Provider, {
|
|
@@ -370,7 +371,7 @@ function SelectContent(props) {
|
|
|
370
371
|
|
|
371
372
|
//#endregion
|
|
372
373
|
//#region src/primitives/select/select-option.tsx
|
|
373
|
-
const calculateState$
|
|
374
|
+
const calculateState$2 = (selectState, hovered, selected) => {
|
|
374
375
|
if (selectState === "disabled") return "disabled";
|
|
375
376
|
if (selected) return "selected";
|
|
376
377
|
if (hovered) return "hovered";
|
|
@@ -380,7 +381,7 @@ function SelectOption(props) {
|
|
|
380
381
|
const [isHovered, setIsHovered] = useState(false);
|
|
381
382
|
const select = useSelect();
|
|
382
383
|
const isSelected = select.value === props.value;
|
|
383
|
-
const optionState = calculateState$
|
|
384
|
+
const optionState = calculateState$2(select.state, isHovered, isSelected);
|
|
384
385
|
const composedStyles = calculateComposedStyles(select.styles, optionState, "option", props.style);
|
|
385
386
|
useEffect(() => {
|
|
386
387
|
select.setOptions((prev) => {
|
|
@@ -706,14 +707,14 @@ const BadgePrimitive = {
|
|
|
706
707
|
|
|
707
708
|
//#endregion
|
|
708
709
|
//#region src/primitives/textarea/textarea.tsx
|
|
709
|
-
const calculateState = (props, isFocused) => {
|
|
710
|
+
const calculateState$1 = (props, isFocused) => {
|
|
710
711
|
if (props.isDisabled) return "disabled";
|
|
711
712
|
if (isFocused) return "focused";
|
|
712
713
|
return "default";
|
|
713
714
|
};
|
|
714
715
|
function TextareaPrimitive(props) {
|
|
715
716
|
const [isFocused, setIsFocused] = useState(false);
|
|
716
|
-
const state = calculateState(props, isFocused);
|
|
717
|
+
const state = calculateState$1(props, isFocused);
|
|
717
718
|
const composedStyles = [
|
|
718
719
|
props.styles?.default?.style,
|
|
719
720
|
props.styles?.[state]?.style,
|
|
@@ -743,4 +744,321 @@ function TextareaPrimitive(props) {
|
|
|
743
744
|
}
|
|
744
745
|
|
|
745
746
|
//#endregion
|
|
746
|
-
|
|
747
|
+
//#region src/primitives/dropdown-menu/context.ts
|
|
748
|
+
const DropdownMenuContext = createContext(void 0);
|
|
749
|
+
const useDropdownMenu = () => {
|
|
750
|
+
const context = useContext(DropdownMenuContext);
|
|
751
|
+
if (!context) throw new Error("useDropdownMenu must be used within a DropdownMenuRoot");
|
|
752
|
+
return context;
|
|
753
|
+
};
|
|
754
|
+
|
|
755
|
+
//#endregion
|
|
756
|
+
//#region src/primitives/dropdown-menu/dropdown-menu-root.tsx
|
|
757
|
+
function DropdownMenuRoot(props) {
|
|
758
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
759
|
+
const [triggerPosition, setTriggerPosition] = useState(DEFAULT_POSITION);
|
|
760
|
+
const [contentLayout, setContentLayout] = useState(DEFAULT_LAYOUT);
|
|
761
|
+
return /* @__PURE__ */ jsx(DropdownMenuContext.Provider, {
|
|
762
|
+
value: {
|
|
763
|
+
isOpen,
|
|
764
|
+
setIsOpen,
|
|
765
|
+
triggerPosition,
|
|
766
|
+
setTriggerPosition,
|
|
767
|
+
contentLayout,
|
|
768
|
+
setContentLayout,
|
|
769
|
+
styles: props.styles
|
|
770
|
+
},
|
|
771
|
+
children: props.children
|
|
772
|
+
});
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
//#endregion
|
|
776
|
+
//#region src/primitives/dropdown-menu/dropdown-menu-trigger.tsx
|
|
777
|
+
const DropdownMenuTrigger = forwardRef((props, ref) => {
|
|
778
|
+
const dropdownMenu = useDropdownMenu();
|
|
779
|
+
const triggerRef = useRef(null);
|
|
780
|
+
const onTriggerPress = async () => {
|
|
781
|
+
triggerRef.current?.measure((_x, _y, width, height, pageX, pageY) => {
|
|
782
|
+
dropdownMenu.setTriggerPosition({
|
|
783
|
+
height,
|
|
784
|
+
width,
|
|
785
|
+
pageX,
|
|
786
|
+
pageY
|
|
787
|
+
});
|
|
788
|
+
});
|
|
789
|
+
dropdownMenu.setIsOpen((prev) => !prev);
|
|
790
|
+
};
|
|
791
|
+
useImperativeHandle(ref, () => ({
|
|
792
|
+
open: () => dropdownMenu.setIsOpen(true),
|
|
793
|
+
close: () => dropdownMenu.setIsOpen(false)
|
|
794
|
+
}));
|
|
795
|
+
return React.cloneElement(props.children, {
|
|
796
|
+
ref: triggerRef,
|
|
797
|
+
onPress: onTriggerPress,
|
|
798
|
+
role: "button",
|
|
799
|
+
accessible: true,
|
|
800
|
+
accessibilityRole: "button",
|
|
801
|
+
accessibilityState: { expanded: dropdownMenu.isOpen },
|
|
802
|
+
...props.children.props
|
|
803
|
+
});
|
|
804
|
+
});
|
|
805
|
+
DropdownMenuTrigger.displayName = "DropdownMenuTrigger";
|
|
806
|
+
|
|
807
|
+
//#endregion
|
|
808
|
+
//#region src/primitives/dropdown-menu/dropdown-menu-content.tsx
|
|
809
|
+
function DropdownMenuContent(props) {
|
|
810
|
+
const menu = useDropdownMenu();
|
|
811
|
+
const composedStyle = [
|
|
812
|
+
useRelativePosition({
|
|
813
|
+
align: "start",
|
|
814
|
+
avoidCollisions: true,
|
|
815
|
+
triggerPosition: menu.triggerPosition,
|
|
816
|
+
contentLayout: menu.contentLayout,
|
|
817
|
+
alignOffset: 0,
|
|
818
|
+
side: "bottom",
|
|
819
|
+
sideOffset: 0
|
|
820
|
+
}),
|
|
821
|
+
menu.styles?.content,
|
|
822
|
+
props.style
|
|
823
|
+
];
|
|
824
|
+
return /* @__PURE__ */ jsx(props.render ?? View, {
|
|
825
|
+
...props,
|
|
826
|
+
onLayout: (e) => {
|
|
827
|
+
menu.setContentLayout(e.nativeEvent.layout);
|
|
828
|
+
},
|
|
829
|
+
style: composedStyle
|
|
830
|
+
});
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
//#endregion
|
|
834
|
+
//#region src/primitives/dropdown-menu/dropdown-menu-button.tsx
|
|
835
|
+
const calculateState = (isHovered) => {
|
|
836
|
+
if (isHovered) return "hovered";
|
|
837
|
+
return "default";
|
|
838
|
+
};
|
|
839
|
+
function DropdownMenuButton(props) {
|
|
840
|
+
const menu = useDropdownMenu();
|
|
841
|
+
const [isHovered, setIsHovered] = useState(false);
|
|
842
|
+
const state = calculateState(isHovered);
|
|
843
|
+
const composedStyle = [
|
|
844
|
+
menu.styles?.button?.default,
|
|
845
|
+
menu.styles?.button?.[state],
|
|
846
|
+
props.style
|
|
847
|
+
];
|
|
848
|
+
const handlePress = () => {
|
|
849
|
+
props.onPress?.();
|
|
850
|
+
menu.setIsOpen((prev) => !prev);
|
|
851
|
+
};
|
|
852
|
+
return /* @__PURE__ */ jsx(props.render ?? Text, {
|
|
853
|
+
...props,
|
|
854
|
+
onPress: handlePress,
|
|
855
|
+
onMouseEnter: () => setIsHovered(true),
|
|
856
|
+
onMouseLeave: () => setIsHovered(false),
|
|
857
|
+
style: composedStyle,
|
|
858
|
+
children: props.children
|
|
859
|
+
});
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
//#endregion
|
|
863
|
+
//#region src/primitives/dropdown-menu/dropdown-menu-divider.tsx
|
|
864
|
+
function DropdownMenuDivider(props) {
|
|
865
|
+
const composedStyle = [useDropdownMenu().styles?.divider, props.style];
|
|
866
|
+
return /* @__PURE__ */ jsx(props.render ?? View, {
|
|
867
|
+
...props,
|
|
868
|
+
style: composedStyle
|
|
869
|
+
});
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
//#endregion
|
|
873
|
+
//#region src/primitives/dropdown-menu/dropdown-menu-portal.tsx
|
|
874
|
+
function DropdownMenuPortal(props) {
|
|
875
|
+
const menu = useDropdownMenu();
|
|
876
|
+
if (!menu.isOpen) return null;
|
|
877
|
+
return /* @__PURE__ */ jsx(Portal, {
|
|
878
|
+
name: "dropdown-menu-portal",
|
|
879
|
+
children: /* @__PURE__ */ jsx(DropdownMenuContext.Provider, {
|
|
880
|
+
value: menu,
|
|
881
|
+
children: props.children
|
|
882
|
+
})
|
|
883
|
+
});
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
//#endregion
|
|
887
|
+
//#region src/primitives/dropdown-menu/dropdown-menu-overlay.tsx
|
|
888
|
+
function DropdownMenuOverlay(props) {
|
|
889
|
+
const menu = useDropdownMenu();
|
|
890
|
+
const composedStyle = [
|
|
891
|
+
StyleSheet.absoluteFill,
|
|
892
|
+
menu.styles?.overlay,
|
|
893
|
+
props.style
|
|
894
|
+
];
|
|
895
|
+
return /* @__PURE__ */ jsx(props.render ?? Pressable, {
|
|
896
|
+
onPress: () => {
|
|
897
|
+
menu.setIsOpen(false);
|
|
898
|
+
},
|
|
899
|
+
style: composedStyle,
|
|
900
|
+
children: props.children
|
|
901
|
+
});
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
//#endregion
|
|
905
|
+
//#region src/primitives/dropdown-menu/index.ts
|
|
906
|
+
const DropdownMenuPrimitive = {
|
|
907
|
+
Root: DropdownMenuRoot,
|
|
908
|
+
Trigger: DropdownMenuTrigger,
|
|
909
|
+
Portal: DropdownMenuPortal,
|
|
910
|
+
Overlay: DropdownMenuOverlay,
|
|
911
|
+
Content: DropdownMenuContent,
|
|
912
|
+
Button: DropdownMenuButton,
|
|
913
|
+
Divider: DropdownMenuDivider
|
|
914
|
+
};
|
|
915
|
+
|
|
916
|
+
//#endregion
|
|
917
|
+
//#region src/primitives/popover/context.ts
|
|
918
|
+
const PopoverContext = createContext(void 0);
|
|
919
|
+
const usePopover = () => {
|
|
920
|
+
const context = useContext(PopoverContext);
|
|
921
|
+
if (!context) throw new Error("usePopover must be used within a PopoverRoot");
|
|
922
|
+
return context;
|
|
923
|
+
};
|
|
924
|
+
|
|
925
|
+
//#endregion
|
|
926
|
+
//#region src/primitives/popover/popover-root.tsx
|
|
927
|
+
function PopoverRoot(props) {
|
|
928
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
929
|
+
const [contentLayout, setContentLayout] = useState(DEFAULT_LAYOUT);
|
|
930
|
+
const [triggerPosition, setTriggerPosition] = useState(DEFAULT_POSITION);
|
|
931
|
+
return /* @__PURE__ */ jsx(PopoverContext.Provider, {
|
|
932
|
+
value: {
|
|
933
|
+
isOpen,
|
|
934
|
+
setIsOpen,
|
|
935
|
+
contentLayout,
|
|
936
|
+
setContentLayout,
|
|
937
|
+
triggerPosition,
|
|
938
|
+
setTriggerPosition,
|
|
939
|
+
styles: props.styles
|
|
940
|
+
},
|
|
941
|
+
children: props.children
|
|
942
|
+
});
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
//#endregion
|
|
946
|
+
//#region src/primitives/popover/popover-trigger.tsx
|
|
947
|
+
const PopoverTrigger = forwardRef((props, ref) => {
|
|
948
|
+
const popover = usePopover();
|
|
949
|
+
const triggerRef = useRef(null);
|
|
950
|
+
const onTriggerPress = async () => {
|
|
951
|
+
triggerRef.current?.measure((_x, _y, width, height, pageX, pageY) => {
|
|
952
|
+
popover.setTriggerPosition({
|
|
953
|
+
height,
|
|
954
|
+
width,
|
|
955
|
+
pageX,
|
|
956
|
+
pageY
|
|
957
|
+
});
|
|
958
|
+
});
|
|
959
|
+
popover.setIsOpen((prev) => !prev);
|
|
960
|
+
};
|
|
961
|
+
useImperativeHandle(ref, () => ({
|
|
962
|
+
open: () => popover.setIsOpen(true),
|
|
963
|
+
close: () => popover.setIsOpen(false)
|
|
964
|
+
}));
|
|
965
|
+
return React.cloneElement(props.children, {
|
|
966
|
+
ref: triggerRef,
|
|
967
|
+
onPress: onTriggerPress,
|
|
968
|
+
role: "button",
|
|
969
|
+
accessible: true,
|
|
970
|
+
accessibilityRole: "button",
|
|
971
|
+
accessibilityState: { expanded: popover.isOpen },
|
|
972
|
+
...props.children.props
|
|
973
|
+
});
|
|
974
|
+
});
|
|
975
|
+
PopoverTrigger.displayName = "PopoverTrigger";
|
|
976
|
+
|
|
977
|
+
//#endregion
|
|
978
|
+
//#region src/primitives/popover/popover-portal.tsx
|
|
979
|
+
function PopoverPortal(props) {
|
|
980
|
+
const popover = usePopover();
|
|
981
|
+
if (!popover.isOpen) return null;
|
|
982
|
+
return /* @__PURE__ */ jsx(Portal, {
|
|
983
|
+
name: "popover-portal",
|
|
984
|
+
children: /* @__PURE__ */ jsx(PopoverContext.Provider, {
|
|
985
|
+
value: popover,
|
|
986
|
+
children: props.children
|
|
987
|
+
})
|
|
988
|
+
});
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
//#endregion
|
|
992
|
+
//#region src/primitives/popover/popover-overlay.tsx
|
|
993
|
+
function PopoverOverlay(props) {
|
|
994
|
+
const { closeOnPress = true, ...restProps } = props;
|
|
995
|
+
const popover = usePopover();
|
|
996
|
+
const composedStyle = [
|
|
997
|
+
StyleSheet.absoluteFill,
|
|
998
|
+
popover.styles?.overlay,
|
|
999
|
+
props.style
|
|
1000
|
+
];
|
|
1001
|
+
return /* @__PURE__ */ jsx(props.render ?? Pressable, {
|
|
1002
|
+
...restProps,
|
|
1003
|
+
onPress: () => {
|
|
1004
|
+
if (closeOnPress) popover.setIsOpen(false);
|
|
1005
|
+
props.onPress?.();
|
|
1006
|
+
},
|
|
1007
|
+
style: composedStyle,
|
|
1008
|
+
children: props.children
|
|
1009
|
+
});
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
//#endregion
|
|
1013
|
+
//#region src/primitives/popover/popover-content.tsx
|
|
1014
|
+
function PopoverContent(props) {
|
|
1015
|
+
const popover = usePopover();
|
|
1016
|
+
const composedStyle = [
|
|
1017
|
+
useRelativePosition({
|
|
1018
|
+
align: "start",
|
|
1019
|
+
avoidCollisions: true,
|
|
1020
|
+
triggerPosition: popover.triggerPosition,
|
|
1021
|
+
contentLayout: popover.contentLayout,
|
|
1022
|
+
alignOffset: 0,
|
|
1023
|
+
side: "bottom",
|
|
1024
|
+
sideOffset: 0
|
|
1025
|
+
}),
|
|
1026
|
+
popover.styles?.content,
|
|
1027
|
+
props.style
|
|
1028
|
+
];
|
|
1029
|
+
return /* @__PURE__ */ jsx(props.render ?? View, {
|
|
1030
|
+
...props,
|
|
1031
|
+
onLayout: (e) => {
|
|
1032
|
+
popover.setContentLayout(e.nativeEvent.layout);
|
|
1033
|
+
},
|
|
1034
|
+
style: composedStyle
|
|
1035
|
+
});
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
//#endregion
|
|
1039
|
+
//#region src/primitives/popover/popover-close.tsx
|
|
1040
|
+
function PopoverClose(props) {
|
|
1041
|
+
const popover = usePopover();
|
|
1042
|
+
return /* @__PURE__ */ jsx(props.render ?? Pressable, {
|
|
1043
|
+
...props,
|
|
1044
|
+
onPress: () => {
|
|
1045
|
+
popover.setIsOpen(false);
|
|
1046
|
+
props.onPress?.();
|
|
1047
|
+
},
|
|
1048
|
+
style: props.style
|
|
1049
|
+
});
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
//#endregion
|
|
1053
|
+
//#region src/primitives/popover/index.ts
|
|
1054
|
+
const PopoverPrimitive = {
|
|
1055
|
+
Root: PopoverRoot,
|
|
1056
|
+
Trigger: PopoverTrigger,
|
|
1057
|
+
Portal: PopoverPortal,
|
|
1058
|
+
Overlay: PopoverOverlay,
|
|
1059
|
+
Content: PopoverContent,
|
|
1060
|
+
Close: PopoverClose
|
|
1061
|
+
};
|
|
1062
|
+
|
|
1063
|
+
//#endregion
|
|
1064
|
+
export { BadgePrimitive as a, EmptyPrimitive as c, ButtonPrimitive as d, InputPrimitive as f, TextareaPrimitive as i, CardPrimitive as l, PortalHost as m, usePopover as n, ToastPrimitive as o, FieldPrimitive as p, DropdownMenuPrimitive as r, AvatarPrimitive as s, PopoverPrimitive as t, SelectPrimitive as u };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { o as ToastPrimitive } from "./primitives-DNeYBN-3.mjs";
|
|
2
2
|
import React, { createContext, useContext, useEffect, useState, useSyncExternalStore } from "react";
|
|
3
3
|
import { StyleSheet, View, useColorScheme } from "react-native";
|
|
4
4
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
//#region src/hooks/use-numeric-mask.d.ts
|
|
2
|
+
type NumericMaskFormat = "currency" | "decimal" | "integer" | "percentage";
|
|
3
|
+
interface UseNumericMaskOptions {
|
|
4
|
+
format?: NumericMaskFormat;
|
|
5
|
+
locale?: string;
|
|
6
|
+
currency?: string;
|
|
7
|
+
precision?: number;
|
|
8
|
+
min?: number;
|
|
9
|
+
max?: number;
|
|
10
|
+
allowNegative?: boolean;
|
|
11
|
+
onChange?: (value: number | null) => void;
|
|
12
|
+
}
|
|
13
|
+
interface UseNumericMaskReturn {
|
|
14
|
+
value: string;
|
|
15
|
+
numericValue: number | null;
|
|
16
|
+
onChangeText: (text: string) => void;
|
|
17
|
+
onBlur: () => void;
|
|
18
|
+
onFocus: () => void;
|
|
19
|
+
keyboardType: "numeric" | "decimal-pad" | "number-pad";
|
|
20
|
+
setValue: (value: number | null) => void;
|
|
21
|
+
}
|
|
22
|
+
declare function useNumericMask({
|
|
23
|
+
format,
|
|
24
|
+
locale,
|
|
25
|
+
currency,
|
|
26
|
+
precision,
|
|
27
|
+
min,
|
|
28
|
+
max,
|
|
29
|
+
allowNegative,
|
|
30
|
+
onChange
|
|
31
|
+
}?: UseNumericMaskOptions): UseNumericMaskReturn;
|
|
32
|
+
//#endregion
|
|
33
|
+
export { useNumericMask as i, UseNumericMaskOptions as n, UseNumericMaskReturn as r, NumericMaskFormat as t };
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { useCallback, useState } from "react";
|
|
2
|
+
|
|
3
|
+
//#region src/hooks/use-numeric-mask.ts
|
|
4
|
+
function useNumericMask({ format = "decimal", locale = "en-US", currency = "USD", precision = 2, min, max, allowNegative = true, onChange } = {}) {
|
|
5
|
+
const [numericValue, setNumericValue] = useState(null);
|
|
6
|
+
const [displayValue, setDisplayValue] = useState("");
|
|
7
|
+
const [isFocused, setIsFocused] = useState(false);
|
|
8
|
+
const effectivePrecision = format === "integer" ? 0 : precision;
|
|
9
|
+
const formatValue = useCallback((num) => {
|
|
10
|
+
if (num === null || isNaN(num)) return "";
|
|
11
|
+
switch (format) {
|
|
12
|
+
case "currency": return new Intl.NumberFormat(locale, {
|
|
13
|
+
style: "currency",
|
|
14
|
+
currency,
|
|
15
|
+
minimumFractionDigits: effectivePrecision,
|
|
16
|
+
maximumFractionDigits: effectivePrecision
|
|
17
|
+
}).format(num);
|
|
18
|
+
case "percentage": return new Intl.NumberFormat(locale, {
|
|
19
|
+
style: "percent",
|
|
20
|
+
minimumFractionDigits: effectivePrecision,
|
|
21
|
+
maximumFractionDigits: effectivePrecision
|
|
22
|
+
}).format(num / 100);
|
|
23
|
+
case "integer": return new Intl.NumberFormat(locale, {
|
|
24
|
+
minimumFractionDigits: 0,
|
|
25
|
+
maximumFractionDigits: 0
|
|
26
|
+
}).format(num);
|
|
27
|
+
case "decimal":
|
|
28
|
+
default: return new Intl.NumberFormat(locale, {
|
|
29
|
+
minimumFractionDigits: effectivePrecision,
|
|
30
|
+
maximumFractionDigits: effectivePrecision
|
|
31
|
+
}).format(num);
|
|
32
|
+
}
|
|
33
|
+
}, [
|
|
34
|
+
format,
|
|
35
|
+
locale,
|
|
36
|
+
currency,
|
|
37
|
+
effectivePrecision
|
|
38
|
+
]);
|
|
39
|
+
const parseValue = useCallback((text) => {
|
|
40
|
+
let cleaned = text.replace(/[^\d.-]/g, "");
|
|
41
|
+
if (!allowNegative) cleaned = cleaned.replace(/-/g, "");
|
|
42
|
+
const parsed = parseFloat(cleaned);
|
|
43
|
+
if (isNaN(parsed) || cleaned === "" || cleaned === "-") return null;
|
|
44
|
+
let constrained = parsed;
|
|
45
|
+
if (min !== void 0 && constrained < min) constrained = min;
|
|
46
|
+
if (max !== void 0 && constrained > max) constrained = max;
|
|
47
|
+
return constrained;
|
|
48
|
+
}, [
|
|
49
|
+
min,
|
|
50
|
+
max,
|
|
51
|
+
allowNegative
|
|
52
|
+
]);
|
|
53
|
+
const handleChangeText = useCallback((text) => {
|
|
54
|
+
if (isFocused) {
|
|
55
|
+
let cleaned = text.replace(/[^\d.-]/g, "");
|
|
56
|
+
if (!allowNegative && cleaned.includes("-")) return;
|
|
57
|
+
if (allowNegative) {
|
|
58
|
+
if ((cleaned.match(/-/g) || []).length > 1 || cleaned.includes("-") && cleaned.indexOf("-") !== 0) return;
|
|
59
|
+
}
|
|
60
|
+
if (effectivePrecision >= 0) {
|
|
61
|
+
const decimalIndex = cleaned.indexOf(".");
|
|
62
|
+
if (decimalIndex !== -1) {
|
|
63
|
+
if (cleaned.substring(decimalIndex + 1).length > effectivePrecision) return;
|
|
64
|
+
}
|
|
65
|
+
if ((cleaned.match(/\./g) || []).length > 1) return;
|
|
66
|
+
if (format === "integer" && cleaned.includes(".")) return;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
setDisplayValue(text);
|
|
70
|
+
const value = parseValue(text);
|
|
71
|
+
setNumericValue(value);
|
|
72
|
+
onChange?.(value);
|
|
73
|
+
}, [
|
|
74
|
+
parseValue,
|
|
75
|
+
onChange,
|
|
76
|
+
isFocused,
|
|
77
|
+
effectivePrecision,
|
|
78
|
+
allowNegative,
|
|
79
|
+
format
|
|
80
|
+
]);
|
|
81
|
+
const handleBlur = useCallback(() => {
|
|
82
|
+
setIsFocused(false);
|
|
83
|
+
if (numericValue !== null) setDisplayValue(formatValue(numericValue));
|
|
84
|
+
else setDisplayValue("");
|
|
85
|
+
}, [numericValue, formatValue]);
|
|
86
|
+
const handleFocus = useCallback(() => {
|
|
87
|
+
setIsFocused(true);
|
|
88
|
+
if (numericValue !== null) setDisplayValue(numericValue.toString());
|
|
89
|
+
}, [numericValue]);
|
|
90
|
+
const setValue = useCallback((value) => {
|
|
91
|
+
setNumericValue(value);
|
|
92
|
+
if (value !== null) if (isFocused) setDisplayValue(value.toString());
|
|
93
|
+
else setDisplayValue(formatValue(value));
|
|
94
|
+
else setDisplayValue("");
|
|
95
|
+
onChange?.(value);
|
|
96
|
+
}, [
|
|
97
|
+
isFocused,
|
|
98
|
+
formatValue,
|
|
99
|
+
onChange
|
|
100
|
+
]);
|
|
101
|
+
return {
|
|
102
|
+
value: displayValue,
|
|
103
|
+
numericValue,
|
|
104
|
+
onChangeText: handleChangeText,
|
|
105
|
+
onBlur: handleBlur,
|
|
106
|
+
onFocus: handleFocus,
|
|
107
|
+
keyboardType: format === "integer" ? allowNegative ? "numeric" : "number-pad" : "decimal-pad",
|
|
108
|
+
setValue
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
//#endregion
|
|
113
|
+
export { useNumericMask as t };
|