@djangocfg/widget-data 0.1.1

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 (157) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +55 -0
  3. package/package.json +122 -0
  4. package/src/DataGrid/README.md +48 -0
  5. package/src/DataGrid/context/DataGridContext.tsx +442 -0
  6. package/src/DataGrid/context/index.ts +4 -0
  7. package/src/DataGrid/index.ts +34 -0
  8. package/src/DataGrid/lazy.tsx +23 -0
  9. package/src/DataGrid/parts/DataGrid.tsx +125 -0
  10. package/src/DataGrid/parts/DataGridCell.tsx +30 -0
  11. package/src/DataGrid/parts/DataGridHeader.tsx +111 -0
  12. package/src/DataGrid/parts/DataGridPagination.tsx +105 -0
  13. package/src/DataGrid/parts/DataGridRow.tsx +84 -0
  14. package/src/DataGrid/parts/index.ts +7 -0
  15. package/src/DataGrid/types.ts +95 -0
  16. package/src/DataTable/README.md +42 -0
  17. package/src/DataTable/context/DataTableContext.tsx +434 -0
  18. package/src/DataTable/context/index.ts +4 -0
  19. package/src/DataTable/index.ts +33 -0
  20. package/src/DataTable/lazy.tsx +23 -0
  21. package/src/DataTable/parts/DataTable.tsx +142 -0
  22. package/src/DataTable/parts/DataTableHeader.tsx +103 -0
  23. package/src/DataTable/parts/DataTablePagination.tsx +115 -0
  24. package/src/DataTable/parts/DataTableRow.tsx +96 -0
  25. package/src/DataTable/parts/index.ts +6 -0
  26. package/src/DataTable/types.ts +88 -0
  27. package/src/FileIcon/FileIcon.tsx +87 -0
  28. package/src/FileIcon/get-file-icon.ts +73 -0
  29. package/src/FileIcon/icons/icon-data.ts +399 -0
  30. package/src/FileIcon/index.ts +19 -0
  31. package/src/FileIcon/loader.ts +29 -0
  32. package/src/FileIcon/specialFolders.ts +110 -0
  33. package/src/FileIcon/treeAdapter.tsx +49 -0
  34. package/src/JsonTree/JsonViewer.tsx +720 -0
  35. package/src/JsonTree/README.md +142 -0
  36. package/src/JsonTree/index.tsx +11 -0
  37. package/src/JsonTree/lazy.tsx +22 -0
  38. package/src/JsonTree/types.ts +91 -0
  39. package/src/Kanban/context/KanbanContext.tsx +165 -0
  40. package/src/Kanban/context/index.ts +4 -0
  41. package/src/Kanban/index.ts +31 -0
  42. package/src/Kanban/lazy.tsx +23 -0
  43. package/src/Kanban/parts/Kanban.tsx +77 -0
  44. package/src/Kanban/parts/KanbanCard.tsx +76 -0
  45. package/src/Kanban/parts/KanbanColumn.tsx +79 -0
  46. package/src/Kanban/parts/KanbanDragOverlay.tsx +46 -0
  47. package/src/Kanban/parts/index.ts +6 -0
  48. package/src/Kanban/types.ts +45 -0
  49. package/src/Listbox/context/ListboxProvider.tsx +616 -0
  50. package/src/Listbox/context/index.ts +8 -0
  51. package/src/Listbox/index.ts +28 -0
  52. package/src/Listbox/lazy.tsx +31 -0
  53. package/src/Listbox/parts/ListboxGroup.tsx +71 -0
  54. package/src/Listbox/parts/ListboxItem.tsx +151 -0
  55. package/src/Listbox/parts/index.ts +12 -0
  56. package/src/Listbox/types.ts +98 -0
  57. package/src/Masonry/README.md +79 -0
  58. package/src/Masonry/context/MasonryProvider.tsx +1205 -0
  59. package/src/Masonry/context/index.ts +8 -0
  60. package/src/Masonry/index.ts +18 -0
  61. package/src/Masonry/lazy.tsx +20 -0
  62. package/src/Masonry/parts/index.ts +2 -0
  63. package/src/Masonry/types.ts +44 -0
  64. package/src/Timeline/context/TimelineProvider.tsx +474 -0
  65. package/src/Timeline/context/index.ts +16 -0
  66. package/src/Timeline/index.ts +29 -0
  67. package/src/Timeline/lazy.tsx +27 -0
  68. package/src/Timeline/parts/index.ts +2 -0
  69. package/src/Timeline/types.ts +25 -0
  70. package/src/Tree/FinderTree.tsx +42 -0
  71. package/src/Tree/README.md +542 -0
  72. package/src/Tree/TreeDndProvider.tsx +137 -0
  73. package/src/Tree/TreeRoot.tsx +290 -0
  74. package/src/Tree/components/TreeChevron.tsx +48 -0
  75. package/src/Tree/components/TreeContent.tsx +70 -0
  76. package/src/Tree/components/TreeDropIndicator.tsx +65 -0
  77. package/src/Tree/components/TreeEmpty.tsx +22 -0
  78. package/src/Tree/components/TreeEmptyArea.tsx +160 -0
  79. package/src/Tree/components/TreeError.tsx +24 -0
  80. package/src/Tree/components/TreeIcon.tsx +39 -0
  81. package/src/Tree/components/TreeIndentGuides.tsx +33 -0
  82. package/src/Tree/components/TreeLabel.tsx +39 -0
  83. package/src/Tree/components/TreeRenameInput.tsx +114 -0
  84. package/src/Tree/components/TreeRow.tsx +300 -0
  85. package/src/Tree/components/TreeSearchInput.tsx +50 -0
  86. package/src/Tree/components/TreeSkeleton.tsx +22 -0
  87. package/src/Tree/components/index.ts +28 -0
  88. package/src/Tree/context/TreeContext.tsx +409 -0
  89. package/src/Tree/context/TreeContextValue.ts +139 -0
  90. package/src/Tree/context/async-children/collect-ids.ts +27 -0
  91. package/src/Tree/context/async-children/index.ts +8 -0
  92. package/src/Tree/context/async-children/use-async-children.ts +157 -0
  93. package/src/Tree/context/clipboard/index.ts +4 -0
  94. package/src/Tree/context/clipboard/use-clipboard.ts +115 -0
  95. package/src/Tree/context/dnd/index.ts +8 -0
  96. package/src/Tree/context/dnd/use-dnd.ts +194 -0
  97. package/src/Tree/context/expansion/index.ts +4 -0
  98. package/src/Tree/context/expansion/use-expansion.ts +55 -0
  99. package/src/Tree/context/hooks.ts +177 -0
  100. package/src/Tree/context/index.ts +16 -0
  101. package/src/Tree/context/menu/builtin-actions.ts +358 -0
  102. package/src/Tree/context/menu/index.ts +11 -0
  103. package/src/Tree/context/menu/render.tsx +104 -0
  104. package/src/Tree/context/menu/use-resolved-menu.ts +141 -0
  105. package/src/Tree/context/persist/index.ts +4 -0
  106. package/src/Tree/context/persist/use-persist-sync.ts +74 -0
  107. package/src/Tree/context/rename/index.ts +4 -0
  108. package/src/Tree/context/rename/use-rename.ts +113 -0
  109. package/src/Tree/context/selection/index.ts +4 -0
  110. package/src/Tree/context/selection/use-selection.ts +146 -0
  111. package/src/Tree/context/state/index.ts +6 -0
  112. package/src/Tree/context/state/initial.ts +41 -0
  113. package/src/Tree/context/state/reducer.ts +76 -0
  114. package/src/Tree/context/state/types.ts +46 -0
  115. package/src/Tree/data/appearance.ts +237 -0
  116. package/src/Tree/data/childCache.ts +43 -0
  117. package/src/Tree/data/clipboard.ts +33 -0
  118. package/src/Tree/data/createDemoTree.ts +42 -0
  119. package/src/Tree/data/dnd.ts +123 -0
  120. package/src/Tree/data/finderShortcuts.ts +67 -0
  121. package/src/Tree/data/flatten.ts +66 -0
  122. package/src/Tree/data/index.ts +45 -0
  123. package/src/Tree/data/persist.ts +62 -0
  124. package/src/Tree/data/renameUtils.ts +51 -0
  125. package/src/Tree/data/selection.ts +161 -0
  126. package/src/Tree/hooks/finder-hotkeys/build-ctx.ts +48 -0
  127. package/src/Tree/hooks/finder-hotkeys/index.ts +8 -0
  128. package/src/Tree/hooks/finder-hotkeys/use-tree-finder-hotkeys.ts +166 -0
  129. package/src/Tree/hooks/index.ts +25 -0
  130. package/src/Tree/hooks/keyboard/activation.ts +27 -0
  131. package/src/Tree/hooks/keyboard/arrow-nav.ts +26 -0
  132. package/src/Tree/hooks/keyboard/expand-collapse.ts +54 -0
  133. package/src/Tree/hooks/keyboard/index.ts +10 -0
  134. package/src/Tree/hooks/keyboard/types.ts +39 -0
  135. package/src/Tree/hooks/keyboard/use-tree-keyboard.ts +196 -0
  136. package/src/Tree/hooks/type-ahead/index.ts +5 -0
  137. package/src/Tree/hooks/type-ahead/match-prefix.ts +42 -0
  138. package/src/Tree/hooks/type-ahead/use-tree-type-ahead.ts +89 -0
  139. package/src/Tree/index.tsx +135 -0
  140. package/src/Tree/lazy.tsx +14 -0
  141. package/src/Tree/types/activation.ts +30 -0
  142. package/src/Tree/types/adapter.ts +70 -0
  143. package/src/Tree/types/index.ts +27 -0
  144. package/src/Tree/types/labels.ts +97 -0
  145. package/src/Tree/types/loader.ts +9 -0
  146. package/src/Tree/types/node.ts +38 -0
  147. package/src/Tree/types/root-props.ts +158 -0
  148. package/src/Tree/types/selection.ts +3 -0
  149. package/src/Tree/types/slots.ts +64 -0
  150. package/src/index.ts +21 -0
  151. package/src/stories/_fixtures/categories.ts +51 -0
  152. package/src/stories/_fixtures/finder-store.ts +196 -0
  153. package/src/stories/_fixtures/fs.ts +83 -0
  154. package/src/stories/_fixtures/index.ts +5 -0
  155. package/src/stories/_fixtures/org.ts +46 -0
  156. package/src/stories/_fixtures/status.ts +21 -0
  157. package/src/styles/index.css +10 -0
