@kala-ui/react-app 0.1.0-beta.0 → 0.1.0-beta.10

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 (116) hide show
  1. package/CHANGELOG.md +83 -0
  2. package/README.md +9 -4
  3. package/dist/components/app-shell/app-shell.d.ts +8 -46
  4. package/dist/components/app-shell/app-shell.js +41 -42
  5. package/dist/components/app-shell/app-shell.types.d.ts +45 -0
  6. package/dist/components/app-shell/app-shell.types.js +2 -0
  7. package/dist/components/app-shell/index.d.ts +1 -0
  8. package/dist/components/charts/area-chart.d.ts +1 -1
  9. package/dist/components/charts/area-chart.js +4 -3
  10. package/dist/components/charts/bar-chart.d.ts +1 -1
  11. package/dist/components/charts/bar-chart.js +4 -3
  12. package/dist/components/charts/chart-skeleton.d.ts +0 -21
  13. package/dist/components/charts/chart-skeleton.js +2 -1
  14. package/dist/components/charts/chart-utils.d.ts +56 -0
  15. package/dist/components/charts/chart-utils.js +135 -0
  16. package/dist/components/charts/chart.d.ts +3 -1
  17. package/dist/components/charts/chart.js +14 -4
  18. package/dist/components/charts/chart.types.d.ts +3 -0
  19. package/dist/components/charts/donut-chart.d.ts +1 -1
  20. package/dist/components/charts/donut-chart.js +5 -4
  21. package/dist/components/charts/index.d.ts +1 -1
  22. package/dist/components/charts/index.js +1 -1
  23. package/dist/components/charts/line-chart.d.ts +1 -1
  24. package/dist/components/charts/line-chart.js +4 -3
  25. package/dist/components/charts/radial-bar-chart.d.ts +1 -1
  26. package/dist/components/charts/radial-bar-chart.js +4 -3
  27. package/dist/components/data-table/column-filters.js +1 -1
  28. package/dist/components/data-table/column-header-filter.js +1 -1
  29. package/dist/components/data-table/data-table-body-rows.js +1 -1
  30. package/dist/components/data-table/data-table-filter-chips.js +1 -1
  31. package/dist/components/data-table/data-table-header-row.js +1 -1
  32. package/dist/components/data-table/data-table-skeleton.js +1 -1
  33. package/dist/components/data-table/data-table-toolbar.js +1 -1
  34. package/dist/components/data-table/data-table.js +6 -4
  35. package/dist/components/data-table/data-table.types.d.ts +2 -0
  36. package/dist/components/data-table/index.d.ts +1 -1
  37. package/dist/components/data-table/index.js +1 -1
  38. package/dist/components/data-table/pagination-nav.js +1 -1
  39. package/dist/components/data-table/use-table-state.d.ts +29 -0
  40. package/dist/components/data-table/use-table-state.js +312 -0
  41. package/dist/components/dnd/dnd.d.ts +16 -98
  42. package/dist/components/dnd/dnd.js +36 -8
  43. package/dist/components/dnd/dnd.types.d.ts +92 -0
  44. package/dist/components/dnd/dnd.types.js +7 -0
  45. package/dist/components/dnd/index.d.ts +2 -1
  46. package/dist/components/dnd/index.js +1 -1
  47. package/dist/components/footer/footer.d.ts +2 -37
  48. package/dist/components/footer/footer.js +18 -2
  49. package/dist/components/footer/footer.types.d.ts +25 -0
  50. package/dist/components/footer/footer.types.js +2 -0
  51. package/dist/components/footer/index.d.ts +1 -1
  52. package/dist/components/header/header-skeleton.js +1 -1
  53. package/dist/components/header/header.js +6 -12
  54. package/dist/components/metric-card/index.d.ts +2 -1
  55. package/dist/components/metric-card/metric-card-skeleton.js +2 -1
  56. package/dist/components/metric-card/metric-card.d.ts +2 -14
  57. package/dist/components/metric-card/metric-card.js +33 -29
  58. package/dist/components/metric-card/metric-card.types.d.ts +3 -0
  59. package/dist/components/nav-link/index.d.ts +2 -1
  60. package/dist/components/nav-link/index.js +1 -1
  61. package/dist/components/nav-link/nav-link.d.ts +2 -25
  62. package/dist/components/nav-link/nav-link.js +43 -5
  63. package/dist/components/nav-link/nav-link.types.d.ts +23 -0
  64. package/dist/components/nav-link/nav-link.types.js +2 -0
  65. package/dist/components/navigation/index.d.ts +1 -1
  66. package/dist/components/navigation/navigation-skeleton.js +1 -1
  67. package/dist/components/navigation/navigation.d.ts +1 -24
  68. package/dist/components/navigation/navigation.js +9 -19
  69. package/dist/components/navigation/navigation.types.d.ts +15 -0
  70. package/dist/components/navigation/navigation.types.js +2 -0
  71. package/dist/components/session-card/index.d.ts +2 -1
  72. package/dist/components/session-card/index.js +1 -1
  73. package/dist/components/session-card/session-card-skeleton.d.ts +3 -1
  74. package/dist/components/session-card/session-card-skeleton.js +3 -2
  75. package/dist/components/session-card/session-card.d.ts +3 -26
  76. package/dist/components/session-card/session-card.js +23 -8
  77. package/dist/components/session-card/session-card.types.d.ts +26 -0
  78. package/dist/components/session-card/session-card.types.js +2 -0
  79. package/dist/components/sidebar/sidebar-skeleton.js +1 -1
  80. package/dist/components/sidebar/sidebar.js +6 -12
  81. package/dist/components/social-login-button/index.d.ts +3 -1
  82. package/dist/components/social-login-button/index.js +2 -1
  83. package/dist/components/social-login-button/social-login-button.d.ts +2 -20
  84. package/dist/components/social-login-button/social-login-button.js +9 -11
  85. package/dist/components/social-login-button/social-login-button.types.d.ts +28 -0
  86. package/dist/components/social-login-button/social-login-button.types.js +2 -0
  87. package/dist/components/social-login-button/social-login-buttons.d.ts +4 -0
  88. package/dist/components/social-login-button/social-login-buttons.js +18 -0
  89. package/dist/components/social-login-buttons/social-login-buttons.js +1 -1
  90. package/dist/components/sparkline-chart/sparkline-chart.js +1 -1
  91. package/dist/components/user-menu-dropdown/index.d.ts +2 -1
  92. package/dist/components/user-menu-dropdown/index.js +1 -1
  93. package/dist/components/user-menu-dropdown/user-menu-dropdown.d.ts +2 -31
  94. package/dist/components/user-menu-dropdown/user-menu-dropdown.js +14 -2
  95. package/dist/components/user-menu-dropdown/user-menu-dropdown.types.d.ts +16 -0
  96. package/dist/components/user-menu-dropdown/user-menu-dropdown.types.js +2 -0
  97. package/dist/config/app-shell.d.ts +13 -0
  98. package/dist/config/app-shell.js +20 -0
  99. package/dist/config/charts.d.ts +23 -0
  100. package/dist/config/charts.js +23 -0
  101. package/dist/config/footer.d.ts +16 -0
  102. package/dist/config/footer.js +16 -0
  103. package/dist/config/index.d.ts +7 -0
  104. package/dist/config/index.js +7 -0
  105. package/dist/config/metric-card.d.ts +36 -0
  106. package/dist/config/metric-card.js +44 -0
  107. package/dist/config/session-card.d.ts +32 -0
  108. package/dist/config/session-card.js +32 -0
  109. package/dist/config/social-login-button.d.ts +15 -0
  110. package/dist/config/social-login-button.js +15 -0
  111. package/dist/config/user-menu-dropdown.d.ts +10 -0
  112. package/dist/config/user-menu-dropdown.js +10 -0
  113. package/dist/index.d.ts +0 -1
  114. package/dist/index.js +0 -1
  115. package/dist/styles/app.css +18 -53
  116. package/package.json +24 -28
