@korsolutions/ui 0.0.65 → 0.0.66

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 (66) hide show
  1. package/dist/module/components/combobox/components/combobox-content.js +32 -0
  2. package/dist/module/components/combobox/components/combobox-content.js.map +1 -0
  3. package/dist/module/components/combobox/components/combobox-empty.js +20 -0
  4. package/dist/module/components/combobox/components/combobox-empty.js.map +1 -0
  5. package/dist/module/components/combobox/components/combobox-option.js +56 -0
  6. package/dist/module/components/combobox/components/combobox-option.js.map +1 -0
  7. package/dist/module/components/combobox/components/combobox-overlay.js +20 -0
  8. package/dist/module/components/combobox/components/combobox-overlay.js.map +1 -0
  9. package/dist/module/components/combobox/components/combobox-portal.js +29 -0
  10. package/dist/module/components/combobox/components/combobox-portal.js.map +1 -0
  11. package/dist/module/components/combobox/components/combobox-root.js +79 -0
  12. package/dist/module/components/combobox/components/combobox-root.js.map +1 -0
  13. package/dist/module/components/combobox/components/combobox-trigger.js +67 -0
  14. package/dist/module/components/combobox/components/combobox-trigger.js.map +1 -0
  15. package/dist/module/components/combobox/context.js +12 -0
  16. package/dist/module/components/combobox/context.js.map +1 -0
  17. package/dist/module/components/combobox/index.js +19 -0
  18. package/dist/module/components/combobox/index.js.map +1 -0
  19. package/dist/module/components/combobox/types.js +4 -0
  20. package/dist/module/components/combobox/types.js.map +1 -0
  21. package/dist/module/components/combobox/variants/default.js +106 -0
  22. package/dist/module/components/combobox/variants/default.js.map +1 -0
  23. package/dist/module/components/combobox/variants/index.js +7 -0
  24. package/dist/module/components/combobox/variants/index.js.map +1 -0
  25. package/dist/module/components/index.js +1 -0
  26. package/dist/module/components/index.js.map +1 -1
  27. package/dist/typescript/src/components/combobox/components/combobox-content.d.ts +8 -0
  28. package/dist/typescript/src/components/combobox/components/combobox-content.d.ts.map +1 -0
  29. package/dist/typescript/src/components/combobox/components/combobox-empty.d.ts +6 -0
  30. package/dist/typescript/src/components/combobox/components/combobox-empty.d.ts.map +1 -0
  31. package/dist/typescript/src/components/combobox/components/combobox-option.d.ts +8 -0
  32. package/dist/typescript/src/components/combobox/components/combobox-option.d.ts.map +1 -0
  33. package/dist/typescript/src/components/combobox/components/combobox-overlay.d.ts +8 -0
  34. package/dist/typescript/src/components/combobox/components/combobox-overlay.d.ts.map +1 -0
  35. package/dist/typescript/src/components/combobox/components/combobox-portal.d.ts +6 -0
  36. package/dist/typescript/src/components/combobox/components/combobox-portal.d.ts.map +1 -0
  37. package/dist/typescript/src/components/combobox/components/combobox-root.d.ts +19 -0
  38. package/dist/typescript/src/components/combobox/components/combobox-root.d.ts.map +1 -0
  39. package/dist/typescript/src/components/combobox/components/combobox-trigger.d.ts +6 -0
  40. package/dist/typescript/src/components/combobox/components/combobox-trigger.d.ts.map +1 -0
  41. package/dist/typescript/src/components/combobox/context.d.ts +25 -0
  42. package/dist/typescript/src/components/combobox/context.d.ts.map +1 -0
  43. package/dist/typescript/src/components/combobox/index.d.ts +25 -0
  44. package/dist/typescript/src/components/combobox/index.d.ts.map +1 -0
  45. package/dist/typescript/src/components/combobox/types.d.ts +21 -0
  46. package/dist/typescript/src/components/combobox/types.d.ts.map +1 -0
  47. package/dist/typescript/src/components/combobox/variants/default.d.ts +3 -0
  48. package/dist/typescript/src/components/combobox/variants/default.d.ts.map +1 -0
  49. package/dist/typescript/src/components/combobox/variants/index.d.ts +5 -0
  50. package/dist/typescript/src/components/combobox/variants/index.d.ts.map +1 -0
  51. package/dist/typescript/src/components/index.d.ts +1 -0
  52. package/dist/typescript/src/components/index.d.ts.map +1 -1
  53. package/package.json +1 -1
  54. package/src/components/combobox/components/combobox-content.tsx +51 -0
  55. package/src/components/combobox/components/combobox-empty.tsx +28 -0
  56. package/src/components/combobox/components/combobox-option.tsx +81 -0
  57. package/src/components/combobox/components/combobox-overlay.tsx +36 -0
  58. package/src/components/combobox/components/combobox-portal.tsx +33 -0
  59. package/src/components/combobox/components/combobox-root.tsx +152 -0
  60. package/src/components/combobox/components/combobox-trigger.tsx +96 -0
  61. package/src/components/combobox/context.ts +40 -0
  62. package/src/components/combobox/index.ts +26 -0
  63. package/src/components/combobox/types.ts +23 -0
  64. package/src/components/combobox/variants/default.tsx +102 -0
  65. package/src/components/combobox/variants/index.ts +5 -0
  66. package/src/components/index.ts +1 -0
