@korsolutions/ui 0.0.18 → 0.0.20
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 +70 -4
- package/dist/components/index.mjs +224 -8
- package/dist/{index-Bfae0NgJ.d.mts → index-CGY0mO6z.d.mts} +216 -8
- package/dist/index.d.mts +3 -3
- package/dist/index.mjs +2 -2
- package/dist/primitives/index.d.mts +2 -2
- package/dist/primitives/index.mjs +2 -2
- package/dist/{primitives-B4L9y32H.mjs → primitives-P_8clvQr.mjs} +513 -11
- package/dist/{toast-manager-Vq38WK76.mjs → toast-manager-DSo9oN8w.mjs} +1 -1
- package/package.json +1 -1
- package/src/components/badge/badge.tsx +23 -0
- package/src/components/badge/variants/default.tsx +26 -0
- package/src/components/badge/variants/index.ts +7 -0
- package/src/components/badge/variants/secondary.tsx +26 -0
- 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 +4 -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/components/textarea/textarea.tsx +14 -0
- package/src/components/textarea/variants/default.tsx +38 -0
- package/src/components/textarea/variants/index.ts +5 -0
- package/src/hooks/useRelativePosition.ts +188 -0
- package/src/primitives/badge/badge-label.tsx +21 -0
- package/src/primitives/badge/badge-root.tsx +30 -0
- package/src/primitives/badge/context.ts +17 -0
- package/src/primitives/badge/index.ts +11 -0
- package/src/primitives/badge/types.ts +9 -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 +4 -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/primitives/textarea/index.ts +2 -0
- package/src/primitives/textarea/textarea.tsx +56 -0
- package/src/primitives/textarea/types.ts +5 -0
- package/src/utils/get-ref-layout.ts +16 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import * as React$1 from "react";
|
|
2
|
+
import React, { createContext, forwardRef, useContext, useEffect, useImperativeHandle, useRef, useState, useSyncExternalStore } from "react";
|
|
3
|
+
import { ActivityIndicator, Image, Pressable, StyleSheet, Text, TextInput, View, useWindowDimensions } from "react-native";
|
|
3
4
|
import { Fragment, jsx } from "react/jsx-runtime";
|
|
4
5
|
|
|
5
6
|
//#region src/primitives/portal/portal.tsx
|
|
@@ -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$2 = (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 = (selectState, hovered, selected) => {
|
|
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(select.state, isHovered, isSelected);
|
|
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) => {
|
|
@@ -661,4 +662,505 @@ const ToastPrimitive = {
|
|
|
661
662
|
};
|
|
662
663
|
|
|
663
664
|
//#endregion
|
|
664
|
-
|
|
665
|
+
//#region src/primitives/badge/context.ts
|
|
666
|
+
const BadgeContext = createContext(void 0);
|
|
667
|
+
const useBadge = () => {
|
|
668
|
+
const context = useContext(BadgeContext);
|
|
669
|
+
if (!context) throw new Error("useBadge must be used within a BadgeProvider");
|
|
670
|
+
return context;
|
|
671
|
+
};
|
|
672
|
+
|
|
673
|
+
//#endregion
|
|
674
|
+
//#region src/primitives/badge/badge-root.tsx
|
|
675
|
+
function BadgeRoot(props) {
|
|
676
|
+
const composedStyle = calculateComposedStyles(props.styles, "default", "root", props.style);
|
|
677
|
+
const Component = props.render ?? View;
|
|
678
|
+
return /* @__PURE__ */ jsx(BadgeContext.Provider, {
|
|
679
|
+
value: {
|
|
680
|
+
state: "default",
|
|
681
|
+
styles: props.styles
|
|
682
|
+
},
|
|
683
|
+
children: /* @__PURE__ */ jsx(Component, {
|
|
684
|
+
...props,
|
|
685
|
+
style: composedStyle
|
|
686
|
+
})
|
|
687
|
+
});
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
//#endregion
|
|
691
|
+
//#region src/primitives/badge/badge-label.tsx
|
|
692
|
+
function BadgeLabel(props) {
|
|
693
|
+
const badge = useBadge();
|
|
694
|
+
const composedStyle = calculateComposedStyles(badge.styles, badge.state, "label", props.style);
|
|
695
|
+
return /* @__PURE__ */ jsx(props.render ?? Text, {
|
|
696
|
+
...props,
|
|
697
|
+
style: composedStyle
|
|
698
|
+
});
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
//#endregion
|
|
702
|
+
//#region src/primitives/badge/index.ts
|
|
703
|
+
const BadgePrimitive = {
|
|
704
|
+
Root: BadgeRoot,
|
|
705
|
+
Label: BadgeLabel
|
|
706
|
+
};
|
|
707
|
+
|
|
708
|
+
//#endregion
|
|
709
|
+
//#region src/primitives/textarea/textarea.tsx
|
|
710
|
+
const calculateState$1 = (props, isFocused) => {
|
|
711
|
+
if (props.isDisabled) return "disabled";
|
|
712
|
+
if (isFocused) return "focused";
|
|
713
|
+
return "default";
|
|
714
|
+
};
|
|
715
|
+
function TextareaPrimitive(props) {
|
|
716
|
+
const [isFocused, setIsFocused] = useState(false);
|
|
717
|
+
const state = calculateState$1(props, isFocused);
|
|
718
|
+
const composedStyles = [
|
|
719
|
+
props.styles?.default?.style,
|
|
720
|
+
props.styles?.[state]?.style,
|
|
721
|
+
props.style
|
|
722
|
+
];
|
|
723
|
+
const composedProps = {
|
|
724
|
+
...props.styles?.default,
|
|
725
|
+
...props.styles?.[state],
|
|
726
|
+
...props
|
|
727
|
+
};
|
|
728
|
+
return /* @__PURE__ */ jsx(props.render ?? TextInput, {
|
|
729
|
+
...composedProps,
|
|
730
|
+
multiline: true,
|
|
731
|
+
onChange: void 0,
|
|
732
|
+
onChangeText: props.onChange,
|
|
733
|
+
onFocus: (e) => {
|
|
734
|
+
setIsFocused(true);
|
|
735
|
+
props.onFocus?.(e);
|
|
736
|
+
},
|
|
737
|
+
onBlur: (e) => {
|
|
738
|
+
setIsFocused(false);
|
|
739
|
+
props.onBlur?.(e);
|
|
740
|
+
},
|
|
741
|
+
readOnly: props.isDisabled || props.readOnly,
|
|
742
|
+
style: composedStyles
|
|
743
|
+
});
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
//#endregion
|
|
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/hooks/useRelativePosition.ts
|
|
757
|
+
function useRelativePosition({ align, avoidCollisions, triggerPosition, contentLayout, alignOffset, insets, sideOffset, side }) {
|
|
758
|
+
const dimensions = useWindowDimensions();
|
|
759
|
+
return React$1.useMemo(() => {
|
|
760
|
+
if (!triggerPosition || !contentLayout) return {
|
|
761
|
+
position: "absolute",
|
|
762
|
+
opacity: 0,
|
|
763
|
+
top: dimensions.height,
|
|
764
|
+
zIndex: -9999999
|
|
765
|
+
};
|
|
766
|
+
return getContentStyle({
|
|
767
|
+
align,
|
|
768
|
+
avoidCollisions,
|
|
769
|
+
contentLayout,
|
|
770
|
+
side,
|
|
771
|
+
triggerPosition,
|
|
772
|
+
alignOffset,
|
|
773
|
+
insets,
|
|
774
|
+
sideOffset,
|
|
775
|
+
dimensions
|
|
776
|
+
});
|
|
777
|
+
}, [
|
|
778
|
+
align,
|
|
779
|
+
avoidCollisions,
|
|
780
|
+
side,
|
|
781
|
+
alignOffset,
|
|
782
|
+
insets,
|
|
783
|
+
triggerPosition,
|
|
784
|
+
contentLayout,
|
|
785
|
+
dimensions.width,
|
|
786
|
+
dimensions.height
|
|
787
|
+
]);
|
|
788
|
+
}
|
|
789
|
+
const DEFAULT_LAYOUT = {
|
|
790
|
+
x: 0,
|
|
791
|
+
y: 0,
|
|
792
|
+
width: 0,
|
|
793
|
+
height: 0
|
|
794
|
+
};
|
|
795
|
+
const DEFAULT_POSITION = {
|
|
796
|
+
height: 0,
|
|
797
|
+
width: 0,
|
|
798
|
+
pageX: 0,
|
|
799
|
+
pageY: 0
|
|
800
|
+
};
|
|
801
|
+
function getSidePosition({ side, triggerPosition, contentLayout, sideOffset, insets, avoidCollisions, dimensions }) {
|
|
802
|
+
const insetTop = insets?.top ?? 0;
|
|
803
|
+
const insetBottom = insets?.bottom ?? 0;
|
|
804
|
+
const positionTop = triggerPosition?.pageY - sideOffset - contentLayout.height;
|
|
805
|
+
const positionBottom = triggerPosition.pageY + triggerPosition.height + sideOffset;
|
|
806
|
+
if (!avoidCollisions) return { top: side === "top" ? positionTop : positionBottom };
|
|
807
|
+
if (side === "top") return { top: Math.min(Math.max(insetTop, positionTop), dimensions.height - insetBottom - contentLayout.height) };
|
|
808
|
+
return { top: Math.min(dimensions.height - insetBottom - contentLayout.height, positionBottom) };
|
|
809
|
+
}
|
|
810
|
+
function getAlignPosition({ align, avoidCollisions, contentLayout, triggerPosition, alignOffset, insets, dimensions }) {
|
|
811
|
+
const insetLeft = insets?.left ?? 0;
|
|
812
|
+
const insetRight = insets?.right ?? 0;
|
|
813
|
+
const maxContentWidth = dimensions.width - insetLeft - insetRight;
|
|
814
|
+
const contentWidth = Math.min(contentLayout.width, maxContentWidth);
|
|
815
|
+
let left = getLeftPosition(align, triggerPosition.pageX, triggerPosition.width, contentWidth, alignOffset, insetLeft, insetRight, dimensions);
|
|
816
|
+
if (avoidCollisions) {
|
|
817
|
+
if (left < insetLeft || left + contentWidth > dimensions.width - insetRight) {
|
|
818
|
+
const spaceLeft = left - insetLeft;
|
|
819
|
+
const spaceRight = dimensions.width - insetRight - (left + contentWidth);
|
|
820
|
+
if (spaceLeft > spaceRight && spaceLeft >= contentWidth) left = insetLeft;
|
|
821
|
+
else if (spaceRight >= contentWidth) left = dimensions.width - insetRight - contentWidth;
|
|
822
|
+
else left = Math.max(insetLeft, (dimensions.width - contentWidth - insetRight) / 2);
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
return {
|
|
826
|
+
left,
|
|
827
|
+
maxWidth: maxContentWidth
|
|
828
|
+
};
|
|
829
|
+
}
|
|
830
|
+
function getLeftPosition(align, triggerPageX, triggerWidth, contentWidth, alignOffset, insetLeft, insetRight, dimensions) {
|
|
831
|
+
let left = 0;
|
|
832
|
+
if (align === "start") left = triggerPageX;
|
|
833
|
+
if (align === "center") left = triggerPageX + triggerWidth / 2 - contentWidth / 2;
|
|
834
|
+
if (align === "end") left = triggerPageX + triggerWidth - contentWidth;
|
|
835
|
+
return Math.max(insetLeft, Math.min(left + alignOffset, dimensions.width - contentWidth - insetRight));
|
|
836
|
+
}
|
|
837
|
+
function getContentStyle({ align, avoidCollisions, contentLayout, side, triggerPosition, alignOffset, insets, sideOffset, dimensions }) {
|
|
838
|
+
return Object.assign({ position: "absolute" }, getSidePosition({
|
|
839
|
+
side,
|
|
840
|
+
triggerPosition,
|
|
841
|
+
contentLayout,
|
|
842
|
+
sideOffset,
|
|
843
|
+
insets,
|
|
844
|
+
avoidCollisions,
|
|
845
|
+
dimensions
|
|
846
|
+
}), getAlignPosition({
|
|
847
|
+
align,
|
|
848
|
+
avoidCollisions,
|
|
849
|
+
triggerPosition,
|
|
850
|
+
contentLayout,
|
|
851
|
+
alignOffset,
|
|
852
|
+
insets,
|
|
853
|
+
dimensions
|
|
854
|
+
}));
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
//#endregion
|
|
858
|
+
//#region src/primitives/dropdown-menu/dropdown-menu-root.tsx
|
|
859
|
+
function DropdownMenuRoot(props) {
|
|
860
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
861
|
+
const [triggerPosition, setTriggerPosition] = useState(DEFAULT_POSITION);
|
|
862
|
+
const [contentLayout, setContentLayout] = useState(DEFAULT_LAYOUT);
|
|
863
|
+
return /* @__PURE__ */ jsx(DropdownMenuContext.Provider, {
|
|
864
|
+
value: {
|
|
865
|
+
isOpen,
|
|
866
|
+
setIsOpen,
|
|
867
|
+
triggerPosition,
|
|
868
|
+
setTriggerPosition,
|
|
869
|
+
contentLayout,
|
|
870
|
+
setContentLayout,
|
|
871
|
+
styles: props.styles
|
|
872
|
+
},
|
|
873
|
+
children: props.children
|
|
874
|
+
});
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
//#endregion
|
|
878
|
+
//#region src/primitives/dropdown-menu/dropdown-menu-trigger.tsx
|
|
879
|
+
const DropdownMenuTrigger = forwardRef((props, ref) => {
|
|
880
|
+
const dropdownMenu = useDropdownMenu();
|
|
881
|
+
const triggerRef = useRef(null);
|
|
882
|
+
const onTriggerPress = async () => {
|
|
883
|
+
triggerRef.current?.measure((_x, _y, width, height, pageX, pageY) => {
|
|
884
|
+
dropdownMenu.setTriggerPosition({
|
|
885
|
+
height,
|
|
886
|
+
width,
|
|
887
|
+
pageX,
|
|
888
|
+
pageY
|
|
889
|
+
});
|
|
890
|
+
});
|
|
891
|
+
dropdownMenu.setIsOpen((prev) => !prev);
|
|
892
|
+
};
|
|
893
|
+
useImperativeHandle(ref, () => ({
|
|
894
|
+
open: () => dropdownMenu.setIsOpen(true),
|
|
895
|
+
close: () => dropdownMenu.setIsOpen(false)
|
|
896
|
+
}));
|
|
897
|
+
return React.cloneElement(props.children, {
|
|
898
|
+
ref: triggerRef,
|
|
899
|
+
onPress: onTriggerPress,
|
|
900
|
+
role: "button",
|
|
901
|
+
accessible: true,
|
|
902
|
+
accessibilityRole: "button",
|
|
903
|
+
accessibilityState: { expanded: dropdownMenu.isOpen },
|
|
904
|
+
...props.children.props
|
|
905
|
+
});
|
|
906
|
+
});
|
|
907
|
+
DropdownMenuTrigger.displayName = "DropdownMenuTrigger";
|
|
908
|
+
|
|
909
|
+
//#endregion
|
|
910
|
+
//#region src/primitives/dropdown-menu/dropdown-menu-content.tsx
|
|
911
|
+
function DropdownMenuContent(props) {
|
|
912
|
+
const menu = useDropdownMenu();
|
|
913
|
+
const composedStyle = [
|
|
914
|
+
useRelativePosition({
|
|
915
|
+
align: "start",
|
|
916
|
+
avoidCollisions: true,
|
|
917
|
+
triggerPosition: menu.triggerPosition,
|
|
918
|
+
contentLayout: menu.contentLayout,
|
|
919
|
+
alignOffset: 0,
|
|
920
|
+
side: "bottom",
|
|
921
|
+
sideOffset: 0
|
|
922
|
+
}),
|
|
923
|
+
menu.styles?.content,
|
|
924
|
+
props.style
|
|
925
|
+
];
|
|
926
|
+
return /* @__PURE__ */ jsx(props.render ?? View, {
|
|
927
|
+
...props,
|
|
928
|
+
onLayout: (e) => {
|
|
929
|
+
menu.setContentLayout(e.nativeEvent.layout);
|
|
930
|
+
},
|
|
931
|
+
style: composedStyle
|
|
932
|
+
});
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
//#endregion
|
|
936
|
+
//#region src/primitives/dropdown-menu/dropdown-menu-button.tsx
|
|
937
|
+
const calculateState = (isHovered) => {
|
|
938
|
+
if (isHovered) return "hovered";
|
|
939
|
+
return "default";
|
|
940
|
+
};
|
|
941
|
+
function DropdownMenuButton(props) {
|
|
942
|
+
const menu = useDropdownMenu();
|
|
943
|
+
const [isHovered, setIsHovered] = useState(false);
|
|
944
|
+
const state = calculateState(isHovered);
|
|
945
|
+
const composedStyle = [
|
|
946
|
+
menu.styles?.button?.default,
|
|
947
|
+
menu.styles?.button?.[state],
|
|
948
|
+
props.style
|
|
949
|
+
];
|
|
950
|
+
const handlePress = () => {
|
|
951
|
+
props.onPress?.();
|
|
952
|
+
menu.setIsOpen((prev) => !prev);
|
|
953
|
+
};
|
|
954
|
+
return /* @__PURE__ */ jsx(props.render ?? Text, {
|
|
955
|
+
...props,
|
|
956
|
+
onPress: handlePress,
|
|
957
|
+
onMouseEnter: () => setIsHovered(true),
|
|
958
|
+
onMouseLeave: () => setIsHovered(false),
|
|
959
|
+
style: composedStyle,
|
|
960
|
+
children: props.children
|
|
961
|
+
});
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
//#endregion
|
|
965
|
+
//#region src/primitives/dropdown-menu/dropdown-menu-divider.tsx
|
|
966
|
+
function DropdownMenuDivider(props) {
|
|
967
|
+
const composedStyle = [useDropdownMenu().styles?.divider, props.style];
|
|
968
|
+
return /* @__PURE__ */ jsx(props.render ?? View, {
|
|
969
|
+
...props,
|
|
970
|
+
style: composedStyle
|
|
971
|
+
});
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
//#endregion
|
|
975
|
+
//#region src/primitives/dropdown-menu/dropdown-menu-portal.tsx
|
|
976
|
+
function DropdownMenuPortal(props) {
|
|
977
|
+
const menu = useDropdownMenu();
|
|
978
|
+
if (!menu.isOpen) return null;
|
|
979
|
+
return /* @__PURE__ */ jsx(Portal, {
|
|
980
|
+
name: "dropdown-menu-portal",
|
|
981
|
+
children: /* @__PURE__ */ jsx(DropdownMenuContext.Provider, {
|
|
982
|
+
value: menu,
|
|
983
|
+
children: props.children
|
|
984
|
+
})
|
|
985
|
+
});
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
//#endregion
|
|
989
|
+
//#region src/primitives/dropdown-menu/dropdown-menu-overlay.tsx
|
|
990
|
+
function DropdownMenuOverlay(props) {
|
|
991
|
+
const menu = useDropdownMenu();
|
|
992
|
+
const composedStyle = [
|
|
993
|
+
StyleSheet.absoluteFill,
|
|
994
|
+
menu.styles?.overlay,
|
|
995
|
+
props.style
|
|
996
|
+
];
|
|
997
|
+
return /* @__PURE__ */ jsx(props.render ?? Pressable, {
|
|
998
|
+
onPress: () => {
|
|
999
|
+
menu.setIsOpen(false);
|
|
1000
|
+
},
|
|
1001
|
+
style: composedStyle,
|
|
1002
|
+
children: props.children
|
|
1003
|
+
});
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
//#endregion
|
|
1007
|
+
//#region src/primitives/dropdown-menu/index.ts
|
|
1008
|
+
const DropdownMenuPrimitive = {
|
|
1009
|
+
Root: DropdownMenuRoot,
|
|
1010
|
+
Trigger: DropdownMenuTrigger,
|
|
1011
|
+
Portal: DropdownMenuPortal,
|
|
1012
|
+
Overlay: DropdownMenuOverlay,
|
|
1013
|
+
Content: DropdownMenuContent,
|
|
1014
|
+
Button: DropdownMenuButton,
|
|
1015
|
+
Divider: DropdownMenuDivider
|
|
1016
|
+
};
|
|
1017
|
+
|
|
1018
|
+
//#endregion
|
|
1019
|
+
//#region src/primitives/popover/context.ts
|
|
1020
|
+
const PopoverContext = createContext(void 0);
|
|
1021
|
+
const usePopover = () => {
|
|
1022
|
+
const context = useContext(PopoverContext);
|
|
1023
|
+
if (!context) throw new Error("usePopover must be used within a PopoverRoot");
|
|
1024
|
+
return context;
|
|
1025
|
+
};
|
|
1026
|
+
|
|
1027
|
+
//#endregion
|
|
1028
|
+
//#region src/primitives/popover/popover-root.tsx
|
|
1029
|
+
function PopoverRoot(props) {
|
|
1030
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
1031
|
+
const [contentLayout, setContentLayout] = useState(DEFAULT_LAYOUT);
|
|
1032
|
+
const [triggerPosition, setTriggerPosition] = useState(DEFAULT_POSITION);
|
|
1033
|
+
return /* @__PURE__ */ jsx(PopoverContext.Provider, {
|
|
1034
|
+
value: {
|
|
1035
|
+
isOpen,
|
|
1036
|
+
setIsOpen,
|
|
1037
|
+
contentLayout,
|
|
1038
|
+
setContentLayout,
|
|
1039
|
+
triggerPosition,
|
|
1040
|
+
setTriggerPosition,
|
|
1041
|
+
styles: props.styles
|
|
1042
|
+
},
|
|
1043
|
+
children: props.children
|
|
1044
|
+
});
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
//#endregion
|
|
1048
|
+
//#region src/primitives/popover/popover-trigger.tsx
|
|
1049
|
+
const PopoverTrigger = forwardRef((props, ref) => {
|
|
1050
|
+
const popover = usePopover();
|
|
1051
|
+
const triggerRef = useRef(null);
|
|
1052
|
+
const onTriggerPress = async () => {
|
|
1053
|
+
triggerRef.current?.measure((_x, _y, width, height, pageX, pageY) => {
|
|
1054
|
+
popover.setTriggerPosition({
|
|
1055
|
+
height,
|
|
1056
|
+
width,
|
|
1057
|
+
pageX,
|
|
1058
|
+
pageY
|
|
1059
|
+
});
|
|
1060
|
+
});
|
|
1061
|
+
popover.setIsOpen((prev) => !prev);
|
|
1062
|
+
};
|
|
1063
|
+
useImperativeHandle(ref, () => ({
|
|
1064
|
+
open: () => popover.setIsOpen(true),
|
|
1065
|
+
close: () => popover.setIsOpen(false)
|
|
1066
|
+
}));
|
|
1067
|
+
return React.cloneElement(props.children, {
|
|
1068
|
+
ref: triggerRef,
|
|
1069
|
+
onPress: onTriggerPress,
|
|
1070
|
+
role: "button",
|
|
1071
|
+
accessible: true,
|
|
1072
|
+
accessibilityRole: "button",
|
|
1073
|
+
accessibilityState: { expanded: popover.isOpen },
|
|
1074
|
+
...props.children.props
|
|
1075
|
+
});
|
|
1076
|
+
});
|
|
1077
|
+
PopoverTrigger.displayName = "PopoverTrigger";
|
|
1078
|
+
|
|
1079
|
+
//#endregion
|
|
1080
|
+
//#region src/primitives/popover/popover-portal.tsx
|
|
1081
|
+
function PopoverPortal(props) {
|
|
1082
|
+
const popover = usePopover();
|
|
1083
|
+
if (!popover.isOpen) return null;
|
|
1084
|
+
return /* @__PURE__ */ jsx(Portal, {
|
|
1085
|
+
name: "popover-portal",
|
|
1086
|
+
children: /* @__PURE__ */ jsx(PopoverContext.Provider, {
|
|
1087
|
+
value: popover,
|
|
1088
|
+
children: props.children
|
|
1089
|
+
})
|
|
1090
|
+
});
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
//#endregion
|
|
1094
|
+
//#region src/primitives/popover/popover-overlay.tsx
|
|
1095
|
+
function PopoverOverlay(props) {
|
|
1096
|
+
const { closeOnPress = true, ...restProps } = props;
|
|
1097
|
+
const popover = usePopover();
|
|
1098
|
+
const composedStyle = [
|
|
1099
|
+
StyleSheet.absoluteFill,
|
|
1100
|
+
popover.styles?.overlay,
|
|
1101
|
+
props.style
|
|
1102
|
+
];
|
|
1103
|
+
return /* @__PURE__ */ jsx(props.render ?? Pressable, {
|
|
1104
|
+
...restProps,
|
|
1105
|
+
onPress: () => {
|
|
1106
|
+
if (closeOnPress) popover.setIsOpen(false);
|
|
1107
|
+
props.onPress?.();
|
|
1108
|
+
},
|
|
1109
|
+
style: composedStyle,
|
|
1110
|
+
children: props.children
|
|
1111
|
+
});
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
//#endregion
|
|
1115
|
+
//#region src/primitives/popover/popover-content.tsx
|
|
1116
|
+
function PopoverContent(props) {
|
|
1117
|
+
const popover = usePopover();
|
|
1118
|
+
const composedStyle = [
|
|
1119
|
+
useRelativePosition({
|
|
1120
|
+
align: "start",
|
|
1121
|
+
avoidCollisions: true,
|
|
1122
|
+
triggerPosition: popover.triggerPosition,
|
|
1123
|
+
contentLayout: popover.contentLayout,
|
|
1124
|
+
alignOffset: 0,
|
|
1125
|
+
side: "bottom",
|
|
1126
|
+
sideOffset: 0
|
|
1127
|
+
}),
|
|
1128
|
+
popover.styles?.content,
|
|
1129
|
+
props.style
|
|
1130
|
+
];
|
|
1131
|
+
return /* @__PURE__ */ jsx(props.render ?? View, {
|
|
1132
|
+
...props,
|
|
1133
|
+
onLayout: (e) => {
|
|
1134
|
+
popover.setContentLayout(e.nativeEvent.layout);
|
|
1135
|
+
},
|
|
1136
|
+
style: composedStyle
|
|
1137
|
+
});
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
//#endregion
|
|
1141
|
+
//#region src/primitives/popover/popover-close.tsx
|
|
1142
|
+
function PopoverClose(props) {
|
|
1143
|
+
const popover = usePopover();
|
|
1144
|
+
return /* @__PURE__ */ jsx(props.render ?? Pressable, {
|
|
1145
|
+
...props,
|
|
1146
|
+
onPress: () => {
|
|
1147
|
+
popover.setIsOpen(false);
|
|
1148
|
+
props.onPress?.();
|
|
1149
|
+
},
|
|
1150
|
+
style: props.style
|
|
1151
|
+
});
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1154
|
+
//#endregion
|
|
1155
|
+
//#region src/primitives/popover/index.ts
|
|
1156
|
+
const PopoverPrimitive = {
|
|
1157
|
+
Root: PopoverRoot,
|
|
1158
|
+
Trigger: PopoverTrigger,
|
|
1159
|
+
Portal: PopoverPortal,
|
|
1160
|
+
Overlay: PopoverOverlay,
|
|
1161
|
+
Content: PopoverContent,
|
|
1162
|
+
Close: PopoverClose
|
|
1163
|
+
};
|
|
1164
|
+
|
|
1165
|
+
//#endregion
|
|
1166
|
+
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-P_8clvQr.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";
|
package/package.json
CHANGED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { BadgePrimitive } from "@/primitives";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { BadgeVariants } from "./variants";
|
|
4
|
+
|
|
5
|
+
interface BadgeProps {
|
|
6
|
+
children: string;
|
|
7
|
+
variant?: keyof typeof BadgeVariants;
|
|
8
|
+
color?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function Badge(props: BadgeProps) {
|
|
12
|
+
const useVariantStyles = BadgeVariants[props.variant || "default"];
|
|
13
|
+
const styles = useVariantStyles();
|
|
14
|
+
|
|
15
|
+
// Override background color if custom color is provided
|
|
16
|
+
const customStyle = props.color ? { backgroundColor: props.color } : undefined;
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<BadgePrimitive.Root styles={styles} style={customStyle}>
|
|
20
|
+
<BadgePrimitive.Label>{props.children}</BadgePrimitive.Label>
|
|
21
|
+
</BadgePrimitive.Root>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { BadgeStyles } from "@/primitives";
|
|
2
|
+
import { useThemedStyles } from "@/utils/use-themed-styles";
|
|
3
|
+
|
|
4
|
+
export const useBadgeVariantDefault = (): BadgeStyles => {
|
|
5
|
+
return useThemedStyles(
|
|
6
|
+
({ colors, radius, fontFamily, fontSize }): BadgeStyles => ({
|
|
7
|
+
root: {
|
|
8
|
+
default: {
|
|
9
|
+
backgroundColor: colors.primary,
|
|
10
|
+
paddingVertical: 4,
|
|
11
|
+
paddingHorizontal: 8,
|
|
12
|
+
borderRadius: radius,
|
|
13
|
+
alignSelf: "flex-start",
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
label: {
|
|
17
|
+
default: {
|
|
18
|
+
color: colors.primaryForeground,
|
|
19
|
+
fontSize: fontSize * 0.75,
|
|
20
|
+
fontWeight: "600",
|
|
21
|
+
fontFamily,
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
})
|
|
25
|
+
);
|
|
26
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { BadgeStyles } from "@/primitives";
|
|
2
|
+
import { useThemedStyles } from "@/utils/use-themed-styles";
|
|
3
|
+
|
|
4
|
+
export const useBadgeVariantSecondary = (): BadgeStyles => {
|
|
5
|
+
return useThemedStyles(
|
|
6
|
+
({ colors, radius, fontFamily, fontSize }): BadgeStyles => ({
|
|
7
|
+
root: {
|
|
8
|
+
default: {
|
|
9
|
+
backgroundColor: colors.secondary,
|
|
10
|
+
paddingVertical: 4,
|
|
11
|
+
paddingHorizontal: 8,
|
|
12
|
+
borderRadius: radius,
|
|
13
|
+
alignSelf: "flex-start",
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
label: {
|
|
17
|
+
default: {
|
|
18
|
+
color: colors.secondaryForeground,
|
|
19
|
+
fontSize: fontSize * 0.75,
|
|
20
|
+
fontWeight: "600",
|
|
21
|
+
fontFamily,
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
})
|
|
25
|
+
);
|
|
26
|
+
};
|