@@ -0,0 +1,312 @@
1
+ "use client";
2
+ /**
3
+ * useTableState Hook
4
+ * Manages table state including sorting, filtering, pagination, and search
5
+ */
6
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
7
+ /**
8
+ * Hook to manage table state (sorting, filtering, search, pagination)
9
+ */
10
+ export function useTableState({ data, columns, defaultSort, defaultFilters = [], searchConfig, pageSize: initialPageSize = 10, total: manualTotal, page, onSortChange, onFilterChange, onSearchChange, onPaginationChange, }) {
11
+ // State
12
+ const [sortConfig, setSortConfig] = useState(defaultSort ?? null);
13
+ const [filterConfigs, setFilterConfigs] = useState(defaultFilters);
14
+ const [searchQuery, setSearchQuery] = useState("");
15
+ const [currentPage, setCurrentPage] = useState(1);
16
+ const [pageSize, setPageSize] = useState(initialPageSize);
17
+ // Controlled page: mirror prop changes into internal state during render
18
+ // (adjust-state-on-prop-change). The hook keeps working uncontrolled when
19
+ // no `page` is supplied.
20
+ const prevControlledPageRef = useRef(undefined);
21
+ if (page !== undefined &&
22
+ page !== prevControlledPageRef.current &&
23
+ page !== currentPage) {
24
+ prevControlledPageRef.current = page;
25
+ setCurrentPage(page);
26
+ }
27
+ else {
28
+ prevControlledPageRef.current = page;
29
+ }
30
+ // Sync pageSize when initialPageSize changes (e.g. data loads and pagination is false)
31
+ useEffect(() => {
32
+ setPageSize(initialPageSize);
33
+ }, [initialPageSize]);
34
+ // Get search keys
35
+ const searchKeys = useMemo(() => {
36
+ if (!searchConfig)
37
+ return [];
38
+ const defaultKeys = columns
39
+ .filter((col) => col.accessorKey)
40
+ .map((col) => col.accessorKey);
41
+ if (typeof searchConfig === "boolean") {
42
+ return defaultKeys;
43
+ }
44
+ return searchConfig.searchKeys ?? defaultKeys;
45
+ }, [searchConfig, columns]);
46
+ // Filter data based on search query
47
+ // When onSearchChange is provided, data is already server-filtered — skip client-side filtering
48
+ const searchedData = useMemo(() => {
49
+ if (onSearchChange)
50
+ return data;
51
+ if (!searchQuery.trim() || searchKeys.length === 0)
52
+ return data;
53
+ const query = searchQuery.toLowerCase();
54
+ return data.filter((row) => {
55
+ return searchKeys.some((key) => {
56
+ const value = row[key];
57
+ if (value === null || value === undefined)
58
+ return false;
59
+ return String(value).toLowerCase().includes(query);
60
+ });
61
+ });
62
+ }, [data, searchQuery, searchKeys, onSearchChange]);
63
+ // Apply filters
64
+ const filteredData = useMemo(() => {
65
+ if (filterConfigs.length === 0)
66
+ return searchedData;
67
+ return searchedData.filter((row) => {
68
+ return filterConfigs.every((filter) => {
69
+ const value = row[filter.key];
70
+ const filterValue = filter.value;
71
+ switch (filter.operator) {
72
+ case "equals":
73
+ if (typeof value === "boolean") {
74
+ return value === (filterValue === "true" || filterValue === true);
75
+ }
76
+ return value === filterValue;
77
+ case "contains":
78
+ return String(value)
79
+ .toLowerCase()
80
+ .includes(String(filterValue).toLowerCase());
81
+ case "startsWith":
82
+ return String(value)
83
+ .toLowerCase()
84
+ .startsWith(String(filterValue).toLowerCase());
85
+ case "endsWith":
86
+ return String(value)
87
+ .toLowerCase()
88
+ .endsWith(String(filterValue).toLowerCase());
89
+ case "in":
90
+ if (typeof value === "boolean") {
91
+ const strVal = String(value);
92
+ return (Array.isArray(filterValue) &&
93
+ filterValue.some((v) => v === strVal || v === value));
94
+ }
95
+ return Array.isArray(filterValue) && filterValue.includes(value);
96
+ default:
97
+ return true;
98
+ }
99
+ });
100
+ });
101
+ }, [searchedData, filterConfigs]);
102
+ // Apply sorting
103
+ const sortedData = useMemo(() => {
104
+ if (!sortConfig)
105
+ return filteredData;
106
+ const { key, direction } = sortConfig;
107
+ const column = columns.find((col) => col.accessorKey === key);
108
+ return [...filteredData].sort((a, b) => {
109
+ // Use custom sort function if provided
110
+ if (column?.sortFn) {
111
+ return column.sortFn(a, b, direction);
112
+ }
113
+ // Default sort
114
+ const aValue = a[key];
115
+ const bValue = b[key];
116
+ if (aValue === bValue)
117
+ return 0;
118
+ if (aValue === null || aValue === undefined)
119
+ return 1;
120
+ if (bValue === null || bValue === undefined)
121
+ return -1;
122
+ // Handle different types
123
+ if (typeof aValue === "string" && typeof bValue === "string") {
124
+ const result = aValue.localeCompare(bValue);
125
+ return direction === "asc" ? result : -result;
126
+ }
127
+ if (typeof aValue === "number" && typeof bValue === "number") {
128
+ return direction === "asc" ? aValue - bValue : bValue - aValue;
129
+ }
130
+ if (aValue instanceof Date && bValue instanceof Date) {
131
+ return direction === "asc"
132
+ ? aValue.getTime() - bValue.getTime()
133
+ : bValue.getTime() - aValue.getTime();
134
+ }
135
+ // Fallback to string comparison
136
+ const result = String(aValue).localeCompare(String(bValue));
137
+ return direction === "asc" ? result : -result;
138
+ });
139
+ }, [filteredData, sortConfig, columns]);
140
+ // Pagination
141
+ const totalPages = Math.ceil((manualTotal ?? sortedData.length) / pageSize);
142
+ const hasNextPage = currentPage < totalPages;
143
+ const hasPreviousPage = currentPage > 1;
144
+ const pageData = useMemo(() => {
145
+ // If manualTotal AND onPaginationChange are provided, assume server-side pagination
146
+ // Otherwise, do client-side pagination
147
+ if (manualTotal !== undefined && onPaginationChange !== undefined) {
148
+ return sortedData;
149
+ }
150
+ const startIndex = (currentPage - 1) * pageSize;
151
+ const endIndex = startIndex + pageSize;
152
+ return sortedData.slice(startIndex, endIndex);
153
+ }, [sortedData, currentPage, pageSize, manualTotal, onPaginationChange]);
154
+ // Toggle sort
155
+ const toggleSort = useCallback((key) => {
156
+ setSortConfig((prev) => {
157
+ let newSort;
158
+ if (!prev || prev.key !== key) {
159
+ newSort = { key, direction: "asc" };
160
+ }
161
+ else if (prev.direction === "asc") {
162
+ newSort = { key, direction: "desc" };
163
+ }
164
+ else {
165
+ newSort = null; // Clear sort
166
+ }
167
+ return newSort;
168
+ });
169
+ setCurrentPage(1); // Reset to first page when sorting changes
170
+ }, []);
171
+ // Notify parent of sort changes after render. Calling the callback directly
172
+ // inside useEffect is safe — the setState that triggered this effect has
173
+ // already committed; the callback runs in the passive-effect phase, not
174
+ // during render. (The prior queueMicrotask deferral broke act() in tests:
175
+ // the microtask fired outside act()'s flush window, so sync assertions saw
176
+ // zero calls.)
177
+ const prevSortRef = useRef(defaultSort ?? null);
178
+ useEffect(() => {
179
+ if (sortConfig !== prevSortRef.current) {
180
+ prevSortRef.current = sortConfig;
181
+ onSortChange?.(sortConfig);
182
+ }
183
+ });
184
+ // Notify parent of filter changes after render.
185
+ const prevFilterRef = useRef(defaultFilters);
186
+ useEffect(() => {
187
+ if (filterConfigs !== prevFilterRef.current) {
188
+ prevFilterRef.current = filterConfigs;
189
+ onFilterChange?.(filterConfigs);
190
+ }
191
+ });
192
+ // Extract debounce ms from searchConfig
193
+ const debounceMs = useMemo(() => {
194
+ if (!searchConfig || typeof searchConfig === "boolean")
195
+ return 0;
196
+ return searchConfig.debounce ?? 0;
197
+ }, [searchConfig]);
198
+ // Notify parent of search changes after render. When a debounce is
199
+ // configured, the parent (server-side search) is notified only after the
200
+ // debounce window elapses — firing on every keystroke would hammer the
201
+ // server. The local searchQuery state updates immediately so the local
202
+ // (client-side) filtering stays responsive; only the parent callback waits.
203
+ // The effect depends on [searchQuery] only: re-running it on unrelated
204
+ // re-renders would clear the pending timer and silently swallow the
205
+ // callback, so the latest callback is read through a ref instead.
206
+ const prevSearchRef = useRef("");
207
+ const onSearchChangeRef = useRef(onSearchChange);
208
+ useEffect(() => {
209
+ onSearchChangeRef.current = onSearchChange;
210
+ });
211
+ useEffect(() => {
212
+ if (searchQuery === prevSearchRef.current)
213
+ return;
214
+ prevSearchRef.current = searchQuery;
215
+ const callback = onSearchChangeRef.current;
216
+ if (!callback)
217
+ return;
218
+ if (debounceMs <= 0) {
219
+ callback(searchQuery);
220
+ return;
221
+ }
222
+ const timer = setTimeout(() => callback(searchQuery), debounceMs);
223
+ return () => clearTimeout(timer);
224
+ }, [searchQuery, debounceMs]);
225
+ // Notify parent of pagination changes after render.
226
+ const prevPaginationRef = useRef({ page: 1, pageSize: initialPageSize });
227
+ useEffect(() => {
228
+ const prev = prevPaginationRef.current;
229
+ if (currentPage !== prev.page || pageSize !== prev.pageSize) {
230
+ prevPaginationRef.current = { page: currentPage, pageSize };
231
+ onPaginationChange?.(currentPage, pageSize);
232
+ }
233
+ });
234
+ // Filter management
235
+ const setFilter = useCallback((filter) => {
236
+ setFilterConfigs((prev) => {
237
+ const filtered = prev.filter((f) => f.key !== filter.key);
238
+ return [...filtered, filter];
239
+ });
240
+ setCurrentPage(1);
241
+ }, []);
242
+ const removeFilter = useCallback((key) => {
243
+ setFilterConfigs((prev) => prev.filter((f) => f.key !== key));
244
+ setCurrentPage(1);
245
+ }, []);
246
+ const clearFilters = useCallback(() => {
247
+ setFilterConfigs([]);
248
+ setCurrentPage(1);
249
+ }, []);
250
+ const searchDebounceRef = useRef(null);
251
+ // Search management
252
+ const handleSetSearchQuery = useCallback((query) => {
253
+ setSearchQuery(query);
254
+ if (searchDebounceRef.current)
255
+ clearTimeout(searchDebounceRef.current);
256
+ if (debounceMs > 0) {
257
+ searchDebounceRef.current = setTimeout(() => {
258
+ setCurrentPage(1);
259
+ }, debounceMs);
260
+ }
261
+ else {
262
+ setCurrentPage(1);
263
+ }
264
+ }, [debounceMs]);
265
+ // Set current page and notify server-side listener
266
+ const handleSetCurrentPage = useCallback((pageOrUpdater) => {
267
+ setCurrentPage((prev) => {
268
+ const newPage = typeof pageOrUpdater === "function"
269
+ ? pageOrUpdater(prev)
270
+ : pageOrUpdater;
271
+ return newPage;
272
+ });
273
+ }, []);
274
+ // Pagination navigation
275
+ const nextPage = useCallback(() => {
276
+ if (hasNextPage) {
277
+ handleSetCurrentPage((prev) => prev + 1);
278
+ }
279
+ }, [hasNextPage, handleSetCurrentPage]);
280
+ const previousPage = useCallback(() => {
281
+ if (hasPreviousPage) {
282
+ handleSetCurrentPage((prev) => prev - 1);
283
+ }
284
+ }, [hasPreviousPage, handleSetCurrentPage]);
285
+ // Page size change — reset page without direct callback
286
+ const handleSetPageSize = useCallback((size) => {
287
+ setPageSize(size);
288
+ setCurrentPage(1);
289
+ }, []);
290
+ return {
291
+ processedData: sortedData,
292
+ pageData,
293
+ sortConfig,
294
+ setSortConfig,
295
+ toggleSort,
296
+ filterConfigs,
297
+ setFilter,
298
+ removeFilter,
299
+ clearFilters,
300
+ searchQuery,
301
+ setSearchQuery: handleSetSearchQuery,
302
+ currentPage,
303
+ setCurrentPage: handleSetCurrentPage,
304
+ pageSize,
305
+ setPageSize: handleSetPageSize,
306
+ totalPages,
307
+ hasNextPage,
308
+ hasPreviousPage,
309
+ nextPage,
310
+ previousPage,
311
+ };
312
+ }
@@ -2,117 +2,35 @@
2
2
  * DnD Component - Drag and Drop primitives for @dnd-kit
