@classytic/fluid 0.2.4 → 0.3.3

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 (69) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +149 -62
  3. package/dist/api-pagination-CJ0vR_w6.d.mts +34 -0
  4. package/dist/api-pagination-DBTE0yk4.mjs +190 -0
  5. package/dist/chunk-DQk6qfdC.mjs +18 -0
  6. package/dist/client/calendar.d.mts +105 -0
  7. package/dist/client/calendar.mjs +202 -0
  8. package/dist/client/core.d.mts +1614 -0
  9. package/dist/client/core.mjs +2779 -0
  10. package/dist/client/error.d.mts +125 -0
  11. package/dist/client/error.mjs +166 -0
  12. package/dist/client/hooks.d.mts +162 -0
  13. package/dist/client/hooks.mjs +447 -0
  14. package/dist/client/table.d.mts +84 -0
  15. package/dist/client/table.mjs +373 -0
  16. package/dist/client/theme.d.mts +6 -0
  17. package/dist/client/theme.mjs +65 -0
  18. package/dist/command.d.mts +134 -0
  19. package/dist/command.mjs +132 -0
  20. package/dist/compact.d.mts +359 -0
  21. package/dist/compact.mjs +892 -0
  22. package/dist/dashboard.d.mts +778 -0
  23. package/dist/dashboard.mjs +1617 -0
  24. package/dist/filter-utils-DqMmy_v-.mjs +72 -0
  25. package/dist/filter-utils-IZ0GtuPo.d.mts +40 -0
  26. package/dist/forms.d.mts +1549 -0
  27. package/dist/forms.mjs +3740 -0
  28. package/dist/index.d.mts +296 -0
  29. package/dist/index.mjs +432 -0
  30. package/dist/layouts.d.mts +215 -0
  31. package/dist/layouts.mjs +460 -0
  32. package/dist/search-context-DR7DBs7S.mjs +19 -0
  33. package/dist/search.d.mts +254 -0
  34. package/dist/search.mjs +523 -0
  35. package/dist/sheet-wrapper-C13Y-Q6w.mjs +211 -0
  36. package/dist/use-base-search-BGgWnWaF.d.mts +35 -0
  37. package/dist/use-debounce-xmZucz5e.mjs +53 -0
  38. package/dist/use-keyboard-shortcut-Bl6YM5Q7.mjs +82 -0
  39. package/dist/use-keyboard-shortcut-_mRCh3QO.d.mts +24 -0
  40. package/dist/use-media-query-BnVNIKT4.mjs +17 -0
  41. package/dist/use-mobile-BX3SQVo2.mjs +20 -0
  42. package/dist/use-scroll-detection-CsgsQYvy.mjs +43 -0
  43. package/dist/utils-CDue7cEt.d.mts +6 -0
  44. package/dist/utils-DQ5SCVoW.mjs +10 -0
  45. package/package.json +85 -45
  46. package/styles.css +2 -2
  47. package/dist/chunk-GUHK2DTW.js +0 -15
  48. package/dist/chunk-GUHK2DTW.js.map +0 -1
  49. package/dist/chunk-H3NFL3GJ.js +0 -57
  50. package/dist/chunk-H3NFL3GJ.js.map +0 -1
  51. package/dist/chunk-J2YRTQE4.js +0 -293
  52. package/dist/chunk-J2YRTQE4.js.map +0 -1
  53. package/dist/compact.d.ts +0 -217
  54. package/dist/compact.js +0 -986
  55. package/dist/compact.js.map +0 -1
  56. package/dist/dashboard.d.ts +0 -387
  57. package/dist/dashboard.js +0 -1032
  58. package/dist/dashboard.js.map +0 -1
  59. package/dist/index.d.ts +0 -2140
  60. package/dist/index.js +0 -6422
  61. package/dist/index.js.map +0 -1
  62. package/dist/layout.d.ts +0 -25
  63. package/dist/layout.js +0 -4
  64. package/dist/layout.js.map +0 -1
  65. package/dist/search.d.ts +0 -172
  66. package/dist/search.js +0 -341
  67. package/dist/search.js.map +0 -1
  68. package/dist/use-base-search-AS5Z3SAy.d.ts +0 -64
  69. package/dist/utils-Cbsgs0XP.d.ts +0 -5