@@ -0,0 +1,19 @@
1
+ import React from "react";
2
+ import { type StyleProp, type ViewStyle } from "react-native";
3
+ import { ComboboxVariants } from "../variants";
4
+ export interface ComboboxRootProps {
5
+ variant?: keyof typeof ComboboxVariants;
6
+ value?: string;
7
+ onChange?: (value: string) => void;
8
+ /** Called when the search input text changes. Use for async/remote filtering. */
9
+ onSearchChange?: (query: string) => void;
10
+ /** Custom filter function. Receives option value and search query, returns whether to show the option.
11
+ * Default: case-insensitive match against option label/keywords.
12
+ * For async/remote filtering, pass `() => true` to show all options. */
13
+ filter?: (value: string, query: string) => boolean;
14
+ isDisabled?: boolean;
15
+ children?: React.ReactNode;
16
+ style?: StyleProp<ViewStyle>;
17
+ }
18
+ export declare function ComboboxRoot(props: ComboboxRootProps): React.JSX.Element;
19
+ //# sourceMappingURL=combobox-root.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"combobox-root.d.ts","sourceRoot":"","sources":["../../../../../../src/components/combobox/components/combobox-root.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAiD,MAAM,OAAO,CAAC;AACtE,OAAO,EAEL,KAAK,SAAS,EAGd,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAQtB,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/C,MAAM,WAAW,iBAAiB;IAChC,OAAO,CAAC,EAAE,MAAM,OAAO,gBAAgB,CAAC;IAExC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAEnC,iFAAiF;IACjF,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAEzC;;4EAEwE;IACxE,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;IAEnD,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;CAC9B;AA8BD,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,qBAsFpD"}
@@ -0,0 +1,6 @@
1
+ import React from "react";
2
+ export interface ComboboxTriggerProps {
3
+ placeholder?: string;
4
+ }
5
+ export declare function ComboboxTrigger(props: ComboboxTriggerProps): React.JSX.Element;
6
+ //# sourceMappingURL=combobox-trigger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"combobox-trigger.d.ts","sourceRoot":"","sources":["../../../../../../src/components/combobox/components/combobox-trigger.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4B,MAAM,OAAO,CAAC;AAOjD,MAAM,WAAW,oBAAoB;IACnC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAWD,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,qBA2E1D"}
@@ -0,0 +1,25 @@
1
+ import { type Dispatch } from "react";
2
+ import type { LayoutRectangle } from "react-native";
3
+ import type { LayoutPosition } from "../../hooks";
4
+ import type { ComboboxOption, ComboboxState, ComboboxStyles } from "./types";
5
+ export interface ComboboxContext {
6
+ value?: string;
7
+ onChange?: (value: string) => void;
8
+ isOpen: boolean;
9
+ setIsOpen: Dispatch<React.SetStateAction<boolean>>;
10
+ triggerPosition: LayoutPosition;
11
+ setTriggerPosition: Dispatch<React.SetStateAction<LayoutPosition>>;
12
+ contentLayout: LayoutRectangle;
13
+ setContentLayout: Dispatch<React.SetStateAction<LayoutRectangle>>;
14
+ options: Array<ComboboxOption>;
15
+ setOptions: Dispatch<React.SetStateAction<Array<ComboboxOption>>>;
16
+ searchQuery: string;
17
+ setSearchQuery: Dispatch<React.SetStateAction<string>>;
18
+ filter: (value: string, query: string) => boolean;
19
+ isDisabled: boolean;
20
+ state: ComboboxState;
21
+ styles: ComboboxStyles;
22
+ }
23
+ export declare const ComboboxContext: import("react").Context<ComboboxContext | undefined>;
24
+ export declare const useCombobox: () => ComboboxContext;
25
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../../../src/components/combobox/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,QAAQ,EAAc,MAAM,OAAO,CAAC;AACjE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE7E,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAEnC,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,EAAE,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IACnD,eAAe,EAAE,cAAc,CAAC;IAChC,kBAAkB,EAAE,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,CAAC,CAAC;IACnE,aAAa,EAAE,eAAe,CAAC;IAC/B,gBAAgB,EAAE,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC,CAAC;IAClE,OAAO,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC;IAC/B,UAAU,EAAE,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;IAElE,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC;IAEvD,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;IAElD,UAAU,EAAE,OAAO,CAAC;IAEpB,KAAK,EAAE,aAAa,CAAC;IACrB,MAAM,EAAE,cAAc,CAAC;CACxB;AAED,eAAO,MAAM,eAAe,sDAE3B,CAAC;AAEF,eAAO,MAAM,WAAW,uBAMvB,CAAC"}
@@ -0,0 +1,25 @@
1
+ import { ComboboxContent } from "./components/combobox-content";
2
+ import { ComboboxEmpty } from "./components/combobox-empty";
3
+ import { ComboboxOption } from "./components/combobox-option";
4
+ import { ComboboxOverlay } from "./components/combobox-overlay";
5
+ import { ComboboxPortal } from "./components/combobox-portal";
6
+ import { ComboboxRoot } from "./components/combobox-root";
7
+ import { ComboboxTrigger } from "./components/combobox-trigger";
8
+ export declare const Combobox: {
9
+ Root: typeof ComboboxRoot;
10
+ Trigger: typeof ComboboxTrigger;
11
+ Portal: typeof ComboboxPortal;
12
+ Overlay: typeof ComboboxOverlay;
13
+ Content: typeof ComboboxContent;
14
+ Option: typeof ComboboxOption;
15
+ Empty: typeof ComboboxEmpty;
16
+ };
17
+ export type { ComboboxContentProps } from "./components/combobox-content";
18
+ export type { ComboboxEmptyProps } from "./components/combobox-empty";
19
+ export type { ComboboxOptionProps } from "./components/combobox-option";
20
+ export type { ComboboxOverlayProps } from "./components/combobox-overlay";
21
+ export type { ComboboxPortalProps } from "./components/combobox-portal";
22
+ export type { ComboboxRootProps } from "./components/combobox-root";
23
+ export type { ComboboxTriggerProps } from "./components/combobox-trigger";
24
+ export type { ComboboxStyles } from "./types";
25
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/combobox/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAEhE,eAAO,MAAM,QAAQ;;;;;;;;CAQpB,CAAC;AAEF,YAAY,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAC1E,YAAY,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACtE,YAAY,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACxE,YAAY,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAC1E,YAAY,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACxE,YAAY,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AACpE,YAAY,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAC1E,YAAY,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC"}
@@ -0,0 +1,21 @@
1
+ import type { TextInputProps, TextStyle } from "react-native";
2
+ import type { ComboboxContentProps } from "./components/combobox-content";
3
+ import type { ComboboxOverlayProps } from "./components/combobox-overlay";
4
+ import type { ComboboxRootProps } from "./components/combobox-root";
5
+ export type ComboboxState = "default" | "disabled";
6
+ export type ComboboxTriggerState = ComboboxState | "focused";
7
+ export type ComboboxOptionState = ComboboxState | "hovered" | "selected";
8
+ export interface ComboboxStyles {
9
+ root?: Partial<Record<ComboboxState, ComboboxRootProps["style"]>>;
10
+ trigger?: Partial<Record<ComboboxTriggerState, TextInputProps>>;
11
+ overlay?: Partial<Record<ComboboxState, ComboboxOverlayProps["style"]>>;
12
+ content?: Partial<Record<ComboboxState, ComboboxContentProps["style"]>>;
13
+ option?: Partial<Record<ComboboxOptionState, TextStyle>>;
14
+ empty?: Partial<Record<ComboboxState, TextStyle>>;
15
+ }
16
+ export interface ComboboxOption {
17
+ value: string;
18
+ label: React.ReactNode;
19
+ keywords?: string[];
20
+ }
21
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../src/components/combobox/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAC1E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAC1E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAEpE,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,UAAU,CAAC;AACnD,MAAM,MAAM,oBAAoB,GAAG,aAAa,GAAG,SAAS,CAAC;AAC7D,MAAM,MAAM,mBAAmB,GAAG,aAAa,GAAG,SAAS,GAAG,UAAU,CAAC;AAEzE,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAClE,OAAO,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,oBAAoB,EAAE,cAAc,CAAC,CAAC,CAAC;IAChE,OAAO,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IACxE,OAAO,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IACxE,MAAM,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,mBAAmB,EAAE,SAAS,CAAC,CAAC,CAAC;IACzD,KAAK,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC,CAAC;CACnD;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB"}
@@ -0,0 +1,3 @@
1
+ import { type ComboboxStyles } from "../types";
2
+ export declare function useComboboxVariantDefault(): ComboboxStyles;
3
+ //# sourceMappingURL=default.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"default.d.ts","sourceRoot":"","sources":["../../../../../../src/components/combobox/variants/default.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,UAAU,CAAC;AAE/C,wBAAgB,yBAAyB,IAAI,cAAc,CAiG1D"}
@@ -0,0 +1,5 @@
1
+ import { useComboboxVariantDefault } from "./default";
2
+ export declare const ComboboxVariants: {
3
+ default: typeof useComboboxVariantDefault;
4
+ };
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/components/combobox/variants/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,WAAW,CAAC;AAEtD,eAAO,MAAM,gBAAgB;;CAE5B,CAAC"}
@@ -5,6 +5,7 @@ export * from "./badge";
5
5
  export * from "./button";
