@korsolutions/ui 0.0.20 → 0.0.22

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.
Files changed (46) hide show
  1. package/dist/components/index.d.mts +50 -2
  2. package/dist/components/index.mjs +177 -4
  3. package/dist/hooks/index.d.mts +32 -2
  4. package/dist/hooks/index.mjs +79 -2
  5. package/dist/{index-CGY0mO6z.d.mts → index-vgnXBa4Z.d.mts} +98 -10
  6. package/dist/index.d.mts +3 -3
  7. package/dist/index.mjs +3 -2
  8. package/dist/primitives/index.d.mts +3 -2
  9. package/dist/primitives/index.mjs +3 -2
  10. package/dist/{primitives-P_8clvQr.mjs → primitives-ApsPS0vU.mjs} +335 -118
  11. package/dist/{toast-manager-DSo9oN8w.mjs → toast-manager-Cdhl1ep0.mjs} +1 -1
  12. package/dist/use-numeric-mask-B9WZG25o.d.mts +33 -0
  13. package/dist/use-numeric-mask-BQlz1Pus.mjs +113 -0
  14. package/dist/use-relative-position-BTKEyT1F.mjs +106 -0
  15. package/dist/use-relative-position-DBzhrBU7.d.mts +61 -0
  16. package/package.json +1 -1
  17. package/src/components/calendar/calendar.tsx +31 -0
  18. package/src/components/calendar/index.ts +1 -0
  19. package/src/components/calendar/variants/default.tsx +127 -0
  20. package/src/components/calendar/variants/index.ts +5 -0
  21. package/src/components/index.ts +2 -1
  22. package/src/components/input/index.ts +2 -0
  23. package/src/components/input/numeric-input.tsx +73 -0
  24. package/src/hooks/index.ts +4 -1
  25. package/src/hooks/use-currency-mask.ts +141 -0
  26. package/src/hooks/use-numeric-mask.ts +202 -0
  27. package/src/primitives/calendar/calendar-day.tsx +64 -0
  28. package/src/primitives/calendar/calendar-header.tsx +21 -0
  29. package/src/primitives/calendar/calendar-nav-button.tsx +60 -0
  30. package/src/primitives/calendar/calendar-root.tsx +41 -0
  31. package/src/primitives/calendar/calendar-title.tsx +23 -0
  32. package/src/primitives/calendar/calendar-week-labels.tsx +45 -0
  33. package/src/primitives/calendar/calendar-weeks.tsx +47 -0
  34. package/src/primitives/calendar/context.ts +23 -0
  35. package/src/primitives/calendar/index.ts +26 -0
  36. package/src/primitives/calendar/types.ts +39 -0
  37. package/src/primitives/dropdown-menu/context.ts +1 -1
  38. package/src/primitives/dropdown-menu/dropdown-menu-content.tsx +1 -1
  39. package/src/primitives/dropdown-menu/dropdown-menu-root.tsx +1 -1
  40. package/src/primitives/index.ts +1 -0
  41. package/src/primitives/popover/context.ts +1 -1
  42. package/src/primitives/popover/popover-content.tsx +1 -1
  43. package/src/primitives/popover/popover-root.tsx +1 -1
  44. package/src/utils/date-utils.ts +113 -0
  45. /package/src/hooks/{useRelativePosition.ts → use-relative-position.ts} +0 -0
  46. /package/src/hooks/{useScreenSize.ts → use-screen-size.ts} +0 -0
@@ -1,6 +1,6 @@
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";
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, useMemo, useRef, useState, useSyncExternalStore } from "react";
3
+ import { ActivityIndicator, Image, Pressable, StyleSheet, Text, TextInput, View } from "react-native";
4
4
  import { Fragment, jsx } from "react/jsx-runtime";
5
5
 
6
6
  //#region src/primitives/portal/portal.tsx
