@ram_28/kf-ai-sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +840 -0
  3. package/dist/api/client.d.ts +78 -0
  4. package/dist/api/client.d.ts.map +1 -0
  5. package/dist/api/datetime.d.ts +21 -0
  6. package/dist/api/datetime.d.ts.map +1 -0
  7. package/dist/api/index.d.ts +7 -0
  8. package/dist/api/index.d.ts.map +1 -0
  9. package/dist/api/metadata.d.ts +75 -0
  10. package/dist/api/metadata.d.ts.map +1 -0
  11. package/dist/components/hooks/index.d.ts +8 -0
  12. package/dist/components/hooks/index.d.ts.map +1 -0
  13. package/dist/components/hooks/useFilter/index.d.ts +5 -0
  14. package/dist/components/hooks/useFilter/index.d.ts.map +1 -0
  15. package/dist/components/hooks/useFilter/payloadBuilder.utils.d.ts +33 -0
  16. package/dist/components/hooks/useFilter/payloadBuilder.utils.d.ts.map +1 -0
  17. package/dist/components/hooks/useFilter/types.d.ts +137 -0
  18. package/dist/components/hooks/useFilter/types.d.ts.map +1 -0
  19. package/dist/components/hooks/useFilter/useFilter.d.ts +3 -0
  20. package/dist/components/hooks/useFilter/useFilter.d.ts.map +1 -0
  21. package/dist/components/hooks/useFilter/validation.utils.d.ts +38 -0
  22. package/dist/components/hooks/useFilter/validation.utils.d.ts.map +1 -0
  23. package/dist/components/hooks/useForm/apiClient.d.ts +71 -0
  24. package/dist/components/hooks/useForm/apiClient.d.ts.map +1 -0
  25. package/dist/components/hooks/useForm/expressionValidator.utils.d.ts +28 -0
  26. package/dist/components/hooks/useForm/expressionValidator.utils.d.ts.map +1 -0
  27. package/dist/components/hooks/useForm/index.d.ts +6 -0
  28. package/dist/components/hooks/useForm/index.d.ts.map +1 -0
  29. package/dist/components/hooks/useForm/optimizedExpressionValidator.utils.d.ts +88 -0
  30. package/dist/components/hooks/useForm/optimizedExpressionValidator.utils.d.ts.map +1 -0
  31. package/dist/components/hooks/useForm/ruleClassifier.utils.d.ts +28 -0
  32. package/dist/components/hooks/useForm/ruleClassifier.utils.d.ts.map +1 -0
  33. package/dist/components/hooks/useForm/schemaParser.utils.d.ts +29 -0
  34. package/dist/components/hooks/useForm/schemaParser.utils.d.ts.map +1 -0
  35. package/dist/components/hooks/useForm/types.d.ts +412 -0
  36. package/dist/components/hooks/useForm/types.d.ts.map +1 -0
  37. package/dist/components/hooks/useForm/useForm.d.ts +3 -0
  38. package/dist/components/hooks/useForm/useForm.d.ts.map +1 -0
  39. package/dist/components/hooks/useKanban/apiClient.d.ts +99 -0
  40. package/dist/components/hooks/useKanban/apiClient.d.ts.map +1 -0
  41. package/dist/components/hooks/useKanban/context.d.ts +4 -0
  42. package/dist/components/hooks/useKanban/context.d.ts.map +1 -0
  43. package/dist/components/hooks/useKanban/dragDropManager.d.ts +27 -0
  44. package/dist/components/hooks/useKanban/dragDropManager.d.ts.map +1 -0
  45. package/dist/components/hooks/useKanban/index.d.ts +6 -0
  46. package/dist/components/hooks/useKanban/index.d.ts.map +1 -0
  47. package/dist/components/hooks/useKanban/types.d.ts +438 -0
  48. package/dist/components/hooks/useKanban/types.d.ts.map +1 -0
  49. package/dist/components/hooks/useKanban/useKanban.d.ts +3 -0
  50. package/dist/components/hooks/useKanban/useKanban.d.ts.map +1 -0
  51. package/dist/components/hooks/useKanban/useKanbanSimple.d.ts +62 -0
  52. package/dist/components/hooks/useKanban/useKanbanSimple.d.ts.map +1 -0
  53. package/dist/components/hooks/useTable/index.d.ts +3 -0
  54. package/dist/components/hooks/useTable/index.d.ts.map +1 -0
  55. package/dist/components/hooks/useTable/types.d.ts +107 -0
  56. package/dist/components/hooks/useTable/types.d.ts.map +1 -0
  57. package/dist/components/hooks/useTable/useTable.d.ts +8 -0
  58. package/dist/components/hooks/useTable/useTable.d.ts.map +1 -0
  59. package/dist/components/index.d.ts +3 -0
  60. package/dist/components/index.d.ts.map +1 -0
  61. package/dist/components/ui/index.d.ts +2 -0
  62. package/dist/components/ui/index.d.ts.map +1 -0
  63. package/dist/components/ui/kanban/Kanban.d.ts +12 -0
  64. package/dist/components/ui/kanban/Kanban.d.ts.map +1 -0
  65. package/dist/components/ui/kanban/index.d.ts +2 -0
  66. package/dist/components/ui/kanban/index.d.ts.map +1 -0
  67. package/dist/index.cjs +45 -0
  68. package/dist/index.d.ts +5 -0
  69. package/dist/index.d.ts.map +1 -0
  70. package/dist/index.mjs +6522 -0
  71. package/dist/types/base-fields.d.ts +182 -0
  72. package/dist/types/base-fields.d.ts.map +1 -0
  73. package/dist/types/common.d.ts +238 -0
  74. package/dist/types/common.d.ts.map +1 -0
  75. package/dist/types/index.d.ts +3 -0
  76. package/dist/types/index.d.ts.map +1 -0
  77. package/dist/utils/cn.d.ts +7 -0
  78. package/dist/utils/cn.d.ts.map +1 -0
  79. package/dist/utils/formatting.d.ts +52 -0
  80. package/dist/utils/formatting.d.ts.map +1 -0
  81. package/dist/utils/index.d.ts +3 -0
  82. package/dist/utils/index.d.ts.map +1 -0
  83. package/package.json +98 -0
  84. package/sdk/api/client.ts +447 -0
  85. package/sdk/api/datetime.ts +33 -0
  86. package/sdk/api/index.ts +61 -0
  87. package/sdk/api/metadata.ts +148 -0
  88. package/sdk/components/hooks/index.ts +34 -0
  89. package/sdk/components/hooks/useFilter/index.ts +37 -0
  90. package/sdk/components/hooks/useFilter/payloadBuilder.utils.ts +298 -0
  91. package/sdk/components/hooks/useFilter/types.ts +158 -0
  92. package/sdk/components/hooks/useFilter/useFilter.llm.txt +497 -0
  93. package/sdk/components/hooks/useFilter/useFilter.ts +494 -0
  94. package/sdk/components/hooks/useFilter/validation.utils.ts +401 -0
  95. package/sdk/components/hooks/useForm/apiClient.ts +441 -0
  96. package/sdk/components/hooks/useForm/expressionValidator.utils.ts +444 -0
  97. package/sdk/components/hooks/useForm/index.ts +64 -0
  98. package/sdk/components/hooks/useForm/optimizedExpressionValidator.utils.ts +482 -0
  99. package/sdk/components/hooks/useForm/ruleClassifier.utils.ts +424 -0
  100. package/sdk/components/hooks/useForm/schemaParser.utils.ts +519 -0
  101. package/sdk/components/hooks/useForm/types.ts +630 -0
  102. package/sdk/components/hooks/useForm/useForm.llm.txt +340 -0
  103. package/sdk/components/hooks/useForm/useForm.ts +821 -0
  104. package/sdk/components/hooks/useKanban/apiClient.ts +494 -0
  105. package/sdk/components/hooks/useKanban/context.ts +14 -0
  106. package/sdk/components/hooks/useKanban/dragDropManager.ts +529 -0
  107. package/sdk/components/hooks/useKanban/index.ts +63 -0
  108. package/sdk/components/hooks/useKanban/types.ts +606 -0
  109. package/sdk/components/hooks/useKanban/useKanban.llm.txt +482 -0
  110. package/sdk/components/hooks/useKanban/useKanban.ts +725 -0
  111. package/sdk/components/hooks/useKanban/useKanbanSimple.ts +389 -0
  112. package/sdk/components/hooks/useTable/index.ts +5 -0
  113. package/sdk/components/hooks/useTable/types.ts +154 -0
  114. package/sdk/components/hooks/useTable/useTable.llm.txt +344 -0
  115. package/sdk/components/hooks/useTable/useTable.ts +413 -0
  116. package/sdk/components/index.ts +15 -0
  117. package/sdk/components/ui/index.ts +2 -0
  118. package/sdk/components/ui/kanban/Kanban.tsx +134 -0
  119. package/sdk/components/ui/kanban/index.ts +11 -0
  120. package/sdk/index.ts +13 -0
  121. package/sdk/types/base-fields.ts +221 -0
  122. package/sdk/types/common.ts +306 -0
  123. package/sdk/types/index.ts +5 -0
  124. package/sdk/utils/cn.ts +10 -0
  125. package/sdk/utils/formatting.ts +212 -0
  126. package/sdk/utils/index.ts +5 -0