3
3
  * Provides consistent wrappers with animations, sortable support, and drag overlays
4
4
  */
5
- import type { Active, Collision, CollisionDetection, DndContextProps as DndKitContextProps, DragEndEvent, DraggableAttributes, DraggableSyntheticListeners, DragOverEvent, DragStartEvent, Modifier, Over, PointerActivationConstraint, UniqueIdentifier } from "@dnd-kit/core";
5
+ import type { DragDropContextProps, DragOverlayComponentProps, DraggableProps, DroppableProps, SortableContextProps, SortableHandleProps, SortableItemProps, UseDragDropSensorsOptions } from "./dnd.types";
6
6
  import { KeyboardSensor, PointerSensor, TouchSensor, useDraggable, useDroppable, useSensor, useSensors } from "@dnd-kit/core";
7
- import { type SortingStrategy, sortableKeyboardCoordinates, useSortable } from "@dnd-kit/sortable";
8
- import type { Transform } from "@dnd-kit/utilities";
7
+ import { sortableKeyboardCoordinates, useSortable } from "@dnd-kit/sortable";
9
8
  import * as React from "react";
10
- type SyntheticListenerMap = DraggableSyntheticListeners;
11
- export type DragDropModifier = Modifier;
12
- export type DragDropCollisionDetection = CollisionDetection;
13
- export type DragDropSortingStrategy = SortingStrategy;
14
- export type DragDropPointerConstraint = PointerActivationConstraint;
15
9
  export declare const collisionDetectionAlgorithms: {
16
- readonly closestCenter: CollisionDetection;
17
- readonly closestCorners: CollisionDetection;
18
- readonly rectIntersection: CollisionDetection;
19
- readonly pointerWithin: CollisionDetection;
10
+ readonly closestCenter: import("@dnd-kit/core").CollisionDetection;
11
+ readonly closestCorners: import("@dnd-kit/core").CollisionDetection;
12
+ readonly rectIntersection: import("@dnd-kit/core").CollisionDetection;
13
+ readonly pointerWithin: import("@dnd-kit/core").CollisionDetection;
20
14
  };