@@ -123,14 +123,14 @@ const FieldPrimitive = {
123
123
 
124
124
  //#endregion
125
125
  //#region src/primitives/input/input.tsx
126
- const calculateState$5 = (props, isFocused) => {
126
+ const calculateState$7 = (props, isFocused) => {
127
127
  if (props.isDisabled) return "disabled";
128
128
  if (isFocused) return "focused";
129
129
  return "default";
130
130
  };
131
131
  function InputPrimitive(props) {
132
132
  const [isFocused, setIsFocused] = useState(false);
133
- const state = calculateState$5(props, isFocused);
133
+ const state = calculateState$7(props, isFocused);
134
134
  const composedStyles = [
135
135
  props.styles?.default?.style,
136
136
  props.styles?.[state]?.style,
@@ -169,7 +169,7 @@ const useButtonPrimitive = () => {
169
169
 
170
170
  //#endregion
171
171
  //#region src/primitives/button/button-root.tsx
172
- const calculateState$4 = (props, isHovered) => {
172
+ const calculateState$6 = (props, isHovered) => {
173
173
  if (props.isDisabled) return "disabled";
174
174
  if (props.isLoading) return "loading";
175
175
  if (isHovered) return "hovered";
@@ -177,7 +177,7 @@ const calculateState$4 = (props, isHovered) => {
177
177
  };
178
178
  function ButtonRoot(props) {
179
179
  const [isHovered, setIsHovered] = useState(false);
180
- const state = calculateState$4(props, isHovered);
180
+ const state = calculateState$6(props, isHovered);
181
181
  const calculatedStyle = [
182
182
  props.styles?.root?.default,
183
183
  props.styles?.root?.[state],
@@ -247,7 +247,7 @@ const useSelect = () => {
247
247
 
248
248
  //#endregion
249
249
  //#region src/primitives/select/select-root.tsx
250
- const calculateState$3 = (props) => {
250
+ const calculateState$5 = (props) => {
251
251
  if (props.isDisabled) return "disabled";
252
252
  return "default";
253
253
  };
@@ -255,7 +255,7 @@ function SelectRoot(props) {
255
255
  const [isOpen, setIsOpen] = useState(false);
256
256
  const [triggerLayout, setTriggerLayout] = useState(null);
257
257
  const [options, setOptions] = useState([]);
258
- const state = calculateState$3(props);
258
+ const state = calculateState$5(props);
259
259
  const composedStyles = calculateComposedStyles(props.styles, state, "root", props.style);
260
260
  const Component = props.render ?? View;
261
261
  return /* @__PURE__ */ jsx(SelectContext.Provider, {
@@ -371,7 +371,7 @@ function SelectContent(props) {
371
371
 
372
372
  //#endregion
373
373
  //#region src/primitives/select/select-option.tsx
374
- const calculateState$2 = (selectState, hovered, selected) => {
374
+ const calculateState$4 = (selectState, hovered, selected) => {
375
375
  if (selectState === "disabled") return "disabled";
376
376
  if (selected) return "selected";
377
377
  if (hovered) return "hovered";
@@ -381,7 +381,7 @@ function SelectOption(props) {
381
381
  const [isHovered, setIsHovered] = useState(false);
382
382
  const select = useSelect();
383
383
  const isSelected = select.value === props.value;
384
- const optionState = calculateState$2(select.state, isHovered, isSelected);
384
+ const optionState = calculateState$4(select.state, isHovered, isSelected);
385
385
  const composedStyles = calculateComposedStyles(select.styles, optionState, "option", props.style);
386
386
  useEffect(() => {
387
387
  select.setOptions((prev) => {
@@ -707,14 +707,14 @@ const BadgePrimitive = {
707
707
 
708
708
  //#endregion
709
709
  //#region src/primitives/textarea/textarea.tsx
710
- const calculateState$1 = (props, isFocused) => {
710
+ const calculateState$3 = (props, isFocused) => {
711
711
  if (props.isDisabled) return "disabled";
712
712
  if (isFocused) return "focused";
713
713
  return "default";
714
714
  };
715
715
  function TextareaPrimitive(props) {
716
716
  const [isFocused, setIsFocused] = useState(false);
717
- const state = calculateState$1(props, isFocused);
717
+ const state = calculateState$3(props, isFocused);
718
718
  const composedStyles = [
719
719
  props.styles?.default?.style,
720
720
  props.styles?.[state]?.style,
@@ -752,108 +752,6 @@ const useDropdownMenu = () => {
752
752
  return context;
753
753
  };
754
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
755
  //#endregion
858
756
  //#region src/primitives/dropdown-menu/dropdown-menu-root.tsx
859
757
  function DropdownMenuRoot(props) {
@@ -934,14 +832,14 @@ function DropdownMenuContent(props) {
934
832
 
935
833
  //#endregion
936
834
  //#region src/primitives/dropdown-menu/dropdown-menu-button.tsx
937
- const calculateState = (isHovered) => {
835
+ const calculateState$2 = (isHovered) => {
938
836
  if (isHovered) return "hovered";
939
837
  return "default";
940
838
  };
941
839
  function DropdownMenuButton(props) {
942
840
  const menu = useDropdownMenu();
943
841
  const [isHovered, setIsHovered] = useState(false);
944
- const state = calculateState(isHovered);
842
+ const state = calculateState$2(isHovered);
945
843
  const composedStyle = [
946
844
  menu.styles?.button?.default,
947
845
  menu.styles?.button?.[state],
@@ -1163,4 +1061,323 @@ const PopoverPrimitive = {
1163
1061
  };
1164
1062
 
1165
1063
  //#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 };
1064
+ //#region src/primitives/calendar/context.ts
1065
+ const CalendarContext = React.createContext(void 0);
1066
+ const useCalendarContext = () => {
1067
+ const context = React.useContext(CalendarContext);
1068
+ if (!context) throw new Error("Calendar components must be used within CalendarRoot");
1069
+ return context;
1070
+ };
1071
+
1072
+ //#endregion
1073
+ //#region src/primitives/calendar/calendar-root.tsx
1074
+ function CalendarRoot(props) {
1075
+ const { children, value, onChange, defaultMonth = /* @__PURE__ */ new Date(), minDate, maxDate, style, styles, ...viewProps } = props;
1076
+ const [currentMonth, setCurrentMonth] = useState(defaultMonth);
1077
+ const containerStyle = [styles?.root, style];
1078
+ return /* @__PURE__ */ jsx(CalendarContext.Provider, {
1079
+ value: {
1080
+ value,
1081
+ onChange,
1082
+ currentMonth,
1083
+ setCurrentMonth,
1084
+ styles,
1085
+ minDate,
1086
+ maxDate
1087
+ },
1088
+ children: /* @__PURE__ */ jsx(View, {
1089
+ ...viewProps,
1090
+ style: containerStyle,
1091
+ children
1092
+ })
1093
+ });
1094
+ }
1095
+
1096
+ //#endregion
1097
+ //#region src/primitives/calendar/calendar-header.tsx
1098
+ function CalendarHeader(props) {
1099
+ const { children, style, ...viewProps } = props;
1100
+ const { styles } = useCalendarContext();
1101
+ const headerStyle = [styles?.header, style];
1102
+ return /* @__PURE__ */ jsx(View, {
1103
+ ...viewProps,
1104
+ style: headerStyle,
1105
+ children
1106
+ });
1107
+ }
1108
+
1109
+ //#endregion
1110
+ //#region src/utils/date-utils.ts
1111
+ const formatDate = (date, format) => {
1112
+ const months = [
1113
+ "January",
1114
+ "February",
1115
+ "March",
1116
+ "April",
1117
+ "May",
1118
+ "June",
1119
+ "July",
1120
+ "August",
1121
+ "September",
1122
+ "October",
1123
+ "November",
1124
+ "December"
1125
+ ];
1126
+ const day = date.getDate();
1127
+ const month = months[date.getMonth()];
1128
+ const year = date.getFullYear();
1129
+ if (format === "MMMM yyyy") return `${month} ${year}`;
1130
+ if (format === "d") return day.toString();
1131
+ return date.toLocaleDateString();
1132
+ };
1133
+ const isDateSameDay = (date1, date2) => {
1134
+ return date1.getFullYear() === date2.getFullYear() && date1.getMonth() === date2.getMonth() && date1.getDate() === date2.getDate();
1135
+ };
1136
+ const isDateToday = (date) => {
1137
+ return isDateSameDay(date, /* @__PURE__ */ new Date());
1138
+ };
1139
+ const isDateBefore = (date1, date2) => {
1140
+ const d1 = new Date(date1.getFullYear(), date1.getMonth(), date1.getDate());
1141
+ const d2 = new Date(date2.getFullYear(), date2.getMonth(), date2.getDate());
1142
+ return d1.getTime() < d2.getTime();
1143
+ };
1144
+ const isDateAfter = (date1, date2) => {
1145
+ const d1 = new Date(date1.getFullYear(), date1.getMonth(), date1.getDate());
1146
+ const d2 = new Date(date2.getFullYear(), date2.getMonth(), date2.getDate());
1147
+ return d1.getTime() > d2.getTime();
1148
+ };
1149
+ const addMonths = (date, months) => {
1150
+ const newDate = new Date(date);
1151
+ newDate.setMonth(newDate.getMonth() + months);
1152
+ return newDate;
1153
+ };
1154
+ const subMonths = (date, months) => {
1155
+ return addMonths(date, -months);
1156
+ };
1157
+ const startOfMonth = (date) => {
1158
+ return new Date(date.getFullYear(), date.getMonth(), 1);
1159
+ };
1160
+ const endOfMonth = (date) => {
1161
+ return new Date(date.getFullYear(), date.getMonth() + 1, 0);
1162
+ };
1163
+ const getDaysInMonth = (date) => {
1164
+ return endOfMonth(date).getDate();
1165
+ };
1166
+ const getFirstDayOfMonth = (date) => {
1167
+ return startOfMonth(date).getDay();
1168
+ };
1169
+ const isSameMonth = (date1, date2) => {
1170
+ return date1.getFullYear() === date2.getFullYear() && date1.getMonth() === date2.getMonth();
1171
+ };
1172
+ const getWeekDays = (month, year, week) => {
1173
+ const days = [];
1174
+ const firstDayOfMonth = new Date(year, month, 1).getDay();
1175
+ const daysInMonth = getDaysInMonth(new Date(year, month));
1176
+ const startDay = week * 7 - (firstDayOfMonth === 0 ? 6 : firstDayOfMonth - 1);
1177
+ for (let i = 0; i < 7; i++) {
1178
+ const day = startDay + i;
1179
+ let date;
1180
+ if (day < 1) {
1181
+ const prevMonth = month === 0 ? 11 : month - 1;
1182
+ const prevYear = month === 0 ? year - 1 : year;
1183
+ const daysInPrevMonth = getDaysInMonth(new Date(prevYear, prevMonth));
1184
+ date = new Date(prevYear, prevMonth, daysInPrevMonth + day);
1185
+ } else if (day > daysInMonth) {
1186
+ const nextMonth = month === 11 ? 0 : month + 1;
1187
+ const nextYear = month === 11 ? year + 1 : year;
1188
+ date = new Date(nextYear, nextMonth, day - daysInMonth);
1189
+ } else date = new Date(year, month, day);
1190
+ days.push(date);
1191
+ }
1192
+ return days;
1193
+ };
1194
+ const getWeeksInMonth = (date) => {
1195
+ const firstDayOfMonth = getFirstDayOfMonth(date);
1196
+ const daysInMonth = getDaysInMonth(date);
1197
+ return Math.ceil((firstDayOfMonth + daysInMonth) / 7);
1198
+ };
1199
+
1200
+ //#endregion
1201
+ //#region src/primitives/calendar/calendar-title.tsx
1202
+ function CalendarTitle(props) {
1203
+ const { children, style, formatStr = "MMMM yyyy", ...textProps } = props;
1204
+ const { currentMonth, styles } = useCalendarContext();
1205
+ const titleStyle = [styles?.headerTitle, style];
1206
+ return /* @__PURE__ */ jsx(Text, {
1207
+ ...textProps,
1208
+ style: titleStyle,
1209
+ children: children ?? formatDate(currentMonth, formatStr)
1210
+ });
1211
+ }
1212
+
1213
+ //#endregion
1214
+ //#region src/primitives/calendar/calendar-nav-button.tsx
1215
+ const calculateState$1 = (isDisabled, isHovered) => {
1216
+ if (isDisabled) return "disabled";
1217
+ if (isHovered) return "hovered";
1218
+ return "default";
1219
+ };
1220
+ function CalendarNavButton(props) {
1221
+ const { children = props.direction === "prev" ? "‹" : "›", direction, style, textStyle, ...pressableProps } = props;
1222
+ const { currentMonth, setCurrentMonth, minDate, maxDate, styles } = useCalendarContext();
1223
+ const [isHovered, setIsHovered] = useState(false);
1224
+ const isDisabled = React.useMemo(() => {
1225
+ if (direction === "prev" && minDate) return subMonths(currentMonth, 1) < minDate;
1226
+ if (direction === "next" && maxDate) return addMonths(currentMonth, 1) > maxDate;
1227
+ return false;
1228
+ }, [
1229
+ direction,
1230
+ currentMonth,
1231
+ minDate,
1232
+ maxDate
1233
+ ]);
1234
+ const state = calculateState$1(isDisabled, isHovered);
1235
+ const handlePress = () => {
1236
+ if (isDisabled) return;
1237
+ setCurrentMonth(direction === "prev" ? subMonths(currentMonth, 1) : addMonths(currentMonth, 1));
1238
+ };
1239
+ const buttonStyle = [
1240
+ styles?.navButton?.default,
1241
+ styles?.navButton?.[state],
1242
+ style
1243
+ ];
1244
+ const textStyleCombined = [
1245
+ styles?.navButtonText?.default,
1246
+ styles?.navButtonText?.[state],
1247
+ textStyle
1248
+ ];
1249
+ return /* @__PURE__ */ jsx(Pressable, {
1250
+ ...pressableProps,
1251
+ onPress: handlePress,
1252
+ onHoverIn: () => setIsHovered(true),
1253
+ onHoverOut: () => setIsHovered(false),
1254
+ disabled: isDisabled,
1255
+ style: buttonStyle,
1256
+ children: /* @__PURE__ */ jsx(Text, {
1257
+ style: textStyleCombined,
1258
+ children
1259
+ })
1260
+ });
1261
+ }
1262
+
1263
+ //#endregion
1264
+ //#region src/primitives/calendar/calendar-week-labels.tsx
1265
+ function CalendarWeekLabel(props) {
1266
+ const { styles } = useCalendarContext();
1267
+ return /* @__PURE__ */ jsx(Text, {
1268
+ numberOfLines: 1,
1269
+ style: [styles?.weekLabel, props.style],
1270
+ children: props.children
1271
+ });
1272
+ }
1273
+ const DEFAULT_WEEK_DAYS = [
1274
+ "Su",
1275
+ "Mo",
1276
+ "Tu",
1277
+ "We",
1278
+ "Th",
1279
+ "Fr",
1280
+ "Sa"
1281
+ ];
1282
+ function CalendarWeekLabels(props) {
1283
+ const { weekDays = DEFAULT_WEEK_DAYS, style } = props;
1284
+ const { styles } = useCalendarContext();
1285
+ return /* @__PURE__ */ jsx(View, {
1286
+ style: [styles?.weekLabels, style],
1287
+ children: weekDays.map((day, index) => /* @__PURE__ */ jsx(CalendarWeekLabel, {
1288
+ style: styles?.weekLabel,
1289
+ children: day
1290
+ }, index))
1291
+ });
1292
+ }
1293
+
1294
+ //#endregion
1295
+ //#region src/primitives/calendar/calendar-day.tsx
1296
+ const calculateState = (date, selected, isCurrentMonth, isDisabled, isHovered) => {
1297
+ if (isDisabled) return "disabled";
1298
+ if (selected && isDateSameDay(date, selected)) return "selected";
1299
+ if (isDateToday(date)) return "today";
1300
+ if (isHovered) return "hovered";
1301
+ if (!isCurrentMonth) return "deprioritized";
1302
+ return "default";
1303
+ };
1304
+ function CalendarDay(props) {
1305
+ const calendar = useCalendarContext();
1306
+ const [isHovered, setIsHovered] = useState(false);
1307
+ const isCurrentMonth = isSameMonth(props.date, calendar.currentMonth);
1308
+ const isDisabled = useMemo(() => {
1309
+ if (calendar.minDate && isDateBefore(props.date, calendar.minDate)) return true;
1310
+ if (calendar.maxDate && isDateAfter(props.date, calendar.maxDate)) return true;
1311
+ return false;
1312
+ }, [
1313
+ props.date,
1314
+ calendar.minDate,
1315
+ calendar.maxDate
1316
+ ]);
1317
+ const state = calculateState(props.date, calendar.value, isCurrentMonth, isDisabled, isHovered);
1318
+ const handlePress = () => {
1319
+ console.log("Day pressed:", isDisabled, calendar.onChange);
1320
+ if (isDisabled || !calendar.onChange) return;
1321
+ calendar.onChange(props.date);
1322
+ };
1323
+ return /* @__PURE__ */ jsx(Pressable, {
1324
+ onPress: handlePress,
1325
+ onHoverIn: () => setIsHovered(true),
1326
+ onHoverOut: () => setIsHovered(false),
1327
+ disabled: isDisabled,
1328
+ style: [
1329
+ calendar.styles?.dayButton?.default,
1330
+ calendar.styles?.dayButton?.[state],
1331
+ props.style
1332
+ ],
1333
+ children: /* @__PURE__ */ jsx(Text, {
1334
+ style: [
1335
+ calendar.styles?.dayText?.default,
1336
+ calendar.styles?.dayText?.[state],
1337
+ props.textStyle
1338
+ ],
1339
+ children: formatDate(props.date, "d")
1340
+ })
1341
+ });
1342
+ }
1343
+
1344
+ //#endregion
1345
+ //#region src/primitives/calendar/calendar-weeks.tsx
1346
+ function CalendarWeek(props) {
1347
+ const { style, ...viewProps } = props;
1348
+ const { currentMonth, styles } = useCalendarContext();
1349
+ const days = getWeekDays(currentMonth.getMonth(), currentMonth.getFullYear(), props.index);
1350
+ const composedStyle = [styles?.week, style];
1351
+ return /* @__PURE__ */ jsx(View, {
1352
+ ...viewProps,
1353
+ style: composedStyle,
1354
+ children: days.map((day, index) => {
1355
+ return /* @__PURE__ */ jsx(CalendarDay, { date: day }, index);
1356
+ })
1357
+ });
1358
+ }
1359
+ function CalendarWeeks(props) {
1360
+ const { currentMonth, styles } = useCalendarContext();
1361
+ const weeks = getWeeksInMonth(currentMonth);
1362
+ return /* @__PURE__ */ jsx(View, {
1363
+ style: [styles?.weeks, props.style],
1364
+ children: Array.from({ length: weeks }).map((_, index) => {
1365
+ return /* @__PURE__ */ jsx(CalendarWeek, { index }, index);
1366
+ })
1367
+ });
1368
+ }
1369
+
1370
+ //#endregion
1371
+ //#region src/primitives/calendar/index.ts
1372
+ const CalendarPrimitive = {
1373
+ Root: CalendarRoot,
1374
+ Header: CalendarHeader,
1375
+ Title: CalendarTitle,
1376
+ NavButton: CalendarNavButton,
1377
+ CalendarWeekLabels,
1378
+ Weeks: CalendarWeeks,
1379
+ Day: CalendarDay
1380
+ };
1381
+
1382
+ //#endregion
1383
+ export { TextareaPrimitive as a, AvatarPrimitive as c, SelectPrimitive as d, ButtonPrimitive as f, PortalHost as h, DropdownMenuPrimitive as i, EmptyPrimitive as l, FieldPrimitive as m, PopoverPrimitive as n, BadgePrimitive as o, InputPrimitive as p, usePopover as r, ToastPrimitive as s, CalendarPrimitive as t, CardPrimitive as u };
@@ -1,4 +1,4 @@
1
- import { o as ToastPrimitive } from "./primitives-P_8clvQr.mjs";
1
+ import { s as ToastPrimitive } from "./primitives-ApsPS0vU.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 };