@rebasepro/ui 0.6.1 → 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.
Files changed (68) hide show
  1. package/dist/components/VirtualTable/fields/VirtualTableDateField.d.ts +13 -0
  2. package/dist/components/VirtualTable/fields/VirtualTableInput.d.ts +10 -0
  3. package/dist/components/VirtualTable/fields/VirtualTableNumberInput.d.ts +9 -0
  4. package/dist/components/VirtualTable/fields/VirtualTableSelect.d.ts +17 -0
  5. package/dist/components/VirtualTable/fields/VirtualTableSwitch.d.ts +8 -0
  6. package/dist/components/VirtualTable/index.d.ts +7 -0
  7. package/dist/components/VirtualTable/selection/SelectionContext.d.ts +11 -0
  8. package/dist/components/VirtualTable/selection/SelectionStore.d.ts +14 -0
  9. package/dist/icons/index.d.ts +1 -1
  10. package/dist/index.d.ts +13 -3
  11. package/dist/index.es.js +2322 -23
  12. package/dist/index.es.js.map +1 -1
  13. package/dist/styles.d.ts +1 -1
  14. package/dist/views/CardView.d.ts +32 -0
  15. package/dist/views/CollectionView/CollectionCardView.d.ts +30 -0
  16. package/dist/views/CollectionView/CollectionKanbanView.d.ts +31 -0
  17. package/dist/views/CollectionView/CollectionListView.d.ts +30 -0
  18. package/dist/views/CollectionView/CollectionTableView.d.ts +37 -0
  19. package/dist/views/CollectionView/CollectionView.d.ts +121 -0
  20. package/dist/views/CollectionView/CollectionViewToolbar.d.ts +31 -0
  21. package/dist/views/CollectionView/CollectionViewTypes.d.ts +106 -0
  22. package/dist/views/CollectionView/DefaultCellRenderer.d.ts +9 -0
  23. package/dist/views/CollectionView/index.d.ts +24 -0
  24. package/dist/views/CollectionView/utils.d.ts +5 -0
  25. package/dist/views/Kanban/Board.d.ts +3 -0
  26. package/dist/views/Kanban/BoardColumn.d.ts +20 -0
  27. package/dist/views/Kanban/BoardColumnTitle.d.ts +8 -0
  28. package/dist/views/Kanban/BoardSortableList.d.ts +14 -0
  29. package/dist/views/Kanban/board_types.d.ts +61 -0
  30. package/dist/views/Kanban/index.d.ts +5 -0
  31. package/dist/views/KanbanView.d.ts +24 -0
  32. package/dist/views/ListView.d.ts +40 -0
  33. package/dist/views/TableView.d.ts +6 -0
  34. package/dist/views/index.d.ts +5 -0
  35. package/package.json +1 -1
  36. package/src/components/Sheet.tsx +8 -4
  37. package/src/components/VirtualTable/fields/VirtualTableDateField.tsx +32 -0
  38. package/src/components/VirtualTable/fields/VirtualTableInput.tsx +82 -0
  39. package/src/components/VirtualTable/fields/VirtualTableNumberInput.tsx +71 -0
  40. package/src/components/VirtualTable/fields/VirtualTableSelect.tsx +107 -0
  41. package/src/components/VirtualTable/fields/VirtualTableSwitch.tsx +28 -0
  42. package/src/components/VirtualTable/index.tsx +7 -0
  43. package/src/components/VirtualTable/selection/SelectionContext.tsx +36 -0
  44. package/src/components/VirtualTable/selection/SelectionStore.ts +54 -0
  45. package/src/icons/index.ts +3 -0
  46. package/src/index.ts +43 -3
  47. package/src/styles.ts +1 -1
  48. package/src/views/CardView.tsx +281 -0
  49. package/src/views/CollectionView/CollectionCardView.tsx +270 -0
  50. package/src/views/CollectionView/CollectionKanbanView.tsx +251 -0
  51. package/src/views/CollectionView/CollectionListView.tsx +245 -0
  52. package/src/views/CollectionView/CollectionTableView.tsx +229 -0
  53. package/src/views/CollectionView/CollectionView.tsx +388 -0
  54. package/src/views/CollectionView/CollectionViewToolbar.tsx +229 -0
  55. package/src/views/CollectionView/CollectionViewTypes.ts +137 -0
  56. package/src/views/CollectionView/DefaultCellRenderer.tsx +404 -0
  57. package/src/views/CollectionView/index.ts +44 -0
  58. package/src/views/CollectionView/utils.ts +14 -0
  59. package/src/views/Kanban/Board.tsx +421 -0
  60. package/src/views/Kanban/BoardColumn.tsx +135 -0
  61. package/src/views/Kanban/BoardColumnTitle.tsx +47 -0
  62. package/src/views/Kanban/BoardSortableList.tsx +170 -0
  63. package/src/views/Kanban/board_types.ts +70 -0
  64. package/src/views/Kanban/index.tsx +5 -0
  65. package/src/views/KanbanView.tsx +32 -0
  66. package/src/views/ListView.tsx +281 -0
  67. package/src/views/TableView.tsx +7 -0
  68. package/src/views/index.ts +5 -0
