@rebasepro/ui 0.17.3 → 0.18.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/README.md +4 -0
- package/dist/components/MultiSelect.d.ts +10 -0
- package/dist/index.es.js +2 -1
- package/dist/index.es.js.map +1 -1
- package/package.json +32 -23
- package/src/components/Alert.tsx +0 -118
- package/src/components/Autocomplete.tsx +0 -93
- package/src/components/Avatar.tsx +0 -73
- package/src/components/Badge.tsx +0 -44
- package/src/components/BooleanSwitch.tsx +0 -116
- package/src/components/BooleanSwitchWithLabel.tsx +0 -120
- package/src/components/Button.tsx +0 -110
- package/src/components/Card.tsx +0 -43
- package/src/components/CenteredView.tsx +0 -35
- package/src/components/Checkbox.tsx +0 -129
- package/src/components/Chip.tsx +0 -131
- package/src/components/CircularProgress.tsx +0 -53
- package/src/components/CircularProgressCenter.tsx +0 -27
- package/src/components/Collapse.tsx +0 -66
- package/src/components/ColorPicker.tsx +0 -140
- package/src/components/Container.tsx +0 -51
- package/src/components/DateTimeField.tsx +0 -363
- package/src/components/DebouncedTextField.tsx +0 -76
- package/src/components/Dialog.tsx +0 -159
- package/src/components/DialogActions.tsx +0 -29
- package/src/components/DialogContent.tsx +0 -27
- package/src/components/DialogTitle.tsx +0 -41
- package/src/components/ErrorBoundary.tsx +0 -236
- package/src/components/ExpandablePanel.tsx +0 -130
- package/src/components/FileUpload.tsx +0 -103
- package/src/components/FilterChip.tsx +0 -89
- package/src/components/IconButton.tsx +0 -101
- package/src/components/InfoLabel.tsx +0 -23
- package/src/components/InputLabel.tsx +0 -40
- package/src/components/Label.tsx +0 -32
- package/src/components/LoadingButton.tsx +0 -32
- package/src/components/Markdown.tsx +0 -55
- package/src/components/Menu.tsx +0 -114
- package/src/components/Menubar.tsx +0 -355
- package/src/components/MultiSelect.tsx +0 -433
- package/src/components/Paper.tsx +0 -23
- package/src/components/Popover.tsx +0 -162
- package/src/components/RadioGroup.tsx +0 -74
- package/src/components/ResizablePanels.tsx +0 -189
- package/src/components/SearchBar.tsx +0 -136
- package/src/components/Select.tsx +0 -326
- package/src/components/Separator.tsx +0 -28
- package/src/components/Sheet.tsx +0 -135
- package/src/components/Skeleton.tsx +0 -54
- package/src/components/Slider.tsx +0 -110
- package/src/components/Table.tsx +0 -178
- package/src/components/Tabs.tsx +0 -185
- package/src/components/TextField.tsx +0 -270
- package/src/components/TextareaAutosize.tsx +0 -368
- package/src/components/ToggleButtonGroup.tsx +0 -69
- package/src/components/Tooltip.tsx +0 -153
- package/src/components/Typography.tsx +0 -132
- package/src/components/VirtualTable/VirtualTable.performance.test.tsx +0 -90
- package/src/components/VirtualTable/VirtualTable.tsx +0 -700
- package/src/components/VirtualTable/VirtualTableCell.tsx +0 -59
- package/src/components/VirtualTable/VirtualTableHeader.tsx +0 -327
- package/src/components/VirtualTable/VirtualTableHeaderRow.tsx +0 -250
- package/src/components/VirtualTable/VirtualTableProps.tsx +0 -339
- package/src/components/VirtualTable/VirtualTableRow.tsx +0 -51
- package/src/components/VirtualTable/fields/VirtualTableDateField.tsx +0 -44
- package/src/components/VirtualTable/fields/VirtualTableInput.tsx +0 -89
- package/src/components/VirtualTable/fields/VirtualTableNumberInput.tsx +0 -71
- package/src/components/VirtualTable/fields/VirtualTableSelect.tsx +0 -107
- package/src/components/VirtualTable/fields/VirtualTableSwitch.tsx +0 -28
- package/src/components/VirtualTable/index.tsx +0 -10
- package/src/components/VirtualTable/selection/SelectionContext.tsx +0 -36
- package/src/components/VirtualTable/selection/SelectionStore.ts +0 -54
- package/src/components/VirtualTable/types.tsx +0 -47
- package/src/components/common/SelectInputLabel.tsx +0 -23
- package/src/components/index.tsx +0 -62
- package/src/hooks/PortalContainerContext.tsx +0 -50
- package/src/hooks/index.ts +0 -7
- package/src/hooks/useDebounceCallback.tsx +0 -21
- package/src/hooks/useDebounceValue.tsx +0 -20
- package/src/hooks/useDebouncedCallback.ts +0 -39
- package/src/hooks/useInjectStyles.tsx +0 -31
- package/src/hooks/useOutsideAlerter.tsx +0 -46
- package/src/icons/GitHubIcon.tsx +0 -21
- package/src/icons/HandleIcon.tsx +0 -23
- package/src/icons/Icon.tsx +0 -33
- package/src/icons/LucideIconByName.tsx +0 -117
- package/src/icons/cool_icon_keys.ts +0 -12
- package/src/icons/icon_keys.ts +0 -1936
- package/src/icons/index.ts +0 -179
- package/src/index.css +0 -169
- package/src/index.ts +0 -47
- package/src/scripts/fixIconSizes.cjs +0 -92
- package/src/scripts/fixIconSizesToConst.cjs +0 -106
- package/src/scripts/generateIconKeys.ts +0 -41
- package/src/scripts/generateIcons.ts +0 -4
- package/src/scripts/saveIconFiles.ts +0 -89
- package/src/styles.ts +0 -141
- package/src/theme.css +0 -168
- package/src/util/chip_colors.ts +0 -242
- package/src/util/cls.ts +0 -8
- package/src/util/debounce.ts +0 -28
- package/src/util/hash.ts +0 -11
- package/src/util/index.ts +0 -4
- package/src/util/key_to_icon_component.ts +0 -11
- package/src/util/lazy_chunk.ts +0 -101
- package/src/views/CardView.tsx +0 -281
- package/src/views/CollectionView/CollectionCardView.tsx +0 -265
- package/src/views/CollectionView/CollectionKanbanView.tsx +0 -246
- package/src/views/CollectionView/CollectionListView.tsx +0 -240
- package/src/views/CollectionView/CollectionTableView.tsx +0 -229
- package/src/views/CollectionView/CollectionView.tsx +0 -450
- package/src/views/CollectionView/CollectionViewToolbar.tsx +0 -242
- package/src/views/CollectionView/CollectionViewTypes.ts +0 -181
- package/src/views/CollectionView/DefaultCellRenderer.tsx +0 -404
- package/src/views/CollectionView/index.ts +0 -39
- package/src/views/CollectionView/resolveTitleProperty.ts +0 -52
- package/src/views/CollectionView/utils.ts +0 -14
- package/src/views/Kanban/Board.tsx +0 -384
- package/src/views/Kanban/BoardColumn.tsx +0 -138
- package/src/views/Kanban/BoardColumnTitle.tsx +0 -47
- package/src/views/Kanban/BoardSortableList.tsx +0 -182
- package/src/views/Kanban/board_types.ts +0 -80
- package/src/views/Kanban/index.tsx +0 -5
- package/src/views/Kanban/placement.ts +0 -62
- package/src/views/KanbanView.tsx +0 -32
- package/src/views/ListView.tsx +0 -296
- package/src/views/index.ts +0 -5
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import React, { useEffect } from "react";
|
|
2
|
-
import { BooleanSwitch } from "../../BooleanSwitch";
|
|
3
|
-
|
|
4
|
-
export function VirtualTableSwitch(props: {
|
|
5
|
-
error?: Error;
|
|
6
|
-
internalValue?: boolean;
|
|
7
|
-
focused: boolean;
|
|
8
|
-
disabled: boolean;
|
|
9
|
-
updateValue: (newValue: (boolean | null)) => void;
|
|
10
|
-
}) {
|
|
11
|
-
const { internalValue, updateValue, focused } = props;
|
|
12
|
-
const ref = React.useRef<HTMLButtonElement>(null);
|
|
13
|
-
|
|
14
|
-
useEffect(() => {
|
|
15
|
-
if (ref.current && focused) {
|
|
16
|
-
ref.current.focus({ preventScroll: true });
|
|
17
|
-
}
|
|
18
|
-
}, [focused, ref]);
|
|
19
|
-
|
|
20
|
-
return (
|
|
21
|
-
<BooleanSwitch
|
|
22
|
-
ref={ref}
|
|
23
|
-
size={"small"}
|
|
24
|
-
value={Boolean(internalValue)}
|
|
25
|
-
onValueChange={updateValue}
|
|
26
|
-
/>
|
|
27
|
-
);
|
|
28
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
export { VirtualTable } from "./VirtualTable";
|
|
2
|
-
export * from "./VirtualTableProps";
|
|
3
|
-
export type { FilterFormFieldProps } from "./VirtualTableHeader";
|
|
4
|
-
export * from "./selection/SelectionStore";
|
|
5
|
-
export * from "./selection/SelectionContext";
|
|
6
|
-
export * from "./fields/VirtualTableInput";
|
|
7
|
-
export * from "./fields/VirtualTableNumberInput";
|
|
8
|
-
export * from "./fields/VirtualTableSwitch";
|
|
9
|
-
export * from "./fields/VirtualTableDateField";
|
|
10
|
-
export * from "./fields/VirtualTableSelect";
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import React, { createContext, useContext } from "react";
|
|
2
|
-
import { VirtualTableSelectionStore, SelectedCell } from "./SelectionStore";
|
|
3
|
-
|
|
4
|
-
export interface VirtualTableSelectionContextProps<T extends SelectedCell = SelectedCell> {
|
|
5
|
-
selectionStore: VirtualTableSelectionStore<T>;
|
|
6
|
-
select: (cell: T | undefined) => void;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
const SelectionContext = createContext<VirtualTableSelectionContextProps<any> | null>(null);
|
|
10
|
-
|
|
11
|
-
export const VirtualTableSelectionProvider = <T extends SelectedCell = SelectedCell>({
|
|
12
|
-
store,
|
|
13
|
-
children
|
|
14
|
-
}: {
|
|
15
|
-
store: VirtualTableSelectionStore<T>;
|
|
16
|
-
children: React.ReactNode;
|
|
17
|
-
}) => {
|
|
18
|
-
const value = React.useMemo(() => ({
|
|
19
|
-
selectionStore: store,
|
|
20
|
-
select: store.select
|
|
21
|
-
}), [store]);
|
|
22
|
-
|
|
23
|
-
return (
|
|
24
|
-
<SelectionContext.Provider value={value}>
|
|
25
|
-
{children}
|
|
26
|
-
</SelectionContext.Provider>
|
|
27
|
-
);
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
export const useVirtualTableSelection = <T extends SelectedCell = SelectedCell>() => {
|
|
31
|
-
const context = useContext(SelectionContext);
|
|
32
|
-
if (!context) {
|
|
33
|
-
throw new Error("useVirtualTableSelection must be used within a VirtualTableSelectionProvider");
|
|
34
|
-
}
|
|
35
|
-
return context as VirtualTableSelectionContextProps<T>;
|
|
36
|
-
};
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { useSyncExternalStore, useCallback, useRef } from "react";
|
|
2
|
-
|
|
3
|
-
export interface SelectedCell {
|
|
4
|
-
columnKey: string;
|
|
5
|
-
id: string | number;
|
|
6
|
-
cellRect?: DOMRect;
|
|
7
|
-
width?: number;
|
|
8
|
-
height?: number;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export function createVirtualTableSelectionStore<T extends SelectedCell = SelectedCell>() {
|
|
12
|
-
let selectedCell: T | undefined = undefined;
|
|
13
|
-
const listeners = new Set<() => void>();
|
|
14
|
-
|
|
15
|
-
function getEntity(): T | undefined {
|
|
16
|
-
return selectedCell;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function subscribe(listener: () => void): () => void {
|
|
20
|
-
listeners.add(listener);
|
|
21
|
-
return () => listeners.delete(listener);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function select(cell: T | undefined) {
|
|
25
|
-
selectedCell = cell;
|
|
26
|
-
listeners.forEach(l => l());
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
return {
|
|
30
|
-
getEntity,
|
|
31
|
-
subscribe,
|
|
32
|
-
select
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export type VirtualTableSelectionStore<T extends SelectedCell = SelectedCell> = ReturnType<typeof createVirtualTableSelectionStore<T>>;
|
|
37
|
-
|
|
38
|
-
export function useVirtualTableCellSelected<T extends SelectedCell = SelectedCell>(
|
|
39
|
-
store: VirtualTableSelectionStore<T>,
|
|
40
|
-
columnKey: string,
|
|
41
|
-
id: string | number
|
|
42
|
-
): boolean {
|
|
43
|
-
const selectorRef = useRef({ columnKey, id });
|
|
44
|
-
selectorRef.current = { columnKey, id };
|
|
45
|
-
|
|
46
|
-
const getEntity = useCallback(() => {
|
|
47
|
-
const cell = store.getEntity();
|
|
48
|
-
if (!cell) return false;
|
|
49
|
-
const s = selectorRef.current;
|
|
50
|
-
return cell.columnKey === s.columnKey && cell.id === s.id;
|
|
51
|
-
}, [store]);
|
|
52
|
-
|
|
53
|
-
return useSyncExternalStore(store.subscribe, getEntity, getEntity);
|
|
54
|
-
}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import {
|
|
3
|
-
CellRendererParams,
|
|
4
|
-
OnRowClickParams,
|
|
5
|
-
OnVirtualTableColumnResizeParams,
|
|
6
|
-
VirtualTableColumn,
|
|
7
|
-
VirtualTableFilterValues,
|
|
8
|
-
VirtualTableWhereFilterOp
|
|
9
|
-
} from "./VirtualTableProps";
|
|
10
|
-
import { FilterFormFieldProps } from "./VirtualTableHeader";
|
|
11
|
-
|
|
12
|
-
export type VirtualTableRowProps<T extends Record<string, unknown>> = {
|
|
13
|
-
style: React.CSSProperties,
|
|
14
|
-
rowHeight: number,
|
|
15
|
-
rowData: T;
|
|
16
|
-
rowIndex: number;
|
|
17
|
-
onRowClick?: (props: OnRowClickParams<Record<string, unknown>>) => void;
|
|
18
|
-
children: React.ReactNode[];
|
|
19
|
-
columns: VirtualTableColumn[];
|
|
20
|
-
hoverRow?: boolean;
|
|
21
|
-
rowClassName?: (rowData: T) => string | undefined;
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
export type VirtualTableContextProps<T> = {
|
|
25
|
-
data?: T[];
|
|
26
|
-
rowHeight?: number,
|
|
27
|
-
headerHeight?: number,
|
|
28
|
-
columns: VirtualTableColumn[];
|
|
29
|
-
cellRenderer: React.ComponentType<CellRendererParams<T>>;
|
|
30
|
-
/** Each sorted column's direction and its rank in the sort, keyed by column. */
|
|
31
|
-
sortIndex: Map<string, { direction: "asc" | "desc"; position: number }>;
|
|
32
|
-
filter?: VirtualTableFilterValues<string>;
|
|
33
|
-
onRowClick?: (props: OnRowClickParams<Record<string, unknown>>) => void;
|
|
34
|
-
onColumnSort: (key: string, additive?: boolean) => void;
|
|
35
|
-
onColumnResize: (params: OnVirtualTableColumnResizeParams) => void;
|
|
36
|
-
onColumnResizeEnd: (params: OnVirtualTableColumnResizeParams) => void;
|
|
37
|
-
onFilterUpdate: (column: VirtualTableColumn, filterForProperty?: [VirtualTableWhereFilterOp, unknown]) => void;
|
|
38
|
-
customView?: React.ReactNode,
|
|
39
|
-
hoverRow: boolean;
|
|
40
|
-
createFilterField?: (props: FilterFormFieldProps<unknown>) => React.ReactNode;
|
|
41
|
-
rowClassName?: (rowData: T) => string | undefined;
|
|
42
|
-
endAdornment?: React.ReactNode;
|
|
43
|
-
AddColumnComponent?: React.ComponentType;
|
|
44
|
-
onColumnsOrderChange?: (columns: VirtualTableColumn[]) => void;
|
|
45
|
-
draggingColumnId?: string | null;
|
|
46
|
-
extraData?: unknown;
|
|
47
|
-
};
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { cls } from "../../util";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* The label above a Select or MultiSelect.
|
|
6
|
-
*
|
|
7
|
-
* It used `text-surface-accent-500` — a SURFACE scale, borrowed for type. The
|
|
8
|
-
* label above a TextField has always used `text-text-secondary`, and the two are
|
|
9
|
-
* the same role, so a form mixing the components showed two different label
|
|
10
|
-
* colours: `#64748b` blue-grey over a Select, `#757575` neutral over a TextField.
|
|
11
|
-
* Measured side by side on /debug/ui, which is where it is most obvious, because
|
|
12
|
-
* the reference puts them in adjacent columns.
|
|
13
|
-
*
|
|
14
|
-
* The text tokens are also the tuned ones: `--color-surface-500` was moved to
|
|
15
|
-
* #797979 precisely so muted type clears AA on both grounds. The slate scale
|
|
16
|
-
* carries no such guarantee — it is for surfaces.
|
|
17
|
-
*/
|
|
18
|
-
export function SelectInputLabel({ children, error }: { children: React.ReactNode, error?: boolean }) {
|
|
19
|
-
return <div className={cls("text-sm font-medium ml-3.5 mb-1",
|
|
20
|
-
error ? "text-red-600 dark:text-red-500" : "text-text-secondary dark:text-text-secondary-dark")}>
|
|
21
|
-
{children}
|
|
22
|
-
</div>;
|
|
23
|
-
}
|
package/src/components/index.tsx
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
// ./common/SelectInputLabel is internal — Select and MultiSelect render it for
|
|
2
|
-
// a string `label`. Pass a ReactNode `label` to override it.
|
|
3
|
-
export * from "./Autocomplete";
|
|
4
|
-
export * from "./Alert";
|
|
5
|
-
export * from "./Avatar";
|
|
6
|
-
export * from "./BooleanSwitch";
|
|
7
|
-
export * from "./BooleanSwitchWithLabel";
|
|
8
|
-
export * from "./Button";
|
|
9
|
-
export * from "./Card";
|
|
10
|
-
export * from "./CenteredView";
|
|
11
|
-
export * from "./Container";
|
|
12
|
-
export * from "./Collapse";
|
|
13
|
-
export * from "./CircularProgress";
|
|
14
|
-
export * from "./CircularProgressCenter";
|
|
15
|
-
export * from "./ErrorBoundary";
|
|
16
|
-
export * from "./Checkbox";
|
|
17
|
-
export * from "./Chip";
|
|
18
|
-
export * from "./ColorPicker";
|
|
19
|
-
export * from "./DateTimeField";
|
|
20
|
-
export * from "./Dialog";
|
|
21
|
-
export * from "./DialogActions";
|
|
22
|
-
export * from "./DialogContent";
|
|
23
|
-
export * from "./DialogTitle";
|
|
24
|
-
export * from "./ExpandablePanel";
|
|
25
|
-
export * from "./FileUpload";
|
|
26
|
-
export * from "./FilterChip";
|
|
27
|
-
export * from "./IconButton";
|
|
28
|
-
export * from "./InputLabel";
|
|
29
|
-
export * from "./InfoLabel";
|
|
30
|
-
export * from "./Label";
|
|
31
|
-
export * from "./LoadingButton";
|
|
32
|
-
export * from "./Markdown";
|
|
33
|
-
export * from "./Menu";
|
|
34
|
-
export * from "./Menubar";
|
|
35
|
-
export * from "./MultiSelect";
|
|
36
|
-
export * from "./Paper";
|
|
37
|
-
export * from "./RadioGroup";
|
|
38
|
-
export * from "./ResizablePanels";
|
|
39
|
-
export * from "./SearchBar";
|
|
40
|
-
export * from "./Select";
|
|
41
|
-
export * from "./Separator";
|
|
42
|
-
export * from "./Slider";
|
|
43
|
-
export * from "./Sheet";
|
|
44
|
-
export * from "./TextareaAutosize";
|
|
45
|
-
export * from "./TextField";
|
|
46
|
-
export * from "./Tooltip";
|
|
47
|
-
export * from "./Typography";
|
|
48
|
-
export * from "./Tabs";
|
|
49
|
-
export * from "./Table";
|
|
50
|
-
export * from "./Popover";
|
|
51
|
-
export * from "./Badge";
|
|
52
|
-
export * from "./DebouncedTextField";
|
|
53
|
-
export * from "./Skeleton";
|
|
54
|
-
export * from "./ToggleButtonGroup";
|
|
55
|
-
export * from "./VirtualTable";
|
|
56
|
-
|
|
57
|
-
// Re-exported Radix primitives — consume these from @rebasepro/ui instead of
|
|
58
|
-
// adding direct @radix-ui/* deps to every sub-package.
|
|
59
|
-
import * as Portal from "@radix-ui/react-portal";
|
|
60
|
-
import * as PopoverPrimitive from "@radix-ui/react-popover";
|
|
61
|
-
export { Portal, PopoverPrimitive };
|
|
62
|
-
export { Slot } from "@radix-ui/react-slot";
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import React, { createContext, useContext, useMemo } from "react";
|
|
3
|
-
|
|
4
|
-
export interface PortalContainerContextType {
|
|
5
|
-
container: HTMLElement | null;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
const PortalContainerContext = createContext<PortalContainerContextType | undefined>(undefined);
|
|
9
|
-
|
|
10
|
-
export interface PortalContainerProviderProps {
|
|
11
|
-
container: HTMLElement | null;
|
|
12
|
-
children: React.ReactNode;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Provider component that sets the portal container for all descendants.
|
|
17
|
-
* This can be used at any level of the tree to specify where portals should be attached.
|
|
18
|
-
*
|
|
19
|
-
* @example
|
|
20
|
-
* ```tsx
|
|
21
|
-
* const containerRef = useRef<HTMLDivElement>(null);
|
|
22
|
-
*
|
|
23
|
-
* <div ref={containerRef}>
|
|
24
|
-
* <PortalContainerProvider container={containerRef.current}>
|
|
25
|
-
* <YourComponents />
|
|
26
|
-
* </PortalContainerProvider>
|
|
27
|
-
* </div>
|
|
28
|
-
* ```
|
|
29
|
-
*/
|
|
30
|
-
export function PortalContainerProvider({ container, children }: PortalContainerProviderProps) {
|
|
31
|
-
const contextValue = useMemo(() => ({ container }), [container]);
|
|
32
|
-
|
|
33
|
-
return (
|
|
34
|
-
<PortalContainerContext.Provider value={contextValue}>
|
|
35
|
-
{children}
|
|
36
|
-
</PortalContainerContext.Provider>
|
|
37
|
-
);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Hook to access the portal container from context.
|
|
42
|
-
* Returns null if no provider is found in the tree.
|
|
43
|
-
*
|
|
44
|
-
* @returns The portal container element or null
|
|
45
|
-
*/
|
|
46
|
-
export function usePortalContainer(): HTMLElement | null {
|
|
47
|
-
const context = useContext(PortalContainerContext);
|
|
48
|
-
return context?.container ?? null;
|
|
49
|
-
}
|
|
50
|
-
|
package/src/hooks/index.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { useCallback, useRef } from "react";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export function useDebounceCallback<T extends (...args: any[]) => unknown>(
|
|
5
|
-
callback?: T,
|
|
6
|
-
delay?: number
|
|
7
|
-
): T {
|
|
8
|
-
const timeoutRef = useRef<number | null>(null);
|
|
9
|
-
|
|
10
|
-
const debouncedCallback = useCallback((...args: Parameters<T>) => {
|
|
11
|
-
if (timeoutRef.current !== null) {
|
|
12
|
-
clearTimeout(timeoutRef.current);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
timeoutRef.current = window.setTimeout(() => {
|
|
16
|
-
callback?.(...args);
|
|
17
|
-
}, delay ?? 200);
|
|
18
|
-
}, [callback, delay]);
|
|
19
|
-
|
|
20
|
-
return debouncedCallback as T;
|
|
21
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import { useEffect, useState } from "react";
|
|
4
|
-
|
|
5
|
-
export function useDebounceValue<T>(value: T, delay = 300): T {
|
|
6
|
-
// State and setters for debounced value
|
|
7
|
-
const [debouncedValue, setDebouncedValue] = useState(value);
|
|
8
|
-
useEffect(
|
|
9
|
-
() => {
|
|
10
|
-
const handler = setTimeout(() => {
|
|
11
|
-
setDebouncedValue(value);
|
|
12
|
-
}, delay);
|
|
13
|
-
return () => {
|
|
14
|
-
clearTimeout(handler);
|
|
15
|
-
};
|
|
16
|
-
},
|
|
17
|
-
[value, delay] // Only re-call effect if value or delay changes
|
|
18
|
-
);
|
|
19
|
-
return debouncedValue;
|
|
20
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
|
|
3
|
-
export function useDebouncedCallback<T>(value: T, callback: () => void, immediate: boolean, timeoutMs = 300) {
|
|
4
|
-
|
|
5
|
-
const pendingUpdate = React.useRef(false);
|
|
6
|
-
|
|
7
|
-
const callbackRef = React.useRef(callback);
|
|
8
|
-
React.useEffect(() => {
|
|
9
|
-
callbackRef.current = callback;
|
|
10
|
-
}, [callback]);
|
|
11
|
-
|
|
12
|
-
const performUpdate = React.useCallback(() => {
|
|
13
|
-
callbackRef.current();
|
|
14
|
-
pendingUpdate.current = false;
|
|
15
|
-
}, []);
|
|
16
|
-
|
|
17
|
-
const handlerRef = React.useRef<ReturnType<typeof setTimeout> | undefined>(undefined);
|
|
18
|
-
|
|
19
|
-
React.useEffect(
|
|
20
|
-
() => {
|
|
21
|
-
if (immediate) {
|
|
22
|
-
clearTimeout(handlerRef.current);
|
|
23
|
-
if (pendingUpdate.current) {
|
|
24
|
-
performUpdate();
|
|
25
|
-
}
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
pendingUpdate.current = true;
|
|
30
|
-
clearTimeout(handlerRef.current);
|
|
31
|
-
handlerRef.current = setTimeout(performUpdate, timeoutMs);
|
|
32
|
-
return () => {
|
|
33
|
-
if (immediate)
|
|
34
|
-
performUpdate();
|
|
35
|
-
};
|
|
36
|
-
},
|
|
37
|
-
[immediate, value, performUpdate, timeoutMs]
|
|
38
|
-
);
|
|
39
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { useEffect } from "react";
|
|
3
|
-
import { usePortalContainer } from "./PortalContainerContext";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Use this hook to create a `<style>` element and inject it into the DOM.
|
|
7
|
-
* It checks if the style already exists, and if it does, it does not inject it again.
|
|
8
|
-
* @param key
|
|
9
|
-
* @param styles
|
|
10
|
-
*/
|
|
11
|
-
export function useInjectStyles(key: string, styles: string) {
|
|
12
|
-
|
|
13
|
-
const portalContainer = usePortalContainer();
|
|
14
|
-
|
|
15
|
-
useEffect(() => {
|
|
16
|
-
if (typeof document === "undefined") return;
|
|
17
|
-
|
|
18
|
-
const targetContainer: HTMLElement | null = portalContainer ?? document.head;
|
|
19
|
-
|
|
20
|
-
// Try to find an existing style element within the target container first
|
|
21
|
-
const existingStyle = (targetContainer as HTMLElement).querySelector?.(`#${key}`) as HTMLStyleElement | null;
|
|
22
|
-
|
|
23
|
-
if (!existingStyle) {
|
|
24
|
-
const style = document.createElement("style");
|
|
25
|
-
style.id = key;
|
|
26
|
-
style.innerHTML = styles;
|
|
27
|
-
(targetContainer || document.head).appendChild(style);
|
|
28
|
-
}
|
|
29
|
-
}, []);
|
|
30
|
-
|
|
31
|
-
}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import { RefObject, useEffect } from "react";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Hook that alerts clicks outside the passed ref
|
|
7
|
-
*/
|
|
8
|
-
export function useOutsideAlerter(ref: RefObject<HTMLElement | null>, onOutsideClick: () => void, active = true): void {
|
|
9
|
-
useEffect(() => {
|
|
10
|
-
if (!active)
|
|
11
|
-
return;
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Alert if clicked on outside of element
|
|
15
|
-
*/
|
|
16
|
-
function handleClickOutside(event: Event) {
|
|
17
|
-
if (isInPresentationLayer(event.target as Node)) {
|
|
18
|
-
return;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
if (ref.current && !ref.current.contains(event.target as Node)) {
|
|
22
|
-
onOutsideClick();
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// Bind the event listener
|
|
27
|
-
document.addEventListener("mousedown", handleClickOutside);
|
|
28
|
-
return () => {
|
|
29
|
-
// Unbind the event listener on clean up
|
|
30
|
-
document.removeEventListener("mousedown", handleClickOutside);
|
|
31
|
-
};
|
|
32
|
-
}, [ref, active, onOutsideClick]);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Check if any parent of the node is a presentation node
|
|
37
|
-
* @param node
|
|
38
|
-
*/
|
|
39
|
-
function isInPresentationLayer(node: Node | null): boolean {
|
|
40
|
-
if (node instanceof HTMLElement) {
|
|
41
|
-
if (node.getAttribute("role") === "presentation")
|
|
42
|
-
return true;
|
|
43
|
-
return isInPresentationLayer(node.parentNode);
|
|
44
|
-
}
|
|
45
|
-
return false;
|
|
46
|
-
}
|
package/src/icons/GitHubIcon.tsx
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
|
|
3
|
-
import { colorClassesMapping, IconProps, iconSize } from "./Icon";
|
|
4
|
-
import { cls } from "../util";
|
|
5
|
-
|
|
6
|
-
export function GitHubIcon({ size = 24, color, className, onClick, style }: IconProps) {
|
|
7
|
-
// `size` is `IconSize | number` — resolve the keyword, or an SVG attribute
|
|
8
|
-
// of width="small" is emitted and the icon renders at its intrinsic size.
|
|
9
|
-
const px = typeof size === "number" ? size : iconSize[size];
|
|
10
|
-
return <svg xmlns="http://www.w3.org/2000/svg"
|
|
11
|
-
className={cls(color ? colorClassesMapping[color] : "", className)}
|
|
12
|
-
onClick={onClick}
|
|
13
|
-
style={style}
|
|
14
|
-
fill={"currentColor"}
|
|
15
|
-
width={px}
|
|
16
|
-
height={px}
|
|
17
|
-
viewBox="0 0 24 24">
|
|
18
|
-
<path
|
|
19
|
-
d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
|
|
20
|
-
</svg>;
|
|
21
|
-
}
|
package/src/icons/HandleIcon.tsx
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
|
|
3
|
-
import { colorClassesMapping, IconProps, iconSize } from "./Icon";
|
|
4
|
-
import { cls } from "../util";
|
|
5
|
-
|
|
6
|
-
export function HandleIcon({ size = 24, color, className, onClick, style }: IconProps) {
|
|
7
|
-
const px = typeof size === "number" ? size : iconSize[size];
|
|
8
|
-
return <svg xmlns="http://www.w3.org/2000/svg"
|
|
9
|
-
className={cls(color ? colorClassesMapping[color] : "", className)}
|
|
10
|
-
onClick={onClick}
|
|
11
|
-
style={style}
|
|
12
|
-
width={px}
|
|
13
|
-
height={px}
|
|
14
|
-
viewBox="0 0 100 100"
|
|
15
|
-
fill="none">
|
|
16
|
-
<circle cx="28" cy="50" r="9" fill={"currentColor"}/>
|
|
17
|
-
<circle cx="28" cy="21" r="9" fill={"currentColor"}/>
|
|
18
|
-
<circle cx="71" cy="21" r="9" fill={"currentColor"}/>
|
|
19
|
-
<circle cx="71" cy="50" r="9" fill={"currentColor"}/>
|
|
20
|
-
<circle cx="71" cy="78" r="9" fill={"currentColor"}/>
|
|
21
|
-
<circle cx="28" cy="78" r="9" fill={"currentColor"}/>
|
|
22
|
-
</svg>;
|
|
23
|
-
}
|
package/src/icons/Icon.tsx
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
export type IconColor = "inherit" | "primary" | "secondary" | "disabled" | "error" | "success" | "warning";
|
|
4
|
-
export type IconSize = "smallest" | "small" | "medium" | "large";
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Standardized icon size map in px.
|
|
8
|
-
* Use with direct Lucide imports: `<Database size={iconSize.small} />`
|
|
9
|
-
*/
|
|
10
|
-
export const iconSize = {
|
|
11
|
-
smallest: 16,
|
|
12
|
-
small: 20,
|
|
13
|
-
medium: 24,
|
|
14
|
-
large: 28
|
|
15
|
-
} as const satisfies Record<IconSize, number>;
|
|
16
|
-
|
|
17
|
-
export type IconProps = {
|
|
18
|
-
size?: IconSize | number,
|
|
19
|
-
color?: IconColor,
|
|
20
|
-
className?: string,
|
|
21
|
-
onClick?: (e: React.SyntheticEvent) => void,
|
|
22
|
-
style?: React.CSSProperties,
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export const colorClassesMapping: Record<IconColor, string> = {
|
|
26
|
-
inherit: "",
|
|
27
|
-
primary: "text-primary",
|
|
28
|
-
success: "text-green-500",
|
|
29
|
-
warning: "text-yellow-500",
|
|
30
|
-
secondary: "text-secondary",
|
|
31
|
-
disabled: "text-text-disabled dark:text-text-disabled-dark",
|
|
32
|
-
error: "text-red-500"
|
|
33
|
-
}
|