21
15
  export declare const modifiers: {
22
- readonly restrictToHorizontalAxis: Modifier;
23
- readonly restrictToVerticalAxis: Modifier;
24
- readonly restrictToWindowEdges: Modifier;
25
- readonly restrictToParentElement: Modifier;
26
- readonly restrictToFirstScrollableAncestor: Modifier;
16
+ readonly restrictToHorizontalAxis: import("@dnd-kit/core").Modifier;
17
+ readonly restrictToVerticalAxis: import("@dnd-kit/core").Modifier;
18
+ readonly restrictToWindowEdges: import("@dnd-kit/core").Modifier;
19
+ readonly restrictToParentElement: import("@dnd-kit/core").Modifier;
20
+ readonly restrictToFirstScrollableAncestor: import("@dnd-kit/core").Modifier;
27
21
  };
28
22
  export declare const sortingStrategies: {
29
- readonly vertical: SortingStrategy;
30
- readonly horizontal: SortingStrategy;
31
- readonly rect: SortingStrategy;
32
- readonly rectSwapping: SortingStrategy;
23
+ readonly vertical: import("@dnd-kit/sortable").SortingStrategy;
24
+ readonly horizontal: import("@dnd-kit/sortable").SortingStrategy;
25
+ readonly rect: import("@dnd-kit/sortable").SortingStrategy;
26
+ readonly rectSwapping: import("@dnd-kit/sortable").SortingStrategy;
33
27
  };
