@soulbatical/tetra-ui 0.1.13 → 0.1.14

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.
@@ -0,0 +1,62 @@
1
+ import React, { type ReactNode } from "react";
2
+ export interface InfiniteGridProps<TItem> {
3
+ /** Items to render */
4
+ items: TItem[];
5
+ /** Render function for each item */
6
+ renderItem: (item: TItem, index: number) => ReactNode;
7
+ /** Number of grid columns (responsive: 1 → sm → lg) */
8
+ columns?: 1 | 2 | 3 | 4;
9
+ /** Gap between items (Tailwind gap class number) */
10
+ gap?: 4 | 6 | 8;
11
+ /** Show initial loading state */
12
+ loading?: boolean;
13
+ /** Show loading-more indicator at bottom */
14
+ loadingMore?: boolean;
15
+ /** Whether more items can be loaded */
16
+ hasMore?: boolean;
17
+ /** Sentinel ref from useInfiniteScroll */
18
+ sentinelRef?: React.RefObject<HTMLDivElement> | ((node: HTMLDivElement | null) => void);
19
+ /** Number of skeleton cards to show during initial load */
20
+ skeletonCount?: number;
21
+ /** Custom skeleton element (default: animated gray box) */
22
+ renderSkeleton?: () => ReactNode;
23
+ /** Skeleton aspect ratio class (default: "aspect-square") */
24
+ skeletonAspect?: string;
25
+ /** Message when no items */
26
+ emptyMessage?: string;
27
+ /** Custom empty state */
28
+ emptyState?: ReactNode;
29
+ /** Total item count (for "Showing X of Y" text) */
30
+ totalCount?: number;
31
+ /** Entity name for display (e.g., "styles", "ads") */
32
+ entityName?: string;
33
+ /** Additional CSS class for the grid container */
34
+ className?: string;
35
+ }
36
+ /**
37
+ * InfiniteGrid — Responsive grid with built-in infinite scroll, skeletons, and empty state.
38
+ *
39
+ * Replaces the pattern of: manual grid + IntersectionObserver + skeleton array + empty div.
40
+ * Pair with `useInfiniteScroll` or `useInfiniteList` hook.
41
+ *
42
+ * @example
43
+ * ```tsx
44
+ * import { InfiniteGrid, useInfiniteScroll } from '@soulbatical/tetra-ui';
45
+ *
46
+ * const { sentinelRef } = useInfiniteScroll({ onLoadMore: loadMore, hasMore });
47
+ *
48
+ * <InfiniteGrid
49
+ * items={styles}
50
+ * renderItem={(style) => <StyleCard key={style.id} style={style} />}
51
+ * columns={3}
52
+ * loading={loading}
53
+ * loadingMore={loadingMore}
54
+ * hasMore={hasMore}
55
+ * sentinelRef={sentinelRef}
56
+ * totalCount={total}
57
+ * entityName="styles"
58
+ * />
59
+ * ```
60
+ */
61
+ export declare function InfiniteGrid<TItem>({ items, renderItem, columns, gap, loading, loadingMore, hasMore, sentinelRef, skeletonCount, renderSkeleton, skeletonAspect, emptyMessage, emptyState, totalCount, entityName, className, }: InfiniteGridProps<TItem>): import("react/jsx-runtime").JSX.Element;
62
+ //# sourceMappingURL=InfiniteGrid.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InfiniteGrid.d.ts","sourceRoot":"","sources":["../../src/components/InfiniteGrid.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAI9C,MAAM,WAAW,iBAAiB,CAAC,KAAK;IACtC,sBAAsB;IACtB,KAAK,EAAE,KAAK,EAAE,CAAC;IAEf,oCAAoC;IACpC,UAAU,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,KAAK,SAAS,CAAC;IAEtD,uDAAuD;IACvD,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAExB,oDAAoD;IACpD,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAEhB,iCAAiC;IACjC,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB,4CAA4C;IAC5C,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB,uCAAuC;IACvC,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB,0CAA0C;IAC1C,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI,KAAK,IAAI,CAAC,CAAC;IAExF,2DAA2D;IAC3D,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,2DAA2D;IAC3D,cAAc,CAAC,EAAE,MAAM,SAAS,CAAC;IAEjC,6DAA6D;IAC7D,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,4BAA4B;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,yBAAyB;IACzB,UAAU,CAAC,EAAE,SAAS,CAAC;IAEvB,mDAAmD;IACnD,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,sDAAsD;IACtD,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,kDAAkD;IAClD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAsCD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,EAClC,KAAK,EACL,UAAU,EACV,OAAW,EACX,GAAO,EACP,OAAe,EACf,WAAmB,EACnB,OAAe,EACf,WAAW,EACX,aAAiB,EACjB,cAAc,EACd,cAAgC,EAChC,YAA+B,EAC/B,UAAU,EACV,UAAU,EACV,UAAoB,EACpB,SAAS,GACV,EAAE,iBAAiB,CAAC,KAAK,CAAC,2CAkD1B"}
@@ -0,0 +1,65 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import React from "react";
4
+ // ─── Column class mapping ───────────────────────────────────
5
+ const GRID_COLS = {
6
+ 1: "grid-cols-1",
7
+ 2: "grid-cols-1 sm:grid-cols-2",
8
+ 3: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3",
9
+ 4: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4",
10
+ };
11
+ const GAP_CLASSES = {
12
+ 4: "gap-4",
13
+ 6: "gap-6",
14
+ 8: "gap-8",
15
+ };
16
+ // ─── Default Skeleton ───────────────────────────────────────
17
+ function DefaultSkeleton({ aspect }) {
18
+ return (_jsx("div", { className: `${aspect} animate-pulse rounded-xl bg-gray-200 dark:bg-gray-800` }));
19
+ }
20
+ // ─── Loading More Indicator ─────────────────────────────────
21
+ function LoadingMoreIndicator({ entityName }) {
22
+ return (_jsxs("div", { className: "flex items-center gap-2 text-sm text-gray-400", children: [_jsx("div", { className: "h-4 w-4 animate-spin rounded-full border-2 border-gray-300 border-t-blue-500" }), "Loading more ", entityName, "..."] }));
23
+ }
24
+ // ─── Component ──────────────────────────────────────────────
25
+ /**
26
+ * InfiniteGrid — Responsive grid with built-in infinite scroll, skeletons, and empty state.
27
+ *
28
+ * Replaces the pattern of: manual grid + IntersectionObserver + skeleton array + empty div.
29
+ * Pair with `useInfiniteScroll` or `useInfiniteList` hook.
30
+ *
31
+ * @example
32
+ * ```tsx
33
+ * import { InfiniteGrid, useInfiniteScroll } from '@soulbatical/tetra-ui';
34
+ *
35
+ * const { sentinelRef } = useInfiniteScroll({ onLoadMore: loadMore, hasMore });
36
+ *
37
+ * <InfiniteGrid
38
+ * items={styles}
39
+ * renderItem={(style) => <StyleCard key={style.id} style={style} />}
40
+ * columns={3}
41
+ * loading={loading}
42
+ * loadingMore={loadingMore}
43
+ * hasMore={hasMore}
44
+ * sentinelRef={sentinelRef}
45
+ * totalCount={total}
46
+ * entityName="styles"
47
+ * />
48
+ * ```
49
+ */
50
+ export function InfiniteGrid({ items, renderItem, columns = 3, gap = 6, loading = false, loadingMore = false, hasMore = false, sentinelRef, skeletonCount = 6, renderSkeleton, skeletonAspect = "aspect-square", emptyMessage = "No items found", emptyState, totalCount, entityName = "items", className, }) {
51
+ const gridClass = `grid ${GRID_COLS[columns]} ${GAP_CLASSES[gap]} ${className ?? ""}`.trim();
52
+ // ─── Initial Loading ──────────────────────────────
53
+ if (loading) {
54
+ return (_jsx("div", { className: gridClass, children: Array.from({ length: skeletonCount }).map((_, i) => renderSkeleton ? (_jsx(React.Fragment, { children: renderSkeleton() }, i)) : (_jsx(DefaultSkeleton, { aspect: skeletonAspect }, i))) }));
55
+ }
56
+ // ─── Empty State ──────────────────────────────────
57
+ if (items.length === 0) {
58
+ if (emptyState)
59
+ return _jsx(_Fragment, { children: emptyState });
60
+ return (_jsx("div", { className: "rounded-lg border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-900 px-6 py-16 text-center", children: _jsx("p", { className: "text-sm text-gray-500", children: emptyMessage }) }));
61
+ }
62
+ // ─── Grid + Sentinel ──────────────────────────────
63
+ return (_jsxs(_Fragment, { children: [_jsx("div", { className: gridClass, children: items.map((item, index) => renderItem(item, index)) }), hasMore && sentinelRef && (_jsx("div", { ref: sentinelRef, className: "mt-8 flex justify-center py-8", children: loadingMore && _jsx(LoadingMoreIndicator, { entityName: entityName }) })), !hasMore && items.length > 0 && totalCount !== undefined && (_jsxs("p", { className: "mt-8 text-center text-xs text-gray-400", children: ["All ", totalCount, " ", entityName, " loaded"] }))] }));
64
+ }
65
+ //# sourceMappingURL=InfiniteGrid.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InfiniteGrid.js","sourceRoot":"","sources":["../../src/components/InfiniteGrid.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,85 @@
1
+ import React, { type ReactNode } from "react";
2
+ export interface ListDetailLayoutProps<TItem> {
3
+ /** Items to display in the list */
4
+ items: TItem[];
5
+ /** Extract unique ID from item */
6
+ getItemId: (item: TItem) => string;
7
+ /** Render a single list row */
8
+ renderListItem: (item: TItem, isSelected: boolean) => ReactNode;
9
+ /** Render the detail panel for the selected item */
10
+ renderDetail: (item: TItem) => ReactNode;
11
+ /** Currently selected item ID (controlled) */
12
+ selectedId?: string | null;
13
+ /** Called when an item is selected */
14
+ onSelect: (id: string | null) => void;
15
+ /** Action buttons at the bottom of the detail panel */
16
+ actions?: (item: TItem) => ReactNode;
17
+ /** Enable keyboard navigation with arrow keys (default: true) */
18
+ keyboardNav?: boolean;
19
+ /** Width of the detail panel (Tailwind class, default: "w-[600px]") */
20
+ detailWidth?: string;
21
+ /** Width of the list when detail is open (Tailwind class, default: "w-80") */
22
+ listCompactWidth?: string;
23
+ /** Title shown above the list */
24
+ title?: string;
25
+ /** Subtitle / count indicator */
26
+ subtitle?: string;
27
+ /** Header actions (create button, etc.) */
28
+ headerActions?: ReactNode;
29
+ /** Show loading state */
30
+ loading?: boolean;
31
+ /** Empty state when no items */
32
+ emptyMessage?: string;
33
+ /** Infinite scroll sentinel ref */
34
+ sentinelRef?: React.RefObject<HTMLDivElement> | ((node: HTMLDivElement | null) => void);
35
+ /** Whether more items can be loaded */
36
+ hasMore?: boolean;
37
+ /** Loading more indicator */
38
+ loadingMore?: boolean;
39
+ /** Additional CSS class for the outer container */
40
+ className?: string;
41
+ }
42
+ /**
43
+ * ListDetailLayout — Master-detail split view (Pipedrive-style).
44
+ *
45
+ * Shows a scrollable list on the left. Clicking an item opens a detail
46
+ * panel on the right with a slide-in animation. Arrow keys navigate
47
+ * between items while the detail panel stays open.
48
+ *
49
+ * @example
50
+ * ```tsx
51
+ * import { ListDetailLayout } from '@soulbatical/tetra-ui';
52
+ *
53
+ * const [selectedId, setSelectedId] = useState<string | null>(null);
54
+ *
55
+ * <ListDetailLayout
56
+ * items={leads}
57
+ * getItemId={(lead) => lead.id}
58
+ * selectedId={selectedId}
59
+ * onSelect={setSelectedId}
60
+ * renderListItem={(lead, isSelected) => (
61
+ * <div className={isSelected ? 'bg-blue-50' : ''}>
62
+ * <p className="font-medium">{lead.name}</p>
63
+ * <p className="text-sm text-gray-500">{lead.company}</p>
64
+ * </div>
65
+ * )}
66
+ * renderDetail={(lead) => (
67
+ * <div>
68
+ * <h2>{lead.name}</h2>
69
+ * <p>{lead.email}</p>
70
+ * <p>{lead.phone}</p>
71
+ * </div>
72
+ * )}
73
+ * actions={(lead) => (
74
+ * <>
75
+ * <button onClick={() => archive(lead.id)}>Archive</button>
76
+ * <button onClick={() => convert(lead.id)}>Convert to Deal</button>
77
+ * </>
78
+ * )}
79
+ * title="Leads Inbox"
80
+ * subtitle="198 leads"
81
+ * />
82
+ * ```
83
+ */
84
+ export declare function ListDetailLayout<TItem>({ items, getItemId, renderListItem, renderDetail, selectedId, onSelect, actions, keyboardNav, detailWidth, listCompactWidth, title, subtitle, headerActions, loading, emptyMessage, sentinelRef, hasMore, loadingMore, className, }: ListDetailLayoutProps<TItem>): import("react/jsx-runtime").JSX.Element;
85
+ //# sourceMappingURL=ListDetailLayout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ListDetailLayout.d.ts","sourceRoot":"","sources":["../../src/components/ListDetailLayout.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAkC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAI9E,MAAM,WAAW,qBAAqB,CAAC,KAAK;IAC1C,mCAAmC;IACnC,KAAK,EAAE,KAAK,EAAE,CAAC;IAEf,kCAAkC;IAClC,SAAS,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,MAAM,CAAC;IAEnC,+BAA+B;IAC/B,cAAc,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,KAAK,SAAS,CAAC;IAEhE,oDAAoD;IACpD,YAAY,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,SAAS,CAAC;IAEzC,8CAA8C;IAC9C,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAE3B,sCAAsC;IACtC,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAEtC,uDAAuD;IACvD,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,SAAS,CAAC;IAErC,iEAAiE;IACjE,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB,uEAAuE;IACvE,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,8EAA8E;IAC9E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B,iCAAiC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,iCAAiC;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,2CAA2C;IAC3C,aAAa,CAAC,EAAE,SAAS,CAAC;IAE1B,yBAAyB;IACzB,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB,gCAAgC;IAChC,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,mCAAmC;IACnC,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI,KAAK,IAAI,CAAC,CAAC;IAExF,uCAAuC;IACvC,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB,6BAA6B;IAC7B,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB,mDAAmD;IACnD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA8BD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,EACtC,KAAK,EACL,SAAS,EACT,cAAc,EACd,YAAY,EACZ,UAAU,EACV,QAAQ,EACR,OAAO,EACP,WAAkB,EAClB,WAAyB,EACzB,gBAAyB,EACzB,KAAK,EACL,QAAQ,EACR,aAAa,EACb,OAAe,EACf,YAA+B,EAC/B,WAAW,EACX,OAAe,EACf,WAAmB,EACnB,SAAS,GACV,EAAE,qBAAqB,CAAC,KAAK,CAAC,2CA6L9B"}
@@ -0,0 +1,113 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { useEffect, useCallback, useRef } from "react";
4
+ // ─── Close Icon ─────────────────────────────────────────────
5
+ function CloseIcon() {
6
+ return (_jsx("svg", { className: "h-5 w-5", fill: "none", viewBox: "0 0 24 24", strokeWidth: 1.5, stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" }) }));
7
+ }
8
+ function ChevronUpIcon() {
9
+ return (_jsx("svg", { className: "h-4 w-4", fill: "none", viewBox: "0 0 24 24", strokeWidth: 2, stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M4.5 15.75l7.5-7.5 7.5 7.5" }) }));
10
+ }
11
+ function ChevronDownIcon() {
12
+ return (_jsx("svg", { className: "h-4 w-4", fill: "none", viewBox: "0 0 24 24", strokeWidth: 2, stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19.5 8.25l-7.5 7.5-7.5-7.5" }) }));
13
+ }
14
+ // ─── Component ──────────────────────────────────────────────
15
+ /**
16
+ * ListDetailLayout — Master-detail split view (Pipedrive-style).
17
+ *
18
+ * Shows a scrollable list on the left. Clicking an item opens a detail
19
+ * panel on the right with a slide-in animation. Arrow keys navigate
20
+ * between items while the detail panel stays open.
21
+ *
22
+ * @example
23
+ * ```tsx
24
+ * import { ListDetailLayout } from '@soulbatical/tetra-ui';
25
+ *
26
+ * const [selectedId, setSelectedId] = useState<string | null>(null);
27
+ *
28
+ * <ListDetailLayout
29
+ * items={leads}
30
+ * getItemId={(lead) => lead.id}
31
+ * selectedId={selectedId}
32
+ * onSelect={setSelectedId}
33
+ * renderListItem={(lead, isSelected) => (
34
+ * <div className={isSelected ? 'bg-blue-50' : ''}>
35
+ * <p className="font-medium">{lead.name}</p>
36
+ * <p className="text-sm text-gray-500">{lead.company}</p>
37
+ * </div>
38
+ * )}
39
+ * renderDetail={(lead) => (
40
+ * <div>
41
+ * <h2>{lead.name}</h2>
42
+ * <p>{lead.email}</p>
43
+ * <p>{lead.phone}</p>
44
+ * </div>
45
+ * )}
46
+ * actions={(lead) => (
47
+ * <>
48
+ * <button onClick={() => archive(lead.id)}>Archive</button>
49
+ * <button onClick={() => convert(lead.id)}>Convert to Deal</button>
50
+ * </>
51
+ * )}
52
+ * title="Leads Inbox"
53
+ * subtitle="198 leads"
54
+ * />
55
+ * ```
56
+ */
57
+ export function ListDetailLayout({ items, getItemId, renderListItem, renderDetail, selectedId, onSelect, actions, keyboardNav = true, detailWidth = "w-[600px]", listCompactWidth = "w-80", title, subtitle, headerActions, loading = false, emptyMessage = "No items found", sentinelRef, hasMore = false, loadingMore = false, className, }) {
58
+ const listRef = useRef(null);
59
+ const selectedItem = items.find((item) => getItemId(item) === selectedId);
60
+ const isDetailOpen = selectedId !== null && selectedItem !== undefined;
61
+ // ─── Keyboard Navigation ──────────────────────────
62
+ const navigateToItem = useCallback((direction) => {
63
+ if (!selectedId || items.length === 0)
64
+ return;
65
+ const currentIndex = items.findIndex((item) => getItemId(item) === selectedId);
66
+ if (currentIndex === -1)
67
+ return;
68
+ const nextIndex = direction === "up"
69
+ ? Math.max(0, currentIndex - 1)
70
+ : Math.min(items.length - 1, currentIndex + 1);
71
+ if (nextIndex !== currentIndex) {
72
+ onSelect(getItemId(items[nextIndex]));
73
+ // Scroll the selected item into view in the list
74
+ const listEl = listRef.current;
75
+ if (listEl) {
76
+ const itemEl = listEl.querySelector(`[data-item-id="${getItemId(items[nextIndex])}"]`);
77
+ itemEl?.scrollIntoView({ block: "nearest", behavior: "smooth" });
78
+ }
79
+ }
80
+ }, [items, selectedId, getItemId, onSelect]);
81
+ useEffect(() => {
82
+ if (!keyboardNav || !isDetailOpen)
83
+ return;
84
+ const handleKeyDown = (e) => {
85
+ if (e.key === "ArrowUp") {
86
+ e.preventDefault();
87
+ navigateToItem("up");
88
+ }
89
+ else if (e.key === "ArrowDown") {
90
+ e.preventDefault();
91
+ navigateToItem("down");
92
+ }
93
+ else if (e.key === "Escape") {
94
+ e.preventDefault();
95
+ onSelect(null);
96
+ }
97
+ };
98
+ window.addEventListener("keydown", handleKeyDown);
99
+ return () => window.removeEventListener("keydown", handleKeyDown);
100
+ }, [keyboardNav, isDetailOpen, navigateToItem, onSelect]);
101
+ // ─── Loading State ────────────────────────────────
102
+ if (loading) {
103
+ return (_jsx("div", { className: `flex h-full ${className ?? ""}`, children: _jsx("div", { className: "flex-1 p-6", children: _jsx("div", { className: "space-y-3", children: Array.from({ length: 8 }).map((_, i) => (_jsx("div", { className: "h-16 animate-pulse rounded-lg bg-gray-200 dark:bg-gray-800" }, i))) }) }) }));
104
+ }
105
+ return (_jsxs("div", { className: `flex h-full overflow-hidden ${className ?? ""}`, children: [_jsxs("div", { ref: listRef, className: `flex flex-col border-r border-gray-200 dark:border-gray-700 overflow-y-auto transition-all duration-300 ${isDetailOpen ? listCompactWidth : "flex-1"}`, children: [(title || headerActions) && (_jsxs("div", { className: "sticky top-0 z-10 flex items-center justify-between border-b border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-900 px-4 py-3", children: [_jsxs("div", { children: [title && (_jsx("h2", { className: "text-lg font-semibold text-gray-900 dark:text-gray-100", children: title })), subtitle && (_jsx("p", { className: "text-xs text-gray-500", children: subtitle }))] }), headerActions] })), items.length === 0 ? (_jsx("div", { className: "flex-1 flex items-center justify-center p-8", children: _jsx("p", { className: "text-sm text-gray-500", children: emptyMessage }) })) : (_jsxs("div", { className: "flex-1", children: [items.map((item) => {
106
+ const id = getItemId(item);
107
+ const isSelected = id === selectedId;
108
+ return (_jsx("button", { type: "button", "data-item-id": id, onClick: () => onSelect(isSelected ? null : id), className: `w-full text-left px-4 py-3 border-b border-gray-100 dark:border-gray-800 transition-colors hover:bg-gray-50 dark:hover:bg-gray-800/50 ${isSelected
109
+ ? "bg-blue-50 dark:bg-blue-900/20 border-l-2 border-l-blue-500"
110
+ : ""}`, children: renderListItem(item, isSelected) }, id));
111
+ }), hasMore && sentinelRef && (_jsx("div", { ref: sentinelRef, className: "py-4 flex justify-center", children: loadingMore && (_jsx("div", { className: "h-4 w-4 animate-spin rounded-full border-2 border-gray-300 border-t-blue-500" })) }))] }))] }), _jsx("div", { className: `flex flex-col overflow-hidden border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-900 transition-all duration-300 ${isDetailOpen ? `${detailWidth} opacity-100` : "w-0 opacity-0"}`, children: selectedItem && (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex items-center justify-between border-b border-gray-200 dark:border-gray-700 px-4 py-2", children: [_jsxs("div", { className: "flex items-center gap-1", children: [_jsx("button", { type: "button", onClick: () => navigateToItem("up"), className: "rounded p-1 text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-800 hover:text-gray-600 disabled:opacity-30", disabled: items.findIndex((item) => getItemId(item) === selectedId) === 0, "aria-label": "Previous item", children: _jsx(ChevronUpIcon, {}) }), _jsx("button", { type: "button", onClick: () => navigateToItem("down"), className: "rounded p-1 text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-800 hover:text-gray-600 disabled:opacity-30", disabled: items.findIndex((item) => getItemId(item) === selectedId) === items.length - 1, "aria-label": "Next item", children: _jsx(ChevronDownIcon, {}) })] }), _jsx("button", { type: "button", onClick: () => onSelect(null), className: "rounded p-1 text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-800 hover:text-gray-600", "aria-label": "Close detail", children: _jsx(CloseIcon, {}) })] }), _jsx("div", { className: "flex-1 overflow-y-auto", children: renderDetail(selectedItem) }), actions && (_jsx("div", { className: "border-t border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800/50 px-4 py-3 flex items-center gap-3", children: actions(selectedItem) }))] })) })] }));
112
+ }
113
+ //# sourceMappingURL=ListDetailLayout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ListDetailLayout.js","sourceRoot":"","sources":["../../src/components/ListDetailLayout.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ export interface UseInfiniteListOptions<TFilters extends Record<string, string>> {
2
+ /** API endpoint (e.g., '/api/admin/style-library') */
3
+ endpoint: string;
4
+ /** Items per page (default: 30) */
5
+ limit?: number;
6
+ /** Filter values — refetches from offset 0 when changed */
7
+ filters?: TFilters;
8
+ /** Enable/disable (default: true) */
9
+ enabled?: boolean;
10
+ /**
11
+ * Key in the response data object that holds the items array.
12
+ * Default: "items". Examples: "styles", "ads", "items"
13
+ */
14
+ dataKey?: string;
15
+ /**
16
+ * Key in the response data object that holds the total count.
17
+ * Default: "total"
18
+ */
19
+ totalKey?: string;
20
+ }
21
+ export interface UseInfiniteListResult<TItem> {
22
+ /** Accumulated items across all loaded pages */
23
+ items: TItem[];
24
+ /** Total count of items matching filters (from server) */
25
+ total: number;
26
+ /** Initial loading (first page) */
27
+ loading: boolean;
28
+ /** Loading additional pages */
29
+ loadingMore: boolean;
30
+ /** Whether more items can be loaded */
31
+ hasMore: boolean;
32
+ /** Sentinel ref to attach to the scroll trigger element */
33
+ sentinelRef: (node: HTMLDivElement | null) => void;
34
+ /** Manually trigger a refresh (resets to page 0) */
35
+ refresh: () => void;
36
+ }
37
+ /**
38
+ * useInfiniteList — Simple infinite scroll hook for REST API endpoints.
39
+ *
40
+ * A lighter alternative to `useGenericList` for pages that don't have a
41
+ * full FeatureConfig. Just point it at an API endpoint and it handles
42
+ * pagination, filter resets, and IntersectionObserver automatically.
43
+ *
44
+ * @example
45
+ * ```tsx
46
+ * import { useInfiniteList, InfiniteGrid } from '@soulbatical/tetra-ui';
47
+ *
48
+ * const { items, loading, loadingMore, hasMore, sentinelRef, total } = useInfiniteList<Style>({
49
+ * endpoint: '/api/admin/style-library',
50
+ * limit: 30,
51
+ * filters: { category, search, complexity },
52
+ * dataKey: 'styles',
53
+ * });
54
+ *
55
+ * return (
56
+ * <InfiniteGrid
57
+ * items={items}
58
+ * renderItem={(style) => <StyleCard style={style} />}
59
+ * loading={loading}
60
+ * loadingMore={loadingMore}
61
+ * hasMore={hasMore}
62
+ * sentinelRef={sentinelRef}
63
+ * totalCount={total}
64
+ * />
65
+ * );
66
+ * ```
67
+ */
68
+ export declare function useInfiniteList<TItem, TFilters extends Record<string, string> = Record<string, string>>({ endpoint, limit, filters, enabled, dataKey, totalKey, }: UseInfiniteListOptions<TFilters>): UseInfiniteListResult<TItem>;
69
+ //# sourceMappingURL=useInfiniteList.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useInfiniteList.d.ts","sourceRoot":"","sources":["../../src/hooks/useInfiniteList.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,sBAAsB,CAAC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAC7E,sDAAsD;IACtD,QAAQ,EAAE,MAAM,CAAC;IAEjB,mCAAmC;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,2DAA2D;IAC3D,OAAO,CAAC,EAAE,QAAQ,CAAC;IAEnB,qCAAqC;IACrC,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,qBAAqB,CAAC,KAAK;IAC1C,gDAAgD;IAChD,KAAK,EAAE,KAAK,EAAE,CAAC;IAEf,0DAA0D;IAC1D,KAAK,EAAE,MAAM,CAAC;IAEd,mCAAmC;IACnC,OAAO,EAAE,OAAO,CAAC;IAEjB,+BAA+B;IAC/B,WAAW,EAAE,OAAO,CAAC;IAErB,uCAAuC;IACvC,OAAO,EAAE,OAAO,CAAC;IAEjB,2DAA2D;IAC3D,WAAW,EAAE,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI,KAAK,IAAI,CAAC;IAEnD,oDAAoD;IACpD,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAID;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EACL,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAChE,EACA,QAAQ,EACR,KAAU,EACV,OAAwB,EACxB,OAAc,EACd,OAAiB,EACjB,QAAkB,GACnB,EAAE,sBAAsB,CAAC,QAAQ,CAAC,GAAG,qBAAqB,CAAC,KAAK,CAAC,CA0GjE"}
@@ -0,0 +1,131 @@
1
+ "use client";
2
+ import { useState, useEffect, useCallback, useRef } from "react";
3
+ import { apiClient } from "../services/apiClient.js";
4
+ import { useInfiniteScroll } from "./useInfiniteScroll.js";
5
+ // ─── Hook ───────────────────────────────────────────────────
6
+ /**
7
+ * useInfiniteList — Simple infinite scroll hook for REST API endpoints.
8
+ *
9
+ * A lighter alternative to `useGenericList` for pages that don't have a
10
+ * full FeatureConfig. Just point it at an API endpoint and it handles
11
+ * pagination, filter resets, and IntersectionObserver automatically.
12
+ *
13
+ * @example
14
+ * ```tsx
15
+ * import { useInfiniteList, InfiniteGrid } from '@soulbatical/tetra-ui';
16
+ *
17
+ * const { items, loading, loadingMore, hasMore, sentinelRef, total } = useInfiniteList<Style>({
18
+ * endpoint: '/api/admin/style-library',
19
+ * limit: 30,
20
+ * filters: { category, search, complexity },
21
+ * dataKey: 'styles',
22
+ * });
23
+ *
24
+ * return (
25
+ * <InfiniteGrid
26
+ * items={items}
27
+ * renderItem={(style) => <StyleCard style={style} />}
28
+ * loading={loading}
29
+ * loadingMore={loadingMore}
30
+ * hasMore={hasMore}
31
+ * sentinelRef={sentinelRef}
32
+ * totalCount={total}
33
+ * />
34
+ * );
35
+ * ```
36
+ */
37
+ export function useInfiniteList({ endpoint, limit = 30, filters = {}, enabled = true, dataKey = "items", totalKey = "total", }) {
38
+ const [items, setItems] = useState([]);
39
+ const [total, setTotal] = useState(0);
40
+ const [loading, setLoading] = useState(true);
41
+ const [loadingMore, setLoadingMore] = useState(false);
42
+ const [hasMore, setHasMore] = useState(true);
43
+ const offsetRef = useRef(0);
44
+ const fetchingRef = useRef(false);
45
+ // Serialize filters for dependency tracking
46
+ const filterKey = JSON.stringify(filters);
47
+ // ─── Fetch Function ───────────────────────────────
48
+ const fetchPage = useCallback(async (offset, append) => {
49
+ if (fetchingRef.current)
50
+ return;
51
+ fetchingRef.current = true;
52
+ if (offset === 0)
53
+ setLoading(true);
54
+ else
55
+ setLoadingMore(true);
56
+ try {
57
+ const params = new URLSearchParams({
58
+ limit: String(limit),
59
+ offset: String(offset),
60
+ });
61
+ // Add non-empty filters to query
62
+ for (const [key, value] of Object.entries(filters)) {
63
+ if (value !== undefined && value !== null && value !== "") {
64
+ params.set(key, value);
65
+ }
66
+ }
67
+ const url = `${endpoint}?${params.toString()}`;
68
+ const res = await apiClient.get(url);
69
+ if (res.success && res.data) {
70
+ const newItems = (res.data[dataKey] ?? res.data.items ?? res.data.data ?? []);
71
+ const serverTotal = res.data[totalKey] ??
72
+ res.data.total ??
73
+ res.data.meta?.total ??
74
+ 0;
75
+ setItems((prev) => (append ? [...prev, ...newItems] : newItems));
76
+ setTotal(serverTotal);
77
+ setHasMore(offset + newItems.length < serverTotal);
78
+ offsetRef.current = offset + newItems.length;
79
+ }
80
+ }
81
+ catch {
82
+ // API unavailable — keep current state
83
+ }
84
+ finally {
85
+ setLoading(false);
86
+ setLoadingMore(false);
87
+ fetchingRef.current = false;
88
+ }
89
+ },
90
+ // eslint-disable-next-line react-hooks/exhaustive-deps
91
+ [endpoint, limit, filterKey, dataKey, totalKey]);
92
+ // ─── Reset on filter change ───────────────────────
93
+ useEffect(() => {
94
+ if (!enabled)
95
+ return;
96
+ offsetRef.current = 0;
97
+ setItems([]);
98
+ setHasMore(true);
99
+ fetchPage(0, false);
100
+ }, [enabled, fetchPage]);
101
+ // ─── Load More ────────────────────────────────────
102
+ const loadMore = useCallback(() => {
103
+ if (!hasMore || loading || loadingMore)
104
+ return;
105
+ fetchPage(offsetRef.current, true);
106
+ }, [hasMore, loading, loadingMore, fetchPage]);
107
+ // ─── Infinite Scroll ──────────────────────────────
108
+ const { sentinelRef } = useInfiniteScroll({
109
+ onLoadMore: loadMore,
110
+ hasMore,
111
+ threshold: 300,
112
+ enabled: enabled && !loading,
113
+ });
114
+ // ─── Manual Refresh ───────────────────────────────
115
+ const refresh = useCallback(() => {
116
+ offsetRef.current = 0;
117
+ setItems([]);
118
+ setHasMore(true);
119
+ fetchPage(0, false);
120
+ }, [fetchPage]);
121
+ return {
122
+ items,
123
+ total,
124
+ loading,
125
+ loadingMore,
126
+ hasMore,
127
+ sentinelRef,
128
+ refresh,
129
+ };
130
+ }
131
+ //# sourceMappingURL=useInfiniteList.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useInfiniteList.js","sourceRoot":"","sources":["../../src/hooks/useInfiniteList.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -26,10 +26,13 @@ export { StatusBadge } from "./components/StatusBadge.js";
26
26
  export { AutoCard, type CardConfig, type AutoCardProps, type LinkComponent } from "./components/AutoCard.js";
27
27
  export { CookieConsent, type CookieConsentProps } from "./components/CookieConsent.js";
28
28
  export { OAuthButtons, type OAuthButtonsProps } from "./components/OAuthButtons.js";
29
+ export { InfiniteGrid, type InfiniteGridProps, } from "./components/InfiniteGrid.js";
30
+ export { ListDetailLayout, type ListDetailLayoutProps, } from "./components/ListDetailLayout.js";
29
31
  export { useDebounce } from "./hooks/useDebounce.js";
30
32
  export { useDialog } from "./hooks/useDialog.js";
31
33
  export { useIsMobile } from "./hooks/use-mobile.js";
32
34
  export { useInfiniteScroll } from "./hooks/useInfiniteScroll.js";
35
+ export { useInfiniteList, type UseInfiniteListOptions, type UseInfiniteListResult, } from "./hooks/useInfiniteList.js";
33
36
  export { useCacheInvalidation } from "./hooks/useCacheInvalidation.js";
34
37
  export { useFormSubmit } from "./hooks/useFormSubmit.js";
35
38
  export { useQueryState } from "./hooks/useQueryState.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -36,11 +36,15 @@ export { StatusBadge } from "./components/StatusBadge.js";
36
36
  export { AutoCard } from "./components/AutoCard.js";
37
37
  export { CookieConsent } from "./components/CookieConsent.js";
38
38
  export { OAuthButtons } from "./components/OAuthButtons.js";
39
+ // Layout components
40
+ export { InfiniteGrid, } from "./components/InfiniteGrid.js";
41
+ export { ListDetailLayout, } from "./components/ListDetailLayout.js";
39
42
  // Hooks — utility
40
43
  export { useDebounce } from "./hooks/useDebounce.js";
41
44
  export { useDialog } from "./hooks/useDialog.js";
42
45
  export { useIsMobile } from "./hooks/use-mobile.js";
43
46
  export { useInfiniteScroll } from "./hooks/useInfiniteScroll.js";
47
+ export { useInfiniteList, } from "./hooks/useInfiniteList.js";
44
48
  export { useCacheInvalidation } from "./hooks/useCacheInvalidation.js";
45
49
  export { useFormSubmit } from "./hooks/useFormSubmit.js";
46
50
  // Hooks — query state & filters
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "publishConfig": {
5
5
  "access": "restricted"
6
6
  },
7
- "version": "0.1.13",
7
+ "version": "0.1.14",
8
8
  "description": "Shared React frontend framework for Tetra platform projects (Soulbatical BV) — config-driven components, hooks, providers, and styling",
9
9
  "type": "module",
10
10
  "main": "dist/index.js",