@@ -0,0 +1,413 @@
1
+ import { useState, useMemo, useCallback } from "react";
2
+ import { useQuery } from "@tanstack/react-query";
3
+ import { api } from "../../../api";
4
+ import type { ListResponse, ListOptions } from "../../../types/common";
5
+ import { useFilter } from "../useFilter";
6
+ import type { UseTableOptions, UseTableReturn } from "./types";
7
+
8
+ // ============================================================
9
+ // INTERNAL STATE TYPES
10
+ // ============================================================
11
+
12
+ interface SearchState {
13
+ query: string;
14
+ }
15
+
16
+ interface SortingState<T> {
17
+ field: keyof T | null;
18
+ direction: "asc" | "desc" | null;
19
+ }
20
+
21
+ interface FilteringState {
22
+ global: string;
23
+ }
24
+
25
+ interface PaginationState {
26
+ pageNo: number; // 1-indexed page number
27
+ pageSize: number;
28
+ }
29
+
30
+ // ============================================================
31
+ // FIELD TYPE DETECTION
32
+ // ============================================================
33
+
34
+ /**
35
+ * Detect field type for auto-formatting
36
+ * This will be enhanced with actual type introspection in the future
37
+ * Currently unused but kept for future auto-formatting implementation
38
+ */
39
+ // function _detectFieldType<T>(fieldId: keyof T): string {
40
+ // const fieldName = String(fieldId);
41
+ //
42
+ // // Basic pattern matching - will be replaced with actual type introspection
43
+ // if (fieldName.includes('price') || fieldName.includes('cost') || fieldName.includes('amount')) {
44
+ // return 'currency';
45
+ // }
46
+ // if (fieldName.includes('date') || fieldName.includes('At') || fieldName === 'created' || fieldName === 'updated') {
47
+ // return 'datetime';
48
+ // }
49
+ // if (fieldName.includes('stock') || fieldName.includes('quantity') || fieldName.includes('count')) {
50
+ // return 'number';
51
+ // }
52
+ // if (fieldName.includes('status') || fieldName.includes('type') || fieldName.includes('category')) {
53
+ // return 'string';
54
+ // }
55
+ //
56
+ // return 'string'; // default
57
+ // }
58
+
59
+ // ============================================================
60
+ // MAIN HOOK
61
+ // ============================================================
62
+
63
+ export function useTable<T = any>(
64
+ options: UseTableOptions<T>
65
+ ): UseTableReturn<T> {
66
+ // ============================================================
67
+ // STATE MANAGEMENT
68
+ // ============================================================
69
+
70
+ const [search, setSearch] = useState<SearchState>({
71
+ query: "",
72
+ });
73
+
74
+ const [sorting, setSorting] = useState<SortingState<T>>({
75
+ field: options.initialState?.sorting?.field || null,
76
+ direction: options.initialState?.sorting?.direction || null,
77
+ });
78
+
79
+ const [filtering, setFiltering] = useState<FilteringState>({
80
+ global: options.initialState?.globalFilter || "",
81
+ });
82
+
83
+ const [pagination, setPagination] = useState<PaginationState>({
84
+ pageNo: options.initialState?.pagination?.pageNo || 1, // Start at page 1
85
+ pageSize: options.initialState?.pagination?.pageSize || 10,
86
+ });
87
+
88
+ // ============================================================
89
+ // FILTER HOOK INTEGRATION
90
+ // ============================================================
91
+
92
+ const filterHook = useFilter<T>({
93
+ initialConditions: options.initialState?.filters,
94
+ initialLogicalOperator: options.initialState?.filterOperator || "And",
95
+ fieldDefinitions: options.fieldDefinitions,
96
+ validateOnChange: true,
97
+ onValidationError: options.onFilterError,
98
+ onConditionAdd: () => {
99
+ // Reset to first page when adding filters
100
+ setPagination((prev) => ({ ...prev, pageNo: 1 }));
101
+ },
102
+ onConditionUpdate: () => {
103
+ // Reset to first page when updating filters
104
+ setPagination((prev) => ({ ...prev, pageNo: 1 }));
105
+ },
106
+ onConditionRemove: () => {
107
+ // Reset to first page when removing filters
108
+ setPagination((prev) => ({ ...prev, pageNo: 1 }));
109
+ },
110
+ });
111
+
112
+ // ============================================================
113
+ // API OPTIONS BUILDER
114
+ // ============================================================
115
+
116
+ // Options for count query - excludes sorting and pagination (they don't affect count)
117
+ const countApiOptions = useMemo((): ListOptions => {
118
+ const opts: ListOptions = {};
119
+
120
+ // Add search query (affects count)
121
+ if (search.query) {
122
+ opts.Search = search.query;
123
+ }
124
+
125
+ // Add filter conditions (affects count)
126
+ if (filterHook.filterPayload) {
127
+ opts.Filter = filterHook.filterPayload;
128
+ }
129
+
130
+ return opts;
131
+ }, [search.query, filterHook.filterPayload]);
132
+
133
+ // Options for list query - includes all options
134
+ const apiOptions = useMemo((): ListOptions => {
135
+ const opts: ListOptions = { ...countApiOptions };
136
+
137
+ // Add sorting - using correct API format: [{ "fieldName": "ASC" }]
138
+ if (sorting.field && sorting.direction) {
139
+ opts.Sort = [
140
+ {
141
+ [String(sorting.field)]: sorting.direction === "asc" ? "ASC" : "DESC",
142
+ },
143
+ ];
144
+ }
145
+
146
+ // Add pagination
147
+ if (options.enablePagination) {
148
+ opts.Page = pagination.pageNo; // Already 1-indexed
149
+ opts.PageSize = pagination.pageSize;
150
+ }
151
+
152
+ return opts;
153
+ }, [countApiOptions, sorting, pagination, options.enablePagination]);
154
+
155
+ // ============================================================
156
+ // DATA FETCHING
157
+ // ============================================================
158
+
159
+ const {
160
+ data,
161
+ isLoading,
162
+ isFetching,
163
+ error,
164
+ refetch: queryRefetch,
165
+ } = useQuery({
166
+ queryKey: ["table", options.source, apiOptions],
167
+ queryFn: async (): Promise<ListResponse<T>> => {
168
+ try {
169
+ const response = await api<T>(options.source).list(apiOptions);
170
+ if (options.onSuccess) {
171
+ options.onSuccess(response.Data);
172
+ }
173
+ return response;
174
+ } catch (err) {
175
+ if (options.onError) {
176
+ options.onError(err as Error);
177
+ }
178
+ throw err;
179
+ }
180
+ },
181
+ staleTime: 0,
182
+ gcTime: 0,
183
+ });
184
+
185
+ // Count query for accurate total items (only depends on filters/search, not sorting/pagination)
186
+ const {
187
+ data: countData,
188
+ isLoading: isCountLoading,
189
+ isFetching: isCountFetching,
190
+ error: countError,
191
+ refetch: countRefetch,
192
+ } = useQuery({
193
+ queryKey: ["table-count", options.source, countApiOptions],
194
+ queryFn: async () => {
195
+ try {
196
+ return await api<T>(options.source).count(countApiOptions);
197
+ } catch (err) {
198
+ if (options.onError) {
199
+ options.onError(err as Error);
200
+ }
201
+ throw err;
202
+ }
203
+ },
204
+ staleTime: 0,
205
+ gcTime: 0,
206
+ });
207
+
208
+ // ============================================================
209
+ // COMPUTED VALUES
210
+ // ============================================================
211
+
212
+ const rows = useMemo(() => data?.Data || [], [data]);
213
+ const totalItems = useMemo(() => countData?.Count || 0, [countData]);
214
+
215
+ const totalPages = useMemo(() => {
216
+ return Math.ceil(totalItems / pagination.pageSize);
217
+ }, [totalItems, pagination.pageSize]);
218
+
219
+ // ============================================================
220
+ // SORTING OPERATIONS
221
+ // ============================================================
222
+
223
+ const toggleSort = useCallback((field: keyof T) => {
224
+ setSorting((prev) => {
225
+ if (prev.field === field) {
226
+ // Same field - toggle direction or clear
227
+ if (prev.direction === "asc") {
228
+ return { field, direction: "desc" };
229
+ } else if (prev.direction === "desc") {
230
+ return { field: null, direction: null };
231
+ }
232
+ }
233
+ // New field or no current sort
234
+ return { field, direction: "asc" };
235
+ });
236
+ }, []);
237
+
238
+ const clearSort = useCallback(() => {
239
+ setSorting({ field: null, direction: null });
240
+ }, []);
241
+
242
+ const setSort = useCallback(
243
+ (field: keyof T | null, direction: "asc" | "desc" | null) => {
244
+ setSorting({ field, direction });
245
+ },
246
+ []
247
+ );
248
+
249
+ // ============================================================
250
+ // SEARCH OPERATIONS
251
+ // ============================================================
252
+
253
+ const setSearchQuery = useCallback((value: string) => {
254
+ setSearch({ query: value });
255
+ // Reset to first page when searching
256
+ setPagination((prev) => ({ ...prev, pageNo: 1 }));
257
+ }, []);
258
+
259
+ const clearSearch = useCallback(() => {
260
+ setSearch({ query: "" });
261
+ }, []);
262
+
263
+ // ============================================================
264
+ // FILTERING OPERATIONS
265
+ // ============================================================
266
+
267
+ const setGlobalFilter = useCallback((value: string) => {
268
+ setFiltering((prev) => ({ ...prev, global: value }));
269
+ // Reset to first page when filtering
270
+ setPagination((prev) => ({ ...prev, pageNo: 1 }));
271
+ }, []);
272
+
273
+ const clearFilter = useCallback(() => {
274
+ setFiltering({ global: "" });
275
+ }, []);
276
+
277
+ // ============================================================
278
+ // PAGINATION OPERATIONS
279
+ // ============================================================
280
+
281
+ const canGoNext = pagination.pageNo < totalPages;
282
+ const canGoPrevious = pagination.pageNo > 1;
283
+
284
+ const goToNext = useCallback(() => {
285
+ if (canGoNext) {
286
+ setPagination((prev) => ({ ...prev, pageNo: prev.pageNo + 1 }));
287
+ }
288
+ }, [canGoNext]);
289
+
290
+ const goToPrevious = useCallback(() => {
291
+ if (canGoPrevious) {
292
+ setPagination((prev) => ({ ...prev, pageNo: prev.pageNo - 1 }));
293
+ }
294
+ }, [canGoPrevious]);
295
+
296
+ const goToPage = useCallback(
297
+ (page: number) => {
298
+ const pageNo = Math.max(1, Math.min(page, totalPages)); // Clamp between 1 and totalPages
299
+ setPagination((prev) => ({ ...prev, pageNo }));
300
+ },
301
+ [totalPages]
302
+ );
303
+
304
+ const setPageSize = useCallback((size: number) => {
305
+ setPagination((prev) => ({
306
+ ...prev,
307
+ pageSize: size,
308
+ pageNo: 1, // Reset to first page
309
+ }));
310
+ }, []);
311
+
312
+ // ============================================================
313
+ // REFETCH OPERATION
314
+ // ============================================================
315
+
316
+ const refetch = useCallback(async (): Promise<ListResponse<T>> => {
317
+ const [listResult] = await Promise.all([queryRefetch(), countRefetch()]);
318
+ return listResult.data || { Data: [] };
319
+ }, [queryRefetch, countRefetch]);
320
+
321
+ // ============================================================
322
+ // RETURN OBJECT
323
+ // ============================================================
324
+
325
+ return {
326
+ // Data
327
+ rows,
328
+ totalItems,
329
+
330
+ // Loading States
331
+ isLoading: isLoading || isCountLoading,
332
+ isFetching: isFetching || isCountFetching,
333
+
334
+ // Error Handling
335
+ error: (error || countError) as Error | null,
336
+
337
+ // Search (Flat Access)
338
+ search: {
339
+ query: search.query,
340
+ setQuery: setSearchQuery,
341
+ clear: clearSearch,
342
+ },
343
+
344
+ // Sorting (Flat Access)
345
+ sort: {
346
+ field: sorting.field,
347
+ direction: sorting.direction,
348
+ toggle: toggleSort,
349
+ clear: clearSort,
350
+ set: setSort,
351
+ },
352
+
353
+ // Legacy Global Filtering (Flat Access)
354
+ globalFilter: {
355
+ value: filtering.global,
356
+ setValue: setGlobalFilter,
357
+ clear: clearFilter,
358
+ },
359
+
360
+ // Advanced Filtering (Filter Conditions)
361
+ filter: {
362
+ // State
363
+ conditions: filterHook.conditions,
364
+ logicalOperator: filterHook.logicalOperator,
365
+ isValid: filterHook.isValid,
366
+ validationErrors: filterHook.validationErrors,
367
+ hasConditions: filterHook.hasConditions,
368
+
369
+ // Condition Management
370
+ addCondition: filterHook.addCondition,
371
+ updateCondition: filterHook.updateCondition,
372
+ removeCondition: filterHook.removeCondition,
373
+ clearConditions: filterHook.clearConditions,
374
+ getCondition: filterHook.getCondition,
375
+
376
+ // Logical Operator
377
+ setLogicalOperator: filterHook.setLogicalOperator,
378
+
379
+ // Bulk Operations
380
+ setConditions: filterHook.setConditions,
381
+ replaceCondition: filterHook.replaceCondition,
382
+
383
+ // Validation
384
+ validateCondition: filterHook.validateCondition,
385
+ validateAllConditions: filterHook.validateAllConditions,
386
+
387
+ // State Management
388
+ exportState: filterHook.exportState,
389
+ importState: filterHook.importState,
390
+ resetToInitial: filterHook.resetToInitial,
391
+
392
+ // Utilities
393
+ getConditionCount: filterHook.getConditionCount,
394
+ },
395
+
396
+ // Pagination (Flat Access)
397
+ pagination: {
398
+ currentPage: pagination.pageNo, // Already 1-indexed
399
+ pageSize: pagination.pageSize,
400
+ totalPages,
401
+ totalItems,
402
+ canGoNext,
403
+ canGoPrevious,
404
+ goToNext,
405
+ goToPrevious,
406
+ goToPage,
407
+ setPageSize,
408
+ },
409
+
410
+ // Operations
411
+ refetch,
412
+ };
413
+ }
@@ -0,0 +1,15 @@
1
+ // Hooks
2
+ export * from "./hooks";
3
+
4
+ // UI Components (explicit exports to avoid naming conflicts with types)
5
+ export {
6
+ Kanban,
7
+ KanbanColumn,
8
+ KanbanColumnHeader,
9
+ KanbanColumnTitle,
10
+ KanbanColumnContent,
11
+ KanbanCard,
12
+ KanbanCardTitle,
13
+ KanbanCardDescription,
14
+ KanbanColumnFooter,
15
+ } from "./ui";
@@ -0,0 +1,2 @@
1
+ // Kanban UI components
2
+ export * from "./kanban";
@@ -0,0 +1,134 @@
1
+ import * as React from "react";
2
+ import { cn } from "../../../utils";
3
+
4
+ // Simple styled wrapper components following the Table pattern
5
+ // No complex logic - just styling and basic structure
6
+
7
+ const Kanban = React.forwardRef<
8
+ HTMLDivElement,
9
+ React.HTMLAttributes<HTMLDivElement>
10
+ >(({ className, ...props }, ref) => (
11
+ <div
12
+ ref={ref}
13
+ className={cn(
14
+ "flex h-full flex-grow items-start gap-x-4 overflow-x-auto py-2",
15
+ className
16
+ )}
17
+ {...props}
18
+ />
19
+ ));
20
+ Kanban.displayName = "Kanban";
21
+
22
+ const KanbanColumn = React.forwardRef<
23
+ HTMLDivElement,
24
+ React.HTMLAttributes<HTMLDivElement>
25
+ >(({ className, ...props }, ref) => (
26
+ <div
27
+ ref={ref}
28
+ className={cn(
29
+ "flex h-full min-w-[300px] flex-col rounded-lg border bg-gray-50 p-3",
30
+ className
31
+ )}
32
+ {...props}
33
+ />
34
+ ));
35
+ KanbanColumn.displayName = "KanbanColumn";
36
+
37
+ const KanbanColumnHeader = React.forwardRef<
38
+ HTMLDivElement,
39
+ React.HTMLAttributes<HTMLDivElement>
40
+ >(({ className, ...props }, ref) => (
41
+ <div
42
+ ref={ref}
43
+ className={cn("mb-3 flex items-center justify-between", className)}
44
+ {...props}
45
+ />
46
+ ));
47
+ KanbanColumnHeader.displayName = "KanbanColumnHeader";
48
+
49
+ const KanbanColumnTitle = React.forwardRef<
50
+ HTMLHeadingElement,
51
+ React.HTMLAttributes<HTMLHeadingElement>
52
+ >(({ className, ...props }, ref) => (
53
+ <h3
54
+ ref={ref}
55
+ className={cn("text-sm font-semibold text-gray-700", className)}
56
+ {...props}
57
+ />
58
+ ));
59
+ KanbanColumnTitle.displayName = "KanbanColumnTitle";
60
+
61
+ const KanbanColumnContent = React.forwardRef<
62
+ HTMLDivElement,
63
+ React.HTMLAttributes<HTMLDivElement>
64
+ >(({ className, ...props }, ref) => (
65
+ <div
66
+ ref={ref}
67
+ className={cn("flex-1 space-y-2 overflow-y-auto", className)}
68
+ {...props}
69
+ />
70
+ ));
71
+ KanbanColumnContent.displayName = "KanbanColumnContent";
72
+
73
+ const KanbanCard = React.forwardRef<
74
+ HTMLDivElement,
75
+ React.HTMLAttributes<HTMLDivElement>
76
+ >(({ className, ...props }, ref) => (
77
+ <div
78
+ ref={ref}
79
+ className={cn(
80
+ "rounded-lg border border-gray-200 bg-white p-3 shadow-sm hover:shadow-md transition-shadow cursor-move",
81
+ className
82
+ )}
83
+ {...props}
84
+ />
85
+ ));
86
+ KanbanCard.displayName = "KanbanCard";
87
+
88
+ const KanbanCardTitle = React.forwardRef<
89
+ HTMLDivElement,
90
+ React.HTMLAttributes<HTMLDivElement>
91
+ >(({ className, ...props }, ref) => (
92
+ <div
93
+ ref={ref}
94
+ className={cn("font-medium text-gray-900 mb-1", className)}
95
+ {...props}
96
+ />
97
+ ));
98
+ KanbanCardTitle.displayName = "KanbanCardTitle";
99
+
100
+ const KanbanCardDescription = React.forwardRef<
101
+ HTMLDivElement,
102
+ React.HTMLAttributes<HTMLDivElement>
103
+ >(({ className, ...props }, ref) => (
104
+ <div
105
+ ref={ref}
106
+ className={cn("text-sm text-gray-600", className)}
107
+ {...props}
108
+ />
109
+ ));
110
+ KanbanCardDescription.displayName = "KanbanCardDescription";
111
+
112
+ const KanbanColumnFooter = React.forwardRef<
113
+ HTMLDivElement,
114
+ React.HTMLAttributes<HTMLDivElement>
115
+ >(({ className, ...props }, ref) => (
116
+ <div
117
+ ref={ref}
118
+ className={cn("mt-3 pt-3 border-t border-gray-200", className)}
119
+ {...props}
120
+ />
121
+ ));
122
+ KanbanColumnFooter.displayName = "KanbanColumnFooter";
123
+
124
+ export {
125
+ Kanban,
126
+ KanbanColumn,
127
+ KanbanColumnHeader,
128
+ KanbanColumnTitle,
129
+ KanbanColumnContent,
130
+ KanbanCard,
131
+ KanbanCardTitle,
132
+ KanbanCardDescription,
133
+ KanbanColumnFooter,
134
+ };
@@ -0,0 +1,11 @@
1
+ export {
2
+ Kanban,
3
+ KanbanColumn,
4
+ KanbanColumnHeader,
5
+ KanbanColumnTitle,
6
+ KanbanColumnContent,
7
+ KanbanCard,
8
+ KanbanCardTitle,
9
+ KanbanCardDescription,
10
+ KanbanColumnFooter,
11
+ } from "./Kanban";
package/sdk/index.ts ADDED
@@ -0,0 +1,13 @@
1
+ // Core SDK exports
2
+
3
+ // Type system
4
+ export * from './types';
5
+
6
+ // API client
7
+ export * from './api';
8
+
9
+ // Utilities
10
+ export * from './utils';
11
+
12
+ // Components
13
+ export * from './components';