34
- export interface UseDragDropSensorsOptions {
35
- activationConstraint?: PointerActivationConstraint;
36
- keyboardCoordinateGetter?: typeof sortableKeyboardCoordinates;
37
- }
38
28
  declare function createDragDropSensors(options?: UseDragDropSensorsOptions): import("@dnd-kit/core").SensorDescriptor<import("@dnd-kit/core").SensorOptions>[];
39
- export interface DragDropContextProps extends Omit<DndKitContextProps, "sensors"> {
40
- children: React.ReactNode;
41
- sensors?: ReturnType<typeof createDragDropSensors>;
42
- useSensors?: UseDragDropSensorsOptions;
43
- }
44
29
  declare function DragDropContext({ children, sensors: sensorsProp, useSensors: useSensorsOptions, ...props }: DragDropContextProps): React.JSX.Element;
45
- export interface DroppableProps {
46
- ref?: React.Ref<HTMLDivElement>;
47
- id: UniqueIdentifier;
48
- children: React.ReactNode | ((args: {
49
- isOver: boolean;
50
- setNodeRef: (node: HTMLElement | null) => void;
51
- }) => React.ReactNode);
52
- className?: string;
53
- disabled?: boolean;
54
- }
55
30
  declare function Droppable({ ref, children, className, id, disabled, ...props }: DroppableProps): React.JSX.Element;
56
- export interface DraggableProps {
57
- ref?: React.Ref<HTMLDivElement>;
58
- id: UniqueIdentifier;
59
- children: React.ReactNode | ((args: {
60
- attributes: DraggableAttributes;
61
- listeners: SyntheticListenerMap | undefined;
62
- setNodeRef: (node: HTMLElement | null) => void;
63
- transform: {
64
- x: number;
65
- y: number;
66
- scaleX: number;
67
- scaleY: number;
68
- } | null;
69
- isDragging: boolean;
70
- }) => React.ReactNode);
71
- className?: string;
72
- disabled?: boolean;
73
- }
74
31
  declare function Draggable({ ref, children, className, id, disabled, ...props }: DraggableProps): React.JSX.Element;
