@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.
- package/dist/module/components/combobox/components/combobox-content.js +32 -0
- package/dist/module/components/combobox/components/combobox-content.js.map +1 -0
- package/dist/module/components/combobox/components/combobox-empty.js +20 -0
- package/dist/module/components/combobox/components/combobox-empty.js.map +1 -0
- package/dist/module/components/combobox/components/combobox-option.js +56 -0
- package/dist/module/components/combobox/components/combobox-option.js.map +1 -0
- package/dist/module/components/combobox/components/combobox-overlay.js +20 -0
- package/dist/module/components/combobox/components/combobox-overlay.js.map +1 -0
- package/dist/module/components/combobox/components/combobox-portal.js +29 -0
- package/dist/module/components/combobox/components/combobox-portal.js.map +1 -0
- package/dist/module/components/combobox/components/combobox-root.js +79 -0
- package/dist/module/components/combobox/components/combobox-root.js.map +1 -0
- package/dist/module/components/combobox/components/combobox-trigger.js +67 -0
- package/dist/module/components/combobox/components/combobox-trigger.js.map +1 -0
- package/dist/module/components/combobox/context.js +12 -0
- package/dist/module/components/combobox/context.js.map +1 -0
- package/dist/module/components/combobox/index.js +19 -0
- package/dist/module/components/combobox/index.js.map +1 -0
- package/dist/module/components/combobox/types.js +4 -0
- package/dist/module/components/combobox/types.js.map +1 -0
- package/dist/module/components/combobox/variants/default.js +106 -0
- package/dist/module/components/combobox/variants/default.js.map +1 -0
- package/dist/module/components/combobox/variants/index.js +7 -0
- package/dist/module/components/combobox/variants/index.js.map +1 -0
- package/dist/module/components/index.js +1 -0
- package/dist/module/components/index.js.map +1 -1
- package/dist/typescript/src/components/combobox/components/combobox-content.d.ts +8 -0
- package/dist/typescript/src/components/combobox/components/combobox-content.d.ts.map +1 -0
- package/dist/typescript/src/components/combobox/components/combobox-empty.d.ts +6 -0
- package/dist/typescript/src/components/combobox/components/combobox-empty.d.ts.map +1 -0
- package/dist/typescript/src/components/combobox/components/combobox-option.d.ts +8 -0
- package/dist/typescript/src/components/combobox/components/combobox-option.d.ts.map +1 -0
- package/dist/typescript/src/components/combobox/components/combobox-overlay.d.ts +8 -0
- package/dist/typescript/src/components/combobox/components/combobox-overlay.d.ts.map +1 -0
- package/dist/typescript/src/components/combobox/components/combobox-portal.d.ts +6 -0
- package/dist/typescript/src/components/combobox/components/combobox-portal.d.ts.map +1 -0
- package/dist/typescript/src/components/combobox/components/combobox-root.d.ts +19 -0
- package/dist/typescript/src/components/combobox/components/combobox-root.d.ts.map +1 -0
- package/dist/typescript/src/components/combobox/components/combobox-trigger.d.ts +6 -0
- package/dist/typescript/src/components/combobox/components/combobox-trigger.d.ts.map +1 -0
- package/dist/typescript/src/components/combobox/context.d.ts +25 -0
- package/dist/typescript/src/components/combobox/context.d.ts.map +1 -0
- package/dist/typescript/src/components/combobox/index.d.ts +25 -0
- package/dist/typescript/src/components/combobox/index.d.ts.map +1 -0
- package/dist/typescript/src/components/combobox/types.d.ts +21 -0
- package/dist/typescript/src/components/combobox/types.d.ts.map +1 -0
- package/dist/typescript/src/components/combobox/variants/default.d.ts +3 -0
- package/dist/typescript/src/components/combobox/variants/default.d.ts.map +1 -0
- package/dist/typescript/src/components/combobox/variants/index.d.ts +5 -0
- package/dist/typescript/src/components/combobox/variants/index.d.ts.map +1 -0
- package/dist/typescript/src/components/index.d.ts +1 -0
- package/dist/typescript/src/components/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/combobox/components/combobox-content.tsx +51 -0
- package/src/components/combobox/components/combobox-empty.tsx +28 -0
- package/src/components/combobox/components/combobox-option.tsx +81 -0
- package/src/components/combobox/components/combobox-overlay.tsx +36 -0
- package/src/components/combobox/components/combobox-portal.tsx +33 -0
- package/src/components/combobox/components/combobox-root.tsx +152 -0
- package/src/components/combobox/components/combobox-trigger.tsx +96 -0
- package/src/components/combobox/context.ts +40 -0
- package/src/components/combobox/index.ts +26 -0
- package/src/components/combobox/types.ts +23 -0
- package/src/components/combobox/variants/default.tsx +102 -0
- package/src/components/combobox/variants/index.ts +5 -0
- 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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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"}
|
|
@@ -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
|
@@ -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
|
+
}
|