@@ -0,0 +1,79 @@
1
+ 'use client';
2
+
3
+ import * as React from 'react';
4
+ import { cn } from '@djangocfg/ui-core/lib';
5
+ import { ScrollArea } from '@djangocfg/ui-core/components';
6
+
7
+ import type { KanbanColumn as KanbanColumnType } from '../types';
8
+ import { useKanbanContext } from '../context/KanbanContext';
9
+ import { KanbanCard } from './KanbanCard';
10
+
11
+ interface KanbanColumnProps {
12
+ column: KanbanColumnType;
13
+ }
14
+
15
+ export function KanbanColumn({ column }: KanbanColumnProps) {
16
+ const { renderColumnHeader, emptyColumnMessage, dragState, setDragState, moveCard, reorderCard } =
17
+ useKanbanContext();
18
+
19
+ const handlePointerEnter = React.useCallback(() => {
20
+ if (dragState.activeCardId && dragState.activeColumnId !== column.id) {
21
+ setDragState((prev) => ({ ...prev, overColumnId: column.id }));
22
+ }
23
+ }, [dragState.activeCardId, dragState.activeColumnId, column.id, setDragState]);
24
+
25
+ const handlePointerUp = React.useCallback(() => {
26
+ if (
27
+ dragState.activeCardId &&
28
+ dragState.activeColumnId &&
29
+ dragState.overColumnId === column.id &&
30
+ dragState.activeColumnId !== column.id
31
+ ) {
32
+ const toIndex = column.cards.length;
33
+ moveCard(dragState.activeCardId, dragState.activeColumnId, column.id, toIndex);
34
+ }
35
+ setDragState({
36
+ activeCardId: null,
37
+ activeColumnId: null,
38
+ overColumnId: null,
39
+ overCardId: null,
40
+ });
41
+ }, [dragState, column.id, column.cards.length, moveCard, setDragState]);
42
+
43
+ const isOver = dragState.overColumnId === column.id && dragState.activeColumnId !== column.id;
44
+
45
+ return (
46
+ <div
47
+ data-slot="kanban-column"
48
+ data-column-id={column.id}
49
+ data-over={isOver ? '' : undefined}
50
+ className={cn(
51
+ 'flex w-72 shrink-0 flex-col rounded-sm border border-border bg-muted/30',
52
+ isOver && 'ring-2 ring-ring/50'
53
+ )}
54
+ onPointerEnter={handlePointerEnter}
55
+ onPointerUp={handlePointerUp}
56
+ >
57
+ <div className="border-b border-border bg-muted/50 px-3 py-2">
58
+ {renderColumnHeader ? (
59
+ renderColumnHeader(column)
60
+ ) : (
61
+ <h3 className="text-sm font-semibold text-foreground">{column.title}</h3>
62
+ )}
63
+ <span className="text-xs text-muted-foreground">{column.cards.length} cards</span>
64
+ </div>
65
+ <ScrollArea className="min-h-0 flex-1" viewportClassName="p-2">
66
+ <div className="flex flex-col gap-2">
67
+ {column.cards.length === 0 ? (
68
+ <div className="py-4 text-center text-sm text-muted-foreground">{emptyColumnMessage}</div>
69
+ ) : (
70
+ column.cards.map((card, index) => (
71
+ <KanbanCard key={card.id} card={card} columnId={column.id} index={index} />
72
+ ))
73
+ )}
74
+ </div>
75
+ </ScrollArea>
76
+ </div>
77
+ );
78
+ }
79
+ KanbanColumn.displayName = 'KanbanColumn';
@@ -0,0 +1,46 @@
1
+ 'use client';
2
+
3
+ import * as React from 'react';
4
+ import { cn } from '@djangocfg/ui-core/lib';
5
+
6
+ import { useKanbanContext } from '../context/KanbanContext';
7
+
8
+ export function KanbanDragOverlay() {
9
+ const { dragState, columns, renderCard } = useKanbanContext();
10
+
11
+ if (!dragState.activeCardId || !dragState.activeColumnId) return null;
12
+
13
+ const column = columns.find((c) => c.id === dragState.activeColumnId);
14
+ const card = column?.cards.find((c) => c.id === dragState.activeCardId);
15
+
16
+ if (!card) return null;
17
+
18
+ return (
19
+ <div
20
+ data-slot="kanban-drag-overlay"
21
+ className={cn(
22
+ 'pointer-events-none fixed z-[100] rounded-sm border border-border bg-background p-3 shadow-lg',
23
+ 'opacity-90'
24
+ )}
25
+ style={{
26
+ // Positioned via pointer events in a real implementation;
27
+ // this is a static overlay that follows the cursor via CSS
28
+ // In a production app, you'd track pointer position in state
29
+ left: 'var(--kanban-drag-x, 50%)',
30
+ top: 'var(--kanban-drag-y, 50%)',
31
+ }}
32
+ >
33
+ {renderCard ? (
34
+ renderCard(card, dragState.activeColumnId)
35
+ ) : (
36
+ <>
37
+ <h4 className="text-sm font-medium text-foreground">{card.title}</h4>
38
+ {card.description && (
39
+ <p className="mt-1 text-xs text-muted-foreground">{card.description}</p>
40
+ )}
41
+ </>
42
+ )}
43
+ </div>
44
+ );
45
+ }
46
+ KanbanDragOverlay.displayName = 'KanbanDragOverlay';
@@ -0,0 +1,6 @@
1
+ 'use client';
2
+
3
+ export { Kanban } from './Kanban';
4
+ export { KanbanColumn } from './KanbanColumn';
5
+ export { KanbanCard } from './KanbanCard';
6
+ export { KanbanDragOverlay } from './KanbanDragOverlay';
@@ -0,0 +1,45 @@
1
+ 'use client';
2
+
3
+ import type { ReactNode } from 'react';
4
+
5
+ export type KanbanCardId = string;
6
+ export type KanbanColumnId = string;
7
+
8
+ export interface KanbanCard {
9
+ id: KanbanCardId;
10
+ title: ReactNode;
11
+ description?: ReactNode;
12
+ /** Extra metadata for custom rendering */
13
+ meta?: Record<string, unknown>;
14
+ }
15
+
16
+ export interface KanbanColumn {
17
+ id: KanbanColumnId;
18
+ title: ReactNode;
19
+ cards: KanbanCard[];
20
+ }
21
+
22
+ export interface KanbanDragState {
23
+ activeCardId: KanbanCardId | null;
24
+ activeColumnId: KanbanColumnId | null;
25
+ overColumnId: KanbanColumnId | null;
26
+ overCardId: KanbanCardId | null;
27
+ }
28
+
29
+ export interface KanbanProps {
30
+ columns: KanbanColumn[];
31
+ /** Called when a card is moved to a different column */
32
+ onMoveCard?: (cardId: KanbanCardId, fromColumnId: KanbanColumnId, toColumnId: KanbanColumnId, toIndex: number) => void;
33
+ /** Called when a card is reordered within the same column */
34
+ onReorderCard?: (columnId: KanbanColumnId, cardId: KanbanCardId, toIndex: number) => void;
35
+ /** Custom card renderer */
36
+ renderCard?: (card: KanbanCard, columnId: KanbanColumnId) => ReactNode;
37
+ /** Custom column header renderer */
38
+ renderColumnHeader?: (column: KanbanColumn) => ReactNode;
39
+ /** Loading state */
40
+ loading?: boolean;
41
+ /** Empty column message */
42
+ emptyColumnMessage?: ReactNode;
43
+ className?: string;
44
+ style?: React.CSSProperties;
45
+ }