75
- export interface SortableContextProps {
76
- id?: UniqueIdentifier;
77
- items: UniqueIdentifier[] | {
78
- id: UniqueIdentifier;
79
- }[];
80
- strategy?: SortingStrategy;
81
- children: React.ReactNode;
82
- }
83
32
  declare function SortableContext({ children, items, strategy, }: SortableContextProps): React.JSX.Element;
84
- export interface SortableItemProps {
85
- ref?: React.Ref<HTMLDivElement>;
86
- id: UniqueIdentifier;
87
- children: React.ReactNode | ((args: {
88
- attributes: DraggableAttributes;
89
- listeners: SyntheticListenerMap | undefined;
90
- setNodeRef: (node: HTMLElement | null) => void;
91
- transform: Transform | null;
92
- transition: string | undefined;
93
- isDragging: boolean;
94
- isSorting: boolean;
95
- isOver: boolean;
96
- }) => React.ReactNode);
97
- className?: string;
98
- disabled?: boolean;
99
- handle?: boolean;
100
- }
101
- declare function SortableItem({ ref, children, className, id, disabled, handle, ...props }: SortableItemProps): React.JSX.Element;
102
- export interface SortableHandleProps {
103
- ref?: React.Ref<HTMLDivElement>;
104
- children: React.ReactNode | ((listeners: SyntheticListenerMap | undefined) => React.ReactNode);
105
- className?: string;
106
- }
33
+ declare function SortableItem({ ref, children, className, id, disabled, handle, slotStyles: slotStylesRaw, ...props }: SortableItemProps): React.JSX.Element;
107
34
  declare function SortableHandle({ ref, children, className, ...props }: SortableHandleProps): React.JSX.Element;
108
- export interface DragOverlayComponentProps {
109
- children: React.ReactNode;
110
- className?: string;
111
- dropAnimation?: {
112
- duration?: number;
113
- easing?: string;
114
- } | null;
115
- }
116
35
  declare function DragOverlayComponent({ children, className, dropAnimation, ...props }: DragOverlayComponentProps): React.JSX.Element;
117
- export type { Active, Collision, DragEndEvent as DropResult, DraggableAttributes, DraggableSyntheticListeners, DragOverEvent as DragUpdate, DragOverEvent, DragStartEvent as DragStart, Over, SortingStrategy, Transform, UniqueIdentifier, };
118
36
  export { createDragDropSensors as useDragDropSensors, DragDropContext, Draggable, DragOverlayComponent, Droppable, KeyboardSensor, PointerSensor, SortableContext, SortableHandle, SortableItem, sortableKeyboardCoordinates, TouchSensor, useDraggable, useDroppable, useSensor, useSensors, useSortable, };
