@korsolutions/ui 0.0.24 → 0.0.26

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/README.md CHANGED
@@ -1,2 +1,5 @@
1
1
  # TODO
2
- - [ ] Line height
2
+ - [ ] Line height
3
+ - [ ] Letter spacing
4
+ - [ ] Custom safe area insets
5
+ - [ ] Custom portal host container
@@ -1,6 +1,7 @@
1
- import { Et as InputStyles, K as AvatarStyles, L as BadgeStyles, M as TextareaPrimitiveBaseProps, P as TextareaStyles, T as DropdownMenuStyles, V as ToastStyles, Z as EmptyStyles, _ as PopoverStyles, a as CalendarStyles, ft as SelectStyles, kt as FieldStyles, r as CalendarRootProps, rt as CardStyles, ut as SelectRootBaseProps, wt as InputPrimitiveBaseProps, x as PopoverTriggerRef, xt as ButtonStyles, yt as ButtonPrimitiveRootProps } from "../index-CCYJiglk.mjs";
1
+ import { $ as EmptyStyles, C as PopoverTriggerRef, Ct as ButtonStyles, D as DropdownMenuStyles, Et as InputPrimitiveBaseProps, I as TextareaStyles, J as AvatarStyles, Ot as InputStyles, P as TextareaPrimitiveBaseProps, U as ToastStyles, a as CalendarStyles, at as CardStyles, ft as SelectRootBaseProps, jt as FieldStyles, mt as SelectStyles, r as CalendarRootProps, xt as ButtonPrimitiveRootProps, y as PopoverStyles, z as BadgeStyles } from "../index-j_OCsdsx.mjs";
2
2
  import "../use-relative-position-DBzhrBU7.mjs";
3
- import { t as NumericMaskFormat } from "../use-numeric-mask-B9WZG25o.mjs";
3
+ import "../portal.constants-ClRV24_C.mjs";
4
+ import { t as NumericMaskFormat } from "../use-numeric-mask-D4zqPOnE.mjs";
4
5
  import React from "react";
5
6
  import { ImageSource, PressableProps, TextProps, TextStyle } from "react-native";
6
7
 
@@ -1,5 +1,5 @@
1
- import { i as useThemedStyles, r as ToastComponent, t as ToastAPI } from "../toast-manager-Cdhl1ep0.mjs";
2
- import { a as TextareaPrimitive, c as AvatarPrimitive, d as SelectPrimitive, f as ButtonPrimitive, i as DropdownMenuPrimitive, l as EmptyPrimitive, m as FieldPrimitive, n as PopoverPrimitive, o as BadgePrimitive, p as InputPrimitive, r as usePopover, t as CalendarPrimitive, u as CardPrimitive } from "../primitives-ApsPS0vU.mjs";
1
+ import { i as useThemedStyles, r as ToastComponent, t as ToastAPI } from "../toast-manager-Bn8NB8Ie.mjs";
2
+ import { a as TextareaPrimitive, c as AvatarPrimitive, d as SelectPrimitive, f as ButtonPrimitive, i as DropdownMenuPrimitive, l as EmptyPrimitive, m as FieldPrimitive, n as PopoverPrimitive, o as BadgePrimitive, p as InputPrimitive, r as usePopover, t as CalendarPrimitive, u as CardPrimitive } from "../primitives-CB1VBoeH.mjs";
3
3
  import "../use-relative-position-BTKEyT1F.mjs";
4
4
  import { t as useNumericMask } from "../use-numeric-mask-BQlz1Pus.mjs";
5
5
  import React, { forwardRef, useEffect, useState } from "react";
