@bccampus/ui-components 0.7.2 → 0.8.0
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/.yarn/install-state.gz +0 -0
- package/.yarnrc.yml +0 -2
- package/dist/_chunks/createLucideIcon.js +11 -10
- package/dist/_chunks/index.js +2 -2
- package/dist/_chunks/index4.js +2 -2
- package/dist/components/index.js +18 -13
- package/dist/components/ui/composite/CompositeData.d.ts +9 -8
- package/dist/components/ui/composite/CompositeData.js +20 -14
- package/dist/components/ui/composite/{FocusProvider/AbstractFocusProvider.d.ts → FocusManager/AbstractFocusManager.d.ts} +2 -19
- package/dist/components/ui/composite/{FocusProvider/AbstractFocusProvider.js → FocusManager/AbstractFocusManager.js} +16 -5
- package/dist/components/ui/composite/{FocusProvider/ListboxFocusProvider.d.ts → FocusManager/ListboxFocusManager.d.ts} +2 -2
- package/dist/components/ui/composite/{FocusProvider/ListboxFocusProvider.js → FocusManager/ListboxFocusManager.js} +3 -3
- package/dist/components/ui/composite/FocusManager/index.d.ts +3 -0
- package/dist/components/ui/composite/FocusManager/index.js +6 -0
- package/dist/components/ui/composite/FocusManager/types.d.ts +20 -0
- package/dist/components/ui/composite/FocusManager/types.js +1 -0
- package/dist/components/ui/composite/{SelectionProvider/AbstractSelectionProvider.d.ts → SelectionManager/AbstractSelectionManager.d.ts} +5 -20
- package/dist/components/ui/composite/{SelectionProvider/AbstractSelectionProvider.js → SelectionManager/AbstractSelectionManager.js} +8 -4
- package/dist/components/ui/composite/{SelectionProvider/MultipleSelectionProvider.d.ts → SelectionManager/MultipleSelectionManager.d.ts} +3 -2
- package/dist/components/ui/composite/{SelectionProvider/MultipleSelectionProvider.js → SelectionManager/MultipleSelectionManager.js} +4 -3
- package/dist/components/ui/composite/{SelectionProvider/SingleSelectionProvider.d.ts → SelectionManager/SingleSelectionManager.d.ts} +3 -2
- package/dist/components/ui/composite/{SelectionProvider/SingleSelectionProvider.js → SelectionManager/SingleSelectionManager.js} +6 -5
- package/dist/components/ui/composite/SelectionManager/index.d.ts +4 -0
- package/dist/components/ui/composite/SelectionManager/index.js +8 -0
- package/dist/components/ui/composite/SelectionManager/types.d.ts +19 -0
- package/dist/components/ui/composite/SelectionManager/types.js +1 -0
- package/dist/components/ui/composite/components/composite-component.d.ts +2 -0
- package/dist/components/ui/composite/{composite-component.js → components/composite-component.js} +16 -38
- package/dist/components/ui/composite/components/index.d.ts +5 -0
- package/dist/components/ui/composite/components/index.js +10 -0
- package/dist/components/ui/composite/{listbox.d.ts → components/listbox.d.ts} +1 -1
- package/dist/components/ui/composite/{listbox.js → components/listbox.js} +17 -12
- package/dist/components/ui/composite/components/types.d.ts +53 -0
- package/dist/components/ui/composite/components/types.js +1 -0
- package/dist/components/ui/composite/components/utils.d.ts +1 -0
- package/dist/components/ui/composite/components/utils.js +8 -0
- package/dist/components/ui/composite/create-composite-data.d.ts +80 -0
- package/dist/components/ui/composite/create-composite-data.js +22 -0
- package/dist/components/ui/composite/index.d.ts +4 -5
- package/dist/components/ui/composite/index.js +18 -13
- package/dist/components/ui/composite/types.d.ts +5 -67
- package/dist/components/ui/navigation-menu.js +1 -1
- package/dist/components/ui/popover.js +1 -1
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.js +3 -1
- package/eslint.config.js +1 -1
- package/package.json +17 -16
- package/src/components/ui/composite/CompositeData.ts +38 -30
- package/src/components/ui/composite/{FocusProvider/AbstractFocusProvider.ts → FocusManager/AbstractFocusManager.ts} +19 -26
- package/src/components/ui/composite/{FocusProvider/ListboxFocusProvider.ts → FocusManager/ListboxFocusManager.ts} +2 -2
- package/src/components/ui/composite/FocusManager/index.ts +3 -0
- package/src/components/ui/composite/FocusManager/types.ts +23 -0
- package/src/components/ui/composite/{SelectionProvider/AbstractSelectionProvider.ts → SelectionManager/AbstractSelectionManager.ts} +13 -28
- package/src/components/ui/composite/{SelectionProvider/MultipleSelectionProvider.ts → SelectionManager/MultipleSelectionManager.ts} +4 -2
- package/src/components/ui/composite/{SelectionProvider/SingleSelectionProvider.ts → SelectionManager/SingleSelectionManager.ts} +6 -4
- package/src/components/ui/composite/SelectionManager/index.ts +4 -0
- package/src/components/ui/composite/SelectionManager/types.ts +24 -0
- package/src/components/ui/composite/{composite-component.tsx → components/composite-component.tsx} +17 -42
- package/src/components/ui/composite/components/index.ts +5 -0
- package/src/components/ui/composite/{listbox.tsx → components/listbox.tsx} +16 -11
- package/src/components/ui/composite/components/types.ts +66 -0
- package/src/components/ui/composite/components/utils.ts +6 -0
- package/src/components/ui/composite/create-composite-data.ts +98 -0
- package/src/components/ui/composite/index.ts +7 -8
- package/src/components/ui/composite/types.ts +5 -86
- package/src/hooks/index.ts +4 -3
- package/.yarn/releases/yarn-4.10.3.cjs +0 -942
- package/dist/components/ui/composite/FocusProvider/index.d.ts +0 -2
- package/dist/components/ui/composite/FocusProvider/index.js +0 -6
- package/dist/components/ui/composite/SelectionProvider/index.d.ts +0 -3
- package/dist/components/ui/composite/SelectionProvider/index.js +0 -8
- package/dist/components/ui/composite/composite-component.d.ts +0 -2
- package/src/components/ui/composite/FocusProvider/index.ts +0 -2
- package/src/components/ui/composite/SelectionProvider/index.ts +0 -3
- /package/dist/components/ui/composite/{composite-component-item.d.ts → components/composite-component-item.d.ts} +0 -0
- /package/dist/components/ui/composite/{composite-component-item.js → components/composite-component-item.js} +0 -0
- /package/src/components/ui/composite/{composite-component-item.tsx → components/composite-component-item.tsx} +0 -0
package/dist/components/ui/composite/{composite-component.js → components/composite-component.js}
RENAMED
|
@@ -1,29 +1,11 @@
|
|
|
1
1
|
import { jsx } from "react/jsx-runtime";
|
|
2
|
-
import { useCallback, useImperativeHandle,
|
|
2
|
+
import { useCallback, useImperativeHandle, useEffect } from "react";
|
|
3
3
|
import { CompositeComponentItem } from "./composite-component-item.js";
|
|
4
|
-
import { useId } from "
|
|
5
|
-
import { useRequiredRef } from "
|
|
6
|
-
|
|
7
|
-
listbox: {
|
|
8
|
-
rootRole: "listbox",
|
|
9
|
-
groupRole: "group",
|
|
10
|
-
itemRole: "option"
|
|
11
|
-
},
|
|
12
|
-
grid: {
|
|
13
|
-
rootRole: "grid",
|
|
14
|
-
groupRole: "rowgroup",
|
|
15
|
-
itemRole: "row"
|
|
16
|
-
},
|
|
17
|
-
custom: void 0
|
|
18
|
-
};
|
|
19
|
-
const isOutsideElement = (parent, el) => {
|
|
20
|
-
if (parent === el) return false;
|
|
21
|
-
const nodeId = !!el?.id && CSS.escape(el.id);
|
|
22
|
-
return !nodeId || parent?.querySelector(`#${nodeId}`) === null;
|
|
23
|
-
};
|
|
4
|
+
import { useId } from "../../../../hooks/use-id.js";
|
|
5
|
+
import { useRequiredRef } from "../../../../hooks/use-required-ref.js";
|
|
6
|
+
import { isOutsideElement } from "./utils.js";
|
|
24
7
|
function CompositeComponent({
|
|
25
8
|
data,
|
|
26
|
-
variant,
|
|
27
9
|
rootRole,
|
|
28
10
|
itemRole,
|
|
29
11
|
groupRole,
|
|
@@ -43,35 +25,31 @@ function CompositeComponent({
|
|
|
43
25
|
const $rootRef = useRequiredRef(rootRef);
|
|
44
26
|
const focusElement = useCallback(() => {
|
|
45
27
|
if (softFocus) return;
|
|
46
|
-
const itemKey = data.
|
|
28
|
+
const itemKey = data.focusManager.focusedItem.get()?.key;
|
|
47
29
|
if (itemKey && $rootRef.current) {
|
|
48
30
|
const focusedItemEl = $rootRef.current.querySelector(`[data-key="${itemKey}"]`);
|
|
49
31
|
if (focusedItemEl) focusedItemEl.focus();
|
|
50
32
|
}
|
|
51
|
-
}, [softFocus, data.
|
|
33
|
+
}, [softFocus, data.focusManager.focusedItem, $rootRef]);
|
|
52
34
|
useImperativeHandle(handleRef, () => {
|
|
53
35
|
return {
|
|
54
|
-
|
|
55
|
-
|
|
36
|
+
focusManager: data.focusManager,
|
|
37
|
+
selectionManager: data.selectionManager,
|
|
56
38
|
focusElement
|
|
57
39
|
};
|
|
58
40
|
}, [data, focusElement]);
|
|
59
|
-
const roles = useMemo(
|
|
60
|
-
() => defaultRoles[variant] ?? { rootRole, groupRole, itemRole },
|
|
61
|
-
[groupRole, itemRole, rootRole, variant]
|
|
62
|
-
);
|
|
63
41
|
const intiFocus = useCallback(
|
|
64
42
|
(onlyData) => {
|
|
65
43
|
let initialFocusItem = null;
|
|
66
|
-
if (initialFocus === "FirstItem") initialFocusItem = data.
|
|
44
|
+
if (initialFocus === "FirstItem") initialFocusItem = data.focusManager.firstFocusableItem;
|
|
67
45
|
else if (initialFocus === "SelectedItem") {
|
|
68
|
-
const selecedItem = data.
|
|
69
|
-
initialFocusItem = selecedItem ?? data.
|
|
46
|
+
const selecedItem = data.selectionManager?.selectedKeys.get().values().next().value;
|
|
47
|
+
initialFocusItem = selecedItem ?? data.focusManager.firstFocusableItem;
|
|
70
48
|
}
|
|
71
|
-
data.
|
|
49
|
+
data.focusManager.focus(initialFocusItem);
|
|
72
50
|
if (!onlyData) focusElement();
|
|
73
51
|
},
|
|
74
|
-
[data.
|
|
52
|
+
[data.focusManager, data.selectionManager?.selectedKeys, focusElement, initialFocus]
|
|
75
53
|
);
|
|
76
54
|
const onFocusHandler = useCallback(
|
|
77
55
|
(ev) => {
|
|
@@ -88,7 +66,7 @@ function CompositeComponent({
|
|
|
88
66
|
id: compositeId,
|
|
89
67
|
className,
|
|
90
68
|
tabIndex: initialFocus === "None" ? 0 : -1,
|
|
91
|
-
role:
|
|
69
|
+
role: rootRole,
|
|
92
70
|
...props,
|
|
93
71
|
onFocus: onFocusHandler,
|
|
94
72
|
children: [...data].map((item) => /* @__PURE__ */ jsx(
|
|
@@ -96,8 +74,8 @@ function CompositeComponent({
|
|
|
96
74
|
{
|
|
97
75
|
className: itemClassName,
|
|
98
76
|
id: `${compositeId}-${item.key}`,
|
|
99
|
-
role:
|
|
100
|
-
groupRole
|
|
77
|
+
role: itemRole,
|
|
78
|
+
groupRole,
|
|
101
79
|
item,
|
|
102
80
|
render: renderItem,
|
|
103
81
|
itemMouseEventHandler,
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { CompositeComponent } from "./composite-component.js";
|
|
2
|
+
import { CompositeComponentItem } from "./composite-component-item.js";
|
|
3
|
+
import { Listbox } from "./listbox.js";
|
|
4
|
+
import { isOutsideElement } from "./utils.js";
|
|
5
|
+
export {
|
|
6
|
+
CompositeComponent,
|
|
7
|
+
CompositeComponentItem,
|
|
8
|
+
Listbox,
|
|
9
|
+
isOutsideElement
|
|
10
|
+
};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { BaseCompositeProps } from './types';
|
|
2
|
-
export declare function Listbox<T extends object>({ data, rootRef, handleRef, initialFocus, ...props }: BaseCompositeProps<T>): import("react").JSX.Element;
|
|
2
|
+
export declare function Listbox<T extends object>({ data, rootRef, handleRef, initialFocus, className, ...props }: BaseCompositeProps<T>): import("react").JSX.Element;
|
|
@@ -2,59 +2,64 @@ import { jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { CompositeComponent } from "./composite-component.js";
|
|
3
3
|
import { useCallback } from "react";
|
|
4
4
|
import "nanostores";
|
|
5
|
-
import { useKeyboardEvent } from "
|
|
6
|
-
import { useRequiredRef } from "
|
|
5
|
+
import { useKeyboardEvent } from "../../../../hooks/use-keyboard-event.js";
|
|
6
|
+
import { useRequiredRef } from "../../../../hooks/use-required-ref.js";
|
|
7
|
+
import { c as cn } from "../../../../_chunks/utils.js";
|
|
7
8
|
function Listbox({
|
|
8
9
|
data,
|
|
9
10
|
rootRef,
|
|
10
11
|
handleRef,
|
|
11
12
|
initialFocus = "SelectedItem",
|
|
13
|
+
className,
|
|
12
14
|
...props
|
|
13
15
|
}) {
|
|
14
16
|
const $handleRef = useRequiredRef(handleRef);
|
|
15
17
|
const handleKeyboardEvent = useKeyboardEvent(
|
|
16
18
|
{
|
|
17
19
|
ArrowUp: () => {
|
|
18
|
-
data.
|
|
20
|
+
data.focusManager.focusUp();
|
|
19
21
|
$handleRef.current?.focusElement();
|
|
20
22
|
},
|
|
21
23
|
ArrowDown: () => {
|
|
22
|
-
data.
|
|
24
|
+
data.focusManager.focusDown();
|
|
23
25
|
$handleRef.current?.focusElement();
|
|
24
26
|
},
|
|
25
27
|
Home: () => {
|
|
26
|
-
data.
|
|
28
|
+
data.focusManager.focusToFirst();
|
|
27
29
|
$handleRef.current?.focusElement();
|
|
28
30
|
},
|
|
29
31
|
End: () => {
|
|
30
|
-
data.
|
|
32
|
+
data.focusManager.focusToLast();
|
|
31
33
|
$handleRef.current?.focusElement();
|
|
32
34
|
},
|
|
33
35
|
Space: () => {
|
|
34
|
-
data.
|
|
36
|
+
data.selectionManager?.toggleSelect();
|
|
35
37
|
$handleRef.current?.focusElement();
|
|
36
38
|
}
|
|
37
39
|
},
|
|
38
|
-
[$handleRef, data.
|
|
40
|
+
[$handleRef, data.focusManager]
|
|
39
41
|
);
|
|
40
42
|
const handleItemMouseEvent = useCallback(
|
|
41
43
|
(item) => {
|
|
42
|
-
data.
|
|
43
|
-
data.
|
|
44
|
+
data.focusManager.focus(item.key);
|
|
45
|
+
data.selectionManager?.toggleSelect(item);
|
|
44
46
|
$handleRef.current?.focusElement();
|
|
45
47
|
},
|
|
46
|
-
[$handleRef, data.
|
|
48
|
+
[$handleRef, data.focusManager, data.selectionManager]
|
|
47
49
|
);
|
|
48
50
|
return /* @__PURE__ */ jsx(
|
|
49
51
|
CompositeComponent,
|
|
50
52
|
{
|
|
51
53
|
rootRef,
|
|
52
54
|
handleRef: $handleRef,
|
|
53
|
-
|
|
55
|
+
rootRole: "listbox",
|
|
56
|
+
groupRole: "group",
|
|
57
|
+
itemRole: "option",
|
|
54
58
|
data,
|
|
55
59
|
initialFocus,
|
|
56
60
|
onKeyDown: handleKeyboardEvent,
|
|
57
61
|
itemMouseEventHandler: handleItemMouseEvent,
|
|
62
|
+
className: cn("flex flex-col gap-1", className),
|
|
58
63
|
...props
|
|
59
64
|
}
|
|
60
65
|
);
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { AriaRole, KeyboardEventHandler, MouseEventHandler, ReactNode } from 'react';
|
|
2
|
+
import { CompositeData } from '../CompositeData';
|
|
3
|
+
import { CompositeDataItemState, CompositeItemKey } from '../types';
|
|
4
|
+
import { IFocusManager } from '../FocusManager';
|
|
5
|
+
import { SelectionManager } from '../SelectionManager';
|
|
6
|
+
import { CompositeDataItem } from '../CompositeDataItem';
|
|
7
|
+
export type InitialFocusTarget = "None" | "LastFocusedItem" | "SelectedItem" | "FirstItem";
|
|
8
|
+
export interface BaseCompositeProps<T extends object> extends React.ComponentPropsWithoutRef<"div"> {
|
|
9
|
+
data: CompositeData<T>;
|
|
10
|
+
className?: string;
|
|
11
|
+
rootRef?: React.RefObject<HTMLDivElement | null>;
|
|
12
|
+
handleRef?: React.RefObject<CompositeHandle<T> | null>;
|
|
13
|
+
renderItem: CompositeItemRenderFn<T>;
|
|
14
|
+
itemClassName?: string;
|
|
15
|
+
initialFocus?: InitialFocusTarget;
|
|
16
|
+
/**
|
|
17
|
+
* Set `item.focused = true`, but not focus on the HTMLElement
|
|
18
|
+
*/
|
|
19
|
+
softFocus?: boolean;
|
|
20
|
+
}
|
|
21
|
+
export interface CompositeProps<T extends object> extends BaseCompositeProps<T>, CompositeItemEventHandlerFunctions<T> {
|
|
22
|
+
rootRole: AriaRole;
|
|
23
|
+
itemRole: AriaRole;
|
|
24
|
+
groupRole: AriaRole;
|
|
25
|
+
}
|
|
26
|
+
export interface CompositeHandle<T extends object> {
|
|
27
|
+
focusManager: IFocusManager<T>;
|
|
28
|
+
focusElement: () => void;
|
|
29
|
+
selectionManager?: SelectionManager<T>;
|
|
30
|
+
}
|
|
31
|
+
export type CompositeItemRenderFn<T extends object> = (item: {
|
|
32
|
+
data: T;
|
|
33
|
+
level: number;
|
|
34
|
+
key: CompositeItemKey;
|
|
35
|
+
}, state: CompositeDataItemState, eventHandlers: CompositeEventHandlers) => ReactNode;
|
|
36
|
+
export interface CompositeItemProps<T extends object> extends CompositeItemEventHandlerFunctions<T> {
|
|
37
|
+
id: string;
|
|
38
|
+
className?: string;
|
|
39
|
+
role?: AriaRole;
|
|
40
|
+
groupRole?: AriaRole;
|
|
41
|
+
item: CompositeDataItem<T>;
|
|
42
|
+
remove?: () => void;
|
|
43
|
+
render: CompositeItemRenderFn<T>;
|
|
44
|
+
softFocus?: boolean;
|
|
45
|
+
}
|
|
46
|
+
export interface CompositeEventHandlers {
|
|
47
|
+
mouseEventHandler?: MouseEventHandler<HTMLElement>;
|
|
48
|
+
keyboardEventHandler?: KeyboardEventHandler<HTMLElement>;
|
|
49
|
+
}
|
|
50
|
+
export interface CompositeItemEventHandlerFunctions<T extends object> {
|
|
51
|
+
itemMouseEventHandler?: (itemAtom: CompositeDataItem<T>) => void;
|
|
52
|
+
itemKeyboardEventHandler?: (itemAtom: CompositeDataItem<T>) => void;
|
|
53
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const isOutsideElement: (parent: Element | null, el: Element | null) => boolean;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { CompositeData } from './CompositeData';
|
|
2
|
+
import { CompositeOptions, CompositeManagerOptions } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Returns nanostores object with `CompositeData` instance,
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```
|
|
8
|
+
* const items = [...];
|
|
9
|
+
* const compositeData = createCompositeData(
|
|
10
|
+
* items,
|
|
11
|
+
* {
|
|
12
|
+
* focusManager: new ListboxFocusManager(),
|
|
13
|
+
* selectionManager: new SingleSelectionManager(),
|
|
14
|
+
* },
|
|
15
|
+
* {
|
|
16
|
+
* disabledKeys: ["key 02", "key 04", "key 3023"],
|
|
17
|
+
* selectedKeys: ["key 207", "key 101", "key 3021"],
|
|
18
|
+
* itemChildrenProp: "nodes",
|
|
19
|
+
* },
|
|
20
|
+
* );
|
|
21
|
+
*
|
|
22
|
+
* export function CompositeSelectedItems() {
|
|
23
|
+
* const composite = useStore(compositeData);
|
|
24
|
+
* const selections = useStore(composite.data.selectionManager!.selectedKeys);
|
|
25
|
+
* return (
|
|
26
|
+
* <div className="py-4 flex gap-2 items-center justify-star ">
|
|
27
|
+
* <span className="text-lg font-semibold text-accent-foreground">Selected Items:</span>
|
|
28
|
+
* <div className="flex gap-2 flex-wrap items-center justify-start *:bg-blue-100 *:p-2">
|
|
29
|
+
* {[...selections].map((selectedKey) => {
|
|
30
|
+
* return <span key={selectedKey}>{composite.data.item(selectedKey)?.data.get().name}</span>;
|
|
31
|
+
* })}
|
|
32
|
+
* </div>
|
|
33
|
+
* </div>
|
|
34
|
+
* );
|
|
35
|
+
* }
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export declare const createCompositeData: <T extends object>(items: T[], managerOptions: CompositeManagerOptions<T>, options?: CompositeOptions) => import('nanostores').ReadableAtom<{
|
|
39
|
+
data: CompositeData<T>;
|
|
40
|
+
version: number;
|
|
41
|
+
}>;
|
|
42
|
+
/**
|
|
43
|
+
* Returns nanostores object with `CompositeData` instance.
|
|
44
|
+
*
|
|
45
|
+
* Intialize the store by calling the `fetch` function without any arguments
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```
|
|
49
|
+
* const compositeAsyncData = createAsyncCompositeData(
|
|
50
|
+
* async (url?: string) => {
|
|
51
|
+
* if (!url) return undefined;
|
|
52
|
+
*
|
|
53
|
+
* const response = await fetch(url);
|
|
54
|
+
* if (response.ok) {
|
|
55
|
+
* const data = await response.json();
|
|
56
|
+
* return data.results as NamedListItem[];
|
|
57
|
+
* }
|
|
58
|
+
*
|
|
59
|
+
* return null;
|
|
60
|
+
* },
|
|
61
|
+
* {
|
|
62
|
+
* focusManager: new ListboxFocusManager(),
|
|
63
|
+
* selectionManager: new MultipleSelectionManager(),
|
|
64
|
+
* },
|
|
65
|
+
* {
|
|
66
|
+
* itemKeyProp: "name",
|
|
67
|
+
* },
|
|
68
|
+
* );
|
|
69
|
+
*
|
|
70
|
+
* export function CompositeSomethign() {
|
|
71
|
+
* const composite = useStore(compositeAsyncData);
|
|
72
|
+
* return <Listbox data={composite.data} ... />
|
|
73
|
+
* }
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
export declare const createAsyncCompositeData: <T extends object, FnArgs = never>(fetch: (options?: FnArgs) => Promise<T[] | undefined | null>, managerOptions: CompositeManagerOptions<T>, options?: CompositeOptions) => import('nanostores').ReadableAtom<{
|
|
77
|
+
data: CompositeData<T>;
|
|
78
|
+
version: number;
|
|
79
|
+
load: (options?: FnArgs) => void;
|
|
80
|
+
}>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { computed } from "nanostores";
|
|
2
|
+
import { CompositeData } from "./CompositeData.js";
|
|
3
|
+
const createCompositeData = (items, managerOptions, options) => {
|
|
4
|
+
const $store = new CompositeData(items, managerOptions, options);
|
|
5
|
+
return computed($store.version, (version) => {
|
|
6
|
+
return { data: $store, version };
|
|
7
|
+
});
|
|
8
|
+
};
|
|
9
|
+
const createAsyncCompositeData = (fetch, managerOptions, options) => {
|
|
10
|
+
const load = (options2) => {
|
|
11
|
+
fetch(options2).then((items) => items && $store.setItems(items));
|
|
12
|
+
};
|
|
13
|
+
const $store = new CompositeData(null, managerOptions, options);
|
|
14
|
+
load();
|
|
15
|
+
return computed($store.version, (version) => {
|
|
16
|
+
return { data: $store, version, load };
|
|
17
|
+
});
|
|
18
|
+
};
|
|
19
|
+
export {
|
|
20
|
+
createAsyncCompositeData,
|
|
21
|
+
createCompositeData
|
|
22
|
+
};
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
export * from './CompositeData.ts';
|
|
2
2
|
export * from './CompositeDataItem.ts';
|
|
3
|
-
export * from './
|
|
4
|
-
export * from './
|
|
5
|
-
export * from './
|
|
6
|
-
export * from './composite-
|
|
7
|
-
export * from './listbox.tsx';
|
|
3
|
+
export * from './FocusManager/index.ts';
|
|
4
|
+
export * from './SelectionManager/index.ts';
|
|
5
|
+
export * from './components';
|
|
6
|
+
export * from './create-composite-data.ts';
|
|
8
7
|
export type * from './types';
|
|
@@ -1,22 +1,27 @@
|
|
|
1
1
|
import { CompositeData } from "./CompositeData.js";
|
|
2
2
|
import { CompositeDataItem } from "./CompositeDataItem.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { CompositeComponent } from "./composite-component.js";
|
|
9
|
-
import { CompositeComponentItem } from "./composite-component-item.js";
|
|
10
|
-
import { Listbox } from "./listbox.js";
|
|
3
|
+
import { AbstractFocusManager } from "./FocusManager/AbstractFocusManager.js";
|
|
4
|
+
import { ListboxFocusManager } from "./FocusManager/ListboxFocusManager.js";
|
|
5
|
+
import { AbstractSelectionManager } from "./SelectionManager/AbstractSelectionManager.js";
|
|
6
|
+
import { SingleSelectionManager } from "./SelectionManager/SingleSelectionManager.js";
|
|
7
|
+
import { MultipleSelectionManager } from "./SelectionManager/MultipleSelectionManager.js";
|
|
8
|
+
import { CompositeComponent } from "./components/composite-component.js";
|
|
9
|
+
import { CompositeComponentItem } from "./components/composite-component-item.js";
|
|
10
|
+
import { Listbox } from "./components/listbox.js";
|
|
11
|
+
import { isOutsideElement } from "./components/utils.js";
|
|
12
|
+
import { createAsyncCompositeData, createCompositeData } from "./create-composite-data.js";
|
|
11
13
|
export {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
+
AbstractFocusManager,
|
|
15
|
+
AbstractSelectionManager,
|
|
14
16
|
CompositeComponent,
|
|
15
17
|
CompositeComponentItem,
|
|
16
18
|
CompositeData,
|
|
17
19
|
CompositeDataItem,
|
|
18
20
|
Listbox,
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
ListboxFocusManager,
|
|
22
|
+
MultipleSelectionManager,
|
|
23
|
+
SingleSelectionManager,
|
|
24
|
+
createAsyncCompositeData,
|
|
25
|
+
createCompositeData,
|
|
26
|
+
isOutsideElement
|
|
22
27
|
};
|
|
@@ -1,26 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { AbstractFocusProvider, FocusProvider } from './FocusProvider/AbstractFocusProvider';
|
|
4
|
-
import { AbstractSelectionProvider, SelectionProvider } from './SelectionProvider/AbstractSelectionProvider';
|
|
5
|
-
import { CompositeData } from './CompositeData';
|
|
1
|
+
import { AbstractFocusManager } from './FocusManager/AbstractFocusManager';
|
|
2
|
+
import { AbstractSelectionManager } from './SelectionManager/AbstractSelectionManager';
|
|
6
3
|
export type CompositeItemKey = string | number;
|
|
7
|
-
export type CompositeRoles = {
|
|
8
|
-
variant: "listbox";
|
|
9
|
-
rootRole?: never;
|
|
10
|
-
itemRole?: never;
|
|
11
|
-
groupRole?: never;
|
|
12
|
-
} | {
|
|
13
|
-
variant: "grid";
|
|
14
|
-
rootRole?: never;
|
|
15
|
-
itemRole?: never;
|
|
16
|
-
groupRole?: never;
|
|
17
|
-
} | {
|
|
18
|
-
variant: "custom";
|
|
19
|
-
rootRole: AriaRole;
|
|
20
|
-
itemRole: AriaRole;
|
|
21
|
-
groupRole: AriaRole;
|
|
22
|
-
};
|
|
23
|
-
export type InitialFocusTarget = "None" | "LastFocusedItem" | "SelectedItem" | "FirstItem";
|
|
24
4
|
export interface CompositeOptions {
|
|
25
5
|
disabledKeys?: CompositeItemKey[];
|
|
26
6
|
selectedKeys?: CompositeItemKey[];
|
|
@@ -31,9 +11,9 @@ interface CompositeDataPropGetters<T> {
|
|
|
31
11
|
getItemKey: (item: T) => CompositeItemKey;
|
|
32
12
|
getItemChildren: (item: T) => T[] | undefined;
|
|
33
13
|
}
|
|
34
|
-
export interface
|
|
35
|
-
|
|
36
|
-
|
|
14
|
+
export interface CompositeManagerOptions<T extends object> {
|
|
15
|
+
focusManager: AbstractFocusManager<T>;
|
|
16
|
+
selectionManager?: AbstractSelectionManager<T>;
|
|
37
17
|
}
|
|
38
18
|
export type CompositeDataOptions<T> = Required<CompositeOptions> & CompositeDataPropGetters<T>;
|
|
39
19
|
export type CompositeDataItemOptions<T> = CompositeDataPropGetters<T> & {
|
|
@@ -45,46 +25,4 @@ export interface CompositeDataItemState {
|
|
|
45
25
|
selected: boolean;
|
|
46
26
|
disabled: boolean;
|
|
47
27
|
}
|
|
48
|
-
export interface CompositeEventHandlers {
|
|
49
|
-
mouseEventHandler?: MouseEventHandler<HTMLElement>;
|
|
50
|
-
keyboardEventHandler?: KeyboardEventHandler<HTMLElement>;
|
|
51
|
-
}
|
|
52
|
-
export interface CompositeItemEventHandlerFunctions<T extends object> {
|
|
53
|
-
itemMouseEventHandler?: (itemAtom: CompositeDataItem<T>) => void;
|
|
54
|
-
itemKeyboardEventHandler?: (itemAtom: CompositeDataItem<T>) => void;
|
|
55
|
-
}
|
|
56
|
-
export interface BaseCompositeProps<T extends object> extends React.ComponentPropsWithoutRef<"div"> {
|
|
57
|
-
data: CompositeData<T>;
|
|
58
|
-
className?: string;
|
|
59
|
-
rootRef?: React.RefObject<HTMLDivElement | null>;
|
|
60
|
-
handleRef?: React.RefObject<CompositeHandle<T> | null>;
|
|
61
|
-
renderItem: CompositeItemRenderFn<T>;
|
|
62
|
-
itemClassName?: string;
|
|
63
|
-
initialFocus?: InitialFocusTarget;
|
|
64
|
-
/**
|
|
65
|
-
* Set `item.focused = true`, but not focus on the HTMLElement
|
|
66
|
-
*/
|
|
67
|
-
softFocus?: boolean;
|
|
68
|
-
}
|
|
69
|
-
export type CompositeProps<T extends object> = BaseCompositeProps<T> & CompositeItemEventHandlerFunctions<T> & CompositeRoles;
|
|
70
|
-
export interface CompositeHandle<T extends object> {
|
|
71
|
-
focusProvider: FocusProvider<T>;
|
|
72
|
-
focusElement: () => void;
|
|
73
|
-
selectionProvider?: SelectionProvider<T>;
|
|
74
|
-
}
|
|
75
|
-
export type CompositeItemRenderFn<T extends object> = (item: {
|
|
76
|
-
data: T;
|
|
77
|
-
level: number;
|
|
78
|
-
key: CompositeItemKey;
|
|
79
|
-
}, state: CompositeDataItemState, eventHandlers: CompositeEventHandlers) => ReactNode;
|
|
80
|
-
export interface CompositeItemProps<T extends object> extends CompositeItemEventHandlerFunctions<T> {
|
|
81
|
-
id: string;
|
|
82
|
-
className?: string;
|
|
83
|
-
role?: AriaRole;
|
|
84
|
-
groupRole?: AriaRole;
|
|
85
|
-
item: CompositeDataItem<T>;
|
|
86
|
-
remove?: () => void;
|
|
87
|
-
render: CompositeItemRenderFn<T>;
|
|
88
|
-
softFocus?: boolean;
|
|
89
|
-
}
|
|
90
28
|
export {};
|
|
@@ -55,7 +55,7 @@ function createSlotClone(ownerName) {
|
|
|
55
55
|
SlotClone.displayName = `${ownerName}.SlotClone`;
|
|
56
56
|
return SlotClone;
|
|
57
57
|
}
|
|
58
|
-
var SLOTTABLE_IDENTIFIER = Symbol("radix.slottable");
|
|
58
|
+
var SLOTTABLE_IDENTIFIER = /* @__PURE__ */ Symbol("radix.slottable");
|
|
59
59
|
function isSlottable(child) {
|
|
60
60
|
return React.isValidElement(child) && typeof child.type === "function" && "__radixId" in child.type && child.type.__radixId === SLOTTABLE_IDENTIFIER;
|
|
61
61
|
}
|
|
@@ -2478,7 +2478,7 @@ function createSlotClone(ownerName) {
|
|
|
2478
2478
|
SlotClone.displayName = `${ownerName}.SlotClone`;
|
|
2479
2479
|
return SlotClone;
|
|
2480
2480
|
}
|
|
2481
|
-
var SLOTTABLE_IDENTIFIER = Symbol("radix.slottable");
|
|
2481
|
+
var SLOTTABLE_IDENTIFIER = /* @__PURE__ */ Symbol("radix.slottable");
|
|
2482
2482
|
function isSlottable(child) {
|
|
2483
2483
|
return React.isValidElement(child) && typeof child.type === "function" && "__radixId" in child.type && child.type.__radixId === SLOTTABLE_IDENTIFIER;
|
|
2484
2484
|
}
|
package/dist/hooks/index.d.ts
CHANGED
package/dist/hooks/index.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { useEffectAfterMount } from "./use-effect-after-mount.js";
|
|
2
2
|
import { useId } from "./use-id.js";
|
|
3
3
|
import { keyboardEventHandler, useKeyboardEvent } from "./use-keyboard-event.js";
|
|
4
|
+
import { useRequiredRef } from "./use-required-ref.js";
|
|
4
5
|
export {
|
|
5
6
|
keyboardEventHandler,
|
|
6
7
|
useEffectAfterMount,
|
|
7
8
|
useId,
|
|
8
|
-
useKeyboardEvent
|
|
9
|
+
useKeyboardEvent,
|
|
10
|
+
useRequiredRef
|
|
9
11
|
};
|
package/eslint.config.js
CHANGED
package/package.json
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bccampus/ui-components",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"packageManager": "yarn@4.10.3",
|
|
6
5
|
"exports": {
|
|
7
6
|
".": {
|
|
8
7
|
"types": "./dist/components/index.d.ts",
|
|
@@ -24,6 +23,7 @@
|
|
|
24
23
|
},
|
|
25
24
|
"scripts": {
|
|
26
25
|
"dev": "vite",
|
|
26
|
+
"check": "tsc -b && eslint ./src",
|
|
27
27
|
"build": "tsc -b && vite build",
|
|
28
28
|
"lint": "eslint .",
|
|
29
29
|
"publish": "yarn build && npm publish --access public --scope=@bccampus",
|
|
@@ -39,10 +39,10 @@
|
|
|
39
39
|
"@radix-ui/react-slot": "^1.2.4",
|
|
40
40
|
"class-variance-authority": "^0.7.1",
|
|
41
41
|
"clsx": "^2.1.1",
|
|
42
|
-
"lucide-react": "^0.
|
|
42
|
+
"lucide-react": "^0.563.0",
|
|
43
43
|
"nanostores": "^1.1.0",
|
|
44
|
-
"react": "^19.2.
|
|
45
|
-
"react-dom": "^19.2.
|
|
44
|
+
"react": "^19.2.3",
|
|
45
|
+
"react-dom": "^19.2.3",
|
|
46
46
|
"tailwind-merge": "^3.4.0",
|
|
47
47
|
"tailwindcss": "^4.1.18",
|
|
48
48
|
"tw-animate-css": "^1.4.0"
|
|
@@ -56,21 +56,22 @@
|
|
|
56
56
|
"tw-animate-css": "^1.4.0"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
|
-
"@eslint/js": "^9.39.
|
|
59
|
+
"@eslint/js": "^9.39.2",
|
|
60
60
|
"@ladle/react": "^5.1.1",
|
|
61
61
|
"@tailwindcss/vite": "^4.1.18",
|
|
62
|
-
"@types/node": "^24.10.
|
|
63
|
-
"@types/react": "^19.2.
|
|
62
|
+
"@types/node": "^24.10.9",
|
|
63
|
+
"@types/react": "^19.2.9",
|
|
64
64
|
"@types/react-dom": "^19.2.3",
|
|
65
65
|
"@vitejs/plugin-react-swc": "^4.2.2",
|
|
66
|
-
"
|
|
67
|
-
"eslint
|
|
68
|
-
"eslint-plugin-react-
|
|
66
|
+
"baseline-browser-mapping": "^2.9.17",
|
|
67
|
+
"eslint": "^9.39.2",
|
|
68
|
+
"eslint-plugin-react-hooks": "^7.0.1",
|
|
69
|
+
"eslint-plugin-react-refresh": "^0.4.26",
|
|
69
70
|
"glob": "^13.0.0",
|
|
70
|
-
"globals": "^
|
|
71
|
-
"typescript": "~5.
|
|
72
|
-
"typescript-eslint": "^8.
|
|
73
|
-
"vite": "^7.
|
|
71
|
+
"globals": "^17.1.0",
|
|
72
|
+
"typescript": "~5.9.3",
|
|
73
|
+
"typescript-eslint": "^8.53.1",
|
|
74
|
+
"vite": "^7.3.1",
|
|
74
75
|
"vite-plugin-dts": "^4.5.4"
|
|
75
76
|
}
|
|
76
|
-
}
|
|
77
|
+
}
|