@@ -10,6 +10,8 @@ import { restrictToFirstScrollableAncestor, restrictToHorizontalAxis, restrictTo
10
10
  import { horizontalListSortingStrategy, rectSortingStrategy, rectSwappingStrategy, SortableContext as SortableContextKit, sortableKeyboardCoordinates, useSortable, verticalListSortingStrategy, } from "@dnd-kit/sortable";
11
11
  import { CSS } from "@dnd-kit/utilities";
12
12
  import { cn } from "@kala-ui/react/lib/utils";
13
+ import { useSlotStyles } from "@kala-ui/react/kala-provider";
14
+ import { applySlot } from "@kala-ui/react/lib/slot-styles";
13
15
  import { useMergedRef } from "@kala-ui/react-hooks";
14
16
  import * as React from "react";
15
17
  // ============================================================================
@@ -40,6 +42,9 @@ export const sortingStrategies = {
40
42
  rect: rectSortingStrategy,
41
43
  rectSwapping: rectSwappingStrategy,
42
44
  };
45
+ // ============================================================================
46
+ // Sensors Hook
47
+ // ============================================================================
43
48
  function createDragDropSensors(options = {}) {
44
49
  const { activationConstraint, keyboardCoordinateGetter = sortableKeyboardCoordinates, } = options;
45
50
  const sensors = useSensors(useSensor(PointerSensor, {
@@ -51,11 +56,17 @@ function createDragDropSensors(options = {}) {
51
56
  }));
52
57
  return sensors;
53
58
  }
59
+ // ============================================================================
60
+ // DndContext
61
+ // ============================================================================
54
62
  function DragDropContext({ children, sensors: sensorsProp, useSensors: useSensorsOptions, ...props }) {
55
63
  const defaultSensors = createDragDropSensors(useSensorsOptions);
56
64
  const sensors = sensorsProp ?? defaultSensors;
57
- return (_jsx(DndKitContext, { sensors: sensors, ...props, children: children }));
65
+ return (_jsx(DndKitContext, { "data-kala-component": "dnd-drag-drop-context", sensors: sensors, ...props, children: children }));
58
66
  }
67
+ // ============================================================================
68
+ // Droppable
69
+ // ============================================================================
59
70
  function Droppable({ ref, children, className, id, disabled = false, ...props }) {
60
71
  const { isOver, setNodeRef } = useDroppable({
61
72
  id,
@@ -64,8 +75,11 @@ function Droppable({ ref, children, className, id, disabled = false, ...props })
64
75
  const content = typeof children === "function"
65
76
  ? children({ isOver, setNodeRef })
66
77
  : children;
67
- return (_jsx("div", { ref: useMergedRef(ref, setNodeRef), className: cn(className), ...props, children: content }));
78
+ return (_jsx("div", { "data-kala-component": "dnd-droppable", ref: useMergedRef(ref, setNodeRef), className: cn(className), ...props, children: content }));
68
79
  }
80
+ // ============================================================================
81
+ // Draggable
82
+ // ============================================================================
69
83
  function Draggable({ ref, children, className, id, disabled = false, ...props }) {
70
84
  const { attributes, listeners, setNodeRef, transform, isDragging } = useDraggable({
71
85
  id,
@@ -79,14 +93,19 @@ function Draggable({ ref, children, className, id, disabled = false, ...props })
79
93
  transform: CSS.Translate.toString(transform),
80
94
  }
81
95
  : undefined;
82
- return (_jsx("div", { ref: useMergedRef(ref, setNodeRef), style: style, className: cn(className), ...attributes, ...listeners, ...props, children: content }));
96
+ return (_jsx("div", { "data-kala-component": "dnd-draggable", ref: useMergedRef(ref, setNodeRef), style: style, className: cn(className), ...attributes, ...listeners, ...props, children: content }));
83
97
  }
98
+ // ============================================================================
99
+ // Sortable Context
100
+ // ============================================================================
84
101
  function SortableContext({ children, items, strategy = verticalListSortingStrategy, }) {
85
102
  const itemIds = React.useMemo(() => items.map((item) => typeof item === "object" && "id" in item ? item.id : item), [items]);
86
- return (_jsx(SortableContextKit, { items: itemIds, strategy: strategy, children: children }));
103
+ return (_jsx(SortableContextKit, { "data-kala-component": "dnd-sortable-context", items: itemIds, strategy: strategy, children: children }));
87
104
  }
88
105
  const SortableHandleContext = React.createContext(null);
89
- function SortableItem({ ref, children, className, id, disabled = false, handle = false, ...props }) {
106
+ function SortableItem({ ref, children, className, id, disabled = false, handle = false, slotStyles: slotStylesRaw, ...props }) {
107
+ const slotStyles = useSlotStyles("dnd", slotStylesRaw);
108
+ const itemRoot = applySlot(cn(className), slotStyles?.root);
90
109
  const { attributes, listeners, setNodeRef, setActivatorNodeRef, transform, transition, isDragging, isSorting, isOver, } = useSortable({
91
110
  id,
92
111
  disabled,
@@ -108,19 +127,28 @@ function SortableItem({ ref, children, className, id, disabled = false, handle =
108
127
  transition,
109
128
  zIndex: isDragging ? 9999 : undefined,
110
129
  };
111
- return (_jsx(SortableHandleContext.Provider, { value: { attributes, listeners, setActivatorNodeRef }, children: _jsx("div", { ref: useMergedRef(ref, setNodeRef), style: style, className: cn(className), ...attributes, ...(handle ? {} : listeners), ...props, children: content }) }));
130
+ return (_jsx(SortableHandleContext.Provider, { value: { attributes, listeners, setActivatorNodeRef }, children: _jsx("div", { "data-kala-component": "dnd-sortable-item", ref: useMergedRef(ref, setNodeRef), style: style, className: itemRoot.className, ...attributes, ...(handle ? {} : listeners), ...props, children: content }) }));
112
131
  }
132
+ // ============================================================================
133
+ // Sortable Handle
134
+ // ============================================================================
113
135
  function SortableHandle({ ref, children, className, ...props }) {
114
136
  const sortable = React.useContext(SortableHandleContext);
115
137
  if (!sortable && process.env.NODE_ENV !== "production") {
116
138
  console.warn("SortableHandle must be rendered inside a SortableItem to receive drag listeners.");
117
139
  }
118
140
  const content = typeof children === "function" ? children(sortable?.listeners) : children;
119
- return (_jsx("div", { ref: useMergedRef(ref, sortable?.setActivatorNodeRef), className: cn("cursor-grab active:cursor-grabbing", className), ...(sortable?.attributes ?? {}), ...(sortable?.listeners ?? {}), ...props, children: content }));
141
+ return (_jsx("div", { "data-kala-component": "dnd-sortable-handle", ref: useMergedRef(ref, sortable?.setActivatorNodeRef), className: cn("cursor-grab active:cursor-grabbing", className), ...(sortable?.attributes ?? {}), ...(sortable?.listeners ?? {}), ...props, children: content }));
120
142
  }
143
+ // ============================================================================
144
+ // Drag Overlay Component
145
+ // ============================================================================
121
146
  function DragOverlayComponent({ children, className, dropAnimation, ...props }) {
122
- return (_jsx(DragOverlay, { dropAnimation: dropAnimation, ...props, children: children ? _jsx("div", { className: cn(className), children: children }) : null }));
147
+ return (_jsx(DragOverlay, { "data-kala-component": "dnd-drag-overlay-component", dropAnimation: dropAnimation, ...props, children: children ? _jsx("div", { className: cn(className), children: children }) : null }));
123
148
  }
149
+ // ============================================================================
150
+ // Exports
151
+ // ============================================================================
124
152
  export { createDragDropSensors as useDragDropSensors, DragDropContext, Draggable, DragOverlayComponent, Droppable,
125
153
  // Re-export sensors
126
154
  KeyboardSensor, PointerSensor, SortableContext, SortableHandle, SortableItem, sortableKeyboardCoordinates, TouchSensor,
@@ -0,0 +1,92 @@
1
+ /**
2
+ * DnD family types — the Kala-named surface over @dnd-kit plus the wrapper
3
+ * component prop shapes. Kept free of runtime code so it doubles as the
4
+ * @dnd-kit type re-export point for the family barrel.
5
+ */
6
+ import type { Active, Collision, CollisionDetection, DndContextProps as DndKitContextProps, DragEndEvent, DraggableAttributes, DraggableSyntheticListeners, DragOverEvent, DragStartEvent, Modifier, Over, PointerActivationConstraint, UniqueIdentifier, useSensors } from "@dnd-kit/core";
7
+ import type { sortableKeyboardCoordinates, SortingStrategy } from "@dnd-kit/sortable";
8
+ import type { Transform } from "@dnd-kit/utilities";
9
+ import type { SlotStyles } from "@kala-ui/react/lib/slot-styles";
10
+ import type * as React from "react";
11
+ export type SyntheticListenerMap = DraggableSyntheticListeners;
12
+ export type DragDropModifier = Modifier;
13
+ export type DragDropCollisionDetection = CollisionDetection;
14
+ export type DragDropSortingStrategy = SortingStrategy;
15
+ export type DragDropPointerConstraint = PointerActivationConstraint;
16
+ export interface UseDragDropSensorsOptions {
17
+ activationConstraint?: PointerActivationConstraint;
18
+ keyboardCoordinateGetter?: typeof sortableKeyboardCoordinates;
19
+ }
20
+ export interface DragDropContextProps extends Omit<DndKitContextProps, "sensors"> {
21
+ children: React.ReactNode;
22
+ sensors?: ReturnType<typeof useSensors>;
23
+ useSensors?: UseDragDropSensorsOptions;
24
+ }
25
+ export interface DroppableProps {
26
+ ref?: React.Ref<HTMLDivElement>;
27
+ id: UniqueIdentifier;
28
+ children: React.ReactNode | ((args: {
29
+ isOver: boolean;
30
+ setNodeRef: (node: HTMLElement | null) => void;
31
+ }) => React.ReactNode);
32
+ className?: string;
33
+ disabled?: boolean;
34
+ }
35
+ export interface DraggableProps {
36
+ ref?: React.Ref<HTMLDivElement>;
37
+ id: UniqueIdentifier;
38
+ children: React.ReactNode | ((args: {
39
+ attributes: DraggableAttributes;
40
+ listeners: SyntheticListenerMap | undefined;
41
+ setNodeRef: (node: HTMLElement | null) => void;
42
+ transform: {
43
+ x: number;
44
+ y: number;
45
+ scaleX: number;
46
+ scaleY: number;
47
+ } | null;
48
+ isDragging: boolean;
49
+ }) => React.ReactNode);
50
+ className?: string;
51
+ disabled?: boolean;
52
+ }
53
+ export interface SortableContextProps {
54
+ id?: UniqueIdentifier;
55
+ items: UniqueIdentifier[] | {
56
+ id: UniqueIdentifier;
57
+ }[];
58
+ strategy?: SortingStrategy;
59
+ children: React.ReactNode;
60
+ }
61
+ export interface SortableItemProps {
62
+ ref?: React.Ref<HTMLDivElement>;
63
+ id: UniqueIdentifier;
64
+ children: React.ReactNode | ((args: {
65
+ attributes: DraggableAttributes;
66
+ listeners: SyntheticListenerMap | undefined;
67
+ setNodeRef: (node: HTMLElement | null) => void;
68
+ transform: Transform | null;
69
+ transition: string | undefined;
70
+ isDragging: boolean;
71
+ isSorting: boolean;
72
+ isOver: boolean;
73
+ }) => React.ReactNode);
74
+ className?: string;
75
+ disabled?: boolean;
76
+ handle?: boolean;
77
+ slotStyles?: SlotStyles;
78
+ }
79
+ export interface SortableHandleProps {
80
+ ref?: React.Ref<HTMLDivElement>;
81
+ children: React.ReactNode | ((listeners: SyntheticListenerMap | undefined) => React.ReactNode);
82
+ className?: string;
83
+ }
84
+ export interface DragOverlayComponentProps {
85
+ children: React.ReactNode;
86
+ className?: string;
87
+ dropAnimation?: {
88
+ duration?: number;
89
+ easing?: string;
90
+ } | null;
91
+ }
92
+ export type { Active, Collision, DragEndEvent as DropResult, DraggableAttributes, DraggableSyntheticListeners, DragOverEvent as DragUpdate, DragOverEvent, DragStartEvent as DragStart, Over, SortingStrategy, Transform, UniqueIdentifier, };
@@ -0,0 +1,7 @@
1
+ "use client";
2
+ /**
3
+ * DnD family types — the Kala-named surface over @dnd-kit plus the wrapper
4
+ * component prop shapes. Kept free of runtime code so it doubles as the
5
+ * @dnd-kit type re-export point for the family barrel.
6
+ */
7
+ export {};
@@ -1 +1,2 @@
1
- export { DragDropContext, type DragDropContextProps, Draggable, type DraggableAttributes, type DraggableProps, type DragStart, type DragUpdate, Droppable, type DroppableProps, type DropResult, type UniqueIdentifier, } from "./dnd";
1
+ export { DragDropContext, Draggable, Droppable } from "./dnd";
2
+ export type { DragDropContextProps, DraggableAttributes, DraggableProps, DragStart, DragUpdate, DroppableProps, DropResult, UniqueIdentifier, } from "./dnd.types";
@@ -1,2 +1,2 @@
1
1
  "use client";
2
- export { DragDropContext, Draggable, Droppable, } from "./dnd.js";
2
+ export { DragDropContext, Draggable, Droppable } from "./dnd.js";