@@ -0,0 +1,447 @@
1
+ "use client";
2
+
3
+ import { a as getApiParams, i as clearSearchAndFilterParams, r as buildSearchParams, t as buildFilterParams } from "../filter-utils-DqMmy_v-.mjs";
4
+ import { t as useIsMobile } from "../use-mobile-BX3SQVo2.mjs";
5
+ import { t as useMediaQuery } from "../use-media-query-BnVNIKT4.mjs";
6
+ import { t as useScrollDetection } from "../use-scroll-detection-CsgsQYvy.mjs";
7
+ import { n as useDebouncedCallback, t as useDebounce } from "../use-debounce-xmZucz5e.mjs";
8
+ import { t as useKeyboardShortcut } from "../use-keyboard-shortcut-Bl6YM5Q7.mjs";
9
+ import { useCallback, useEffect, useRef, useState } from "react";
10
+ import { useRouter, useSearchParams } from "next/navigation";
11
+
12
+ //#region src/hooks/use-base-search.ts
13
+ /**
14
+ * Base search hook that provides common search functionality
15
+ * Can be extended by specific search hooks for different entities
16
+ * Supports bracket syntax: field[operator]=value
17
+ */
18
+ function useBaseSearch(config) {
19
+ const { basePath, searchFields = {}, filterFields = {}, defaultSearchType = Object.keys(searchFields)[0] || "" } = config;
20
+ const router = useRouter();
21
+ const searchParams = useSearchParams();
22
+ const [searchType, setSearchType] = useState(() => {
23
+ for (const [type, paramName] of Object.entries(searchFields)) if (searchParams.has(paramName)) return type;
24
+ return defaultSearchType;
25
+ });
26
+ const [searchValue, setSearchValue] = useState(() => {
27
+ for (const paramName of Object.values(searchFields)) {
28
+ const value = searchParams.get(paramName);
29
+ if (value) return value;
30
+ }
31
+ return "";
32
+ });
33
+ const [filters, setFilters] = useState(() => {
34
+ const initialFilters = {};
35
+ Object.entries(filterFields).forEach(([key, fieldConfig]) => {
36
+ const paramValue = searchParams.get(fieldConfig.paramName);
37
+ if (paramValue) if (fieldConfig.type === "array") initialFilters[key] = paramValue.split(",");
38
+ else initialFilters[key] = paramValue;
39
+ else initialFilters[key] = fieldConfig.defaultValue ?? (fieldConfig.type === "array" ? [] : "");
40
+ });
41
+ return initialFilters;
42
+ });
43
+ useEffect(() => {
44
+ let urlType = defaultSearchType;
45
+ for (const [type, paramName] of Object.entries(searchFields)) if (searchParams.has(paramName)) {
46
+ urlType = type;
47
+ break;
48
+ }
49
+ setSearchType((prev) => prev === urlType ? prev : urlType);
50
+ let urlValue = "";
51
+ for (const paramName of Object.values(searchFields)) {
52
+ const v = searchParams.get(paramName);
53
+ if (v) {
54
+ urlValue = v;
55
+ break;
56
+ }
57
+ }
58
+ setSearchValue((prev) => prev === urlValue ? prev : urlValue);
59
+ const urlFilters = {};
60
+ Object.entries(filterFields).forEach(([key, fieldConfig]) => {
61
+ const paramValue = searchParams.get(fieldConfig.paramName);
62
+ if (paramValue) urlFilters[key] = fieldConfig.type === "array" ? paramValue.split(",") : paramValue;
63
+ else urlFilters[key] = fieldConfig.defaultValue ?? (fieldConfig.type === "array" ? [] : "");
64
+ });
65
+ setFilters((prev) => {
66
+ return Object.keys(urlFilters).some((k) => {
67
+ const a = prev[k];
68
+ const b = urlFilters[k];
69
+ if (a === b) return false;
70
+ if (Array.isArray(a) && Array.isArray(b) && a.length === b.length && a.every((v, i) => v === b[i])) return false;
71
+ return true;
72
+ }) ? urlFilters : prev;
73
+ });
74
+ }, [searchParams]);
75
+ const stableConfig = {
76
+ basePath,
77
+ searchFields,
78
+ filterFields,
79
+ defaultSearchType
80
+ };
81
+ const handleSearch = useCallback(() => {
82
+ const params = new URLSearchParams(searchParams);
83
+ clearSearchAndFilterParams(params, stableConfig);
84
+ const searchParamsNew = buildSearchParams(searchType, searchValue, searchFields);
85
+ for (const [key, value] of searchParamsNew) params.set(key, value);
86
+ const filterParams = buildFilterParams(filters, filterFields);
87
+ for (const [key, value] of filterParams) params.set(key, value);
88
+ const nextQs = params.toString();
89
+ if (nextQs !== searchParams.toString()) router.push(nextQs ? `${basePath}?${nextQs}` : basePath);
90
+ }, [
91
+ searchType,
92
+ searchValue,
93
+ filters,
94
+ searchFields,
95
+ filterFields,
96
+ searchParams,
97
+ router,
98
+ basePath,
99
+ defaultSearchType
100
+ ]);
101
+ const clearSearch = useCallback(() => {
102
+ const params = new URLSearchParams(searchParams);
103
+ clearSearchAndFilterParams(params, stableConfig);
104
+ setSearchValue("");
105
+ setSearchType(defaultSearchType);
106
+ const resetFilters = {};
107
+ Object.entries(filterFields).forEach(([key, fieldConfig]) => {
108
+ resetFilters[key] = fieldConfig.defaultValue ?? (fieldConfig.type === "array" ? [] : "");
109
+ });
110
+ setFilters(resetFilters);
111
+ const next = params.toString();
112
+ router.push(next ? `${basePath}?${next}` : `${basePath}`);
113
+ }, [
114
+ searchParams,
115
+ router,
116
+ basePath,
117
+ defaultSearchType,
118
+ searchFields,
119
+ filterFields
120
+ ]);
121
+ const clearSearchValue = useCallback(() => {
122
+ const params = new URLSearchParams(searchParams);
123
+ Object.values(searchFields).forEach((paramName) => {
124
+ params.delete(paramName);
125
+ });
126
+ setSearchValue("");
127
+ setSearchType(defaultSearchType);
128
+ params.delete("page");
129
+ const next = params.toString();
130
+ router.push(next ? `${basePath}?${next}` : basePath);
131
+ }, [
132
+ searchParams,
133
+ router,
134
+ basePath,
135
+ defaultSearchType,
136
+ searchFields
137
+ ]);
138
+ const clearFilters = useCallback(() => {
139
+ const params = new URLSearchParams(searchParams);
140
+ Object.values(filterFields).forEach((fc) => {
141
+ params.delete(fc.paramName);
142
+ const base = fc.paramName.replace(/\[.*\]$/, "");
143
+ params.delete(`${base}[in]`);
144
+ });
145
+ const resetFilters = {};
146
+ Object.entries(filterFields).forEach(([key, fieldConfig]) => {
147
+ resetFilters[key] = fieldConfig.defaultValue ?? (fieldConfig.type === "array" ? [] : "");
148
+ });
149
+ setFilters(resetFilters);
150
+ params.delete("page");
151
+ const next = params.toString();
152
+ router.push(next ? `${basePath}?${next}` : basePath);
153
+ }, [
154
+ searchParams,
155
+ router,
156
+ basePath,
157
+ filterFields
158
+ ]);
159
+ const removeFilter = useCallback((key) => {
160
+ const fieldConfig = filterFields[key];
161
+ if (!fieldConfig) return;
162
+ const defaultValue = fieldConfig.defaultValue ?? (fieldConfig.type === "array" ? [] : "");
163
+ setFilters((prev) => ({
164
+ ...prev,
165
+ [key]: defaultValue
166
+ }));
167
+ const params = new URLSearchParams(searchParams);
168
+ params.delete(fieldConfig.paramName);
169
+ const base = fieldConfig.paramName.replace(/\[.*\]$/, "");
170
+ params.delete(`${base}[in]`);
171
+ params.delete("page");
172
+ const next = params.toString();
173
+ router.push(next ? `${basePath}?${next}` : basePath);
174
+ }, [
175
+ filterFields,
176
+ searchParams,
177
+ router,
178
+ basePath
179
+ ]);
180
+ const getSearchParamsForApi = useCallback(() => {
181
+ return getApiParams(searchParams);
182
+ }, [searchParams]);
183
+ return {
184
+ searchType,
185
+ setSearchType,
186
+ searchValue,
187
+ setSearchValue,
188
+ filters,
189
+ setFilters,
190
+ updateFilter: useCallback((key, value) => {
191
+ setFilters((prev) => ({
192
+ ...prev,
193
+ [key]: value
194
+ }));
195
+ }, []),
196
+ handleSearch,
197
+ clearSearch,
198
+ clearSearchValue,
199
+ clearFilters,
200
+ removeFilter,
201
+ getSearchParams: getSearchParamsForApi,
202
+ filterFields,
203
+ hasActiveSearch: Object.values(searchFields).some((paramName) => {
204
+ return searchParams.has(paramName);
205
+ }),
206
+ hasActiveFilters: Object.values(filterFields).some((fieldConfig) => {
207
+ const baseField = fieldConfig.paramName.replace(/\[.*\]$/, "");
208
+ return searchParams.has(fieldConfig.paramName) || searchParams.has(`${baseField}[in]`) || searchParams.has(baseField);
209
+ })
210
+ };
211
+ }
212
+
213
+ //#endregion
214
+ //#region src/hooks/use-copy-to-clipboard.ts
215
+ /**
216
+ * useCopyToClipboard — Copy text to clipboard with status tracking.
217
+ *
218
+ * @param resetDelay - How long (ms) the `copied` state stays true. Default: 2000
219
+ *
220
+ * @example
221
+ * ```tsx
222
+ * const { copy, copied } = useCopyToClipboard();
223
+ *
224
+ * <Button onClick={() => copy(apiKey)}>
225
+ * {copied ? "Copied!" : "Copy API Key"}
226
+ * </Button>
227
+ * ```
228
+ */
229
+ function useCopyToClipboard(resetDelay = 2e3) {
230
+ const [copied, setCopied] = useState(false);
231
+ const [error, setError] = useState(null);
232
+ const timerRef = useRef(void 0);
233
+ useEffect(() => {
234
+ return () => {
235
+ if (timerRef.current) clearTimeout(timerRef.current);
236
+ };
237
+ }, []);
238
+ const reset = useCallback(() => {
239
+ setCopied(false);
240
+ setError(null);
241
+ }, []);
242
+ return {
243
+ copy: useCallback(async (text) => {
244
+ if (!navigator?.clipboard) {
245
+ setError(/* @__PURE__ */ new Error("Clipboard API not available"));
246
+ return false;
247
+ }
248
+ try {
249
+ await navigator.clipboard.writeText(text);
250
+ setCopied(true);
251
+ setError(null);
252
+ if (timerRef.current) clearTimeout(timerRef.current);
253
+ timerRef.current = setTimeout(() => setCopied(false), resetDelay);
254
+ return true;
255
+ } catch (e) {
256
+ setError(e instanceof Error ? e : /* @__PURE__ */ new Error("Copy failed"));
257
+ setCopied(false);
258
+ return false;
259
+ }
260
+ }, [resetDelay]),
261
+ copied,
262
+ error,
263
+ reset
264
+ };
265
+ }
266
+
267
+ //#endregion
268
+ //#region src/lib/storage.ts
269
+ /**
270
+ * A utility module for handling localStorage operations with error handling and SSR safety
271
+ */
272
+ /**
273
+ * Gets an item from localStorage with parsing and expiry check
274
+ * @param {string} key - The key to retrieve from localStorage
275
+ * @param {any} defaultValue - Default value to return if key doesn't exist or on error
276
+ * @returns {any} The parsed value or defaultValue
277
+ */
278
+ const getStorageItem = (key, defaultValue = null) => {
279
+ if (typeof window === "undefined") return defaultValue;
280
+ try {
281
+ const item = window.localStorage.getItem(key);
282
+ if (!item) return defaultValue;
283
+ const parsed = JSON.parse(item);
284
+ if (parsed && typeof parsed === "object" && parsed.__expiresAt) {
285
+ if (Date.now() > parsed.__expiresAt) {
286
+ window.localStorage.removeItem(key);
287
+ return defaultValue;
288
+ }
289
+ return parsed.value;
290
+ }
291
+ return parsed;
292
+ } catch (error) {
293
+ console.error(`Error reading localStorage key "${key}":`, error);
294
+ return defaultValue;
295
+ }
296
+ };
297
+ /**
298
+ * Sets an item in localStorage with serialization and optional expiry
299
+ * @param {string} key - The key to set in localStorage
300
+ * @param {any} value - The value to serialize and store
301
+ * @param {number} [ttl] - Time to live in milliseconds (optional)
302
+ * @returns {boolean} Success status
303
+ */
304
+ const setStorageItem = (key, value, ttl = null) => {
305
+ if (typeof window === "undefined") return false;
306
+ try {
307
+ let itemToStore = value;
308
+ if (ttl && typeof ttl === "number" && ttl > 0) itemToStore = {
309
+ value,
310
+ __expiresAt: Date.now() + ttl
311
+ };
312
+ window.localStorage.setItem(key, JSON.stringify(itemToStore));
313
+ return true;
314
+ } catch (error) {
315
+ console.error(`Error setting localStorage key "${key}":`, error);
316
+ return false;
317
+ }
318
+ };
319
+ /**
320
+ * Removes an item from localStorage
321
+ * @param {string} key - The key to remove from localStorage
322
+ * @returns {boolean} Success status
323
+ */
324
+ const removeStorageItem = (key) => {
325
+ if (typeof window === "undefined") return false;
326
+ try {
327
+ window.localStorage.removeItem(key);
328
+ return true;
329
+ } catch (error) {
330
+ console.error(`Error removing localStorage key "${key}":`, error);
331
+ return false;
332
+ }
333
+ };
334
+ /**
335
+ * Clears all items from localStorage
336
+ * @returns {boolean} Success status
337
+ */
338
+ const clearStorage = () => {
339
+ if (typeof window === "undefined") return false;
340
+ try {
341
+ window.localStorage.clear();
342
+ return true;
343
+ } catch (error) {
344
+ console.error("Error clearing localStorage:", error);
345
+ return false;
346
+ }
347
+ };
348
+ /**
349
+ * Checks if localStorage is empty for a specific key
350
+ * @param {string} key - The key to check in localStorage
351
+ * @returns {boolean} True if empty or doesn't exist
352
+ */
353
+ const isStorageEmpty = (key) => {
354
+ const data = getStorageItem(key);
355
+ return !data || Array.isArray(data) && data.length === 0;
356
+ };
357
+ /**
358
+ * Generates a UUID (v4)
359
+ * Uses crypto.randomUUID() when available, with a fallback for older environments.
360
+ * @returns {string} A random UUID
361
+ */
362
+ const generateUUID = () => {
363
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") return crypto.randomUUID();
364
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
365
+ const r = Math.random() * 16 | 0;
366
+ return (c === "x" ? r : r & 3 | 8).toString(16);
367
+ });
368
+ };
369
+ /**
370
+ * Common expiry durations in milliseconds
371
+ */
372
+ const TTL = {
373
+ MINUTE: 60 * 1e3,
374
+ HOUR: 3600 * 1e3,
375
+ DAY: 1440 * 60 * 1e3,
376
+ WEEK: 10080 * 60 * 1e3,
377
+ MONTH: 720 * 60 * 60 * 1e3
378
+ };
379
+ /**
380
+ * Shorthand object for all localStorage operations
381
+ */
382
+ const storage = {
383
+ get: getStorageItem,
384
+ set: setStorageItem,
385
+ remove: removeStorageItem,
386
+ clear: clearStorage,
387
+ isEmpty: isStorageEmpty,
388
+ generateUUID,
389
+ TTL
390
+ };
391
+
392
+ //#endregion
393
+ //#region src/hooks/use-local-storage.ts
394
+ /**
395
+ * useLocalStorage — Persist state in localStorage with type safety and optional expiry.
396
+ *
397
+ * @param key - The localStorage key
398
+ * @param initialValue - Default value if no stored value exists
399
+ * @param ttl - Time to live in milliseconds (optional)
400
+ *
401
+ * @example
402
+ * ```tsx
403
+ * const [theme, setTheme] = useLocalStorage("theme", "light");
404
+ * const [cache, setCache] = useLocalStorage("api-cache", {}, 60000); // 1 min TTL
405
+ * ```
406
+ */
407
+ function useLocalStorage(key, initialValue, ttl) {
408
+ const [storedValue, setStoredValue] = useState(() => {
409
+ const item = storage.get(key, initialValue);
410
+ return item !== null ? item : initialValue;
411
+ });
412
+ const keyRef = useRef(key);
413
+ const ttlRef = useRef(ttl);
414
+ useEffect(() => {
415
+ keyRef.current = key;
416
+ ttlRef.current = ttl;
417
+ }, [key, ttl]);
418
+ const setValue = useCallback((value) => {
419
+ setStoredValue((prev) => {
420
+ const nextValue = value instanceof Function ? value(prev) : value;
421
+ storage.set(keyRef.current, nextValue, ttlRef.current);
422
+ return nextValue;
423
+ });
424
+ }, []);
425
+ const removeValue = useCallback(() => {
426
+ storage.remove(keyRef.current);
427
+ setStoredValue(initialValue);
428
+ }, [initialValue]);
429
+ useEffect(() => {
430
+ const handleStorage = (e) => {
431
+ if (e.key === keyRef.current) {
432
+ const item = storage.get(keyRef.current, initialValue);
433
+ setStoredValue(item !== null ? item : initialValue);
434
+ }
435
+ };
436
+ window.addEventListener("storage", handleStorage);
437
+ return () => window.removeEventListener("storage", handleStorage);
438
+ }, [initialValue]);
439
+ return [
440
+ storedValue,
441
+ setValue,
442
+ removeValue
443
+ ];
444
+ }
445
+
446
+ //#endregion
447
+ export { TTL, clearStorage, generateUUID, getStorageItem, isStorageEmpty, removeStorageItem, setStorageItem, storage, useBaseSearch, useCopyToClipboard, useDebounce, useDebouncedCallback, useIsMobile, useKeyboardShortcut, useLocalStorage, useMediaQuery, useScrollDetection };
@@ -0,0 +1,84 @@
1
+ import { n as ApiPaginationData } from "../api-pagination-CJ0vR_w6.mjs";
2
+ import * as react_jsx_runtime0 from "react/jsx-runtime";
3
+ import React, { ReactNode } from "react";
4
+ import { ColumnDef } from "@tanstack/react-table";
5
+
6
+ //#region src/components/data-table.d.ts
7
+ interface DataTablePaginationProps extends Partial<ApiPaginationData> {
8
+ onPageChange?: (page: number) => void;
9
+ }
10
+ interface DataTableProps<TData, TValue> {
11
+ columns: ColumnDef<TData, TValue>[];
12
+ data: TData[];
13
+ isLoading?: boolean;
14
+ pagination?: DataTablePaginationProps;
15
+ enableSorting?: boolean;
16
+ enableRowSelection?: boolean;
17
+ onRowSelectionChange?: (selectedRows: TData[]) => void;
18
+ className?: string;
19
+ /** Custom loading state renderer */
20
+ loadingState?: React.ReactNode;
21
+ /** Custom empty state renderer */
22
+ emptyState?: React.ReactNode;
23
+ }
24
+ declare function DataTable<TData, TValue>({
25
+ columns,
26
+ data,
27
+ isLoading,
28
+ pagination,
29
+ enableSorting,
30
+ enableRowSelection,
31
+ onRowSelectionChange,
32
+ className,
33
+ loadingState: customLoadingState,
34
+ emptyState: customEmptyState
35
+ }: DataTableProps<TData, TValue>): react_jsx_runtime0.JSX.Element;
36
+ //#endregion
37
+ //#region src/components/data-table-toolbar.d.ts
38
+ interface DataTableToolbarProps {
39
+ children?: ReactNode;
40
+ className?: string;
41
+ showSearch?: boolean;
42
+ searchPlaceholder?: string;
43
+ showFilters?: boolean;
44
+ filterContent?: ReactNode;
45
+ filterTitle?: string;
46
+ selectedCount?: number;
47
+ bulkActions?: ReactNode;
48
+ totalResults?: number;
49
+ showResultCount?: boolean;
50
+ }
51
+ /**
52
+ * DataTableToolbar - Composable toolbar with search, filters, and bulk actions
53
+ *
54
+ * Must be used inside a `Search.Root` context.
55
+ *
56
+ * @example
57
+ * ```tsx
58
+ * <Search.Root hook={searchHook}>
59
+ * <DataTableToolbar
60
+ * searchPlaceholder="Search users..."
61
+ * filterContent={<SelectInput name="role" items={roles} />}
62
+ * totalResults={data?.total}
63
+ * selectedCount={selected.length}
64
+ * bulkActions={<Button variant="destructive">Delete</Button>}
65
+ * />
66
+ * <DataTable columns={columns} data={data?.items ?? []} />
67
+ * </Search.Root>
68
+ * ```
69
+ */
70
+ declare function DataTableToolbar({
71
+ children,
72
+ className,
73
+ showSearch,
74
+ searchPlaceholder,
75
+ showFilters,
76
+ filterContent,
77
+ filterTitle,
78
+ selectedCount,
79
+ bulkActions,
80
+ totalResults,
81
+ showResultCount
82
+ }: DataTableToolbarProps): react_jsx_runtime0.JSX.Element;
83
+ //#endregion
84
+ export { DataTable, type DataTablePaginationProps, type DataTableProps, DataTableToolbar, type DataTableToolbarProps };