6
6
  export * from "./calendar";
7
7
  export * from "./card";
8
+ export * from "./combobox";
8
9
  export * from "./checkbox";
9
10
  export * from "./empty";
10
11
  export * from "./field";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,eAAe,CAAC;AAC9B,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC;AACvB,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,eAAe,CAAC;AAC9B,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC;AACvB,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@korsolutions/ui",
3
- "version": "0.0.65",
3
+ "version": "0.0.66",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -0,0 +1,51 @@
1
+ import React from "react";
2
+ import {
3
+ ScrollView,
4
+ StyleSheet,
5
+ type StyleProp,
6
+ type ViewStyle,
7
+ } from "react-native";
8
+ import { useRelativePosition } from "../../../hooks/use-relative-position";
9
+ import { useCombobox } from "../context";
10
+
11
+ export interface ComboboxContentProps {
12
+ children?: React.ReactNode;
13
+ style?: StyleProp<ViewStyle>;
14
+ }
15
+
16
+ export function ComboboxContent(props: ComboboxContentProps) {
17
+ const combobox = useCombobox();
18
+ const composedStyles = StyleSheet.flatten([
19
+ combobox.styles?.content?.default,
20
+ combobox.styles?.content?.[combobox.state],
21
+ props.style,
22
+ ]);
23
+
24
+ const flatStyles = StyleSheet.flatten(composedStyles);
25
+
26
+ const positionStyle = useRelativePosition({
27
+ align: "start",
28
+ triggerPosition: combobox.triggerPosition,
29
+ contentLayout: combobox.contentLayout,
30
+ alignOffset: 0,
31
+ preferredSide: "bottom",
32
+ sideOffset: 2,
33
+ });
34
+
35
+ return (
36
+ <ScrollView
37
+ style={[
38
+ positionStyle,
39
+ flatStyles,
40
+ { width: combobox.triggerPosition.width },
41
+ ]}
42
+ onLayout={(e) => {
43
+ combobox.setContentLayout(e.nativeEvent.layout);
44
+ }}
45
+ keyboardShouldPersistTaps="handled"
46
+ nestedScrollEnabled
47
+ >
48
+ {props.children}
49
+ </ScrollView>
50
+ );
51
+ }
@@ -0,0 +1,28 @@
1
+ import React from "react";
2
+ import { Text } from "react-native";
3
+ import { calculateComposedStyles } from "../../../utils/calculate-styles";
4
+ import { useCombobox } from "../context";
5
+
6
+ export interface ComboboxEmptyProps {
7
+ children?: React.ReactNode;
8
+ }
9
+
10
+ export function ComboboxEmpty(props: ComboboxEmptyProps) {
11
+ const combobox = useCombobox();
12
+
13
+ const hasVisibleOptions = combobox.options.some((option) =>
14
+ combobox.filter(option.value, combobox.searchQuery),
15
+ );
16
+
17
+ if (hasVisibleOptions) {
18
+ return null;
19
+ }
20
+
21
+ const composedStyles = calculateComposedStyles(
22
+ combobox.styles,
23
+ combobox.state,
24
+ "empty",
25
+ );
26
+
27
+ return <Text style={composedStyles}>{props.children}</Text>;
28
+ }
@@ -0,0 +1,81 @@
1
+ import React, { useEffect, useState } from "react";
2
+ import { Pressable, StyleSheet, Text } from "react-native";
3
+ import { useCombobox } from "../context";
4
+ import type { ComboboxOptionState, ComboboxState } from "../types";
5
+
6
+ export type ComboboxOptionProps = {
7
+ value: string;
8
+ label?: string;
9
+ children?: React.ReactNode;
10
+ };
11
+
12
+ const calculateState = (
13
+ comboboxState: ComboboxState,
14
+ hovered: boolean,
15
+ selected: boolean,
16
+ ): ComboboxOptionState => {
17
+ if (comboboxState === "disabled") {
18
+ return "disabled";
19
+ }
20
+ if (selected) {
21
+ return "selected";
22
+ }
23
+ if (hovered) {
24
+ return "hovered";
25
+ }
26
+ return "default";
27
+ };
28
+
29
+ export function ComboboxOption(
30
+ props: ComboboxOptionProps,
31
+ ): React.ReactElement | null {
32
+ const [isHovered, setIsHovered] = useState(false);
33
+ const combobox = useCombobox();
34
+ const isSelected = combobox.value === props.value;
35
+
36
+ const optionState = calculateState(combobox.state, isHovered, isSelected);
37
+ const composedStyles = StyleSheet.flatten([
38
+ combobox.styles?.option?.default,
39
+ combobox.styles?.option?.[optionState],
40
+ ]);
41
+
42
+ useEffect(() => {
43
+ combobox.setOptions((prev) => {
44
+ if (prev.find((option) => option.value === props.value)) {
45
+ return prev;
46
+ }
47
+ return [
48
+ ...prev,
49
+ {
50
+ value: props.value,
51
+ label: props.label ?? props.children,
52
+ },
53
+ ];
54
+ });
55
+ }, [props.value, props.label, props.children]);
56
+
57
+ if (!combobox.filter(props.value, combobox.searchQuery)) {
58
+ return null;
59
+ }
60
+
61
+ const Component = typeof props.children === "string" ? Text : Pressable;
62
+
63
+ return (
64
+ <Component
65
+ onPress={() => {
66
+ combobox.onChange?.(props.value);
67
+ combobox.setIsOpen(false);
68
+ combobox.setSearchQuery("");
69
+ }}
70
+ onPointerEnter={() => {
71
+ setIsHovered(true);
72
+ }}
73
+ onPointerLeave={() => {
74
+ setIsHovered(false);
75
+ }}
76
+ style={composedStyles}
77
+ >
78
+ {props.children}
79
+ </Component>
80
+ );
81
+ }
@@ -0,0 +1,36 @@
1
+ import React from "react";
2
+ import {
3
+ Pressable,
4
+ type StyleProp,
5
+ StyleSheet,
6
+ type ViewStyle,
7
+ } from "react-native";
8
+ import { useCombobox } from "../context";
9
+
10
+ export interface ComboboxOverlayProps {
11
+ children?: React.ReactNode;
12
+ style?: StyleProp<ViewStyle>;
13
+ }
14
+
15
+ export function ComboboxOverlay(props: ComboboxOverlayProps) {
16
+ const combobox = useCombobox();
17
+
18
+ const composedStyles = StyleSheet.flatten([
19
+ combobox.styles?.overlay?.default,
20
+ combobox.styles?.overlay?.[combobox.state],
21
+ props.style,
22
+ ]);
23
+
24
+ return (
25
+ <Pressable
26
+ onPress={() => {
27
+ combobox.setIsOpen(false);
28
+ combobox.setSearchQuery("");
29
+ }}
30
+ pointerEvents="auto"
31
+ style={[StyleSheet.absoluteFill, composedStyles]}
32
+ >
33
+ {props.children}
34
+ </Pressable>
35
+ );
36
+ }
@@ -0,0 +1,33 @@
1
+ import React from "react";
2
+ import { View } from "react-native";
3
+ import { Portal } from "../../portal";
4
+ import { ComboboxContext, useCombobox } from "../context";
5
+
6
+ export interface ComboboxPortalProps {
7
+ children?: React.ReactNode;
8
+ }
9
+
10
+ export function ComboboxPortal(props: ComboboxPortalProps) {
11
+ const combobox = useCombobox();
12
+
13
+ if (!combobox.isOpen) {
14
+ return (
15
+ <View
16
+ style={{ display: "none" }}
17
+ aria-hidden
18
+ accessibilityElementsHidden
19
+ importantForAccessibility="no-hide-descendants"
20
+ >
21
+ {props.children}
22
+ </View>
23
+ );
24
+ }
25
+
26
+ return (
27
+ <Portal name="combobox-portal">
28
+ <ComboboxContext.Provider value={combobox}>
29
+ {props.children}
30
+ </ComboboxContext.Provider>
31
+ </Portal>
32
+ );
33
+ }
@@ -0,0 +1,152 @@
1
+ import React, { useCallback, useMemo, useRef, useState } from "react";
2
+ import {
3
+ type LayoutRectangle,
4
+ type StyleProp,
5
+ StyleSheet,
6
+ View,
7
+ type ViewStyle,
8
+ } from "react-native";
9
+ import {
10
+ DEFAULT_LAYOUT,
11
+ DEFAULT_POSITION,
12
+ type LayoutPosition,
13
+ } from "../../../hooks";
14
+ import { ComboboxContext } from "../context";
15
+ import type { ComboboxOption, ComboboxState } from "../types";
16
+ import { ComboboxVariants } from "../variants";
17
+
18
+ export interface ComboboxRootProps {
19
+ variant?: keyof typeof ComboboxVariants;
20
+
21
+ value?: string;
22
+ onChange?: (value: string) => void;
23
+
24
+ /** Called when the search input text changes. Use for async/remote filtering. */
25
+ onSearchChange?: (query: string) => void;
26
+
27
+ /** Custom filter function. Receives option value and search query, returns whether to show the option.
28
+ * Default: case-insensitive match against option label/keywords.
29
+ * For async/remote filtering, pass `() => true` to show all options. */
30
+ filter?: (value: string, query: string) => boolean;
31
+
32
+ isDisabled?: boolean;
33
+
34
+ children?: React.ReactNode;
35
+ style?: StyleProp<ViewStyle>;
36
+ }
37
+
38
+ const calculateState = (props: ComboboxRootProps): ComboboxState => {
39
+ if (props.isDisabled) {
40
+ return "disabled";
41
+ }
42
+ return "default";
43
+ };
44
+
45
+ const defaultFilter = (
46
+ value: string,
47
+ query: string,
48
+ options: Array<ComboboxOption>,
49
+ ): boolean => {
50
+ if (!query) return true;
51
+ const lowerQuery = query.toLowerCase();
52
+ const option = options.find((o) => o.value === value);
53
+ if (!option) return true;
54
+
55
+ if (option.keywords) {
56
+ return option.keywords.some((kw) => kw.toLowerCase().includes(lowerQuery));
57
+ }
58
+
59
+ if (typeof option.label === "string") {
60
+ return option.label.toLowerCase().includes(lowerQuery);
61
+ }
62
+
63
+ return true;
64
+ };
65
+
66
+ export function ComboboxRoot(props: ComboboxRootProps) {
67
+ const variantStyles = ComboboxVariants[props.variant ?? "default"]();
68
+
69
+ const [isOpen, setIsOpen] = useState(false);
70
+ const [contentLayout, setContentLayout] =
71
+ useState<LayoutRectangle>(DEFAULT_LAYOUT);
72
+ const [triggerPosition, setTriggerPosition] =
73
+ useState<LayoutPosition>(DEFAULT_POSITION);
74
+ const [options, setOptions] = useState<Array<ComboboxOption>>([]);
75
+ const [searchQuery, setSearchQueryInternal] = useState("");
76
+
77
+ const onSearchChangeRef = useRef(props.onSearchChange);
78
+ onSearchChangeRef.current = props.onSearchChange;
79
+
80
+ const setSearchQuery: React.Dispatch<React.SetStateAction<string>> =
81
+ useCallback((action) => {
82
+ setSearchQueryInternal((prev) => {
83
+ const next = typeof action === "function" ? action(prev) : action;
84
+ if (next !== prev) {
85
+ onSearchChangeRef.current?.(next);
86
+ }
87
+ return next;
88
+ });
89
+ }, []);
90
+
91
+ const filterRef = useRef(props.filter);
92
+ filterRef.current = props.filter;
93
+
94
+ const optionsRef = useRef(options);
95
+ optionsRef.current = options;
96
+
97
+ const filter = useCallback(
98
+ (value: string, query: string) =>
99
+ filterRef.current
100
+ ? filterRef.current(value, query)
101
+ : defaultFilter(value, query, optionsRef.current),
102
+ [],
103
+ );
104
+
105
+ const state = calculateState(props);
106
+ const composedStyles = StyleSheet.flatten([
107
+ variantStyles?.root?.default,
108
+ variantStyles?.root?.[state],
109
+ props.style,
110
+ ]);
111
+
112
+ const contextValue: ComboboxContext = useMemo(
113
+ () => ({
114
+ value: props.value,
115
+ onChange: props.onChange,
116
+ isOpen,
117
+ setIsOpen,
118
+ triggerPosition,
119
+ setTriggerPosition,
120
+ contentLayout,
121
+ setContentLayout,
122
+ options,
123
+ setOptions,
124
+ searchQuery,
125
+ setSearchQuery,
126
+ filter,
127
+ state,
128
+ isDisabled: props.isDisabled ?? false,
129
+ styles: variantStyles,
130
+ }),
131
+ [
132
+ props.value,
133
+ props.onChange,
134
+ isOpen,
135
+ triggerPosition,
136
+ contentLayout,
137
+ options,
138
+ searchQuery,
139
+ setSearchQuery,
140
+ filter,
141
+ state,
142
+ props.isDisabled,
143
+ variantStyles,
144
+ ],
145
+ );
146
+
147
+ return (
148
+ <ComboboxContext.Provider value={contextValue}>
149
+ <View style={composedStyles}>{props.children}</View>
150
+ </ComboboxContext.Provider>
151
+ );
152
+ }
@@ -0,0 +1,96 @@
1
+ import React, { useEffect, useRef } from "react";
2
+ import { StyleSheet, TextInput, type TextInputProps } from "react-native";
3
+ import type { TextInputRef } from "../../../types/element.types";
4
+ import { measureLayoutPosition } from "../../../utils/normalize-layout";
5
+ import { useCombobox } from "../context";
6
+ import type { ComboboxTriggerState } from "../types";
7
+
8
+ export interface ComboboxTriggerProps {
9
+ placeholder?: string;
10
+ }
11
+
12
+ const calculateState = (
13
+ isDisabled: boolean,
14
+ isOpen: boolean,
15
+ ): ComboboxTriggerState => {
16
+ if (isDisabled) return "disabled";
17
+ if (isOpen) return "focused";
18
+ return "default";
19
+ };
20
+
21
+ export function ComboboxTrigger(props: ComboboxTriggerProps) {
22
+ const combobox = useCombobox();
23
+ const triggerRef = useRef<TextInputRef>(null);
24
+
25
+ const triggerState = calculateState(combobox.isDisabled, combobox.isOpen);
26
+ const selectedOption = combobox.options.find(
27
+ (option) => option.value === combobox.value,
28
+ );
29
+
30
+ const displayValue = combobox.isOpen
31
+ ? combobox.searchQuery
32
+ : selectedOption
33
+ ? typeof selectedOption.label === "string"
34
+ ? selectedOption.label
35
+ : selectedOption.value
36
+ : "";
37
+
38
+ const open = () => {
39
+ if (combobox.isDisabled) return;
40
+ combobox.setSearchQuery("");
41
+ requestAnimationFrame(() => {
42
+ measureLayoutPosition(triggerRef.current, (layout) => {
43
+ combobox.setTriggerPosition(layout);
44
+ combobox.setIsOpen(true);
45
+ });
46
+ });
47
+ };
48
+
49
+ useEffect(() => {
50
+ triggerRef.current?.setNativeProps({ text: displayValue });
51
+ }, [displayValue]);
52
+
53
+ useEffect(() => {
54
+ if (!combobox.isOpen) {
55
+ triggerRef.current?.blur();
56
+ }
57
+ }, [combobox.isOpen]);
58
+
59
+ const triggerStyles = combobox.styles?.trigger;
60
+ const composedProps: TextInputProps = {
61
+ ...triggerStyles?.default,
62
+ ...triggerStyles?.[triggerState],
63
+ ...props,
64
+ style: StyleSheet.flatten([
65
+ triggerStyles?.default?.style,
66
+ triggerStyles?.[triggerState]?.style,
67
+ ]),
68
+ };
69
+
70
+ const composedStyle = StyleSheet.flatten([
71
+ triggerStyles?.default?.style,
72
+ triggerStyles?.[triggerState]?.style,
73
+ ]);
74
+
75
+ return (
76
+ <TextInput
77
+ {...composedProps}
78
+ ref={triggerRef}
79
+ value={undefined}
80
+ onChange={undefined}
81
+ onChangeText={(text) => {
82
+ if (combobox.isDisabled) return;
83
+ combobox.setSearchQuery(text);
84
+ if (!combobox.isOpen) {
85
+ open();
86
+ }
87
+ }}
88
+ onFocus={() => {
89
+ if (!combobox.isOpen) {
90
+ open();
91
+ }
92
+ }}
93
+ style={composedStyle}
94
+ />
95
+ );
96
+ }