@@ -282,7 +282,7 @@ function Field(props) {
282
282
  styles: variantStyles,
283
283
  children: [
284
284
  props.label && /* @__PURE__ */ jsx(FieldPrimitive.Label, {
285
- htmlFor: props.id,
285
+ for: props.id,
286
286
  children: props.label
287
287
  }),
288
288
  props.description && /* @__PURE__ */ jsx(FieldPrimitive.Description, { children: props.description }),
@@ -1,5 +1,5 @@
1
1
  import { i as useRelativePosition, n as DEFAULT_POSITION, r as LayoutPosition, t as DEFAULT_LAYOUT } from "../use-relative-position-DBzhrBU7.mjs";
2
- import { i as useNumericMask, n as UseNumericMaskOptions, r as UseNumericMaskReturn, t as NumericMaskFormat } from "../use-numeric-mask-B9WZG25o.mjs";
2
+ import { i as useNumericMask, n as UseNumericMaskOptions, r as UseNumericMaskReturn, t as NumericMaskFormat } from "../use-numeric-mask-D4zqPOnE.mjs";
3
3
 
4
4
  //#region src/hooks/use-screen-size.d.ts
5
5
  type ScreenSize = "mobile" | "tablet" | "desktop";
@@ -1,12 +1,13 @@
1
1
  import { r as LayoutPosition } from "./use-relative-position-DBzhrBU7.mjs";
2
- import * as react8 from "react";
2
+ import { n as PortalHostProps, r as PortalProps } from "./portal.constants-ClRV24_C.mjs";
3
+ import * as react9 from "react";
3
4
  import React$1, { Dispatch, RefAttributes } from "react";
4
- import { ImageSource, ImageStyle, LayoutRectangle, PressableProps, StyleProp, TextInputProps, TextProps, TextStyle, View, ViewProps, ViewStyle } from "react-native";
5
+ import { ImageSource, ImageStyle, LayoutRectangle, PressableProps, StyleProp, TextInput, TextInputProps, TextProps, TextStyle, View, ViewProps, ViewStyle } from "react-native";
5
6
 
6
7
  //#region src/primitives/field/field-label.d.ts
7
8
  interface FieldLabelProps {
8
9
  children: string;
9
- htmlFor?: string;
10
+ for?: string;
10
11
  render?: (props: FieldLabelProps) => React$1.ReactNode;
11
12
  style?: TextProps["style"];
12
13
  }
@@ -59,6 +60,7 @@ type InputStyles = Partial<Record<InputState, InputPrimitiveBaseProps>>;
59
60
  //#endregion
60
61
  //#region src/primitives/input/input.d.ts
61
62
  type InputPrimitiveBaseProps = Omit<TextInputProps, "onChange"> & {
63
+ ref?: React.Ref<TextInput>;
62
64
  onChange?: TextInputProps["onChangeText"];
63
65
  isDisabled?: boolean;
64
66
  };
@@ -66,7 +68,7 @@ interface InputPrimitiveProps extends InputPrimitiveBaseProps {
66
68
  render?: (props: InputPrimitiveProps) => React.ReactNode;
67
69
  styles?: InputStyles;
68
70
  }
69
- declare function InputPrimitive(props: InputPrimitiveProps): react8.JSX.Element;
71
+ declare const InputPrimitive: react9.ForwardRefExoticComponent<Omit<InputPrimitiveProps, "ref"> & react9.RefAttributes<TextInput>>;
70
72
  //#endregion
71
73
  //#region src/primitives/button/button-label.d.ts
72
74
  interface ButtonPrimitiveLabelProps {
@@ -152,7 +154,7 @@ interface SelectOptionProps {
152
154
  render?: (props: SelectOptionProps) => React.ReactElement;
153
155
  style?: StyleProp<TextStyle>;
154
156
  }
155
- declare function SelectOption(props: SelectOptionProps): react8.JSX.Element;
157
+ declare function SelectOption(props: SelectOptionProps): react9.JSX.Element;
156
158
  //#endregion
157
159
  //#region src/primitives/select/types.d.ts
158
160
  type SelectState = "default" | "disabled";
@@ -433,7 +435,7 @@ interface TextareaPrimitiveProps extends TextareaPrimitiveBaseProps {
433
435
  render?: (props: TextareaPrimitiveProps) => React.ReactNode;
434
436
  styles?: TextareaStyles;
435
437
  }
436
- declare function TextareaPrimitive(props: TextareaPrimitiveProps): react8.JSX.Element;
438
+ declare function TextareaPrimitive(props: TextareaPrimitiveProps): react9.JSX.Element;
437
439
  //#endregion
438
440
  //#region src/primitives/dropdown-menu/dropdown-menu-trigger.d.ts
439
441
  interface DropdownMenuTriggerProps extends PressableProps {
@@ -504,7 +506,7 @@ declare function DropdownMenuPortal(props: DropdownMenuPortalProps): React$1.JSX
504
506
  //#region src/primitives/dropdown-menu/index.d.ts
505
507
  declare const DropdownMenuPrimitive: {
506
508
  Root: typeof DropdownMenuRoot;
507
- Trigger: react8.ForwardRefExoticComponent<DropdownMenuTriggerProps & react8.RefAttributes<DropdownMenuTriggerRef>>;
509
+ Trigger: react9.ForwardRefExoticComponent<DropdownMenuTriggerProps & react9.RefAttributes<DropdownMenuTriggerRef>>;
508
510
  Portal: typeof DropdownMenuPortal;
509
511
  Overlay: typeof DropdownMenuOverlay;
510
512
  Content: typeof DropdownMenuContent;
@@ -578,19 +580,32 @@ interface PopoverContext {
578
580
  setTriggerPosition: Dispatch<React.SetStateAction<LayoutPosition>>;
579
581
  styles?: PopoverStyles;
580
582
  }
581
- declare const PopoverContext: react8.Context<PopoverContext | undefined>;
583
+ declare const PopoverContext: react9.Context<PopoverContext | undefined>;
582
584
  declare const usePopover: () => PopoverContext;
583
585
  //#endregion
584
586
  //#region src/primitives/popover/index.d.ts
585
587
  declare const PopoverPrimitive: {
586
588
  Root: typeof PopoverRoot;
587
- Trigger: react8.ForwardRefExoticComponent<PopoverTriggerProps & react8.RefAttributes<PopoverTriggerRef>>;
589
+ Trigger: react9.ForwardRefExoticComponent<PopoverTriggerProps & react9.RefAttributes<PopoverTriggerRef>>;
588
590
  Portal: typeof PopoverPortal;
589
591
  Overlay: typeof PopoverOverlay;
590
592
  Content: typeof PopoverContent;
591
593
  Close: typeof PopoverClose;
592
594
  };
593
595
  //#endregion
596
+ //#region src/primitives/portal/portal.d.ts
597
+ declare function NativePortalHost({
598
+ name,
599
+ container
600
+ }: PortalHostProps): react9.JSX.Element | null;
601
+ declare const PortalHost: typeof NativePortalHost;
602
+ declare function NativePortal({
603
+ name,
604
+ hostName,
605
+ children
606
+ }: PortalProps): react9.JSX.Element;
607
+ declare const Portal: typeof NativePortal;
608
+ //#endregion
594
609
  //#region src/primitives/calendar/calendar-weeks.d.ts
595
610
  interface CalendarWeekProps extends ViewProps {
596
611
  index: number;
@@ -686,4 +701,4 @@ declare const CalendarPrimitive: {
686
701
  Day: typeof CalendarDay;
687
702
  };
688
703
  //#endregion
689
- export { EmptyMediaProps as $, DropdownMenuTriggerProps as A, FieldErrorProps as At, ToastRootProps as B, DropdownMenuPortalProps as C, InputPrimitive as Ct, DropdownMenuDividerProps as D, FieldPrimitive as Dt, DropdownMenuOverlayProps as E, InputStyles as Et, BadgePrimitive as F, AvatarRootProps as G, ToastDescriptionProps as H, BadgeRootProps as I, AvatarFallbackProps as J, AvatarStyles as K, BadgeStyles as L, TextareaPrimitiveBaseProps as M, FieldLabelProps as Mt, TextareaPrimitiveProps as N, DropdownMenuButtonProps as O, FieldPrimitiveRootProps as Ot, TextareaStyles as P, EmptyTitleProps as Q, BadgeLabelProps as R, DropdownMenuPrimitive as S, ButtonPrimitiveLabelProps as St, DropdownMenuStyles as T, InputPrimitiveProps as Tt, ToastTitleProps as U, ToastStyles as V, AvatarPrimitive as W, EmptyRootProps as X, EmptyPrimitive as Y, EmptyStyles as Z, PopoverStyles as _, SelectTriggerProps as _t, CalendarStyles as a, CardBodyProps as at, PopoverTriggerProps as b, ButtonState as bt, CalendarDayProps as c, SelectPrimitive as ct, PopoverPrimitive as d, SelectRootProps as dt, EmptyDescriptionProps as et, PopoverContext as f, SelectStyles as ft, PopoverRootProps as g, SelectValueProps as gt, PopoverPortalProps as h, SelectOverlayProps as ht, CalendarDayState as i, CardFooterProps as it, TextareaPrimitive as j, FieldDescriptionProps as jt, DropdownMenuContentProps as k, FieldStyles as kt, CalendarWeekLabelsProps as l, SelectPortalProps as lt, PopoverCloseProps as m, SelectContentProps as mt, CalendarNavButtonProps as n, CardRootProps as nt, CalendarTitleProps as o, CardTitleProps as ot, usePopover as p, SelectOptionProps as pt, AvatarImageProps as q, CalendarRootProps as r, CardStyles as rt, CalendarHeaderProps as s, CardHeaderProps as st, CalendarPrimitive as t, CardPrimitive as tt, CalendarWeeksProps as u, SelectRootBaseProps as ut, PopoverOverlayProps as v, ButtonPrimitive as vt, DropdownMenuRootProps as w, InputPrimitiveBaseProps as wt, PopoverTriggerRef as x, ButtonStyles as xt, PopoverContentProps as y, ButtonPrimitiveRootProps as yt, ToastPrimitive as z };
704
+ export { EmptyStyles as $, DropdownMenuButtonProps as A, FieldPrimitiveRootProps as At, BadgeLabelProps as B, PopoverTriggerRef as C, ButtonStyles as Ct, DropdownMenuStyles as D, InputPrimitiveProps as Dt, DropdownMenuRootProps as E, InputPrimitiveBaseProps as Et, TextareaPrimitiveProps as F, ToastTitleProps as G, ToastRootProps as H, TextareaStyles as I, AvatarStyles as J, AvatarPrimitive as K, BadgePrimitive as L, DropdownMenuTriggerProps as M, FieldErrorProps as Mt, TextareaPrimitive as N, FieldDescriptionProps as Nt, DropdownMenuOverlayProps as O, InputStyles as Ot, TextareaPrimitiveBaseProps as P, FieldLabelProps as Pt, EmptyRootProps as Q, BadgeRootProps as R, PopoverTriggerProps as S, ButtonState as St, DropdownMenuPortalProps as T, InputPrimitive as Tt, ToastStyles as U, ToastPrimitive as V, ToastDescriptionProps as W, AvatarFallbackProps as X, AvatarImageProps as Y, EmptyPrimitive as Z, PopoverPortalProps as _, SelectOverlayProps as _t, CalendarStyles as a, CardStyles as at, PopoverOverlayProps as b, ButtonPrimitive as bt, CalendarDayProps as c, CardTitleProps as ct, Portal as d, SelectPortalProps as dt, EmptyTitleProps as et, PortalHost as f, SelectRootBaseProps as ft, PopoverCloseProps as g, SelectContentProps as gt, usePopover as h, SelectOptionProps as ht, CalendarDayState as i, CardRootProps as it, DropdownMenuContentProps as j, FieldStyles as jt, DropdownMenuDividerProps as k, FieldPrimitive as kt, CalendarWeekLabelsProps as l, CardHeaderProps as lt, PopoverContext as m, SelectStyles as mt, CalendarNavButtonProps as n, EmptyDescriptionProps as nt, CalendarTitleProps as o, CardFooterProps as ot, PopoverPrimitive as p, SelectRootProps as pt, AvatarRootProps as q, CalendarRootProps as r, CardPrimitive as rt, CalendarHeaderProps as s, CardBodyProps as st, CalendarPrimitive as t, EmptyMediaProps as tt, CalendarWeeksProps as u, SelectPrimitive as ut, PopoverRootProps as v, SelectValueProps as vt, DropdownMenuPrimitive as w, ButtonPrimitiveLabelProps as wt, PopoverContentProps as x, ButtonPrimitiveRootProps as xt, PopoverStyles as y, SelectTriggerProps as yt, BadgeStyles as z };
package/dist/index.d.mts CHANGED
@@ -1,3 +1,4 @@
1
+ import { n as PortalHostProps } from "./portal.constants-ClRV24_C.mjs";
1
2
  import * as react4 from "react";
2
3
 
3
4
  //#region src/themes/types.d.ts
@@ -41,10 +42,13 @@ declare const ThemeContext: react4.Context<ThemeContext | null>;
41
42
  declare const useTheme: () => ThemeContext;
42
43
  //#endregion
43
44
  //#region src/index.d.ts
44
- declare const UniversalUIProvider: ({
45
- children
46
- }: {
45
+ interface ProviderProps {
47
46
  children: React.ReactNode;
48
- }) => react4.JSX.Element;
47
+ portalContainer?: PortalHostProps["container"];
48
+ }
49
+ declare const UniversalUIProvider: ({
50
+ children,
51
+ portalContainer
52
+ }: ProviderProps) => react4.JSX.Element;
49
53
  //#endregion
50
- export { UniversalUIProvider, useTheme };
54
+ export { ProviderProps, UniversalUIProvider, useTheme };
package/dist/index.mjs CHANGED
@@ -1,14 +1,14 @@
1
- import { a as ThemeProvider, n as ToastContainer, o as useTheme } from "./toast-manager-Cdhl1ep0.mjs";
2
- import { h as PortalHost } from "./primitives-ApsPS0vU.mjs";
1
+ import { a as ThemeProvider, n as ToastContainer, o as useTheme } from "./toast-manager-Bn8NB8Ie.mjs";
2
+ import { g as PortalHost } from "./primitives-CB1VBoeH.mjs";
3
3
  import "./use-relative-position-BTKEyT1F.mjs";
4
4
  import { jsx, jsxs } from "react/jsx-runtime";
5
5
 
6
6
  //#region src/index.tsx
7
- const UniversalUIProvider = ({ children }) => {
7
+ const UniversalUIProvider = ({ children, portalContainer }) => {
8
8
  return /* @__PURE__ */ jsxs(ThemeProvider, { children: [
9
+ /* @__PURE__ */ jsx(ToastContainer, {}),
9
10
  children,
10
- /* @__PURE__ */ jsx(PortalHost, {}),
11
- /* @__PURE__ */ jsx(ToastContainer, {})
11
+ /* @__PURE__ */ jsx(PortalHost, { container: portalContainer })
12
12
  ] });
13
13
  };
14
14
 
@@ -0,0 +1,16 @@
1
+ //#region src/primitives/portal/portal.constants.d.ts
2
+ declare const DEFAULT_PORTAL_HOST = "__KOR_PORTAL_HOST__";
3
+ interface PortalHostProps {
4
+ name?: string;
5
+ container?: {
6
+ ios?: React.ComponentType<React.PropsWithChildren>;
7
+ android?: React.ComponentType<React.PropsWithChildren>;
8
+ };
9
+ }
10
+ interface PortalProps {
11
+ name: string;
12
+ hostName?: string;
13
+ children: React.ReactNode;
14
+ }
15
+ //#endregion
16
+ export { PortalHostProps as n, PortalProps as r, DEFAULT_PORTAL_HOST as t };
@@ -1,3 +1,4 @@
1
- import { $ as EmptyMediaProps, A as DropdownMenuTriggerProps, At as FieldErrorProps, B as ToastRootProps, C as DropdownMenuPortalProps, Ct as InputPrimitive, D as DropdownMenuDividerProps, Dt as FieldPrimitive, E as DropdownMenuOverlayProps, Et as InputStyles, F as BadgePrimitive, G as AvatarRootProps, H as ToastDescriptionProps, I as BadgeRootProps, J as AvatarFallbackProps, K as AvatarStyles, L as BadgeStyles, M as TextareaPrimitiveBaseProps, Mt as FieldLabelProps, N as TextareaPrimitiveProps, O as DropdownMenuButtonProps, Ot as FieldPrimitiveRootProps, P as TextareaStyles, Q as EmptyTitleProps, R as BadgeLabelProps, S as DropdownMenuPrimitive, St as ButtonPrimitiveLabelProps, T as DropdownMenuStyles, Tt as InputPrimitiveProps, U as ToastTitleProps, V as ToastStyles, W as AvatarPrimitive, X as EmptyRootProps, Y as EmptyPrimitive, Z as EmptyStyles, _t as SelectTriggerProps, a as CalendarStyles, at as CardBodyProps, b as PopoverTriggerProps, bt as ButtonState, c as CalendarDayProps, ct as SelectPrimitive, d as PopoverPrimitive, dt as SelectRootProps, et as EmptyDescriptionProps, f as PopoverContext, ft as SelectStyles, g as PopoverRootProps, gt as SelectValueProps, h as PopoverPortalProps, ht as SelectOverlayProps, i as CalendarDayState, it as CardFooterProps, j as TextareaPrimitive, jt as FieldDescriptionProps, k as DropdownMenuContentProps, kt as FieldStyles, l as CalendarWeekLabelsProps, lt as SelectPortalProps, m as PopoverCloseProps, mt as SelectContentProps, n as CalendarNavButtonProps, nt as CardRootProps, o as CalendarTitleProps, ot as CardTitleProps, p as usePopover, pt as SelectOptionProps, q as AvatarImageProps, r as CalendarRootProps, rt as CardStyles, s as CalendarHeaderProps, st as CardHeaderProps, t as CalendarPrimitive, tt as CardPrimitive, u as CalendarWeeksProps, ut as SelectRootBaseProps, v as PopoverOverlayProps, vt as ButtonPrimitive, w as DropdownMenuRootProps, wt as InputPrimitiveBaseProps, x as PopoverTriggerRef, xt as ButtonStyles, y as PopoverContentProps, yt as ButtonPrimitiveRootProps, z as ToastPrimitive } from "../index-CCYJiglk.mjs";
1
+ import { $ as EmptyStyles, A as DropdownMenuButtonProps, At as FieldPrimitiveRootProps, B as BadgeLabelProps, C as PopoverTriggerRef, Ct as ButtonStyles, D as DropdownMenuStyles, Dt as InputPrimitiveProps, E as DropdownMenuRootProps, Et as InputPrimitiveBaseProps, F as TextareaPrimitiveProps, G as ToastTitleProps, H as ToastRootProps, I as TextareaStyles, J as AvatarStyles, K as AvatarPrimitive, L as BadgePrimitive, M as DropdownMenuTriggerProps, Mt as FieldErrorProps, N as TextareaPrimitive, Nt as FieldDescriptionProps, O as DropdownMenuOverlayProps, Ot as InputStyles, P as TextareaPrimitiveBaseProps, Pt as FieldLabelProps, Q as EmptyRootProps, R as BadgeRootProps, S as PopoverTriggerProps, St as ButtonState, T as DropdownMenuPortalProps, Tt as InputPrimitive, U as ToastStyles, V as ToastPrimitive, W as ToastDescriptionProps, X as AvatarFallbackProps, Y as AvatarImageProps, Z as EmptyPrimitive, _ as PopoverPortalProps, _t as SelectOverlayProps, a as CalendarStyles, at as CardStyles, b as PopoverOverlayProps, bt as ButtonPrimitive, c as CalendarDayProps, ct as CardTitleProps, d as Portal, dt as SelectPortalProps, et as EmptyTitleProps, f as PortalHost, ft as SelectRootBaseProps, g as PopoverCloseProps, gt as SelectContentProps, h as usePopover, ht as SelectOptionProps, i as CalendarDayState, it as CardRootProps, j as DropdownMenuContentProps, jt as FieldStyles, k as DropdownMenuDividerProps, kt as FieldPrimitive, l as CalendarWeekLabelsProps, lt as CardHeaderProps, m as PopoverContext, mt as SelectStyles, n as CalendarNavButtonProps, nt as EmptyDescriptionProps, o as CalendarTitleProps, ot as CardFooterProps, p as PopoverPrimitive, pt as SelectRootProps, q as AvatarRootProps, r as CalendarRootProps, rt as CardPrimitive, s as CalendarHeaderProps, st as CardBodyProps, t as CalendarPrimitive, tt as EmptyMediaProps, u as CalendarWeeksProps, ut as SelectPrimitive, v as PopoverRootProps, vt as SelectValueProps, w as DropdownMenuPrimitive, wt as ButtonPrimitiveLabelProps, x as PopoverContentProps, xt as ButtonPrimitiveRootProps, yt as SelectTriggerProps, z as BadgeStyles } from "../index-j_OCsdsx.mjs";
2
2
  import "../use-relative-position-DBzhrBU7.mjs";
3
- export { AvatarFallbackProps, AvatarImageProps, AvatarPrimitive, AvatarRootProps, AvatarStyles, BadgeLabelProps, BadgePrimitive, BadgeRootProps, BadgeStyles, ButtonPrimitive, ButtonPrimitiveLabelProps, ButtonPrimitiveRootProps, ButtonState, ButtonStyles, CalendarDayProps, CalendarDayState, CalendarHeaderProps, CalendarNavButtonProps, CalendarPrimitive, CalendarRootProps, CalendarStyles, CalendarTitleProps, CalendarWeekLabelsProps, CalendarWeeksProps, 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 };
3
+ import { n as PortalHostProps, r as PortalProps, t as DEFAULT_PORTAL_HOST } from "../portal.constants-ClRV24_C.mjs";
4
+ export { AvatarFallbackProps, AvatarImageProps, AvatarPrimitive, AvatarRootProps, AvatarStyles, BadgeLabelProps, BadgePrimitive, BadgeRootProps, BadgeStyles, ButtonPrimitive, ButtonPrimitiveLabelProps, ButtonPrimitiveRootProps, ButtonState, ButtonStyles, CalendarDayProps, CalendarDayState, CalendarHeaderProps, CalendarNavButtonProps, CalendarPrimitive, CalendarRootProps, CalendarStyles, CalendarTitleProps, CalendarWeekLabelsProps, CalendarWeeksProps, CardBodyProps, CardFooterProps, CardHeaderProps, CardPrimitive, CardRootProps, CardStyles, CardTitleProps, DEFAULT_PORTAL_HOST, 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, Portal, PortalHost, PortalHostProps, PortalProps, SelectContentProps, SelectOptionProps, SelectOverlayProps, SelectPortalProps, SelectPrimitive, SelectRootBaseProps, SelectRootProps, SelectStyles, SelectTriggerProps, SelectValueProps, TextareaPrimitive, TextareaPrimitiveBaseProps, TextareaPrimitiveProps, TextareaStyles, ToastDescriptionProps, ToastPrimitive, ToastRootProps, ToastStyles, ToastTitleProps, usePopover };
@@ -1,4 +1,4 @@
1
- import { a as TextareaPrimitive, c as AvatarPrimitive, d as SelectPrimitive, f as ButtonPrimitive, i as DropdownMenuPrimitive, l as EmptyPrimitive, m as FieldPrimitive, n as PopoverPrimitive, o as BadgePrimitive, p as InputPrimitive, r as usePopover, s as ToastPrimitive, t as CalendarPrimitive, u as CardPrimitive } from "../primitives-ApsPS0vU.mjs";
1
+ import { _ as DEFAULT_PORTAL_HOST, a as TextareaPrimitive, c as AvatarPrimitive, d as SelectPrimitive, f as ButtonPrimitive, g as PortalHost, h as Portal, i as DropdownMenuPrimitive, l as EmptyPrimitive, m as FieldPrimitive, n as PopoverPrimitive, o as BadgePrimitive, p as InputPrimitive, r as usePopover, s as ToastPrimitive, t as CalendarPrimitive, u as CardPrimitive } from "../primitives-CB1VBoeH.mjs";
2
2
  import "../use-relative-position-BTKEyT1F.mjs";
3
3
 
4
- export { AvatarPrimitive, BadgePrimitive, ButtonPrimitive, CalendarPrimitive, CardPrimitive, DropdownMenuPrimitive, EmptyPrimitive, FieldPrimitive, InputPrimitive, PopoverPrimitive, SelectPrimitive, TextareaPrimitive, ToastPrimitive, usePopover };
4
+ export { AvatarPrimitive, BadgePrimitive, ButtonPrimitive, CalendarPrimitive, CardPrimitive, DEFAULT_PORTAL_HOST, DropdownMenuPrimitive, EmptyPrimitive, FieldPrimitive, InputPrimitive, PopoverPrimitive, Portal, PortalHost, SelectPrimitive, TextareaPrimitive, ToastPrimitive, usePopover };
@@ -1,10 +1,14 @@
1
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";
2
+ import React, { createContext, forwardRef, useContext, useEffect, useId, useImperativeHandle, useMemo, useRef, useState, useSyncExternalStore } from "react";
3
+ import { ActivityIndicator, Image, Platform, Pressable, StyleSheet, Text, TextInput, View } from "react-native";
4
4
  import { Fragment, jsx } from "react/jsx-runtime";
5
+ import { createPortal } from "react-dom";
5
6
 
7
+ //#region src/primitives/portal/portal.constants.tsx
8
+ const DEFAULT_PORTAL_HOST = "__KOR_PORTAL_HOST__";
9
+
10
+ //#endregion
6
11
  //#region src/primitives/portal/portal.tsx
7
- const DEFAULT_PORTAL_HOST = "KOR_NATIVE_DEFAULT_HOST_NAME";
8
12
  const store = {
9
13
  map: (/* @__PURE__ */ new Map()).set(DEFAULT_PORTAL_HOST, /* @__PURE__ */ new Map()),
10
14
  listeners: /* @__PURE__ */ new Set()
@@ -37,12 +41,35 @@ function removePortal(hostName, name) {
37
41
  store.map = next;
38
42
  emit();
39
43
  }
40
- function PortalHost({ name = DEFAULT_PORTAL_HOST }) {
44
+ function NativePortalHost({ name = DEFAULT_PORTAL_HOST, container }) {
41
45
  const portalMap = useSyncExternalStore(subscribe, getSnapshot, getSnapshot).get(name) ?? /* @__PURE__ */ new Map();
42
46
  if (portalMap.size === 0) return null;
43
- return /* @__PURE__ */ jsx(Fragment, { children: Array.from(portalMap.values()) });
47
+ return /* @__PURE__ */ jsx(Platform.select({
48
+ default: (props) => /* @__PURE__ */ jsx(View, {
49
+ ...props,
50
+ style: {
51
+ position: "absolute",
52
+ top: 0,
53
+ left: 0,
54
+ right: 0,
55
+ bottom: 0,
56
+ elevation: 999,
57
+ zIndex: 999,
58
+ pointerEvents: "box-none"
59
+ }
60
+ }),
61
+ ios: container?.ios,
62
+ android: container?.android
63
+ }), { children: Array.from(portalMap.values()) });
44
64
  }
45
- function Portal({ name, hostName = DEFAULT_PORTAL_HOST, children }) {
65
+ function WebPortalHost() {
66
+ return /* @__PURE__ */ jsx(Fragment, {});
67
+ }
68
+ const PortalHost = Platform.select({
69
+ default: NativePortalHost,
70
+ web: WebPortalHost
71
+ });
72
+ function NativePortal({ name, hostName = DEFAULT_PORTAL_HOST, children }) {
46
73
  useEffect(() => {
47
74
  updatePortal(hostName, name, children);
48
75
  }, [
@@ -55,8 +82,24 @@ function Portal({ name, hostName = DEFAULT_PORTAL_HOST, children }) {
55
82
  removePortal(hostName, name);
56
83
  };
57
84
  }, [hostName, name]);
58
- return null;
85
+ return /* @__PURE__ */ jsx(Fragment, {});
86
+ }
87
+ function WebPortal({ name, hostName = DEFAULT_PORTAL_HOST, children }) {
88
+ const [container] = useState(() => {
89
+ let container$1 = document.getElementById(hostName);
90
+ if (!container$1) {
91
+ container$1 = document.createElement("div");
92
+ container$1.id = hostName;
93
+ document.body.appendChild(container$1);
94
+ }
95
+ return container$1;
96
+ });
97
+ return /* @__PURE__ */ jsx(Fragment, { children: createPortal(children, container, name) });
59
98
  }
99
+ const Portal = Platform.select({
100
+ default: NativePortal,
101
+ web: WebPortal
102
+ });
60
103
 
61
104
  //#endregion
62
105
  //#region src/primitives/field/context.ts
@@ -66,14 +109,21 @@ const useField = () => {
66
109
  if (!context) throw new Error("useField must be used within a FieldProvider");
67
110
  return context;
68
111
  };
112
+ const useFieldOptional = () => {
113
+ return useContext(FieldContext);
114
+ };
69
115
 
70
116
  //#endregion
71
117
  //#region src/primitives/field/field-root.tsx
72
118
  function FieldRoot(props) {
119
+ const id = useId();
73
120
  const composedStyles = [props.styles?.root, props.style];
74
121
  const Component = props.render ?? View;
75
122
  return /* @__PURE__ */ jsx(FieldContext.Provider, {
76
- value: { styles: props.styles },
123
+ value: {
124
+ styles: props.styles,
125
+ id
126
+ },
77
127
  children: /* @__PURE__ */ jsx(Component, {
78
128
  ...props,
79
129
  style: composedStyles
@@ -87,7 +137,7 @@ function FieldLabel(props) {
87
137
  const field = useField();
88
138
  return /* @__PURE__ */ jsx(props.render ?? Text, {
89
139
  ...props,
90
- htmlFor: props.htmlFor,
140
+ for: props.for ?? field.id,
91
141
  style: [field.styles?.label, props.style]
92
142
  });
93
143
  }
@@ -128,9 +178,10 @@ const calculateState$7 = (props, isFocused) => {
128
178
  if (isFocused) return "focused";
129
179
  return "default";
130
180
  };
131
- function InputPrimitive(props) {
181
+ const InputPrimitive = forwardRef((props, ref) => {
132
182
  const [isFocused, setIsFocused] = useState(false);
133
183
  const state = calculateState$7(props, isFocused);
184
+ const field = useFieldOptional();
134
185
  const composedStyles = [
135
186
  props.styles?.default?.style,
136
187
  props.styles?.[state]?.style,
@@ -143,6 +194,8 @@ function InputPrimitive(props) {
143
194
  };
144
195
  return /* @__PURE__ */ jsx(props.render ?? TextInput, {
145
196
  ...composedProps,
197
+ ref,
198
+ id: field?.id,
146
199
  onChange: void 0,
147
200
  onChangeText: props.onChange,
148
201
  onFocus: (e) => {
@@ -156,7 +209,8 @@ function InputPrimitive(props) {
156
209
  readOnly: props.isDisabled || props.readOnly,
157
210
  style: composedStyles
158
211
  });
159
- }
212
+ });
213
+ InputPrimitive.displayName = "InputPrimitive";
160
214
 
161
215
  //#endregion
162
216
  //#region src/primitives/button/button-context.tsx
@@ -1380,4 +1434,4 @@ const CalendarPrimitive = {
1380
1434
  };
1381
1435
 
1382
1436
  //#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 };
1437
+ export { DEFAULT_PORTAL_HOST as _, TextareaPrimitive as a, AvatarPrimitive as c, SelectPrimitive as d, ButtonPrimitive as f, PortalHost as g, Portal 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 { s as ToastPrimitive } from "./primitives-ApsPS0vU.mjs";
1
+ import { h as Portal, s as ToastPrimitive } from "./primitives-CB1VBoeH.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";
@@ -198,15 +198,16 @@ const ToastVariants = {
198
198
  //#region src/components/toast/toast.tsx
199
199
  function ToastComponent(props) {
200
200
  const useVariantStyles = ToastVariants[props.variant || "default"];
201
- const styles$1 = useVariantStyles();
201
+ const styles = useVariantStyles();
202
202
  return /* @__PURE__ */ jsxs(ToastPrimitive.Root, {
203
- styles: styles$1,
203
+ styles,
204
204
  children: [/* @__PURE__ */ jsx(ToastPrimitive.Title, { children: props.title }), !!props.description && /* @__PURE__ */ jsx(ToastPrimitive.Description, { children: props.description })]
205
205
  });
206
206
  }
207
207
 
208
208
  //#endregion
209
209
  //#region src/components/toast/toast-manager.tsx
210
+ const TOAST_PORTAL_NAME = "toast-portal";
210
211
  const store = {
211
212
  toasts: [],
212
213
  listeners: /* @__PURE__ */ new Set()
@@ -248,34 +249,25 @@ const ToastAPI = {
248
249
  function ToastContainer() {
249
250
  const toasts = useSyncExternalStore(subscribe, getSnapshot);
250
251
  if (!toasts.length) return null;
251
- return /* @__PURE__ */ jsx(View, {
252
- style: styles.container,
253
- pointerEvents: "box-none",
254
- children: toasts.map((toast) => /* @__PURE__ */ jsx(View, {
255
- style: styles.toastWrapper,
256
- children: /* @__PURE__ */ jsx(ToastComponent, {
252
+ return /* @__PURE__ */ jsx(Portal, {
253
+ name: TOAST_PORTAL_NAME,
254
+ children: /* @__PURE__ */ jsx(View, {
255
+ style: s.wrapper,
256
+ children: toasts.map((toast) => /* @__PURE__ */ jsx(ToastComponent, {
257
257
  title: toast.title,
258
258
  description: toast.description,
259
259
  variant: toast.variant
260
- })
261
- }, toast.id))
260
+ }, toast.id))
261
+ })
262
262
  });
263
263
  }
264
- const styles = StyleSheet.create({
265
- container: {
266
- position: "absolute",
267
- top: 50,
268
- left: 0,
269
- right: 0,
270
- alignItems: "center",
271
- gap: 12,
272
- zIndex: 9999
273
- },
274
- toastWrapper: {
275
- width: "100%",
276
- alignItems: "center"
277
- }
278
- });
264
+ const s = StyleSheet.create({ wrapper: {
265
+ width: "100%",
266
+ alignItems: "center",
267
+ position: "absolute",
268
+ top: 24,
269
+ gap: 8
270
+ } });
279
271
 
280
272
  //#endregion
281
273
  export { ThemeProvider as a, useThemedStyles as i, ToastContainer as n, useTheme as o, ToastComponent as r, ToastAPI as t };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@korsolutions/ui",
3
- "version": "0.0.24",
3
+ "version": "0.0.26",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.mjs",
6
6
  "module": "dist/index.mjs",
@@ -27,19 +27,15 @@
27
27
  "dev-source": "./src/hooks/index.ts"
28
28
  }
29
29
  },
30
- "scripts": {
31
- "build": "tsdown",
32
- "prepublish": "tsdown",
33
- "publish": "npm publish --access public",
34
- "ts-check": "tsc --noEmit"
35
- },
36
30
  "peerDependencies": {
37
31
  "react": "*",
32
+ "react-dom": "*",
38
33
  "react-native": "*",
39
34
  "react-native-web": "*"
40
35
  },
41
36
  "devDependencies": {
42
37
  "@types/react": "^19.2.3",
38
+ "@types/react-dom": "^19.2.3",
43
39
  "tsdown": "0.17.0-beta.4"
44
40
  },
45
41
  "repository": {
@@ -48,5 +44,10 @@
48
44
  },
49
45
  "bugs": {
50
46
  "url": "https://github.com/KorSoftwareSolutions/ui/issues"
47
+ },
48
+ "scripts": {
49
+ "build": "tsdown",
50
+ "prepublish": "tsdown",
51
+ "ts-check": "tsc --noEmit"
51
52
  }
52
- }
53
+ }
@@ -18,7 +18,7 @@ export function Field(props: FieldProps) {
18
18
 
19
19
  return (
20
20
  <FieldPrimitive.Root styles={variantStyles}>
21
- {props.label && <FieldPrimitive.Label htmlFor={props.id}>{props.label}</FieldPrimitive.Label>}
21
+ {props.label && <FieldPrimitive.Label for={props.id}>{props.label}</FieldPrimitive.Label>}
22
22
  {props.description && <FieldPrimitive.Description>{props.description}</FieldPrimitive.Description>}
23
23
  {props.children}
24
24
  {props.error && <FieldPrimitive.Error>{props.error}</FieldPrimitive.Error>}
@@ -2,6 +2,9 @@ import React, { useSyncExternalStore } from "react";
2
2
  import { View, StyleSheet } from "react-native";
3
3
  import { ToastComponent } from "./toast";
4
4
  import { ToastVariants } from "./variants";
5
+ import { Portal } from "@/primitives/portal";
6
+
7
+ export const TOAST_PORTAL_NAME = "toast-portal";
5
8
 
6
9
  export interface ToastConfig {
7
10
  id: string;
@@ -77,28 +80,22 @@ export function ToastContainer() {
77
80
  if (!toasts.length) return null;
78
81
 
79
82
  return (
80
- <View style={styles.container} pointerEvents="box-none">
81
- {toasts.map((toast) => (
82
- <View key={toast.id} style={styles.toastWrapper}>
83
- <ToastComponent title={toast.title} description={toast.description} variant={toast.variant} />
84
- </View>
85
- ))}
86
- </View>
83
+ <Portal name={TOAST_PORTAL_NAME}>
84
+ <View style={s.wrapper}>
85
+ {toasts.map((toast) => (
86
+ <ToastComponent key={toast.id} title={toast.title} description={toast.description} variant={toast.variant} />
87
+ ))}
88
+ </View>
89
+ </Portal>
87
90
  );
88
91
  }
89
92
 
90
- const styles = StyleSheet.create({
91
- container: {
92
- position: "absolute",
93
- top: 50,
94
- left: 0,
95
- right: 0,
96
- alignItems: "center",
97
- gap: 12,
98
- zIndex: 9999,
99
- },
100
- toastWrapper: {
93
+ const s = StyleSheet.create({
94
+ wrapper: {
101
95
  width: "100%",
102
96
  alignItems: "center",
97
+ position: "absolute",
98
+ top: 24,
99
+ gap: 8,
103
100
  },
104
101
  });
package/src/index.tsx CHANGED
@@ -1,13 +1,20 @@
1
1
  import { ThemeProvider } from "@/themes";
2
2
  import { PortalHost } from "./primitives/portal";
3
3
  import { ToastContainer } from "./components/toast/toast-manager";
4
+ import { PortalHostProps } from "./primitives/portal/portal.constants";
4
5
 
5
- export const UniversalUIProvider = ({ children }: { children: React.ReactNode }) => {
6
+ export interface ProviderProps {
7
+ children: React.ReactNode;
8
+
9
+ portalContainer?: PortalHostProps["container"];
10
+ }
11
+
12
+ export const UniversalUIProvider = ({ children, portalContainer }: ProviderProps) => {
6
13
  return (
7
14
  <ThemeProvider>
8
- {children}
9
- <PortalHost />
10
15
  <ToastContainer />
16
+ {children}
17
+ <PortalHost container={portalContainer} />
11
18
  </ThemeProvider>
12
19
  );
13
20
  };
@@ -3,6 +3,7 @@ import { FieldStyles } from "./types";
3
3
 
4
4
  export interface FieldContext {
5
5
  styles?: FieldStyles;
6
+ id: string;
6
7
  }
7
8
 
8
9
  export const FieldContext = createContext<FieldContext | undefined>(undefined);
@@ -14,3 +15,7 @@ export const useField = () => {
14
15
  }
15
16
  return context;
16
17
  };
18
+
19
+ export const useFieldOptional = () => {
20
+ return useContext(FieldContext);
21
+ };
@@ -5,7 +5,7 @@ import { Text, TextProps } from "react-native";
5
5
  export interface FieldLabelProps {
6
6
  children: string;
7
7
 
8
- htmlFor?: string;
8
+ for?: string;
9
9
 
10
10
  render?: (props: FieldLabelProps) => React.ReactNode;
11
11
 
@@ -16,5 +16,5 @@ export function FieldLabel(props: FieldLabelProps) {
16
16
  const field = useField();
17
17
 
18
18
  const Component = props.render ?? Text;
19
- return <Component {...props} htmlFor={props.htmlFor} style={[field.styles?.label, props.style]} />;
19
+ return <Component {...props} for={props.for ?? field.id} style={[field.styles?.label, props.style]} />;
20
20
  }
@@ -1,4 +1,4 @@
1
- import React from "react";
1
+ import React, { useId } from "react";
2
2
  import { StyleProp, View, ViewStyle } from "react-native";
3
3
  import { FieldContext } from "./context";
4
4
  import { FieldStyles } from "./types";
@@ -13,10 +13,11 @@ export interface FieldPrimitiveRootProps {
13
13
  }
14
14
 
15
15
  export function FieldRoot(props: FieldPrimitiveRootProps) {
16
+ const id = useId();
16
17
  const composedStyles = [props.styles?.root, props.style];
17
18
  const Component = props.render ?? View;
18
19
  return (
19
- <FieldContext.Provider value={{ styles: props.styles }}>
20
+ <FieldContext.Provider value={{ styles: props.styles, id }}>
20
21
  <Component {...props} style={composedStyles} />
21
22
  </FieldContext.Provider>
22
23
  );
@@ -10,4 +10,5 @@ export * from "./badge";
10
10
  export * from "./textarea";
11
11
  export * from "./dropdown-menu";
12
12
  export * from "./popover";
13
+ export * from "./portal";
13
14
  export * from "./calendar";
@@ -1,10 +1,11 @@
1
1
  import { TextInput, TextInputProps } from "react-native";
2
2
  import { InputState, InputStyles } from "./types";
3
- import { useState } from "react";
3
+ import { useState, forwardRef } from "react";
4
+ import { useFieldOptional } from "../field/context";
4
5
 
5
6
  export type InputPrimitiveBaseProps = Omit<TextInputProps, "onChange"> & {
7
+ ref?: React.Ref<TextInput>;
6
8
  onChange?: TextInputProps["onChangeText"];
7
-
8
9
  isDisabled?: boolean;
9
10
  };
10
11
 
@@ -24,9 +25,10 @@ const calculateState = (props: InputPrimitiveProps, isFocused: boolean): InputSt
24
25
  return "default";
25
26
  };
26
27
 
27
- export function InputPrimitive(props: InputPrimitiveProps) {
28
+ export const InputPrimitive = forwardRef<TextInput, InputPrimitiveProps>((props, ref) => {
28
29
  const [isFocused, setIsFocused] = useState(false);
29
30
  const state = calculateState(props, isFocused);
31
+ const field = useFieldOptional();
30
32
 
31
33
  const composedStyles = [props.styles?.default?.style, props.styles?.[state]?.style, props.style];
32
34
  const composedProps = {
@@ -35,9 +37,12 @@ export function InputPrimitive(props: InputPrimitiveProps) {
35
37
  ...props,
36
38
  };
37
39
  const Component = props.render ?? TextInput;
40
+
38
41
  return (
39
42
  <Component
40
43
  {...composedProps}
44
+ ref={ref}
45
+ id={field?.id}
41
46
  onChange={undefined}
42
47
  onChangeText={props.onChange}
43
48
  onFocus={(e) => {
@@ -52,4 +57,6 @@ export function InputPrimitive(props: InputPrimitiveProps) {
52
57
  style={composedStyles}
53
58
  />
54
59
  );
55
- }
60
+ });
61
+
62
+ InputPrimitive.displayName = "InputPrimitive";
@@ -1 +1,2 @@
1
1
  export * from "./portal";
2
+ export * from "./portal.constants";
@@ -0,0 +1,15 @@
1
+ export const DEFAULT_PORTAL_HOST = "__KOR_PORTAL_HOST__";
2
+
3
+ export interface PortalHostProps {
4
+ name?: string;
5
+ container?: {
6
+ ios?: React.ComponentType<React.PropsWithChildren>;
7
+ android?: React.ComponentType<React.PropsWithChildren>;
8
+ };
9
+ }
10
+
11
+ export interface PortalProps {
12
+ name: string;
13
+ hostName?: string;
14
+ children: React.ReactNode;
15
+ }
@@ -1,8 +1,7 @@
1
- import * as React from "react";
2
- import { useCallback, useEffect, useRef, useState, useSyncExternalStore } from "react";
3
- import { Platform, type View, type ViewStyle } from "react-native";
4
-
5
- const DEFAULT_PORTAL_HOST = "KOR_NATIVE_DEFAULT_HOST_NAME";
1
+ import { useEffect, useSyncExternalStore, useState } from "react";
2
+ import { Platform, View } from "react-native";
3
+ import { DEFAULT_PORTAL_HOST, PortalHostProps, PortalProps } from "./portal.constants";
4
+ import { createPortal } from "react-dom";
6
5
 
7
6
  type PortalMap = Map<string, React.ReactNode>;
8
7
  type PortalHostMap = Map<string, PortalMap>;
@@ -50,14 +49,44 @@ function removePortal(hostName: string, name: string) {
50
49
  emit();
51
50
  }
52
51
 
53
- export function PortalHost({ name = DEFAULT_PORTAL_HOST }: { name?: string }) {
52
+ function NativePortalHost({ name = DEFAULT_PORTAL_HOST, container }: PortalHostProps) {
54
53
  const map = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
55
54
  const portalMap = map.get(name) ?? new Map<string, React.ReactNode>();
56
55
  if (portalMap.size === 0) return null;
57
- return <>{Array.from(portalMap.values())}</>;
56
+
57
+ const Container = Platform.select({
58
+ default: (props: React.PropsWithChildren) => (
59
+ <View
60
+ {...props}
61
+ style={{
62
+ position: "absolute",
63
+ top: 0,
64
+ left: 0,
65
+ right: 0,
66
+ bottom: 0,
67
+ elevation: 999,
68
+ zIndex: 999,
69
+ pointerEvents: "box-none",
70
+ }}
71
+ />
72
+ ),
73
+ ios: container?.ios,
74
+ android: container?.android,
75
+ });
76
+
77
+ return <Container>{Array.from(portalMap.values())}</Container>;
58
78
  }
59
79
 
60
- export function Portal({ name, hostName = DEFAULT_PORTAL_HOST, children }: { name: string; hostName?: string; children: React.ReactNode }) {
80
+ function WebPortalHost() {
81
+ return <></>;
82
+ }
83
+
84
+ export const PortalHost = Platform.select({
85
+ default: NativePortalHost,
86
+ web: WebPortalHost,
87
+ });
88
+
89
+ function NativePortal({ name, hostName = DEFAULT_PORTAL_HOST, children }: PortalProps) {
61
90
  useEffect(() => {
62
91
  updatePortal(hostName, name, children);
63
92
  }, [hostName, name, children]);
@@ -68,28 +97,25 @@ export function Portal({ name, hostName = DEFAULT_PORTAL_HOST, children }: { nam
68
97
  };
69
98
  }, [hostName, name]);
70
99
 
71
- return null;
100
+ return <></>;
72
101
  }
73
102
 
74
- const ROOT: ViewStyle = {
75
- flex: 1,
76
- };
103
+ function WebPortal({ name, hostName = DEFAULT_PORTAL_HOST, children }: PortalProps) {
104
+ const [container] = useState(() => {
105
+ let container = document.getElementById(hostName);
77
106
 
78
- export function useModalPortalRoot() {
79
- const ref = useRef<View>(null);
80
- const [offset, setSideOffSet] = useState(0);
81
-
82
- const onLayout = useCallback(() => {
83
- if (Platform.OS === "web") return;
84
- ref.current?.measure((_x, _y, _width, _height, _pageX, pageY) => {
85
- setSideOffSet(-pageY);
86
- });
87
- }, []);
88
-
89
- return {
90
- ref,
91
- offset,
92
- onLayout,
93
- style: ROOT,
94
- };
107
+ if (!container) {
108
+ container = document.createElement("div");
109
+ container.id = hostName;
110
+ document.body.appendChild(container);
111
+ }
112
+ return container;
113
+ });
114
+
115
+ return <>{createPortal(children, container, name)}</>;
95
116
  }
117
+
118
+ export const Portal = Platform.select({
119
+ default: NativePortal,
120
+ web: WebPortal,
121
+ });