@@ -0,0 +1,6 @@
1
+ export { VirtualTable as TableView } from "../components/VirtualTable/VirtualTable";
2
+ export type { VirtualTableProps as TableViewProps } from "../components/VirtualTable/VirtualTableProps";
3
+ export type OnColumnResizeParams = {
4
+ width: number;
5
+ key: string;
6
+ };
@@ -0,0 +1,5 @@
1
+ export * from "./ListView";
2
+ export * from "./CardView";
3
+ export * from "./KanbanView";
4
+ export * from "./TableView";
5
+ export * from "./CollectionView";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@rebasepro/ui",
3
3
  "type": "module",
4
- "version": "0.6.1",
4
+ "version": "0.8.0",
5
5
  "description": "Awesome Firebase/Firestore-based headless open-source CMS",
6
6
  "funding": {
7
7
  "url": "https://github.com/sponsors/rebaseco"
@@ -3,7 +3,7 @@ import React, { useEffect, useState } from "react";
3
3
  import { cls } from "../util";
4
4
  import { defaultBorderMixin } from "../styles";
5
5
  import * as DialogPrimitive from "@radix-ui/react-dialog";
6
- import { usePortalContainer } from "../hooks/PortalContainerContext";
6
+ import { usePortalContainer, PortalContainerProvider } from "../hooks/PortalContainerContext";
7
7
 
8
8
  interface SheetProps {
9
9
  children: React.ReactNode;
@@ -45,6 +45,7 @@ export const Sheet: React.FC<SheetProps> = ({
45
45
  ...props
46
46
  }) => {
47
47
  const [displayed, setDisplayed] = useState(false);
48
+ const [contentEl, setContentEl] = useState<HTMLDivElement | null>(null);
48
49
 
49
50
  // Get the portal container from context
50
51
  const contextContainer = usePortalContainer();
@@ -90,7 +91,8 @@ export const Sheet: React.FC<SheetProps> = ({
90
91
  />}
91
92
  <DialogPrimitive.Content
92
93
  {...props}
93
- onFocusCapture={(event) => event.preventDefault()}
94
+ ref={setContentEl}
95
+ onOpenAutoFocus={(event) => event.preventDefault()}
94
96
  onPointerDownOutside={onPointerDownOutside}
95
97
  onInteractOutside={onInteractOutside}
96
98
  className={cls(
@@ -112,10 +114,12 @@ export const Sheet: React.FC<SheetProps> = ({
112
114
  )}
113
115
  style={style}
114
116
  >
115
- <DialogPrimitive.Title autoFocus tabIndex={0} className="sr-only outline-none focus:outline-none focus-visible:outline-none focus-visible:ring-0 focus:ring-0">
117
+ <DialogPrimitive.Title className="sr-only outline-none focus:outline-none focus-visible:outline-none focus-visible:ring-0 focus:ring-0">
116
118
  {title ?? "Sheet"}
117
119
  </DialogPrimitive.Title>
118
- {children}
120
+ <PortalContainerProvider container={contentEl}>
121
+ {children}
122
+ </PortalContainerProvider>
119
123
  </DialogPrimitive.Content>
120
124
  </DialogPrimitive.Portal>
121
125
  </DialogPrimitive.Root>
@@ -0,0 +1,32 @@
1
+ import React from "react";
2
+ import { cls } from "../../../util";
3
+ import { focusedDisabled } from "../../../styles";
4
+ import { DateTimeField } from "../../DateTimeField";
5
+
6
+ export function VirtualTableDateField(props: {
7
+ name?: string;
8
+ error?: Error;
9
+ mode?: "date" | "date_time";
10
+ timezone?: string;
11
+ internalValue: Date | undefined | null;
12
+ updateValue: (newValue: (Date | null)) => void;
13
+ focused: boolean;
14
+ disabled: boolean;
15
+ locale?: string;
16
+ onBlur?: React.FocusEventHandler<HTMLInputElement | HTMLTextAreaElement>;
17
+ }) {
18
+ const { disabled, error, mode, timezone, internalValue, updateValue, locale } = props;
19
+
20
+ return (
21
+ <DateTimeField
22
+ value={internalValue ?? undefined}
23
+ onChange={(dateValue) => updateValue(dateValue ?? null)}
24
+ invisible={true}
25
+ inputClassName={cls("w-full h-full", focusedDisabled)}
26
+ className={cls("w-full h-full", focusedDisabled)}
27
+ mode={mode}
28
+ timezone={timezone}
29
+ locale={locale}
30
+ />
31
+ );
32
+ }
@@ -0,0 +1,82 @@
1
+ import React, { useEffect, useRef, useState } from "react";
2
+ import { useDebouncedCallback } from "../../../hooks/useDebouncedCallback";
3
+ import { focusedDisabled } from "../../../styles";
4
+ import { TextareaAutosize } from "../../TextareaAutosize";
5
+
6
+ export function VirtualTableInput(props: {
7
+ error?: Error;
8
+ value: string;
9
+ multiline?: boolean;
10
+ focused: boolean;
11
+ disabled: boolean;
12
+ updateValue: (newValue: (string | null)) => void;
13
+ onBlur?: () => void;
14
+ }) {
15
+ const ref = React.useRef<HTMLTextAreaElement>(null);
16
+ const { disabled, value, multiline = false, updateValue, focused } = props;
17
+ const prevValue = useRef<string | null>(value);
18
+ const [internalValue, setInternalValue] = useState<typeof value>(value);
19
+ const focusedState = useRef<boolean>(false);
20
+
21
+ useEffect(() => {
22
+ if (prevValue.current !== value && value !== internalValue)
23
+ setInternalValue(value);
24
+ prevValue.current = value;
25
+ }, [value]);
26
+
27
+ const doUpdate = React.useCallback(() => {
28
+ const emptyInitialValue = !value;
29
+ if (emptyInitialValue && !internalValue) return;
30
+ if (internalValue !== value && internalValue !== prevValue.current) {
31
+ prevValue.current = internalValue;
32
+ updateValue(internalValue);
33
+ }
34
+ }, [internalValue, updateValue, value]);
35
+
36
+ useDebouncedCallback(internalValue, doUpdate, !focused, 400);
37
+
38
+ useEffect(() => {
39
+ if (ref.current && focused && !focusedState.current) {
40
+ focusedState.current = true;
41
+ ref.current.focus({ preventScroll: true });
42
+ ref.current.selectionStart = ref.current.value.length;
43
+ ref.current.selectionEnd = ref.current.value.length;
44
+ } else {
45
+ focusedState.current = focused;
46
+ }
47
+ }, [focused, ref]);
48
+
49
+ return (
50
+ <TextareaAutosize
51
+ className={focusedDisabled}
52
+ ref={ref}
53
+ style={{
54
+ padding: 0,
55
+ margin: 0,
56
+ width: "100%",
57
+ color: "unset",
58
+ fontWeight: "unset",
59
+ fontSize: "unset",
60
+ fontFamily: "unset",
61
+ background: "unset",
62
+ border: "unset",
63
+ resize: "none",
64
+ outline: "none"
65
+ }}
66
+ value={internalValue ?? ""}
67
+ onChange={(evt) => {
68
+ const newValue = evt.target.value as string;
69
+ if (multiline || !newValue.endsWith("\n"))
70
+ setInternalValue(newValue);
71
+ }}
72
+ onFocus={() => {
73
+ focusedState.current = true;
74
+ }}
75
+ onBlur={() => {
76
+ focusedState.current = false;
77
+ doUpdate();
78
+ if (props.onBlur) props.onBlur();
79
+ }}
80
+ />
81
+ );
82
+ }
@@ -0,0 +1,71 @@
1
+ import React, { useEffect, useRef, useState } from "react";
2
+ import { useDebouncedCallback } from "../../../hooks/useDebouncedCallback";
3
+ import { cls } from "../../../util";
4
+ import { focusedDisabled } from "../../../styles";
5
+ import { TextField } from "../../TextField";
6
+
7
+ export function VirtualTableNumberInput(props: {
8
+ error?: Error;
9
+ value: number;
10
+ align?: "right" | "left" | "center";
11
+ updateValue: (newValue: (number | null)) => void;
12
+ focused: boolean;
13
+ disabled: boolean;
14
+ }) {
15
+ const { align = "left", value, updateValue, focused } = props;
16
+ const propStringValue = (value && typeof value === "number") ? value.toString() : "";
17
+ const [internalValue, setInternalValue] = useState<string | null>(propStringValue);
18
+ const prevValue = useRef<number | null>(value);
19
+
20
+ useEffect(() => {
21
+ if (prevValue.current !== value && String(value) !== internalValue)
22
+ setInternalValue(value ? value.toString() : null);
23
+ prevValue.current = value;
24
+ }, [value]);
25
+
26
+ const doUpdate = React.useCallback(() => {
27
+ if (internalValue !== propStringValue) {
28
+ if (internalValue !== undefined && internalValue !== null) {
29
+ const numberValue = parseFloat(internalValue);
30
+ if (isNaN(numberValue)) return;
31
+ updateValue(numberValue);
32
+ } else {
33
+ updateValue(null);
34
+ }
35
+ }
36
+ }, [internalValue, value]);
37
+
38
+ useDebouncedCallback(internalValue, doUpdate, !focused, 400);
39
+
40
+ useEffect(() => {
41
+ if (!focused && propStringValue !== internalValue)
42
+ setInternalValue(value !== undefined && value !== null ? value.toString() : null);
43
+ }, [value, focused]);
44
+
45
+ const inputRef = React.useRef<HTMLInputElement>(null);
46
+
47
+ useEffect(() => {
48
+ if (inputRef.current && focused) {
49
+ inputRef.current.focus({ preventScroll: true });
50
+ }
51
+ }, [focused, inputRef]);
52
+
53
+ const regexp = /^-?[0-9]+[,.]?[0-9]*$/;
54
+
55
+ return (
56
+ <TextField
57
+ inputRef={inputRef}
58
+ invisible={true}
59
+ size="small"
60
+ className="w-full"
61
+ inputClassName={cls("p-0 m-0 bg-transparent border-none outline-hidden font-normal leading-normal text-unset", focusedDisabled)}
62
+ inputStyle={{ textAlign: align }}
63
+ value={internalValue ?? ""}
64
+ onChange={(evt) => {
65
+ const newValue = evt.target.value.replace(",", ".");
66
+ if (newValue.length === 0) setInternalValue(null);
67
+ if (regexp.test(newValue) || newValue.startsWith("-")) setInternalValue(newValue);
68
+ }}
69
+ />
70
+ );
71
+ }
@@ -0,0 +1,107 @@
1
+ import React, { useCallback, useEffect, useRef } from "react";
2
+ import { Select, SelectItem } from "../../Select";
3
+ import { MultiSelect, MultiSelectItem } from "../../MultiSelect";
4
+ import { Chip } from "../../Chip";
5
+
6
+ export interface VirtualTableSelectOption {
7
+ value: string | number;
8
+ label: string;
9
+ color?: string;
10
+ }
11
+
12
+ export function VirtualTableSelect(props: {
13
+ options: VirtualTableSelectOption[];
14
+ error?: Error;
15
+ multiple?: boolean;
16
+ disabled: boolean;
17
+ small?: boolean;
18
+ value: string | number | string[] | number[] | undefined;
19
+ updateValue: (newValue: (string | number | string[] | number[] | null)) => void;
20
+ focused: boolean;
21
+ onBlur?: React.FocusEventHandler<HTMLInputElement | HTMLTextAreaElement>;
22
+ }) {
23
+ const { options, value, disabled, small = false, focused, updateValue, multiple = false } = props;
24
+ const validValue = (Array.isArray(value) && multiple) || (!Array.isArray(value) && !multiple);
25
+ const ref = useRef<HTMLButtonElement>(null);
26
+
27
+ useEffect(() => {
28
+ if (ref.current && focused) {
29
+ ref.current?.focus({ preventScroll: true });
30
+ }
31
+ }, [focused, ref]);
32
+
33
+ const onChange = useCallback((updatedValue: string | string[]) => {
34
+ if (multiple) {
35
+ const isNumber = options.some(o => typeof o.value === "number");
36
+ const newValue = (updatedValue as string[]).map((v) => {
37
+ const opt = options.find(o => String(o.value) === v);
38
+ return typeof opt?.value === "number" ? parseFloat(v) : v;
39
+ });
40
+ if (isNumber) {
41
+ updateValue(newValue as number[]);
42
+ } else {
43
+ updateValue(newValue as string[]);
44
+ }
45
+ } else {
46
+ const opt = options.find(o => String(o.value) === updatedValue);
47
+ updateValue(typeof opt?.value === "number" ? parseFloat(updatedValue as string) : (updatedValue as string || null));
48
+ }
49
+ }, [multiple, updateValue, options]);
50
+
51
+ const renderValue = (val?: string | number) => {
52
+ const option = options.find(o => o.value === val);
53
+ return (
54
+ <Chip size={small ? "small" : "medium"}>
55
+ {option ? option.label : String(val)}
56
+ </Chip>
57
+ );
58
+ };
59
+
60
+ const handleOpenChange = useCallback((open: boolean) => {
61
+ if (!open && ref.current) {
62
+ setTimeout(() => {
63
+ ref.current?.focus({ preventScroll: true });
64
+ }, 0);
65
+ }
66
+ }, []);
67
+
68
+ return multiple ? (
69
+ <MultiSelect
70
+ inputRef={ref}
71
+ className="w-full h-full p-0 bg-transparent outline-none"
72
+ position={"item-aligned"}
73
+ disabled={disabled}
74
+ includeClear={false}
75
+ useChips={false}
76
+ value={validValue ? (value as (string | number)[]).map(v => String(v)) : []}
77
+ onValueChange={onChange}
78
+ onOpenChange={handleOpenChange}
79
+ >
80
+ {options.map((opt) => (
81
+ <MultiSelectItem key={String(opt.value)} value={String(opt.value)}>
82
+ <Chip size={small ? "small" : "medium"}>{opt.label}</Chip>
83
+ </MultiSelectItem>
84
+ ))}
85
+ </MultiSelect>
86
+ ) : (
87
+ <Select
88
+ inputRef={ref}
89
+ fullWidth
90
+ className="w-full h-full p-0 bg-transparent outline-none [&_button]:ring-0 [&_button]:ring-offset-0"
91
+ inputClassName="ring-0 ring-offset-0 focus:ring-0 focus-visible:ring-0 outline-none focus:outline-none focus-visible:outline-none focus-visible:ring-offset-0"
92
+ position={"item-aligned"}
93
+ disabled={disabled}
94
+ padding={false}
95
+ value={validValue ? String(value) : ""}
96
+ onValueChange={onChange}
97
+ onOpenChange={handleOpenChange}
98
+ renderValue={renderValue}
99
+ >
100
+ {options.map((opt) => (
101
+ <SelectItem key={String(opt.value)} value={String(opt.value)}>
102
+ <Chip size={small ? "small" : "medium"}>{opt.label}</Chip>
103
+ </SelectItem>
104
+ ))}
105
+ </Select>
106
+ );
107
+ }
@@ -0,0 +1,28 @@
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,3 +1,10 @@
1
1
  export { VirtualTable } from "./VirtualTable";
2
2
  export * from "./VirtualTableProps";
3
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";
@@ -0,0 +1,36 @@
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
+ };
@@ -0,0 +1,54 @@
1
+ import { useSyncExternalStore, useCallback, useRef } from "react";
2
+
3
+ export interface SelectedCell {
4
+ columnKey: string;
5
+ rowId: 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 getSnapshot(): 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
+ getSnapshot,
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
+ rowId: string | number
42
+ ): boolean {
43
+ const selectorRef = useRef({ columnKey, rowId });
44
+ selectorRef.current = { columnKey, rowId };
45
+
46
+ const getSnapshot = useCallback(() => {
47
+ const cell = store.getSnapshot();
48
+ if (!cell) return false;
49
+ const s = selectorRef.current;
50
+ return cell.columnKey === s.columnKey && cell.rowId === s.rowId;
51
+ }, [store]);
52
+
53
+ return useSyncExternalStore(store.subscribe, getSnapshot, getSnapshot);
54
+ }
@@ -74,7 +74,9 @@ export {
74
74
  LanguagesIcon,
75
75
  LayoutGridIcon,
76
76
  LinkIcon,
77
+ Link2Icon,
77
78
  ListIcon,
79
+ LockIcon,
78
80
  ListOrderedIcon,
79
81
  LoaderIcon,
80
82
  LogOutIcon,
@@ -121,6 +123,7 @@ export {
121
123
  UploadIcon,
122
124
  UserCheckIcon,
123
125
  UserIcon,
126
+ UserPlus,
124
127
  VideoIcon,
125
128
  VoteIcon,
126
129
  Wand2Icon,
package/src/index.ts CHANGED
@@ -1,5 +1,45 @@
1
+ // =============================================================================
2
+ // Components
3
+ // =============================================================================
1
4
  export * from "./components";
2
- export * from "./styles";
3
- export * from "./util";
5
+
6
+ // =============================================================================
7
+ // Views
8
+ // =============================================================================
9
+ export * from "./views";
10
+
11
+ // =============================================================================
12
+ // Icons
13
+ // =============================================================================
4
14
  export * from "./icons";
5
- export * from "./hooks";
15
+
16
+ // =============================================================================
17
+ // Design System Utilities
18
+ // =============================================================================
19
+ export * from "./styles";
20
+ export { cls } from "./util/cls";
21
+ export { CHIP_COLORS, getColorSchemeForKey, getColorSchemeForSeed } from "./util/chip_colors";
22
+
23
+ // =============================================================================
24
+ // Public Hooks
25
+ // =============================================================================
26
+ export { useOutsideAlerter } from "./hooks/useOutsideAlerter";
27
+ export { useDebouncedCallback } from "./hooks/useDebouncedCallback";
28
+ export { useDebounceCallback } from "./hooks/useDebounceCallback";
29
+ export { useDebounceValue } from "./hooks/useDebounceValue";
30
+ export { useInjectStyles } from "./hooks/useInjectStyles";
31
+ export { PortalContainerProvider, usePortalContainer } from "./hooks/PortalContainerContext";
32
+ export type { PortalContainerContextType, PortalContainerProviderProps } from "./hooks/PortalContainerContext";
33
+
34
+ // =============================================================================
35
+ // Lower-level utilities (used by framework packages)
36
+ // =============================================================================
37
+ export { debounce } from "./util/debounce";
38
+ export type { Cancelable } from "./util/debounce";
39
+
40
+ // =============================================================================
41
+ // NOT exported (internal plumbing — import directly if needed):
42
+ //
43
+ // ./util/hash – hashString
44
+ // ./util/key_to_icon_component – keyToIconComponent
45
+ // =============================================================================
package/src/styles.ts CHANGED
@@ -5,7 +5,7 @@ export const fieldBackgroundMixin = "bg-surface-accent-200/50 dark:bg-black/30";
5
5
  export const fieldBackgroundInvisibleMixin = "bg-surface-accent-200/0 dark:bg-black/0";
6
6
  export const fieldBackgroundDisabledMixin = "bg-surface-accent-200/50 dark:bg-black/20";
7
7
  export const fieldBackgroundHoverMixin = "hover:bg-surface-accent-200/70 hover:dark:bg-black/50";
8
- export const defaultBorderMixin = "border-surface-200 dark:border-surface-700 ";
8
+ export const defaultBorderMixin = "border-surface-200 dark:border-surface-700/60 ";
9
9
  export const paperMixin = "bg-white rounded-lg dark:bg-surface-900 border border-surface-200 dark:border-surface-700";
10
10
  export const cardMixin = "bg-white dark:bg-surface-900 rounded-lg border border-surface-200 dark:border-surface-700";
11
11
  export const cardClickableMixin = "hover:bg-primary/5 dark:hover:bg-primary/5 cursor-pointer transition-colors duration-150";