@flanksource/clicky-ui 0.3.45 → 0.3.47
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.
- package/NOTICE.md +11 -0
- package/README.md +22 -0
- package/dist/ai.cjs +13 -8
- package/dist/ai.cjs.map +1 -1
- package/dist/ai.js +7 -2
- package/dist/ai.js.map +1 -1
- package/dist/components/ErrorWrapper.cjs +2 -3
- package/dist/components/ErrorWrapper.cjs.map +1 -1
- package/dist/components/ErrorWrapper.d.ts.map +1 -1
- package/dist/components/ErrorWrapper.js +3 -4
- package/dist/components/ErrorWrapper.js.map +1 -1
- package/dist/data/AccessMark.cjs +23 -0
- package/dist/data/AccessMark.cjs.map +1 -0
- package/dist/data/AccessMark.d.ts +11 -0
- package/dist/data/AccessMark.d.ts.map +1 -0
- package/dist/data/AccessMark.js +23 -0
- package/dist/data/AccessMark.js.map +1 -0
- package/dist/data/Clicky.cjs +3 -0
- package/dist/data/Clicky.cjs.map +1 -1
- package/dist/data/Clicky.js +3 -0
- package/dist/data/Clicky.js.map +1 -1
- package/dist/data/CodeDiff.cjs +116 -23
- package/dist/data/CodeDiff.cjs.map +1 -1
- package/dist/data/CodeDiff.d.ts +26 -0
- package/dist/data/CodeDiff.d.ts.map +1 -1
- package/dist/data/CodeDiff.js +116 -23
- package/dist/data/CodeDiff.js.map +1 -1
- package/dist/data/FilterPill.cjs +15 -2
- package/dist/data/FilterPill.cjs.map +1 -1
- package/dist/data/FilterPill.d.ts +1 -1
- package/dist/data/FilterPill.d.ts.map +1 -1
- package/dist/data/FilterPill.js +15 -2
- package/dist/data/FilterPill.js.map +1 -1
- package/dist/data/GraphDiagram.cjs +65 -13
- package/dist/data/GraphDiagram.cjs.map +1 -1
- package/dist/data/GraphDiagram.d.ts +9 -2
- package/dist/data/GraphDiagram.d.ts.map +1 -1
- package/dist/data/GraphDiagram.js +66 -14
- package/dist/data/GraphDiagram.js.map +1 -1
- package/dist/data/GraphDiagramGroups.cjs +100 -0
- package/dist/data/GraphDiagramGroups.cjs.map +1 -0
- package/dist/data/GraphDiagramGroups.d.ts +24 -0
- package/dist/data/GraphDiagramGroups.d.ts.map +1 -0
- package/dist/data/GraphDiagramGroups.js +100 -0
- package/dist/data/GraphDiagramGroups.js.map +1 -0
- package/dist/data/GraphDiagramNodes.cjs +17 -31
- package/dist/data/GraphDiagramNodes.cjs.map +1 -1
- package/dist/data/GraphDiagramNodes.d.ts +6 -13
- package/dist/data/GraphDiagramNodes.d.ts.map +1 -1
- package/dist/data/GraphDiagramNodes.js +17 -31
- package/dist/data/GraphDiagramNodes.js.map +1 -1
- package/dist/data/LogViewer.cjs +27 -8
- package/dist/data/LogViewer.cjs.map +1 -1
- package/dist/data/LogViewer.d.ts +11 -3
- package/dist/data/LogViewer.d.ts.map +1 -1
- package/dist/data/LogViewer.js +27 -8
- package/dist/data/LogViewer.js.map +1 -1
- package/dist/data/Properties.cjs +2 -15
- package/dist/data/Properties.cjs.map +1 -1
- package/dist/data/Properties.d.ts +4 -0
- package/dist/data/Properties.d.ts.map +1 -1
- package/dist/data/Properties.js +2 -15
- package/dist/data/Properties.js.map +1 -1
- package/dist/data/PropertyValue.cjs +37 -0
- package/dist/data/PropertyValue.cjs.map +1 -0
- package/dist/data/PropertyValue.d.ts +6 -0
- package/dist/data/PropertyValue.d.ts.map +1 -0
- package/dist/data/PropertyValue.js +37 -0
- package/dist/data/PropertyValue.js.map +1 -0
- package/dist/data/Tree.cjs +4 -3
- package/dist/data/Tree.cjs.map +1 -1
- package/dist/data/Tree.d.ts +3 -1
- package/dist/data/Tree.d.ts.map +1 -1
- package/dist/data/Tree.js +4 -3
- package/dist/data/Tree.js.map +1 -1
- package/dist/data/TreeNode.cjs +1 -1
- package/dist/data/TreeNode.cjs.map +1 -1
- package/dist/data/TreeNode.d.ts.map +1 -1
- package/dist/data/TreeNode.js +1 -1
- package/dist/data/TreeNode.js.map +1 -1
- package/dist/data/ai/ChatFab.cjs +1 -1
- package/dist/data/ai/ChatFab.cjs.map +1 -1
- package/dist/data/ai/ChatFab.js +1 -1
- package/dist/data/ai/ChatFab.js.map +1 -1
- package/dist/data/ai/ChatWindow.cjs +106 -171
- package/dist/data/ai/ChatWindow.cjs.map +1 -1
- package/dist/data/ai/ChatWindow.d.ts +6 -2
- package/dist/data/ai/ChatWindow.d.ts.map +1 -1
- package/dist/data/ai/ChatWindow.header.cjs +104 -0
- package/dist/data/ai/ChatWindow.header.cjs.map +1 -0
- package/dist/data/ai/ChatWindow.header.d.ts +29 -0
- package/dist/data/ai/ChatWindow.header.d.ts.map +1 -0
- package/dist/data/ai/ChatWindow.header.js +104 -0
- package/dist/data/ai/ChatWindow.header.js.map +1 -0
- package/dist/data/ai/ChatWindow.js +107 -172
- package/dist/data/ai/ChatWindow.js.map +1 -1
- package/dist/data/ai/ChatWindow.placement.cjs +95 -0
- package/dist/data/ai/ChatWindow.placement.cjs.map +1 -0
- package/dist/data/ai/ChatWindow.placement.d.ts +32 -0
- package/dist/data/ai/ChatWindow.placement.d.ts.map +1 -0
- package/dist/data/ai/ChatWindow.placement.js +95 -0
- package/dist/data/ai/ChatWindow.placement.js.map +1 -0
- package/dist/data/ai/SessionChatComposer.cjs +3 -1
- package/dist/data/ai/SessionChatComposer.cjs.map +1 -1
- package/dist/data/ai/SessionChatComposer.d.ts +4 -1
- package/dist/data/ai/SessionChatComposer.d.ts.map +1 -1
- package/dist/data/ai/SessionChatComposer.js +3 -1
- package/dist/data/ai/SessionChatComposer.js.map +1 -1
- package/dist/data/ai/SessionInspector.cjs +68 -72
- package/dist/data/ai/SessionInspector.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.composer-slot.cjs +8 -0
- package/dist/data/ai/SessionInspector.composer-slot.cjs.map +1 -0
- package/dist/data/ai/SessionInspector.composer-slot.d.ts +9 -0
- package/dist/data/ai/SessionInspector.composer-slot.d.ts.map +1 -0
- package/dist/data/ai/SessionInspector.composer-slot.js +8 -0
- package/dist/data/ai/SessionInspector.composer-slot.js.map +1 -0
- package/dist/data/ai/SessionInspector.d.ts +6 -1
- package/dist/data/ai/SessionInspector.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.js +69 -73
- package/dist/data/ai/SessionInspector.js.map +1 -1
- package/dist/data/ai/SessionInspector.legacy.cjs +41 -42
- package/dist/data/ai/SessionInspector.legacy.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.legacy.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.legacy.js +41 -42
- package/dist/data/ai/SessionInspector.legacy.js.map +1 -1
- package/dist/data/ai/SessionInspector.remote-view.cjs +14 -9
- package/dist/data/ai/SessionInspector.remote-view.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.remote-view.d.ts +6 -2
- package/dist/data/ai/SessionInspector.remote-view.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.remote-view.js +14 -9
- package/dist/data/ai/SessionInspector.remote-view.js.map +1 -1
- package/dist/data/ai/SessionInspector.remote.cjs +84 -16
- package/dist/data/ai/SessionInspector.remote.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.remote.d.ts +42 -7
- package/dist/data/ai/SessionInspector.remote.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.remote.js +86 -18
- package/dist/data/ai/SessionInspector.remote.js.map +1 -1
- package/dist/data/ai/SessionInspector.transcript.cjs +5 -0
- package/dist/data/ai/SessionInspector.transcript.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.transcript.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.transcript.js +5 -0
- package/dist/data/ai/SessionInspector.transcript.js.map +1 -1
- package/dist/data/ai/SessionTail.cjs +63 -0
- package/dist/data/ai/SessionTail.cjs.map +1 -0
- package/dist/data/ai/SessionTail.d.ts +14 -0
- package/dist/data/ai/SessionTail.d.ts.map +1 -0
- package/dist/data/ai/SessionTail.js +63 -0
- package/dist/data/ai/SessionTail.js.map +1 -0
- package/dist/data/ai/SessionViewer.cjs +10 -3
- package/dist/data/ai/SessionViewer.cjs.map +1 -1
- package/dist/data/ai/SessionViewer.d.ts +7 -1
- package/dist/data/ai/SessionViewer.d.ts.map +1 -1
- package/dist/data/ai/SessionViewer.js +10 -3
- package/dist/data/ai/SessionViewer.js.map +1 -1
- package/dist/data/ai/SessionViewer.unified.d.ts +14 -0
- package/dist/data/ai/SessionViewer.unified.d.ts.map +1 -1
- package/dist/data/ai/index.d.ts +4 -3
- package/dist/data/ai/index.d.ts.map +1 -1
- package/dist/data/ai/use-session-scroll.cjs +30 -6
- package/dist/data/ai/use-session-scroll.cjs.map +1 -1
- package/dist/data/ai/use-session-scroll.d.ts +7 -0
- package/dist/data/ai/use-session-scroll.d.ts.map +1 -1
- package/dist/data/ai/use-session-scroll.js +30 -6
- package/dist/data/ai/use-session-scroll.js.map +1 -1
- package/dist/data/call-graph/CallGraph.cjs +50 -31
- package/dist/data/call-graph/CallGraph.cjs.map +1 -1
- package/dist/data/call-graph/CallGraph.d.ts +10 -1
- package/dist/data/call-graph/CallGraph.d.ts.map +1 -1
- package/dist/data/call-graph/CallGraph.js +52 -33
- package/dist/data/call-graph/CallGraph.js.map +1 -1
- package/dist/data/call-graph/CallGraphMembers.cjs +5 -4
- package/dist/data/call-graph/CallGraphMembers.cjs.map +1 -1
- package/dist/data/call-graph/CallGraphMembers.d.ts +1 -1
- package/dist/data/call-graph/CallGraphMembers.d.ts.map +1 -1
- package/dist/data/call-graph/CallGraphMembers.js +5 -4
- package/dist/data/call-graph/CallGraphMembers.js.map +1 -1
- package/dist/data/call-graph/CallGraphToolbar.cjs +17 -5
- package/dist/data/call-graph/CallGraphToolbar.cjs.map +1 -1
- package/dist/data/call-graph/CallGraphToolbar.d.ts +10 -0
- package/dist/data/call-graph/CallGraphToolbar.d.ts.map +1 -1
- package/dist/data/call-graph/CallGraphToolbar.js +18 -6
- package/dist/data/call-graph/CallGraphToolbar.js.map +1 -1
- package/dist/data/call-graph/call-graph-model.cjs +169 -18
- package/dist/data/call-graph/call-graph-model.cjs.map +1 -1
- package/dist/data/call-graph/call-graph-model.d.ts +40 -4
- package/dist/data/call-graph/call-graph-model.d.ts.map +1 -1
- package/dist/data/call-graph/call-graph-model.js +170 -19
- package/dist/data/call-graph/call-graph-model.js.map +1 -1
- package/dist/data/call-graph/call-graph-vocabulary.cjs +19 -1
- package/dist/data/call-graph/call-graph-vocabulary.cjs.map +1 -1
- package/dist/data/call-graph/call-graph-vocabulary.d.ts +4 -0
- package/dist/data/call-graph/call-graph-vocabulary.d.ts.map +1 -1
- package/dist/data/call-graph/call-graph-vocabulary.js +19 -1
- package/dist/data/call-graph/call-graph-vocabulary.js.map +1 -1
- package/dist/data/call-graph/call-graph.fixtures.d.ts.map +1 -1
- package/dist/data/call-graph/index.d.ts +2 -2
- package/dist/data/call-graph/index.d.ts.map +1 -1
- package/dist/data/call-graph/types.cjs.map +1 -1
- package/dist/data/call-graph/types.d.ts +7 -2
- package/dist/data/call-graph/types.d.ts.map +1 -1
- package/dist/data/call-graph/types.js.map +1 -1
- package/dist/data/chat/Chat.cjs +1 -1
- package/dist/data/chat/Chat.cjs.map +1 -1
- package/dist/data/chat/Chat.js +1 -1
- package/dist/data/chat/Chat.js.map +1 -1
- package/dist/data/chat/ChatRuntimeToolbar.cjs +4 -4
- package/dist/data/chat/ChatRuntimeToolbar.cjs.map +1 -1
- package/dist/data/chat/ChatRuntimeToolbar.d.ts.map +1 -1
- package/dist/data/chat/ChatRuntimeToolbar.js +4 -4
- package/dist/data/chat/ChatRuntimeToolbar.js.map +1 -1
- package/dist/data/chat/PromptInput.cjs +4 -2
- package/dist/data/chat/PromptInput.cjs.map +1 -1
- package/dist/data/chat/PromptInput.d.ts +5 -1
- package/dist/data/chat/PromptInput.d.ts.map +1 -1
- package/dist/data/chat/PromptInput.js +4 -2
- package/dist/data/chat/PromptInput.js.map +1 -1
- package/dist/data/data-access.cjs +8 -0
- package/dist/data/data-access.cjs.map +1 -0
- package/dist/data/data-access.d.ts +5 -0
- package/dist/data/data-access.d.ts.map +1 -0
- package/dist/data/data-access.js +8 -0
- package/dist/data/data-access.js.map +1 -0
- package/dist/data/diagnostics/ErrorDetails.cjs +13 -2
- package/dist/data/diagnostics/ErrorDetails.cjs.map +1 -1
- package/dist/data/diagnostics/ErrorDetails.d.ts +3 -1
- package/dist/data/diagnostics/ErrorDetails.d.ts.map +1 -1
- package/dist/data/diagnostics/ErrorDetails.js +14 -3
- package/dist/data/diagnostics/ErrorDetails.js.map +1 -1
- package/dist/data/diagnostics/FrameSourceWindow.cjs +3 -2
- package/dist/data/diagnostics/FrameSourceWindow.cjs.map +1 -1
- package/dist/data/diagnostics/FrameSourceWindow.d.ts.map +1 -1
- package/dist/data/diagnostics/FrameSourceWindow.js +3 -2
- package/dist/data/diagnostics/FrameSourceWindow.js.map +1 -1
- package/dist/data/diagnostics/error-diagnostics.cjs +5 -0
- package/dist/data/diagnostics/error-diagnostics.cjs.map +1 -1
- package/dist/data/diagnostics/error-diagnostics.d.ts +1 -0
- package/dist/data/diagnostics/error-diagnostics.d.ts.map +1 -1
- package/dist/data/diagnostics/error-diagnostics.js +6 -1
- package/dist/data/diagnostics/error-diagnostics.js.map +1 -1
- package/dist/data/git/GitChangeList.cjs +6 -2
- package/dist/data/git/GitChangeList.cjs.map +1 -1
- package/dist/data/git/GitChangeList.d.ts +6 -1
- package/dist/data/git/GitChangeList.d.ts.map +1 -1
- package/dist/data/git/GitChangeList.js +6 -2
- package/dist/data/git/GitChangeList.js.map +1 -1
- package/dist/data/graph-columns-layout.cjs +47 -16
- package/dist/data/graph-columns-layout.cjs.map +1 -1
- package/dist/data/graph-columns-layout.d.ts +34 -0
- package/dist/data/graph-columns-layout.d.ts.map +1 -1
- package/dist/data/graph-columns-layout.js +47 -16
- package/dist/data/graph-columns-layout.js.map +1 -1
- package/dist/data/graph-diagram-model.cjs +5 -0
- package/dist/data/graph-diagram-model.cjs.map +1 -1
- package/dist/data/graph-diagram-model.d.ts +19 -0
- package/dist/data/graph-diagram-model.d.ts.map +1 -1
- package/dist/data/graph-diagram-model.js +5 -0
- package/dist/data/graph-diagram-model.js.map +1 -1
- package/dist/data/graph-group-window.cjs +60 -0
- package/dist/data/graph-group-window.cjs.map +1 -0
- package/dist/data/graph-group-window.d.ts +33 -0
- package/dist/data/graph-group-window.d.ts.map +1 -0
- package/dist/data/graph-group-window.js +60 -0
- package/dist/data/graph-group-window.js.map +1 -0
- package/dist/data/har/HarPanel.cjs +3 -1
- package/dist/data/har/HarPanel.cjs.map +1 -1
- package/dist/data/har/HarPanel.d.ts +4 -1
- package/dist/data/har/HarPanel.d.ts.map +1 -1
- package/dist/data/har/HarPanel.js +3 -1
- package/dist/data/har/HarPanel.js.map +1 -1
- package/dist/data/test-runner/Expectation.cjs +57 -0
- package/dist/data/test-runner/Expectation.cjs.map +1 -0
- package/dist/data/test-runner/Expectation.d.ts +19 -0
- package/dist/data/test-runner/Expectation.d.ts.map +1 -0
- package/dist/data/test-runner/Expectation.js +57 -0
- package/dist/data/test-runner/Expectation.js.map +1 -0
- package/dist/data/test-runner/MarkIcons.cjs +38 -0
- package/dist/data/test-runner/MarkIcons.cjs.map +1 -0
- package/dist/data/test-runner/MarkIcons.d.ts +15 -0
- package/dist/data/test-runner/MarkIcons.d.ts.map +1 -0
- package/dist/data/test-runner/MarkIcons.js +38 -0
- package/dist/data/test-runner/MarkIcons.js.map +1 -0
- package/dist/data/test-runner/TestDetailPanel.cjs +74 -42
- package/dist/data/test-runner/TestDetailPanel.cjs.map +1 -1
- package/dist/data/test-runner/TestDetailPanel.d.ts.map +1 -1
- package/dist/data/test-runner/TestDetailPanel.js +76 -44
- package/dist/data/test-runner/TestDetailPanel.js.map +1 -1
- package/dist/data/test-runner/TestFailureDetail.cjs +23 -27
- package/dist/data/test-runner/TestFailureDetail.cjs.map +1 -1
- package/dist/data/test-runner/TestFailureDetail.d.ts +2 -2
- package/dist/data/test-runner/TestFailureDetail.d.ts.map +1 -1
- package/dist/data/test-runner/TestFailureDetail.js +23 -27
- package/dist/data/test-runner/TestFailureDetail.js.map +1 -1
- package/dist/data/test-runner/TestFilterBar.cjs +87 -93
- package/dist/data/test-runner/TestFilterBar.cjs.map +1 -1
- package/dist/data/test-runner/TestFilterBar.d.ts +3 -2
- package/dist/data/test-runner/TestFilterBar.d.ts.map +1 -1
- package/dist/data/test-runner/TestFilterBar.js +89 -95
- package/dist/data/test-runner/TestFilterBar.js.map +1 -1
- package/dist/data/test-runner/TestRunSummary.cjs +35 -21
- package/dist/data/test-runner/TestRunSummary.cjs.map +1 -1
- package/dist/data/test-runner/TestRunSummary.d.ts.map +1 -1
- package/dist/data/test-runner/TestRunSummary.js +35 -21
- package/dist/data/test-runner/TestRunSummary.js.map +1 -1
- package/dist/data/test-runner/TestRunner.cjs +52 -30
- package/dist/data/test-runner/TestRunner.cjs.map +1 -1
- package/dist/data/test-runner/TestRunner.d.ts +3 -2
- package/dist/data/test-runner/TestRunner.d.ts.map +1 -1
- package/dist/data/test-runner/TestRunner.js +52 -30
- package/dist/data/test-runner/TestRunner.js.map +1 -1
- package/dist/data/test-runner/TestTree.cjs +5 -2
- package/dist/data/test-runner/TestTree.cjs.map +1 -1
- package/dist/data/test-runner/TestTree.d.ts +5 -2
- package/dist/data/test-runner/TestTree.d.ts.map +1 -1
- package/dist/data/test-runner/TestTree.js +5 -2
- package/dist/data/test-runner/TestTree.js.map +1 -1
- package/dist/data/test-runner/TestTreeNode.cjs +27 -19
- package/dist/data/test-runner/TestTreeNode.cjs.map +1 -1
- package/dist/data/test-runner/TestTreeNode.d.ts.map +1 -1
- package/dist/data/test-runner/TestTreeNode.js +28 -20
- package/dist/data/test-runner/TestTreeNode.js.map +1 -1
- package/dist/data/test-runner/adapter.cjs +11 -0
- package/dist/data/test-runner/adapter.cjs.map +1 -1
- package/dist/data/test-runner/adapter.d.ts +18 -7
- package/dist/data/test-runner/adapter.d.ts.map +1 -1
- package/dist/data/test-runner/adapter.js +11 -0
- package/dist/data/test-runner/adapter.js.map +1 -1
- package/dist/data/test-runner/copy.cjs +114 -0
- package/dist/data/test-runner/copy.cjs.map +1 -0
- package/dist/data/test-runner/copy.d.ts +47 -0
- package/dist/data/test-runner/copy.d.ts.map +1 -0
- package/dist/data/test-runner/copy.js +114 -0
- package/dist/data/test-runner/copy.js.map +1 -0
- package/dist/data/test-runner/index.d.ts +5 -2
- package/dist/data/test-runner/index.d.ts.map +1 -1
- package/dist/data/test-runner/marks.cjs +143 -0
- package/dist/data/test-runner/marks.cjs.map +1 -0
- package/dist/data/test-runner/marks.d.ts +30 -0
- package/dist/data/test-runner/marks.d.ts.map +1 -0
- package/dist/data/test-runner/marks.js +143 -0
- package/dist/data/test-runner/marks.js.map +1 -0
- package/dist/data/test-runner/status.cjs +27 -44
- package/dist/data/test-runner/status.cjs.map +1 -1
- package/dist/data/test-runner/status.d.ts +12 -3
- package/dist/data/test-runner/status.d.ts.map +1 -1
- package/dist/data/test-runner/status.js +27 -44
- package/dist/data/test-runner/status.js.map +1 -1
- package/dist/data/use-group-windows.cjs +50 -0
- package/dist/data/use-group-windows.cjs.map +1 -0
- package/dist/data/use-group-windows.d.ts +27 -0
- package/dist/data/use-group-windows.d.ts.map +1 -0
- package/dist/data/use-group-windows.js +50 -0
- package/dist/data/use-group-windows.js.map +1 -0
- package/dist/data/verification/adapterViews.cjs +16 -41
- package/dist/data/verification/adapterViews.cjs.map +1 -1
- package/dist/data/verification/adapterViews.d.ts.map +1 -1
- package/dist/data/verification/adapterViews.js +16 -41
- package/dist/data/verification/adapterViews.js.map +1 -1
- package/dist/data/verification/adapters.cjs +115 -3
- package/dist/data/verification/adapters.cjs.map +1 -1
- package/dist/data/verification/adapters.d.ts.map +1 -1
- package/dist/data/verification/adapters.js +115 -3
- package/dist/data/verification/adapters.js.map +1 -1
- package/dist/data/verification/verifyReportTests.cjs.map +1 -1
- package/dist/data/verification/verifyReportTests.js.map +1 -1
- package/dist/data/version-info.cjs +3 -3
- package/dist/data/version-info.js +3 -3
- package/dist/data.cjs +54 -3
- package/dist/data.cjs.map +1 -1
- package/dist/data.d.ts +6 -2
- package/dist/data.d.ts.map +1 -1
- package/dist/data.js +58 -7
- package/dist/data.js.map +1 -1
- package/dist/hooks/event-hub.cjs +229 -0
- package/dist/hooks/event-hub.cjs.map +1 -0
- package/dist/hooks/event-hub.d.ts +26 -0
- package/dist/hooks/event-hub.d.ts.map +1 -0
- package/dist/hooks/event-hub.js +229 -0
- package/dist/hooks/event-hub.js.map +1 -0
- package/dist/hooks.cjs +2 -0
- package/dist/hooks.cjs.map +1 -1
- package/dist/hooks.d.ts +1 -0
- package/dist/hooks.d.ts.map +1 -1
- package/dist/hooks.js +2 -0
- package/dist/hooks.js.map +1 -1
- package/dist/icons/components/UiLogoEslint.cjs +10 -0
- package/dist/icons/components/UiLogoEslint.cjs.map +1 -0
- package/dist/icons/components/UiLogoEslint.d.ts +9 -0
- package/dist/icons/components/UiLogoEslint.d.ts.map +1 -0
- package/dist/icons/components/UiLogoEslint.js +10 -0
- package/dist/icons/components/UiLogoEslint.js.map +1 -0
- package/dist/icons/components/UiLogoGo.cjs +10 -0
- package/dist/icons/components/UiLogoGo.cjs.map +1 -0
- package/dist/icons/components/UiLogoGo.d.ts +9 -0
- package/dist/icons/components/UiLogoGo.d.ts.map +1 -0
- package/dist/icons/components/UiLogoGo.js +10 -0
- package/dist/icons/components/UiLogoGo.js.map +1 -0
- package/dist/icons/components/UiLogoJest.cjs +10 -0
- package/dist/icons/components/UiLogoJest.cjs.map +1 -0
- package/dist/icons/components/UiLogoJest.d.ts +9 -0
- package/dist/icons/components/UiLogoJest.d.ts.map +1 -0
- package/dist/icons/components/UiLogoJest.js +10 -0
- package/dist/icons/components/UiLogoJest.js.map +1 -0
- package/dist/icons/components/UiLogoMarkdown.cjs +10 -0
- package/dist/icons/components/UiLogoMarkdown.cjs.map +1 -0
- package/dist/icons/components/UiLogoMarkdown.d.ts +9 -0
- package/dist/icons/components/UiLogoMarkdown.d.ts.map +1 -0
- package/dist/icons/components/UiLogoMarkdown.js +10 -0
- package/dist/icons/components/UiLogoMarkdown.js.map +1 -0
- package/dist/icons/components/UiLogoOxc.cjs +10 -0
- package/dist/icons/components/UiLogoOxc.cjs.map +1 -0
- package/dist/icons/components/UiLogoOxc.d.ts +9 -0
- package/dist/icons/components/UiLogoOxc.d.ts.map +1 -0
- package/dist/icons/components/UiLogoOxc.js +10 -0
- package/dist/icons/components/UiLogoOxc.js.map +1 -0
- package/dist/icons/components/UiLogoPlaywright.cjs +10 -0
- package/dist/icons/components/UiLogoPlaywright.cjs.map +1 -0
- package/dist/icons/components/UiLogoPlaywright.d.ts +9 -0
- package/dist/icons/components/UiLogoPlaywright.d.ts.map +1 -0
- package/dist/icons/components/UiLogoPlaywright.js +10 -0
- package/dist/icons/components/UiLogoPlaywright.js.map +1 -0
- package/dist/icons/components/UiLogoPython.cjs +10 -0
- package/dist/icons/components/UiLogoPython.cjs.map +1 -0
- package/dist/icons/components/UiLogoPython.d.ts +9 -0
- package/dist/icons/components/UiLogoPython.d.ts.map +1 -0
- package/dist/icons/components/UiLogoPython.js +10 -0
- package/dist/icons/components/UiLogoPython.js.map +1 -0
- package/dist/icons/components/UiLogoReact.cjs +10 -0
- package/dist/icons/components/UiLogoReact.cjs.map +1 -0
- package/dist/icons/components/UiLogoReact.d.ts +9 -0
- package/dist/icons/components/UiLogoReact.d.ts.map +1 -0
- package/dist/icons/components/UiLogoReact.js +10 -0
- package/dist/icons/components/UiLogoReact.js.map +1 -0
- package/dist/icons/components/UiLogoRuff.cjs +10 -0
- package/dist/icons/components/UiLogoRuff.cjs.map +1 -0
- package/dist/icons/components/UiLogoRuff.d.ts +9 -0
- package/dist/icons/components/UiLogoRuff.d.ts.map +1 -0
- package/dist/icons/components/UiLogoRuff.js +10 -0
- package/dist/icons/components/UiLogoRuff.js.map +1 -0
- package/dist/icons/components/UiLogoTypescript.cjs +10 -0
- package/dist/icons/components/UiLogoTypescript.cjs.map +1 -0
- package/dist/icons/components/UiLogoTypescript.d.ts +9 -0
- package/dist/icons/components/UiLogoTypescript.d.ts.map +1 -0
- package/dist/icons/components/UiLogoTypescript.js +10 -0
- package/dist/icons/components/UiLogoTypescript.js.map +1 -0
- package/dist/icons/components/UiLogoVitest.cjs +10 -0
- package/dist/icons/components/UiLogoVitest.cjs.map +1 -0
- package/dist/icons/components/UiLogoVitest.d.ts +9 -0
- package/dist/icons/components/UiLogoVitest.d.ts.map +1 -0
- package/dist/icons/components/UiLogoVitest.js +10 -0
- package/dist/icons/components/UiLogoVitest.js.map +1 -0
- package/dist/icons/index.d.ts +11 -0
- package/dist/icons/index.d.ts.map +1 -1
- package/dist/icons/registry.cjs +22 -0
- package/dist/icons/registry.cjs.map +1 -1
- package/dist/icons/registry.d.ts.map +1 -1
- package/dist/icons/registry.js +22 -0
- package/dist/icons/registry.js.map +1 -1
- package/dist/icons.cjs +22 -0
- package/dist/icons.cjs.map +1 -1
- package/dist/icons.js +22 -0
- package/dist/icons.js.map +1 -1
- package/dist/index.cjs +56 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +60 -7
- package/dist/index.js.map +1 -1
- package/dist/overlay/DropdownMenuSubmenu.cjs +4 -4
- package/dist/overlay/DropdownMenuSubmenu.cjs.map +1 -1
- package/dist/overlay/DropdownMenuSubmenu.js +4 -4
- package/dist/overlay/DropdownMenuSubmenu.js.map +1 -1
- package/dist/overlay/modalStack.cjs +13 -6
- package/dist/overlay/modalStack.cjs.map +1 -1
- package/dist/overlay/modalStack.d.ts.map +1 -1
- package/dist/overlay/modalStack.js +13 -6
- package/dist/overlay/modalStack.js.map +1 -1
- package/dist/rpc/InlineError.cjs +12 -43
- package/dist/rpc/InlineError.cjs.map +1 -1
- package/dist/rpc/InlineError.d.ts.map +1 -1
- package/dist/rpc/InlineError.js +13 -44
- package/dist/rpc/InlineError.js.map +1 -1
- package/dist/rpc/OperationScheduleDialog.cjs +63 -10
- package/dist/rpc/OperationScheduleDialog.cjs.map +1 -1
- package/dist/rpc/OperationScheduleDialog.d.ts +4 -0
- package/dist/rpc/OperationScheduleDialog.d.ts.map +1 -1
- package/dist/rpc/OperationScheduleDialog.js +63 -10
- package/dist/rpc/OperationScheduleDialog.js.map +1 -1
- package/dist/rpc/OperationSchedules.cjs +12 -2
- package/dist/rpc/OperationSchedules.cjs.map +1 -1
- package/dist/rpc/OperationSchedules.d.ts.map +1 -1
- package/dist/rpc/OperationSchedules.js +12 -2
- package/dist/rpc/OperationSchedules.js.map +1 -1
- package/dist/rpc/operation-schedule-model.cjs +2 -0
- package/dist/rpc/operation-schedule-model.cjs.map +1 -1
- package/dist/rpc/operation-schedule-model.d.ts.map +1 -1
- package/dist/rpc/operation-schedule-model.js +2 -0
- package/dist/rpc/operation-schedule-model.js.map +1 -1
- package/dist/rpc/operation-schedule-types.d.ts +7 -1
- package/dist/rpc/operation-schedule-types.d.ts.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
- package/dist/data/test-runner/frameworkIcon.cjs +0 -27
- package/dist/data/test-runner/frameworkIcon.cjs.map +0 -1
- package/dist/data/test-runner/frameworkIcon.d.ts +0 -3
- package/dist/data/test-runner/frameworkIcon.d.ts.map +0 -1
- package/dist/data/test-runner/frameworkIcon.js +0 -27
- package/dist/data/test-runner/frameworkIcon.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Properties.cjs","sources":["../../src/data/Properties.tsx"],"sourcesContent":["import {\n Fragment,\n useContext,\n useEffect,\n useState,\n type ReactNode,\n} from \"react\";\nimport { IconButton } from \"../components/IconButton\";\nimport {\n UiCheck,\n UiDotsVertical,\n UiListDashes,\n UiListFlat,\n UiRows,\n} from \"../icons\";\nimport { cn } from \"../lib/utils\";\nimport { DropdownMenu } from \"../overlay/DropdownMenu\";\nimport { Icon, type StaticIconComponent } from \"./Icon\";\nimport { formatPropertyLabel } from \"./properties-utils\";\nimport { PropertiesContext } from \"./properties-context\";\n\nexport type PropertiesAction<V = unknown> = {\n /** Stable action id. */\n id: string;\n /** Iconify name or imported icon component. */\n icon: string | StaticIconComponent;\n /** Accessible label and tooltip for this row action. */\n label: (key: string, value: V, item: PropertiesItem<V>) => string;\n /** Return false to hide the action for a specific row. */\n visible?: (key: string, value: V, item: PropertiesItem<V>) => boolean;\n /** Return true to disable the action for a specific row. */\n disabled?: (key: string, value: V, item: PropertiesItem<V>) => boolean;\n /** Called when the row action is clicked. */\n onClick: (key: string, value: V, item: PropertiesItem<V>) => void;\n};\n\nexport type PropertiesItem<V = unknown> = {\n /** Stable property key. Also used as the default label. */\n key: string;\n /** Property value passed to renderers and actions. */\n value: V;\n /** Secondary text shown below the label. */\n subtitle?: ReactNode;\n /** Hide this row without removing it from the item array. */\n hidden?: boolean;\n /** Enables a child area spanning both columns, with nested labels indented. */\n expandable?: boolean;\n /** Controlled expanded state. */\n expanded?: boolean;\n /** Called when an expandable row is toggled. */\n onToggle?: (next: boolean) => void;\n /** Child content rendered when the row is expanded. */\n renderChildren?: () => ReactNode;\n};\n\nexport type PropertiesDensity = \"comfortable\" | \"compact\" | \"spacious\";\n\nexport type PropertiesProps<V = unknown> = {\n /** Property rows to render. Hidden items are filtered out. */\n items: PropertiesItem<V>[];\n /** Custom label renderer. */\n renderLabel?: (key: string, value: V, item: PropertiesItem<V>) => ReactNode;\n /** Custom value renderer. */\n renderValue?: (key: string, value: V, item: PropertiesItem<V>) => ReactNode;\n /** Static icon name or function that returns an icon name per row. */\n labelIcon?:\n | string\n | ((key: string, value: V, item: PropertiesItem<V>) => string | undefined);\n /** Actions rendered before the value. */\n prefixActions?: PropertiesAction<V>[];\n /** Actions rendered after the value. */\n suffixActions?: PropertiesAction<V>[];\n /** Classes applied to the list root. */\n className?: string;\n /** Classes applied to each row. */\n rowClassName?: string;\n /** CSS grid columns applied to each row. Defaults to the selected density preset. */\n gridTemplateColumns?: string;\n /** Classes applied to each label cell. */\n labelClassName?: string;\n /** Classes applied to each value cell. */\n valueClassName?: string;\n /** Row density preset. */\n density?: PropertiesDensity;\n /** Stable reference used to persist this instance's density preference. */\n keyRef?: string;\n /** Show the display-options menu. */\n showDensityMenu?: boolean;\n /** Empty-state content when no rows are visible. */\n emptyMessage?: ReactNode;\n};\n\nconst PROPERTIES_DENSITY_STORAGE_PREFIX = \"clicky-ui-properties\";\n\nconst PROPERTIES_DENSITY_OPTIONS: Array<{\n value: PropertiesDensity;\n label: string;\n icon: StaticIconComponent;\n}> = [\n { value: \"compact\", label: \"Compact\", icon: UiRows },\n { value: \"comfortable\", label: \"Comfortable\", icon: UiListFlat },\n { value: \"spacious\", label: \"Spacious\", icon: UiListDashes },\n];\n\nconst DENSITY_CLASSES: Record<\n PropertiesDensity,\n { row: string; label: string; value: string; gridTemplateColumns: string }\n> = {\n spacious: {\n row: \"px-density-4 py-density-3\",\n label: \"text-sm font-medium text-muted-foreground\",\n value: \"text-base text-foreground\",\n gridTemplateColumns: \"minmax(12rem, 20rem) minmax(0, 1fr)\",\n },\n comfortable: {\n row: \"px-density-3 py-density-2\",\n label: \"text-xs font-medium text-muted-foreground\",\n value: \"text-sm text-foreground\",\n gridTemplateColumns: \"minmax(7rem, 12rem) minmax(0, 1fr)\",\n },\n compact: {\n row: \"px-density-2 py-density-1.5\",\n label: \"font-mono text-[11px] text-muted-foreground\",\n value: \"text-xs text-foreground\",\n gridTemplateColumns: \"minmax(8rem, 14rem) minmax(0, 1fr)\",\n },\n};\n\nexport function Properties<V = unknown>({\n items,\n renderLabel,\n renderValue,\n labelIcon,\n prefixActions,\n suffixActions,\n className,\n rowClassName,\n gridTemplateColumns,\n labelClassName,\n valueClassName,\n density = \"comfortable\",\n keyRef,\n showDensityMenu = true,\n emptyMessage = \"No properties\",\n}: PropertiesProps<V>) {\n const parent = useContext(PropertiesContext);\n const [densityOverride, setDensityOverride] = useState<PropertiesDensity>();\n useEffect(() => setDensityOverride(readStoredDensity(keyRef)), [keyRef]);\n\n const visible = items.filter((item) => !item.hidden);\n\n if (visible.length === 0) {\n return <div className=\"text-sm text-muted-foreground\">{emptyMessage}</div>;\n }\n\n const activeDensity = parent?.density ?? densityOverride ?? density;\n const styles = DENSITY_CLASSES[activeDensity];\n const columns =\n parent?.columns ?? gridTemplateColumns ?? styles.gridTemplateColumns;\n const depth = parent?.depth ?? 0;\n\n const updateDensity = (next: PropertiesDensity) => {\n setDensityOverride(next);\n writeStoredDensity(keyRef, next);\n };\n\n return (\n <dl\n className={cn(\n \"grid gap-x-density-3 divide-y divide-border rounded-md border border-border bg-muted/20\",\n parent && \"col-span-full rounded-none border-0 bg-transparent\",\n className,\n )}\n style={{ gridTemplateColumns: parent ? \"subgrid\" : columns }}\n >\n {showDensityMenu && !parent ? (\n <div className=\"col-span-full flex items-center justify-end px-density-2 py-density-1\">\n <dt className=\"sr-only\">Properties display options</dt>\n <dd>\n <PropertiesDensityMenu\n density={activeDensity}\n onChange={updateDensity}\n />\n </dd>\n </div>\n ) : null}\n {visible.map((item) => {\n const iconName =\n typeof labelIcon === \"function\"\n ? labelIcon(item.key, item.value, item)\n : labelIcon;\n const renderedLabel = renderLabel\n ? renderLabel(item.key, item.value, item)\n : formatPropertyLabel(item.key);\n const ariaLabel =\n typeof renderedLabel === \"string\" ? renderedLabel : item.key;\n\n return (\n <Fragment key={item.key}>\n <div\n className={cn(\n \"col-span-full grid min-w-0 grid-cols-subgrid gap-density-3\",\n styles.row,\n rowClassName,\n )}\n >\n <dt\n aria-label={ariaLabel}\n className={cn(\"min-w-0 truncate\", styles.label, labelClassName)}\n style={{ paddingInlineStart: depth * 16 }}\n >\n <div className=\"flex min-w-0 items-center gap-density-1\">\n {iconName ? (\n <Icon name={iconName} className=\"text-xs shrink-0\" />\n ) : null}\n <span className=\"min-w-0 truncate\">{renderedLabel}</span>\n </div>\n {item.subtitle ? (\n <div className=\"mt-0.5 text-[10px] font-normal text-muted-foreground/80\">\n {item.subtitle}\n </div>\n ) : null}\n </dt>\n <dd className={cn(\"min-w-0 space-y-density-1\", valueClassName)}>\n <div className=\"flex min-w-0 items-start gap-density-1\">\n <ActionList\n actions={prefixActions}\n item={item}\n className=\"shrink-0 pt-0.5\"\n />\n <div\n className={cn(\"min-w-0 max-w-full flex-1\", styles.value)}\n >\n {renderValue\n ? renderValue(item.key, item.value, item)\n : defaultRenderValue(item.value)}\n </div>\n <ActionList\n actions={suffixActions}\n item={item}\n className=\"shrink-0 pt-0.5\"\n />\n </div>\n </dd>\n </div>\n {item.expandable && item.expanded && item.renderChildren ? (\n <div className=\"col-span-full grid grid-cols-subgrid\">\n <dt className=\"sr-only\">{ariaLabel} properties</dt>\n <dd className=\"col-span-full grid min-w-0 grid-cols-subgrid\">\n <PropertiesContext.Provider\n value={{\n depth: depth + 1,\n columns,\n density: activeDensity,\n }}\n >\n {item.renderChildren()}\n </PropertiesContext.Provider>\n </dd>\n </div>\n ) : null}\n </Fragment>\n );\n })}\n </dl>\n );\n}\n\nfunction PropertiesDensityMenu({\n density,\n onChange,\n}: {\n density: PropertiesDensity;\n onChange: (density: PropertiesDensity) => void;\n}) {\n return (\n <DropdownMenu\n align=\"right\"\n menuLabel=\"Properties options\"\n trigger={\n <IconButton\n icon={UiDotsVertical}\n label=\"Properties options\"\n className=\"h-6 w-6\"\n />\n }\n >\n {(closeMenu) => (\n <div className=\"min-w-44 py-1 text-popover-foreground\">\n <div className=\"px-2 py-1 text-xs font-medium text-muted-foreground\">\n Density\n </div>\n {PROPERTIES_DENSITY_OPTIONS.map((option) => {\n const active = density === option.value;\n return (\n <button\n key={option.value}\n type=\"button\"\n role=\"menuitemradio\"\n aria-checked={active}\n className={densityMenuItemClassName(active)}\n onClick={() => {\n onChange(option.value);\n closeMenu();\n }}\n >\n <Icon\n icon={option.icon}\n className=\"text-sm text-muted-foreground\"\n />\n <span className=\"min-w-0 flex-1 truncate\">{option.label}</span>\n {active ? (\n <Icon icon={UiCheck} className=\"text-sm text-foreground\" />\n ) : (\n <span className=\"inline-block h-4 w-4\" aria-hidden />\n )}\n </button>\n );\n })}\n </div>\n )}\n </DropdownMenu>\n );\n}\n\nfunction densityMenuItemClassName(active: boolean): string {\n return cn(\n \"flex w-full items-center gap-2 px-2 py-1.5 text-left text-sm\",\n \"hover:bg-accent focus:bg-accent focus:outline-none\",\n active && \"bg-accent/60\",\n );\n}\n\nfunction readStoredDensity(\n keyRef: string | undefined,\n): PropertiesDensity | undefined {\n const storageKey = propertiesDensityStorageKey(keyRef);\n if (!storageKey || typeof window === \"undefined\") return undefined;\n\n try {\n const value = window.localStorage.getItem(storageKey);\n return isPropertiesDensity(value) ? value : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction writeStoredDensity(\n keyRef: string | undefined,\n density: PropertiesDensity,\n): void {\n const storageKey = propertiesDensityStorageKey(keyRef);\n if (!storageKey || typeof window === \"undefined\") return;\n\n try {\n window.localStorage.setItem(storageKey, density);\n } catch {\n // Display preferences are best-effort when browser storage is unavailable.\n }\n}\n\nfunction propertiesDensityStorageKey(\n keyRef: string | undefined,\n): string | undefined {\n const normalized = keyRef?.trim();\n return normalized\n ? `${PROPERTIES_DENSITY_STORAGE_PREFIX}:${normalized}:density`\n : undefined;\n}\n\nfunction isPropertiesDensity(value: unknown): value is PropertiesDensity {\n return value === \"compact\" || value === \"comfortable\" || value === \"spacious\";\n}\n\nfunction ActionList<V>({\n actions,\n item,\n className,\n}: {\n actions: PropertiesAction<V>[] | undefined;\n item: PropertiesItem<V>;\n className?: string;\n}) {\n if (!actions || actions.length === 0) return null;\n const rendered = actions.filter(\n (action) => !action.visible || action.visible(item.key, item.value, item),\n );\n if (rendered.length === 0) return null;\n return (\n <span className={cn(\"inline-flex items-center\", className)}>\n {rendered.map((action) => (\n <PropertiesActionButton key={action.id} action={action} item={item} />\n ))}\n </span>\n );\n}\n\nfunction PropertiesActionButton<V>({\n action,\n item,\n}: {\n action: PropertiesAction<V>;\n item: PropertiesItem<V>;\n}) {\n const label = action.label(item.key, item.value, item);\n const disabled = action.disabled?.(item.key, item.value, item) ?? false;\n return (\n <button\n type=\"button\"\n aria-label={label}\n title={label}\n disabled={disabled}\n className={cn(\n \"inline-flex h-5 w-5 items-center justify-center rounded text-muted-foreground\",\n \"hover:bg-accent hover:text-foreground\",\n \"disabled:opacity-35 disabled:hover:bg-transparent disabled:hover:text-muted-foreground\",\n )}\n onClick={(event) => {\n event.stopPropagation();\n action.onClick(item.key, item.value, item);\n }}\n >\n <Icon\n {...(typeof action.icon === \"string\"\n ? { name: action.icon }\n : { icon: action.icon })}\n className=\"text-xs\"\n />\n </button>\n );\n}\n\nfunction defaultRenderValue(value: unknown): ReactNode {\n if (value === null || value === undefined) {\n return <span className=\"font-mono italic text-muted-foreground\">null</span>;\n }\n if (typeof value === \"string\") return value;\n if (typeof value === \"number\" || typeof value === \"boolean\") {\n return <span className=\"font-mono\">{String(value)}</span>;\n }\n try {\n return (\n <pre className=\"max-h-48 overflow-auto whitespace-pre-wrap break-words font-mono text-[11px] leading-relaxed\">\n {JSON.stringify(value, null, 2)}\n </pre>\n );\n } catch {\n return String(value);\n }\n}\n"],"names":["UiRows","UiListFlat","UiListDashes","useContext","PropertiesContext","useState","useEffect","jsx","jsxs","cn","formatPropertyLabel","Fragment","Icon","DropdownMenu","IconButton","UiDotsVertical","UiCheck"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Properties.cjs","sources":["../../src/data/Properties.tsx"],"sourcesContent":["import {\n Fragment,\n useContext,\n useEffect,\n useState,\n type ReactNode,\n} from \"react\";\nimport { IconButton } from \"../components/IconButton\";\nimport {\n UiCheck,\n UiDotsVertical,\n UiListDashes,\n UiListFlat,\n UiRows,\n} from \"../icons\";\nimport { cn } from \"../lib/utils\";\nimport { DropdownMenu } from \"../overlay/DropdownMenu\";\nimport { Icon, type StaticIconComponent } from \"./Icon\";\nimport { formatPropertyLabel } from \"./properties-utils\";\nimport { PropertiesContext } from \"./properties-context\";\nimport { PropertyValue } from \"./PropertyValue\";\n\nexport type PropertiesAction<V = unknown> = {\n /** Stable action id. */\n id: string;\n /** Iconify name or imported icon component. */\n icon: string | StaticIconComponent;\n /** Accessible label and tooltip for this row action. */\n label: (key: string, value: V, item: PropertiesItem<V>) => string;\n /** Return false to hide the action for a specific row. */\n visible?: (key: string, value: V, item: PropertiesItem<V>) => boolean;\n /** Return true to disable the action for a specific row. */\n disabled?: (key: string, value: V, item: PropertiesItem<V>) => boolean;\n /** Called when the row action is clicked. */\n onClick: (key: string, value: V, item: PropertiesItem<V>) => void;\n};\n\nexport type PropertiesItem<V = unknown> = {\n /** Stable property key. Also used as the default label. */\n key: string;\n /** Property value passed to renderers and actions. */\n value: V;\n /** Optional display type; structured values otherwise render as JSON. */\n type?: \"text\" | \"json\" | \"bytes\" | \"duration\" | \"number\" | \"boolean\" | \"date\";\n /** Unit for numeric values, such as ms, s, bytes, or percent. */\n unit?: string;\n /** Secondary text shown below the label. */\n subtitle?: ReactNode;\n /** Hide this row without removing it from the item array. */\n hidden?: boolean;\n /** Enables a child area spanning both columns, with nested labels indented. */\n expandable?: boolean;\n /** Controlled expanded state. */\n expanded?: boolean;\n /** Called when an expandable row is toggled. */\n onToggle?: (next: boolean) => void;\n /** Child content rendered when the row is expanded. */\n renderChildren?: () => ReactNode;\n};\n\nexport type PropertiesDensity = \"comfortable\" | \"compact\" | \"spacious\";\n\nexport type PropertiesProps<V = unknown> = {\n /** Property rows to render. Hidden items are filtered out. */\n items: PropertiesItem<V>[];\n /** Custom label renderer. */\n renderLabel?: (key: string, value: V, item: PropertiesItem<V>) => ReactNode;\n /** Custom value renderer. */\n renderValue?: (key: string, value: V, item: PropertiesItem<V>) => ReactNode;\n /** Static icon name or function that returns an icon name per row. */\n labelIcon?:\n | string\n | ((key: string, value: V, item: PropertiesItem<V>) => string | undefined);\n /** Actions rendered before the value. */\n prefixActions?: PropertiesAction<V>[];\n /** Actions rendered after the value. */\n suffixActions?: PropertiesAction<V>[];\n /** Classes applied to the list root. */\n className?: string;\n /** Classes applied to each row. */\n rowClassName?: string;\n /** CSS grid columns applied to each row. Defaults to the selected density preset. */\n gridTemplateColumns?: string;\n /** Classes applied to each label cell. */\n labelClassName?: string;\n /** Classes applied to each value cell. */\n valueClassName?: string;\n /** Row density preset. */\n density?: PropertiesDensity;\n /** Stable reference used to persist this instance's density preference. */\n keyRef?: string;\n /** Show the display-options menu. */\n showDensityMenu?: boolean;\n /** Empty-state content when no rows are visible. */\n emptyMessage?: ReactNode;\n};\n\nconst PROPERTIES_DENSITY_STORAGE_PREFIX = \"clicky-ui-properties\";\n\nconst PROPERTIES_DENSITY_OPTIONS: Array<{\n value: PropertiesDensity;\n label: string;\n icon: StaticIconComponent;\n}> = [\n { value: \"compact\", label: \"Compact\", icon: UiRows },\n { value: \"comfortable\", label: \"Comfortable\", icon: UiListFlat },\n { value: \"spacious\", label: \"Spacious\", icon: UiListDashes },\n];\n\nconst DENSITY_CLASSES: Record<\n PropertiesDensity,\n { row: string; label: string; value: string; gridTemplateColumns: string }\n> = {\n spacious: {\n row: \"px-density-4 py-density-3\",\n label: \"text-sm font-medium text-muted-foreground\",\n value: \"text-base text-foreground\",\n gridTemplateColumns: \"minmax(12rem, 20rem) minmax(0, 1fr)\",\n },\n comfortable: {\n row: \"px-density-3 py-density-2\",\n label: \"text-xs font-medium text-muted-foreground\",\n value: \"text-sm text-foreground\",\n gridTemplateColumns: \"minmax(7rem, 12rem) minmax(0, 1fr)\",\n },\n compact: {\n row: \"px-density-2 py-density-1.5\",\n label: \"font-mono text-[11px] text-muted-foreground\",\n value: \"text-xs text-foreground\",\n gridTemplateColumns: \"minmax(8rem, 14rem) minmax(0, 1fr)\",\n },\n};\n\nexport function Properties<V = unknown>({\n items,\n renderLabel,\n renderValue,\n labelIcon,\n prefixActions,\n suffixActions,\n className,\n rowClassName,\n gridTemplateColumns,\n labelClassName,\n valueClassName,\n density = \"comfortable\",\n keyRef,\n showDensityMenu = true,\n emptyMessage = \"No properties\",\n}: PropertiesProps<V>) {\n const parent = useContext(PropertiesContext);\n const [densityOverride, setDensityOverride] = useState<PropertiesDensity>();\n useEffect(() => setDensityOverride(readStoredDensity(keyRef)), [keyRef]);\n\n const visible = items.filter((item) => !item.hidden);\n\n if (visible.length === 0) {\n return <div className=\"text-sm text-muted-foreground\">{emptyMessage}</div>;\n }\n\n const activeDensity = parent?.density ?? densityOverride ?? density;\n const styles = DENSITY_CLASSES[activeDensity];\n const columns =\n parent?.columns ?? gridTemplateColumns ?? styles.gridTemplateColumns;\n const depth = parent?.depth ?? 0;\n\n const updateDensity = (next: PropertiesDensity) => {\n setDensityOverride(next);\n writeStoredDensity(keyRef, next);\n };\n\n return (\n <dl\n className={cn(\n \"grid gap-x-density-3 divide-y divide-border rounded-md border border-border bg-muted/20\",\n parent && \"col-span-full rounded-none border-0 bg-transparent\",\n className,\n )}\n style={{ gridTemplateColumns: parent ? \"subgrid\" : columns }}\n >\n {showDensityMenu && !parent ? (\n <div className=\"col-span-full flex items-center justify-end px-density-2 py-density-1\">\n <dt className=\"sr-only\">Properties display options</dt>\n <dd>\n <PropertiesDensityMenu\n density={activeDensity}\n onChange={updateDensity}\n />\n </dd>\n </div>\n ) : null}\n {visible.map((item) => {\n const iconName =\n typeof labelIcon === \"function\"\n ? labelIcon(item.key, item.value, item)\n : labelIcon;\n const renderedLabel = renderLabel\n ? renderLabel(item.key, item.value, item)\n : formatPropertyLabel(item.key);\n const ariaLabel =\n typeof renderedLabel === \"string\" ? renderedLabel : item.key;\n\n return (\n <Fragment key={item.key}>\n <div\n className={cn(\n \"col-span-full grid min-w-0 grid-cols-subgrid gap-density-3\",\n styles.row,\n rowClassName,\n )}\n >\n <dt\n aria-label={ariaLabel}\n className={cn(\"min-w-0 truncate\", styles.label, labelClassName)}\n style={{ paddingInlineStart: depth * 16 }}\n >\n <div className=\"flex min-w-0 items-center gap-density-1\">\n {iconName ? (\n <Icon name={iconName} className=\"text-xs shrink-0\" />\n ) : null}\n <span className=\"min-w-0 truncate\">{renderedLabel}</span>\n </div>\n {item.subtitle ? (\n <div className=\"mt-0.5 text-[10px] font-normal text-muted-foreground/80\">\n {item.subtitle}\n </div>\n ) : null}\n </dt>\n <dd className={cn(\"min-w-0 space-y-density-1\", valueClassName)}>\n <div className=\"flex min-w-0 items-start gap-density-1\">\n <ActionList\n actions={prefixActions}\n item={item}\n className=\"shrink-0 pt-0.5\"\n />\n <div\n className={cn(\"min-w-0 max-w-full flex-1\", styles.value)}\n >\n {renderValue\n ? renderValue(item.key, item.value, item)\n : <PropertyValue item={item} density={activeDensity} />}\n </div>\n <ActionList\n actions={suffixActions}\n item={item}\n className=\"shrink-0 pt-0.5\"\n />\n </div>\n </dd>\n </div>\n {item.expandable && item.expanded && item.renderChildren ? (\n <div className=\"col-span-full grid grid-cols-subgrid\">\n <dt className=\"sr-only\">{ariaLabel} properties</dt>\n <dd className=\"col-span-full grid min-w-0 grid-cols-subgrid\">\n <PropertiesContext.Provider\n value={{\n depth: depth + 1,\n columns,\n density: activeDensity,\n }}\n >\n {item.renderChildren()}\n </PropertiesContext.Provider>\n </dd>\n </div>\n ) : null}\n </Fragment>\n );\n })}\n </dl>\n );\n}\n\nfunction PropertiesDensityMenu({\n density,\n onChange,\n}: {\n density: PropertiesDensity;\n onChange: (density: PropertiesDensity) => void;\n}) {\n return (\n <DropdownMenu\n align=\"right\"\n menuLabel=\"Properties options\"\n trigger={\n <IconButton\n icon={UiDotsVertical}\n label=\"Properties options\"\n className=\"h-6 w-6\"\n />\n }\n >\n {(closeMenu) => (\n <div className=\"min-w-44 py-1 text-popover-foreground\">\n <div className=\"px-2 py-1 text-xs font-medium text-muted-foreground\">\n Density\n </div>\n {PROPERTIES_DENSITY_OPTIONS.map((option) => {\n const active = density === option.value;\n return (\n <button\n key={option.value}\n type=\"button\"\n role=\"menuitemradio\"\n aria-checked={active}\n className={densityMenuItemClassName(active)}\n onClick={() => {\n onChange(option.value);\n closeMenu();\n }}\n >\n <Icon\n icon={option.icon}\n className=\"text-sm text-muted-foreground\"\n />\n <span className=\"min-w-0 flex-1 truncate\">{option.label}</span>\n {active ? (\n <Icon icon={UiCheck} className=\"text-sm text-foreground\" />\n ) : (\n <span className=\"inline-block h-4 w-4\" aria-hidden />\n )}\n </button>\n );\n })}\n </div>\n )}\n </DropdownMenu>\n );\n}\n\nfunction densityMenuItemClassName(active: boolean): string {\n return cn(\n \"flex w-full items-center gap-2 px-2 py-1.5 text-left text-sm\",\n \"hover:bg-accent focus:bg-accent focus:outline-none\",\n active && \"bg-accent/60\",\n );\n}\n\nfunction readStoredDensity(\n keyRef: string | undefined,\n): PropertiesDensity | undefined {\n const storageKey = propertiesDensityStorageKey(keyRef);\n if (!storageKey || typeof window === \"undefined\") return undefined;\n\n try {\n const value = window.localStorage.getItem(storageKey);\n return isPropertiesDensity(value) ? value : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction writeStoredDensity(\n keyRef: string | undefined,\n density: PropertiesDensity,\n): void {\n const storageKey = propertiesDensityStorageKey(keyRef);\n if (!storageKey || typeof window === \"undefined\") return;\n\n try {\n window.localStorage.setItem(storageKey, density);\n } catch {\n // Display preferences are best-effort when browser storage is unavailable.\n }\n}\n\nfunction propertiesDensityStorageKey(\n keyRef: string | undefined,\n): string | undefined {\n const normalized = keyRef?.trim();\n return normalized\n ? `${PROPERTIES_DENSITY_STORAGE_PREFIX}:${normalized}:density`\n : undefined;\n}\n\nfunction isPropertiesDensity(value: unknown): value is PropertiesDensity {\n return value === \"compact\" || value === \"comfortable\" || value === \"spacious\";\n}\n\nfunction ActionList<V>({\n actions,\n item,\n className,\n}: {\n actions: PropertiesAction<V>[] | undefined;\n item: PropertiesItem<V>;\n className?: string;\n}) {\n if (!actions || actions.length === 0) return null;\n const rendered = actions.filter(\n (action) => !action.visible || action.visible(item.key, item.value, item),\n );\n if (rendered.length === 0) return null;\n return (\n <span className={cn(\"inline-flex items-center\", className)}>\n {rendered.map((action) => (\n <PropertiesActionButton key={action.id} action={action} item={item} />\n ))}\n </span>\n );\n}\n\nfunction PropertiesActionButton<V>({\n action,\n item,\n}: {\n action: PropertiesAction<V>;\n item: PropertiesItem<V>;\n}) {\n const label = action.label(item.key, item.value, item);\n const disabled = action.disabled?.(item.key, item.value, item) ?? false;\n return (\n <button\n type=\"button\"\n aria-label={label}\n title={label}\n disabled={disabled}\n className={cn(\n \"inline-flex h-5 w-5 items-center justify-center rounded text-muted-foreground\",\n \"hover:bg-accent hover:text-foreground\",\n \"disabled:opacity-35 disabled:hover:bg-transparent disabled:hover:text-muted-foreground\",\n )}\n onClick={(event) => {\n event.stopPropagation();\n action.onClick(item.key, item.value, item);\n }}\n >\n <Icon\n {...(typeof action.icon === \"string\"\n ? { name: action.icon }\n : { icon: action.icon })}\n className=\"text-xs\"\n />\n </button>\n );\n}\n"],"names":["UiRows","UiListFlat","UiListDashes","useContext","PropertiesContext","useState","useEffect","jsx","jsxs","cn","formatPropertyLabel","Fragment","Icon","PropertyValue","DropdownMenu","IconButton","UiDotsVertical","UiCheck"],"mappings":"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"}
|
|
@@ -19,6 +19,10 @@ export type PropertiesItem<V = unknown> = {
|
|
|
19
19
|
key: string;
|
|
20
20
|
/** Property value passed to renderers and actions. */
|
|
21
21
|
value: V;
|
|
22
|
+
/** Optional display type; structured values otherwise render as JSON. */
|
|
23
|
+
type?: "text" | "json" | "bytes" | "duration" | "number" | "boolean" | "date";
|
|
24
|
+
/** Unit for numeric values, such as ms, s, bytes, or percent. */
|
|
25
|
+
unit?: string;
|
|
22
26
|
/** Secondary text shown below the label. */
|
|
23
27
|
subtitle?: ReactNode;
|
|
24
28
|
/** Hide this row without removing it from the item array. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Properties.d.ts","sourceRoot":"","sources":["../../src/data/Properties.tsx"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAWf,OAAO,EAAQ,KAAK,mBAAmB,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"Properties.d.ts","sourceRoot":"","sources":["../../src/data/Properties.tsx"],"names":[],"mappings":"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"}
|
package/dist/data/Properties.js
CHANGED
|
@@ -6,6 +6,7 @@ import { DropdownMenu } from "../overlay/DropdownMenu.js";
|
|
|
6
6
|
import { Icon } from "./Icon.js";
|
|
7
7
|
import { formatPropertyLabel } from "./properties-utils.js";
|
|
8
8
|
import { PropertiesContext } from "./properties-context.js";
|
|
9
|
+
import { PropertyValue } from "./PropertyValue.js";
|
|
9
10
|
import { UiRows } from "../icons/components/UiRows.js";
|
|
10
11
|
import { UiListFlat } from "../icons/components/UiListFlat.js";
|
|
11
12
|
import { UiListDashes } from "../icons/components/UiListDashes.js";
|
|
@@ -131,7 +132,7 @@ function Properties({
|
|
|
131
132
|
"div",
|
|
132
133
|
{
|
|
133
134
|
className: cn("min-w-0 max-w-full flex-1", styles.value),
|
|
134
|
-
children: renderValue ? renderValue(item.key, item.value, item) :
|
|
135
|
+
children: renderValue ? renderValue(item.key, item.value, item) : /* @__PURE__ */ jsx(PropertyValue, { item, density: activeDensity })
|
|
135
136
|
}
|
|
136
137
|
),
|
|
137
138
|
/* @__PURE__ */ jsx(
|
|
@@ -297,20 +298,6 @@ function PropertiesActionButton({
|
|
|
297
298
|
}
|
|
298
299
|
);
|
|
299
300
|
}
|
|
300
|
-
function defaultRenderValue(value) {
|
|
301
|
-
if (value === null || value === void 0) {
|
|
302
|
-
return /* @__PURE__ */ jsx("span", { className: "font-mono italic text-muted-foreground", children: "null" });
|
|
303
|
-
}
|
|
304
|
-
if (typeof value === "string") return value;
|
|
305
|
-
if (typeof value === "number" || typeof value === "boolean") {
|
|
306
|
-
return /* @__PURE__ */ jsx("span", { className: "font-mono", children: String(value) });
|
|
307
|
-
}
|
|
308
|
-
try {
|
|
309
|
-
return /* @__PURE__ */ jsx("pre", { className: "max-h-48 overflow-auto whitespace-pre-wrap break-words font-mono text-[11px] leading-relaxed", children: JSON.stringify(value, null, 2) });
|
|
310
|
-
} catch {
|
|
311
|
-
return String(value);
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
301
|
export {
|
|
315
302
|
Properties
|
|
316
303
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Properties.js","sources":["../../src/data/Properties.tsx"],"sourcesContent":["import {\n Fragment,\n useContext,\n useEffect,\n useState,\n type ReactNode,\n} from \"react\";\nimport { IconButton } from \"../components/IconButton\";\nimport {\n UiCheck,\n UiDotsVertical,\n UiListDashes,\n UiListFlat,\n UiRows,\n} from \"../icons\";\nimport { cn } from \"../lib/utils\";\nimport { DropdownMenu } from \"../overlay/DropdownMenu\";\nimport { Icon, type StaticIconComponent } from \"./Icon\";\nimport { formatPropertyLabel } from \"./properties-utils\";\nimport { PropertiesContext } from \"./properties-context\";\n\nexport type PropertiesAction<V = unknown> = {\n /** Stable action id. */\n id: string;\n /** Iconify name or imported icon component. */\n icon: string | StaticIconComponent;\n /** Accessible label and tooltip for this row action. */\n label: (key: string, value: V, item: PropertiesItem<V>) => string;\n /** Return false to hide the action for a specific row. */\n visible?: (key: string, value: V, item: PropertiesItem<V>) => boolean;\n /** Return true to disable the action for a specific row. */\n disabled?: (key: string, value: V, item: PropertiesItem<V>) => boolean;\n /** Called when the row action is clicked. */\n onClick: (key: string, value: V, item: PropertiesItem<V>) => void;\n};\n\nexport type PropertiesItem<V = unknown> = {\n /** Stable property key. Also used as the default label. */\n key: string;\n /** Property value passed to renderers and actions. */\n value: V;\n /** Secondary text shown below the label. */\n subtitle?: ReactNode;\n /** Hide this row without removing it from the item array. */\n hidden?: boolean;\n /** Enables a child area spanning both columns, with nested labels indented. */\n expandable?: boolean;\n /** Controlled expanded state. */\n expanded?: boolean;\n /** Called when an expandable row is toggled. */\n onToggle?: (next: boolean) => void;\n /** Child content rendered when the row is expanded. */\n renderChildren?: () => ReactNode;\n};\n\nexport type PropertiesDensity = \"comfortable\" | \"compact\" | \"spacious\";\n\nexport type PropertiesProps<V = unknown> = {\n /** Property rows to render. Hidden items are filtered out. */\n items: PropertiesItem<V>[];\n /** Custom label renderer. */\n renderLabel?: (key: string, value: V, item: PropertiesItem<V>) => ReactNode;\n /** Custom value renderer. */\n renderValue?: (key: string, value: V, item: PropertiesItem<V>) => ReactNode;\n /** Static icon name or function that returns an icon name per row. */\n labelIcon?:\n | string\n | ((key: string, value: V, item: PropertiesItem<V>) => string | undefined);\n /** Actions rendered before the value. */\n prefixActions?: PropertiesAction<V>[];\n /** Actions rendered after the value. */\n suffixActions?: PropertiesAction<V>[];\n /** Classes applied to the list root. */\n className?: string;\n /** Classes applied to each row. */\n rowClassName?: string;\n /** CSS grid columns applied to each row. Defaults to the selected density preset. */\n gridTemplateColumns?: string;\n /** Classes applied to each label cell. */\n labelClassName?: string;\n /** Classes applied to each value cell. */\n valueClassName?: string;\n /** Row density preset. */\n density?: PropertiesDensity;\n /** Stable reference used to persist this instance's density preference. */\n keyRef?: string;\n /** Show the display-options menu. */\n showDensityMenu?: boolean;\n /** Empty-state content when no rows are visible. */\n emptyMessage?: ReactNode;\n};\n\nconst PROPERTIES_DENSITY_STORAGE_PREFIX = \"clicky-ui-properties\";\n\nconst PROPERTIES_DENSITY_OPTIONS: Array<{\n value: PropertiesDensity;\n label: string;\n icon: StaticIconComponent;\n}> = [\n { value: \"compact\", label: \"Compact\", icon: UiRows },\n { value: \"comfortable\", label: \"Comfortable\", icon: UiListFlat },\n { value: \"spacious\", label: \"Spacious\", icon: UiListDashes },\n];\n\nconst DENSITY_CLASSES: Record<\n PropertiesDensity,\n { row: string; label: string; value: string; gridTemplateColumns: string }\n> = {\n spacious: {\n row: \"px-density-4 py-density-3\",\n label: \"text-sm font-medium text-muted-foreground\",\n value: \"text-base text-foreground\",\n gridTemplateColumns: \"minmax(12rem, 20rem) minmax(0, 1fr)\",\n },\n comfortable: {\n row: \"px-density-3 py-density-2\",\n label: \"text-xs font-medium text-muted-foreground\",\n value: \"text-sm text-foreground\",\n gridTemplateColumns: \"minmax(7rem, 12rem) minmax(0, 1fr)\",\n },\n compact: {\n row: \"px-density-2 py-density-1.5\",\n label: \"font-mono text-[11px] text-muted-foreground\",\n value: \"text-xs text-foreground\",\n gridTemplateColumns: \"minmax(8rem, 14rem) minmax(0, 1fr)\",\n },\n};\n\nexport function Properties<V = unknown>({\n items,\n renderLabel,\n renderValue,\n labelIcon,\n prefixActions,\n suffixActions,\n className,\n rowClassName,\n gridTemplateColumns,\n labelClassName,\n valueClassName,\n density = \"comfortable\",\n keyRef,\n showDensityMenu = true,\n emptyMessage = \"No properties\",\n}: PropertiesProps<V>) {\n const parent = useContext(PropertiesContext);\n const [densityOverride, setDensityOverride] = useState<PropertiesDensity>();\n useEffect(() => setDensityOverride(readStoredDensity(keyRef)), [keyRef]);\n\n const visible = items.filter((item) => !item.hidden);\n\n if (visible.length === 0) {\n return <div className=\"text-sm text-muted-foreground\">{emptyMessage}</div>;\n }\n\n const activeDensity = parent?.density ?? densityOverride ?? density;\n const styles = DENSITY_CLASSES[activeDensity];\n const columns =\n parent?.columns ?? gridTemplateColumns ?? styles.gridTemplateColumns;\n const depth = parent?.depth ?? 0;\n\n const updateDensity = (next: PropertiesDensity) => {\n setDensityOverride(next);\n writeStoredDensity(keyRef, next);\n };\n\n return (\n <dl\n className={cn(\n \"grid gap-x-density-3 divide-y divide-border rounded-md border border-border bg-muted/20\",\n parent && \"col-span-full rounded-none border-0 bg-transparent\",\n className,\n )}\n style={{ gridTemplateColumns: parent ? \"subgrid\" : columns }}\n >\n {showDensityMenu && !parent ? (\n <div className=\"col-span-full flex items-center justify-end px-density-2 py-density-1\">\n <dt className=\"sr-only\">Properties display options</dt>\n <dd>\n <PropertiesDensityMenu\n density={activeDensity}\n onChange={updateDensity}\n />\n </dd>\n </div>\n ) : null}\n {visible.map((item) => {\n const iconName =\n typeof labelIcon === \"function\"\n ? labelIcon(item.key, item.value, item)\n : labelIcon;\n const renderedLabel = renderLabel\n ? renderLabel(item.key, item.value, item)\n : formatPropertyLabel(item.key);\n const ariaLabel =\n typeof renderedLabel === \"string\" ? renderedLabel : item.key;\n\n return (\n <Fragment key={item.key}>\n <div\n className={cn(\n \"col-span-full grid min-w-0 grid-cols-subgrid gap-density-3\",\n styles.row,\n rowClassName,\n )}\n >\n <dt\n aria-label={ariaLabel}\n className={cn(\"min-w-0 truncate\", styles.label, labelClassName)}\n style={{ paddingInlineStart: depth * 16 }}\n >\n <div className=\"flex min-w-0 items-center gap-density-1\">\n {iconName ? (\n <Icon name={iconName} className=\"text-xs shrink-0\" />\n ) : null}\n <span className=\"min-w-0 truncate\">{renderedLabel}</span>\n </div>\n {item.subtitle ? (\n <div className=\"mt-0.5 text-[10px] font-normal text-muted-foreground/80\">\n {item.subtitle}\n </div>\n ) : null}\n </dt>\n <dd className={cn(\"min-w-0 space-y-density-1\", valueClassName)}>\n <div className=\"flex min-w-0 items-start gap-density-1\">\n <ActionList\n actions={prefixActions}\n item={item}\n className=\"shrink-0 pt-0.5\"\n />\n <div\n className={cn(\"min-w-0 max-w-full flex-1\", styles.value)}\n >\n {renderValue\n ? renderValue(item.key, item.value, item)\n : defaultRenderValue(item.value)}\n </div>\n <ActionList\n actions={suffixActions}\n item={item}\n className=\"shrink-0 pt-0.5\"\n />\n </div>\n </dd>\n </div>\n {item.expandable && item.expanded && item.renderChildren ? (\n <div className=\"col-span-full grid grid-cols-subgrid\">\n <dt className=\"sr-only\">{ariaLabel} properties</dt>\n <dd className=\"col-span-full grid min-w-0 grid-cols-subgrid\">\n <PropertiesContext.Provider\n value={{\n depth: depth + 1,\n columns,\n density: activeDensity,\n }}\n >\n {item.renderChildren()}\n </PropertiesContext.Provider>\n </dd>\n </div>\n ) : null}\n </Fragment>\n );\n })}\n </dl>\n );\n}\n\nfunction PropertiesDensityMenu({\n density,\n onChange,\n}: {\n density: PropertiesDensity;\n onChange: (density: PropertiesDensity) => void;\n}) {\n return (\n <DropdownMenu\n align=\"right\"\n menuLabel=\"Properties options\"\n trigger={\n <IconButton\n icon={UiDotsVertical}\n label=\"Properties options\"\n className=\"h-6 w-6\"\n />\n }\n >\n {(closeMenu) => (\n <div className=\"min-w-44 py-1 text-popover-foreground\">\n <div className=\"px-2 py-1 text-xs font-medium text-muted-foreground\">\n Density\n </div>\n {PROPERTIES_DENSITY_OPTIONS.map((option) => {\n const active = density === option.value;\n return (\n <button\n key={option.value}\n type=\"button\"\n role=\"menuitemradio\"\n aria-checked={active}\n className={densityMenuItemClassName(active)}\n onClick={() => {\n onChange(option.value);\n closeMenu();\n }}\n >\n <Icon\n icon={option.icon}\n className=\"text-sm text-muted-foreground\"\n />\n <span className=\"min-w-0 flex-1 truncate\">{option.label}</span>\n {active ? (\n <Icon icon={UiCheck} className=\"text-sm text-foreground\" />\n ) : (\n <span className=\"inline-block h-4 w-4\" aria-hidden />\n )}\n </button>\n );\n })}\n </div>\n )}\n </DropdownMenu>\n );\n}\n\nfunction densityMenuItemClassName(active: boolean): string {\n return cn(\n \"flex w-full items-center gap-2 px-2 py-1.5 text-left text-sm\",\n \"hover:bg-accent focus:bg-accent focus:outline-none\",\n active && \"bg-accent/60\",\n );\n}\n\nfunction readStoredDensity(\n keyRef: string | undefined,\n): PropertiesDensity | undefined {\n const storageKey = propertiesDensityStorageKey(keyRef);\n if (!storageKey || typeof window === \"undefined\") return undefined;\n\n try {\n const value = window.localStorage.getItem(storageKey);\n return isPropertiesDensity(value) ? value : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction writeStoredDensity(\n keyRef: string | undefined,\n density: PropertiesDensity,\n): void {\n const storageKey = propertiesDensityStorageKey(keyRef);\n if (!storageKey || typeof window === \"undefined\") return;\n\n try {\n window.localStorage.setItem(storageKey, density);\n } catch {\n // Display preferences are best-effort when browser storage is unavailable.\n }\n}\n\nfunction propertiesDensityStorageKey(\n keyRef: string | undefined,\n): string | undefined {\n const normalized = keyRef?.trim();\n return normalized\n ? `${PROPERTIES_DENSITY_STORAGE_PREFIX}:${normalized}:density`\n : undefined;\n}\n\nfunction isPropertiesDensity(value: unknown): value is PropertiesDensity {\n return value === \"compact\" || value === \"comfortable\" || value === \"spacious\";\n}\n\nfunction ActionList<V>({\n actions,\n item,\n className,\n}: {\n actions: PropertiesAction<V>[] | undefined;\n item: PropertiesItem<V>;\n className?: string;\n}) {\n if (!actions || actions.length === 0) return null;\n const rendered = actions.filter(\n (action) => !action.visible || action.visible(item.key, item.value, item),\n );\n if (rendered.length === 0) return null;\n return (\n <span className={cn(\"inline-flex items-center\", className)}>\n {rendered.map((action) => (\n <PropertiesActionButton key={action.id} action={action} item={item} />\n ))}\n </span>\n );\n}\n\nfunction PropertiesActionButton<V>({\n action,\n item,\n}: {\n action: PropertiesAction<V>;\n item: PropertiesItem<V>;\n}) {\n const label = action.label(item.key, item.value, item);\n const disabled = action.disabled?.(item.key, item.value, item) ?? false;\n return (\n <button\n type=\"button\"\n aria-label={label}\n title={label}\n disabled={disabled}\n className={cn(\n \"inline-flex h-5 w-5 items-center justify-center rounded text-muted-foreground\",\n \"hover:bg-accent hover:text-foreground\",\n \"disabled:opacity-35 disabled:hover:bg-transparent disabled:hover:text-muted-foreground\",\n )}\n onClick={(event) => {\n event.stopPropagation();\n action.onClick(item.key, item.value, item);\n }}\n >\n <Icon\n {...(typeof action.icon === \"string\"\n ? { name: action.icon }\n : { icon: action.icon })}\n className=\"text-xs\"\n />\n </button>\n );\n}\n\nfunction defaultRenderValue(value: unknown): ReactNode {\n if (value === null || value === undefined) {\n return <span className=\"font-mono italic text-muted-foreground\">null</span>;\n }\n if (typeof value === \"string\") return value;\n if (typeof value === \"number\" || typeof value === \"boolean\") {\n return <span className=\"font-mono\">{String(value)}</span>;\n }\n try {\n return (\n <pre className=\"max-h-48 overflow-auto whitespace-pre-wrap break-words font-mono text-[11px] leading-relaxed\">\n {JSON.stringify(value, null, 2)}\n </pre>\n );\n } catch {\n return String(value);\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Properties.js","sources":["../../src/data/Properties.tsx"],"sourcesContent":["import {\n Fragment,\n useContext,\n useEffect,\n useState,\n type ReactNode,\n} from \"react\";\nimport { IconButton } from \"../components/IconButton\";\nimport {\n UiCheck,\n UiDotsVertical,\n UiListDashes,\n UiListFlat,\n UiRows,\n} from \"../icons\";\nimport { cn } from \"../lib/utils\";\nimport { DropdownMenu } from \"../overlay/DropdownMenu\";\nimport { Icon, type StaticIconComponent } from \"./Icon\";\nimport { formatPropertyLabel } from \"./properties-utils\";\nimport { PropertiesContext } from \"./properties-context\";\nimport { PropertyValue } from \"./PropertyValue\";\n\nexport type PropertiesAction<V = unknown> = {\n /** Stable action id. */\n id: string;\n /** Iconify name or imported icon component. */\n icon: string | StaticIconComponent;\n /** Accessible label and tooltip for this row action. */\n label: (key: string, value: V, item: PropertiesItem<V>) => string;\n /** Return false to hide the action for a specific row. */\n visible?: (key: string, value: V, item: PropertiesItem<V>) => boolean;\n /** Return true to disable the action for a specific row. */\n disabled?: (key: string, value: V, item: PropertiesItem<V>) => boolean;\n /** Called when the row action is clicked. */\n onClick: (key: string, value: V, item: PropertiesItem<V>) => void;\n};\n\nexport type PropertiesItem<V = unknown> = {\n /** Stable property key. Also used as the default label. */\n key: string;\n /** Property value passed to renderers and actions. */\n value: V;\n /** Optional display type; structured values otherwise render as JSON. */\n type?: \"text\" | \"json\" | \"bytes\" | \"duration\" | \"number\" | \"boolean\" | \"date\";\n /** Unit for numeric values, such as ms, s, bytes, or percent. */\n unit?: string;\n /** Secondary text shown below the label. */\n subtitle?: ReactNode;\n /** Hide this row without removing it from the item array. */\n hidden?: boolean;\n /** Enables a child area spanning both columns, with nested labels indented. */\n expandable?: boolean;\n /** Controlled expanded state. */\n expanded?: boolean;\n /** Called when an expandable row is toggled. */\n onToggle?: (next: boolean) => void;\n /** Child content rendered when the row is expanded. */\n renderChildren?: () => ReactNode;\n};\n\nexport type PropertiesDensity = \"comfortable\" | \"compact\" | \"spacious\";\n\nexport type PropertiesProps<V = unknown> = {\n /** Property rows to render. Hidden items are filtered out. */\n items: PropertiesItem<V>[];\n /** Custom label renderer. */\n renderLabel?: (key: string, value: V, item: PropertiesItem<V>) => ReactNode;\n /** Custom value renderer. */\n renderValue?: (key: string, value: V, item: PropertiesItem<V>) => ReactNode;\n /** Static icon name or function that returns an icon name per row. */\n labelIcon?:\n | string\n | ((key: string, value: V, item: PropertiesItem<V>) => string | undefined);\n /** Actions rendered before the value. */\n prefixActions?: PropertiesAction<V>[];\n /** Actions rendered after the value. */\n suffixActions?: PropertiesAction<V>[];\n /** Classes applied to the list root. */\n className?: string;\n /** Classes applied to each row. */\n rowClassName?: string;\n /** CSS grid columns applied to each row. Defaults to the selected density preset. */\n gridTemplateColumns?: string;\n /** Classes applied to each label cell. */\n labelClassName?: string;\n /** Classes applied to each value cell. */\n valueClassName?: string;\n /** Row density preset. */\n density?: PropertiesDensity;\n /** Stable reference used to persist this instance's density preference. */\n keyRef?: string;\n /** Show the display-options menu. */\n showDensityMenu?: boolean;\n /** Empty-state content when no rows are visible. */\n emptyMessage?: ReactNode;\n};\n\nconst PROPERTIES_DENSITY_STORAGE_PREFIX = \"clicky-ui-properties\";\n\nconst PROPERTIES_DENSITY_OPTIONS: Array<{\n value: PropertiesDensity;\n label: string;\n icon: StaticIconComponent;\n}> = [\n { value: \"compact\", label: \"Compact\", icon: UiRows },\n { value: \"comfortable\", label: \"Comfortable\", icon: UiListFlat },\n { value: \"spacious\", label: \"Spacious\", icon: UiListDashes },\n];\n\nconst DENSITY_CLASSES: Record<\n PropertiesDensity,\n { row: string; label: string; value: string; gridTemplateColumns: string }\n> = {\n spacious: {\n row: \"px-density-4 py-density-3\",\n label: \"text-sm font-medium text-muted-foreground\",\n value: \"text-base text-foreground\",\n gridTemplateColumns: \"minmax(12rem, 20rem) minmax(0, 1fr)\",\n },\n comfortable: {\n row: \"px-density-3 py-density-2\",\n label: \"text-xs font-medium text-muted-foreground\",\n value: \"text-sm text-foreground\",\n gridTemplateColumns: \"minmax(7rem, 12rem) minmax(0, 1fr)\",\n },\n compact: {\n row: \"px-density-2 py-density-1.5\",\n label: \"font-mono text-[11px] text-muted-foreground\",\n value: \"text-xs text-foreground\",\n gridTemplateColumns: \"minmax(8rem, 14rem) minmax(0, 1fr)\",\n },\n};\n\nexport function Properties<V = unknown>({\n items,\n renderLabel,\n renderValue,\n labelIcon,\n prefixActions,\n suffixActions,\n className,\n rowClassName,\n gridTemplateColumns,\n labelClassName,\n valueClassName,\n density = \"comfortable\",\n keyRef,\n showDensityMenu = true,\n emptyMessage = \"No properties\",\n}: PropertiesProps<V>) {\n const parent = useContext(PropertiesContext);\n const [densityOverride, setDensityOverride] = useState<PropertiesDensity>();\n useEffect(() => setDensityOverride(readStoredDensity(keyRef)), [keyRef]);\n\n const visible = items.filter((item) => !item.hidden);\n\n if (visible.length === 0) {\n return <div className=\"text-sm text-muted-foreground\">{emptyMessage}</div>;\n }\n\n const activeDensity = parent?.density ?? densityOverride ?? density;\n const styles = DENSITY_CLASSES[activeDensity];\n const columns =\n parent?.columns ?? gridTemplateColumns ?? styles.gridTemplateColumns;\n const depth = parent?.depth ?? 0;\n\n const updateDensity = (next: PropertiesDensity) => {\n setDensityOverride(next);\n writeStoredDensity(keyRef, next);\n };\n\n return (\n <dl\n className={cn(\n \"grid gap-x-density-3 divide-y divide-border rounded-md border border-border bg-muted/20\",\n parent && \"col-span-full rounded-none border-0 bg-transparent\",\n className,\n )}\n style={{ gridTemplateColumns: parent ? \"subgrid\" : columns }}\n >\n {showDensityMenu && !parent ? (\n <div className=\"col-span-full flex items-center justify-end px-density-2 py-density-1\">\n <dt className=\"sr-only\">Properties display options</dt>\n <dd>\n <PropertiesDensityMenu\n density={activeDensity}\n onChange={updateDensity}\n />\n </dd>\n </div>\n ) : null}\n {visible.map((item) => {\n const iconName =\n typeof labelIcon === \"function\"\n ? labelIcon(item.key, item.value, item)\n : labelIcon;\n const renderedLabel = renderLabel\n ? renderLabel(item.key, item.value, item)\n : formatPropertyLabel(item.key);\n const ariaLabel =\n typeof renderedLabel === \"string\" ? renderedLabel : item.key;\n\n return (\n <Fragment key={item.key}>\n <div\n className={cn(\n \"col-span-full grid min-w-0 grid-cols-subgrid gap-density-3\",\n styles.row,\n rowClassName,\n )}\n >\n <dt\n aria-label={ariaLabel}\n className={cn(\"min-w-0 truncate\", styles.label, labelClassName)}\n style={{ paddingInlineStart: depth * 16 }}\n >\n <div className=\"flex min-w-0 items-center gap-density-1\">\n {iconName ? (\n <Icon name={iconName} className=\"text-xs shrink-0\" />\n ) : null}\n <span className=\"min-w-0 truncate\">{renderedLabel}</span>\n </div>\n {item.subtitle ? (\n <div className=\"mt-0.5 text-[10px] font-normal text-muted-foreground/80\">\n {item.subtitle}\n </div>\n ) : null}\n </dt>\n <dd className={cn(\"min-w-0 space-y-density-1\", valueClassName)}>\n <div className=\"flex min-w-0 items-start gap-density-1\">\n <ActionList\n actions={prefixActions}\n item={item}\n className=\"shrink-0 pt-0.5\"\n />\n <div\n className={cn(\"min-w-0 max-w-full flex-1\", styles.value)}\n >\n {renderValue\n ? renderValue(item.key, item.value, item)\n : <PropertyValue item={item} density={activeDensity} />}\n </div>\n <ActionList\n actions={suffixActions}\n item={item}\n className=\"shrink-0 pt-0.5\"\n />\n </div>\n </dd>\n </div>\n {item.expandable && item.expanded && item.renderChildren ? (\n <div className=\"col-span-full grid grid-cols-subgrid\">\n <dt className=\"sr-only\">{ariaLabel} properties</dt>\n <dd className=\"col-span-full grid min-w-0 grid-cols-subgrid\">\n <PropertiesContext.Provider\n value={{\n depth: depth + 1,\n columns,\n density: activeDensity,\n }}\n >\n {item.renderChildren()}\n </PropertiesContext.Provider>\n </dd>\n </div>\n ) : null}\n </Fragment>\n );\n })}\n </dl>\n );\n}\n\nfunction PropertiesDensityMenu({\n density,\n onChange,\n}: {\n density: PropertiesDensity;\n onChange: (density: PropertiesDensity) => void;\n}) {\n return (\n <DropdownMenu\n align=\"right\"\n menuLabel=\"Properties options\"\n trigger={\n <IconButton\n icon={UiDotsVertical}\n label=\"Properties options\"\n className=\"h-6 w-6\"\n />\n }\n >\n {(closeMenu) => (\n <div className=\"min-w-44 py-1 text-popover-foreground\">\n <div className=\"px-2 py-1 text-xs font-medium text-muted-foreground\">\n Density\n </div>\n {PROPERTIES_DENSITY_OPTIONS.map((option) => {\n const active = density === option.value;\n return (\n <button\n key={option.value}\n type=\"button\"\n role=\"menuitemradio\"\n aria-checked={active}\n className={densityMenuItemClassName(active)}\n onClick={() => {\n onChange(option.value);\n closeMenu();\n }}\n >\n <Icon\n icon={option.icon}\n className=\"text-sm text-muted-foreground\"\n />\n <span className=\"min-w-0 flex-1 truncate\">{option.label}</span>\n {active ? (\n <Icon icon={UiCheck} className=\"text-sm text-foreground\" />\n ) : (\n <span className=\"inline-block h-4 w-4\" aria-hidden />\n )}\n </button>\n );\n })}\n </div>\n )}\n </DropdownMenu>\n );\n}\n\nfunction densityMenuItemClassName(active: boolean): string {\n return cn(\n \"flex w-full items-center gap-2 px-2 py-1.5 text-left text-sm\",\n \"hover:bg-accent focus:bg-accent focus:outline-none\",\n active && \"bg-accent/60\",\n );\n}\n\nfunction readStoredDensity(\n keyRef: string | undefined,\n): PropertiesDensity | undefined {\n const storageKey = propertiesDensityStorageKey(keyRef);\n if (!storageKey || typeof window === \"undefined\") return undefined;\n\n try {\n const value = window.localStorage.getItem(storageKey);\n return isPropertiesDensity(value) ? value : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction writeStoredDensity(\n keyRef: string | undefined,\n density: PropertiesDensity,\n): void {\n const storageKey = propertiesDensityStorageKey(keyRef);\n if (!storageKey || typeof window === \"undefined\") return;\n\n try {\n window.localStorage.setItem(storageKey, density);\n } catch {\n // Display preferences are best-effort when browser storage is unavailable.\n }\n}\n\nfunction propertiesDensityStorageKey(\n keyRef: string | undefined,\n): string | undefined {\n const normalized = keyRef?.trim();\n return normalized\n ? `${PROPERTIES_DENSITY_STORAGE_PREFIX}:${normalized}:density`\n : undefined;\n}\n\nfunction isPropertiesDensity(value: unknown): value is PropertiesDensity {\n return value === \"compact\" || value === \"comfortable\" || value === \"spacious\";\n}\n\nfunction ActionList<V>({\n actions,\n item,\n className,\n}: {\n actions: PropertiesAction<V>[] | undefined;\n item: PropertiesItem<V>;\n className?: string;\n}) {\n if (!actions || actions.length === 0) return null;\n const rendered = actions.filter(\n (action) => !action.visible || action.visible(item.key, item.value, item),\n );\n if (rendered.length === 0) return null;\n return (\n <span className={cn(\"inline-flex items-center\", className)}>\n {rendered.map((action) => (\n <PropertiesActionButton key={action.id} action={action} item={item} />\n ))}\n </span>\n );\n}\n\nfunction PropertiesActionButton<V>({\n action,\n item,\n}: {\n action: PropertiesAction<V>;\n item: PropertiesItem<V>;\n}) {\n const label = action.label(item.key, item.value, item);\n const disabled = action.disabled?.(item.key, item.value, item) ?? false;\n return (\n <button\n type=\"button\"\n aria-label={label}\n title={label}\n disabled={disabled}\n className={cn(\n \"inline-flex h-5 w-5 items-center justify-center rounded text-muted-foreground\",\n \"hover:bg-accent hover:text-foreground\",\n \"disabled:opacity-35 disabled:hover:bg-transparent disabled:hover:text-muted-foreground\",\n )}\n onClick={(event) => {\n event.stopPropagation();\n action.onClick(item.key, item.value, item);\n }}\n >\n <Icon\n {...(typeof action.icon === \"string\"\n ? { name: action.icon }\n : { icon: action.icon })}\n className=\"text-xs\"\n />\n </button>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const jsxRuntime = require("react/jsx-runtime");
|
|
4
|
+
const format = require("../lib/format.cjs");
|
|
5
|
+
const JsonView = require("./JsonView.cjs");
|
|
6
|
+
function PropertyValue({ item, density }) {
|
|
7
|
+
const { value, type, unit } = item;
|
|
8
|
+
if (value === null || value === void 0) {
|
|
9
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono italic text-muted-foreground", children: "null" });
|
|
10
|
+
}
|
|
11
|
+
if (type === "json" || type === void 0 && typeof value === "object") {
|
|
12
|
+
return typeof value === "string" ? /* @__PURE__ */ jsxRuntime.jsx(JsonView.JsonView, { source: value, format: "json", density }) : /* @__PURE__ */ jsxRuntime.jsx(JsonView.JsonView, { data: value, format: "json", density });
|
|
13
|
+
}
|
|
14
|
+
if (type === "bytes" || type === "duration" || type === "number" || unit !== void 0) {
|
|
15
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
16
|
+
throw new Error(`Property ${item.key}: expected a finite numeric value for ${type ?? unit}`);
|
|
17
|
+
}
|
|
18
|
+
const displayUnit = unit ?? (type === "bytes" ? "bytes" : type === "duration" ? "ms" : void 0);
|
|
19
|
+
const formatted = displayUnit === "bytes" && value < 0 ? `-${format.formatUnit(Math.abs(value), displayUnit)}` : format.formatUnit(value, displayUnit);
|
|
20
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono", title: String(value), children: formatted });
|
|
21
|
+
}
|
|
22
|
+
if (type === "date") {
|
|
23
|
+
if (typeof value !== "number" && typeof value !== "string" && !(value instanceof Date)) {
|
|
24
|
+
throw new Error(`Property ${item.key}: expected a date or timestamp`);
|
|
25
|
+
}
|
|
26
|
+
return /* @__PURE__ */ jsxRuntime.jsx("time", { dateTime: new Date(value).toISOString(), title: String(value), children: new Date(value).toISOString() });
|
|
27
|
+
}
|
|
28
|
+
if (type === "boolean" && typeof value !== "boolean") {
|
|
29
|
+
throw new Error(`Property ${item.key}: expected a boolean`);
|
|
30
|
+
}
|
|
31
|
+
if (typeof value === "boolean") {
|
|
32
|
+
return /* @__PURE__ */ jsxRuntime.jsx("input", { type: "checkbox", checked: value, disabled: true, "aria-label": `${item.key} value`, title: String(value), className: "h-4 w-4 accent-primary" });
|
|
33
|
+
}
|
|
34
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "whitespace-pre-wrap break-words font-mono", children: String(value) });
|
|
35
|
+
}
|
|
36
|
+
exports.PropertyValue = PropertyValue;
|
|
37
|
+
//# sourceMappingURL=PropertyValue.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PropertyValue.cjs","sources":["../../src/data/PropertyValue.tsx"],"sourcesContent":["import { formatUnit } from \"../lib/format\";\nimport { JsonView } from \"./JsonView\";\nimport type { PropertiesDensity, PropertiesItem } from \"./Properties\";\n\nexport function PropertyValue({ item, density }: { item: PropertiesItem; density: PropertiesDensity }) {\n const { value, type, unit } = item;\n if (value === null || value === undefined) {\n return <span className=\"font-mono italic text-muted-foreground\">null</span>;\n }\n if (type === \"json\" || (type === undefined && typeof value === \"object\")) {\n return typeof value === \"string\"\n ? <JsonView source={value} format=\"json\" density={density} />\n : <JsonView data={value} format=\"json\" density={density} />;\n }\n if (type === \"bytes\" || type === \"duration\" || type === \"number\" || unit !== undefined) {\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n throw new Error(`Property ${item.key}: expected a finite numeric value for ${type ?? unit}`);\n }\n const displayUnit = unit ?? (type === \"bytes\" ? \"bytes\" : type === \"duration\" ? \"ms\" : undefined);\n const formatted = displayUnit === \"bytes\" && value < 0\n ? `-${formatUnit(Math.abs(value), displayUnit)}` : formatUnit(value, displayUnit);\n return <span className=\"font-mono\" title={String(value)}>{formatted}</span>;\n }\n if (type === \"date\") {\n if (typeof value !== \"number\" && typeof value !== \"string\" && !(value instanceof Date)) {\n throw new Error(`Property ${item.key}: expected a date or timestamp`);\n }\n return <time dateTime={new Date(value).toISOString()} title={String(value)}>{new Date(value).toISOString()}</time>;\n }\n if (type === \"boolean\" && typeof value !== \"boolean\") {\n throw new Error(`Property ${item.key}: expected a boolean`);\n }\n if (typeof value === \"boolean\") {\n return <input type=\"checkbox\" checked={value} disabled aria-label={`${item.key} value`} title={String(value)} className=\"h-4 w-4 accent-primary\" />;\n }\n return <span className=\"whitespace-pre-wrap break-words font-mono\">{String(value)}</span>;\n}\n"],"names":["jsx","JsonView","formatUnit"],"mappings":";;;;;AAIO,SAAS,cAAc,EAAE,MAAM,WAAiE;AACrG,QAAM,EAAE,OAAO,MAAM,KAAA,IAAS;AAC9B,MAAI,UAAU,QAAQ,UAAU,QAAW;AACzC,WAAOA,2BAAAA,IAAC,QAAA,EAAK,WAAU,0CAAyC,UAAA,QAAI;AAAA,EACtE;AACA,MAAI,SAAS,UAAW,SAAS,UAAa,OAAO,UAAU,UAAW;AACxE,WAAO,OAAO,UAAU,WACpBA,2BAAAA,IAACC,SAAAA,UAAA,EAAS,QAAQ,OAAO,QAAO,QAAO,QAAA,CAAkB,IACzDD,2BAAAA,IAACC,SAAAA,UAAA,EAAS,MAAM,OAAO,QAAO,QAAO,SAAkB;AAAA,EAC7D;AACA,MAAI,SAAS,WAAW,SAAS,cAAc,SAAS,YAAY,SAAS,QAAW;AACtF,QAAI,OAAO,UAAU,YAAY,CAAC,OAAO,SAAS,KAAK,GAAG;AACxD,YAAM,IAAI,MAAM,YAAY,KAAK,GAAG,yCAAyC,QAAQ,IAAI,EAAE;AAAA,IAC7F;AACA,UAAM,cAAc,SAAS,SAAS,UAAU,UAAU,SAAS,aAAa,OAAO;AACvF,UAAM,YAAY,gBAAgB,WAAW,QAAQ,IACjD,IAAIC,OAAAA,WAAW,KAAK,IAAI,KAAK,GAAG,WAAW,CAAC,KAAKA,OAAAA,WAAW,OAAO,WAAW;AAClF,WAAOF,+BAAC,UAAK,WAAU,aAAY,OAAO,OAAO,KAAK,GAAI,UAAA,UAAA,CAAU;AAAA,EACtE;AACA,MAAI,SAAS,QAAQ;AACnB,QAAI,OAAO,UAAU,YAAY,OAAO,UAAU,YAAY,EAAE,iBAAiB,OAAO;AACtF,YAAM,IAAI,MAAM,YAAY,KAAK,GAAG,gCAAgC;AAAA,IACtE;AACA,0CAAQ,QAAA,EAAK,UAAU,IAAI,KAAK,KAAK,EAAE,YAAA,GAAe,OAAO,OAAO,KAAK,GAAI,UAAA,IAAI,KAAK,KAAK,EAAE,eAAc;AAAA,EAC7G;AACA,MAAI,SAAS,aAAa,OAAO,UAAU,WAAW;AACpD,UAAM,IAAI,MAAM,YAAY,KAAK,GAAG,sBAAsB;AAAA,EAC5D;AACA,MAAI,OAAO,UAAU,WAAW;AAC9B,0CAAQ,SAAA,EAAM,MAAK,YAAW,SAAS,OAAO,UAAQ,MAAC,cAAY,GAAG,KAAK,GAAG,UAAU,OAAO,OAAO,KAAK,GAAG,WAAU,0BAAyB;AAAA,EACnJ;AACA,wCAAQ,QAAA,EAAK,WAAU,6CAA6C,UAAA,OAAO,KAAK,GAAE;AACpF;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PropertyValue.d.ts","sourceRoot":"","sources":["../../src/data/PropertyValue.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEtE,wBAAgB,aAAa,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,iBAAiB,CAAA;CAAE,+BAgCpG"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { formatUnit } from "../lib/format.js";
|
|
3
|
+
import { JsonView } from "./JsonView.js";
|
|
4
|
+
function PropertyValue({ item, density }) {
|
|
5
|
+
const { value, type, unit } = item;
|
|
6
|
+
if (value === null || value === void 0) {
|
|
7
|
+
return /* @__PURE__ */ jsx("span", { className: "font-mono italic text-muted-foreground", children: "null" });
|
|
8
|
+
}
|
|
9
|
+
if (type === "json" || type === void 0 && typeof value === "object") {
|
|
10
|
+
return typeof value === "string" ? /* @__PURE__ */ jsx(JsonView, { source: value, format: "json", density }) : /* @__PURE__ */ jsx(JsonView, { data: value, format: "json", density });
|
|
11
|
+
}
|
|
12
|
+
if (type === "bytes" || type === "duration" || type === "number" || unit !== void 0) {
|
|
13
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
14
|
+
throw new Error(`Property ${item.key}: expected a finite numeric value for ${type ?? unit}`);
|
|
15
|
+
}
|
|
16
|
+
const displayUnit = unit ?? (type === "bytes" ? "bytes" : type === "duration" ? "ms" : void 0);
|
|
17
|
+
const formatted = displayUnit === "bytes" && value < 0 ? `-${formatUnit(Math.abs(value), displayUnit)}` : formatUnit(value, displayUnit);
|
|
18
|
+
return /* @__PURE__ */ jsx("span", { className: "font-mono", title: String(value), children: formatted });
|
|
19
|
+
}
|
|
20
|
+
if (type === "date") {
|
|
21
|
+
if (typeof value !== "number" && typeof value !== "string" && !(value instanceof Date)) {
|
|
22
|
+
throw new Error(`Property ${item.key}: expected a date or timestamp`);
|
|
23
|
+
}
|
|
24
|
+
return /* @__PURE__ */ jsx("time", { dateTime: new Date(value).toISOString(), title: String(value), children: new Date(value).toISOString() });
|
|
25
|
+
}
|
|
26
|
+
if (type === "boolean" && typeof value !== "boolean") {
|
|
27
|
+
throw new Error(`Property ${item.key}: expected a boolean`);
|
|
28
|
+
}
|
|
29
|
+
if (typeof value === "boolean") {
|
|
30
|
+
return /* @__PURE__ */ jsx("input", { type: "checkbox", checked: value, disabled: true, "aria-label": `${item.key} value`, title: String(value), className: "h-4 w-4 accent-primary" });
|
|
31
|
+
}
|
|
32
|
+
return /* @__PURE__ */ jsx("span", { className: "whitespace-pre-wrap break-words font-mono", children: String(value) });
|
|
33
|
+
}
|
|
34
|
+
export {
|
|
35
|
+
PropertyValue
|
|
36
|
+
};
|
|
37
|
+
//# sourceMappingURL=PropertyValue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PropertyValue.js","sources":["../../src/data/PropertyValue.tsx"],"sourcesContent":["import { formatUnit } from \"../lib/format\";\nimport { JsonView } from \"./JsonView\";\nimport type { PropertiesDensity, PropertiesItem } from \"./Properties\";\n\nexport function PropertyValue({ item, density }: { item: PropertiesItem; density: PropertiesDensity }) {\n const { value, type, unit } = item;\n if (value === null || value === undefined) {\n return <span className=\"font-mono italic text-muted-foreground\">null</span>;\n }\n if (type === \"json\" || (type === undefined && typeof value === \"object\")) {\n return typeof value === \"string\"\n ? <JsonView source={value} format=\"json\" density={density} />\n : <JsonView data={value} format=\"json\" density={density} />;\n }\n if (type === \"bytes\" || type === \"duration\" || type === \"number\" || unit !== undefined) {\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n throw new Error(`Property ${item.key}: expected a finite numeric value for ${type ?? unit}`);\n }\n const displayUnit = unit ?? (type === \"bytes\" ? \"bytes\" : type === \"duration\" ? \"ms\" : undefined);\n const formatted = displayUnit === \"bytes\" && value < 0\n ? `-${formatUnit(Math.abs(value), displayUnit)}` : formatUnit(value, displayUnit);\n return <span className=\"font-mono\" title={String(value)}>{formatted}</span>;\n }\n if (type === \"date\") {\n if (typeof value !== \"number\" && typeof value !== \"string\" && !(value instanceof Date)) {\n throw new Error(`Property ${item.key}: expected a date or timestamp`);\n }\n return <time dateTime={new Date(value).toISOString()} title={String(value)}>{new Date(value).toISOString()}</time>;\n }\n if (type === \"boolean\" && typeof value !== \"boolean\") {\n throw new Error(`Property ${item.key}: expected a boolean`);\n }\n if (typeof value === \"boolean\") {\n return <input type=\"checkbox\" checked={value} disabled aria-label={`${item.key} value`} title={String(value)} className=\"h-4 w-4 accent-primary\" />;\n }\n return <span className=\"whitespace-pre-wrap break-words font-mono\">{String(value)}</span>;\n}\n"],"names":[],"mappings":";;;AAIO,SAAS,cAAc,EAAE,MAAM,WAAiE;AACrG,QAAM,EAAE,OAAO,MAAM,KAAA,IAAS;AAC9B,MAAI,UAAU,QAAQ,UAAU,QAAW;AACzC,WAAO,oBAAC,QAAA,EAAK,WAAU,0CAAyC,UAAA,QAAI;AAAA,EACtE;AACA,MAAI,SAAS,UAAW,SAAS,UAAa,OAAO,UAAU,UAAW;AACxE,WAAO,OAAO,UAAU,WACpB,oBAAC,UAAA,EAAS,QAAQ,OAAO,QAAO,QAAO,QAAA,CAAkB,IACzD,oBAAC,UAAA,EAAS,MAAM,OAAO,QAAO,QAAO,SAAkB;AAAA,EAC7D;AACA,MAAI,SAAS,WAAW,SAAS,cAAc,SAAS,YAAY,SAAS,QAAW;AACtF,QAAI,OAAO,UAAU,YAAY,CAAC,OAAO,SAAS,KAAK,GAAG;AACxD,YAAM,IAAI,MAAM,YAAY,KAAK,GAAG,yCAAyC,QAAQ,IAAI,EAAE;AAAA,IAC7F;AACA,UAAM,cAAc,SAAS,SAAS,UAAU,UAAU,SAAS,aAAa,OAAO;AACvF,UAAM,YAAY,gBAAgB,WAAW,QAAQ,IACjD,IAAI,WAAW,KAAK,IAAI,KAAK,GAAG,WAAW,CAAC,KAAK,WAAW,OAAO,WAAW;AAClF,WAAO,oBAAC,UAAK,WAAU,aAAY,OAAO,OAAO,KAAK,GAAI,UAAA,UAAA,CAAU;AAAA,EACtE;AACA,MAAI,SAAS,QAAQ;AACnB,QAAI,OAAO,UAAU,YAAY,OAAO,UAAU,YAAY,EAAE,iBAAiB,OAAO;AACtF,YAAM,IAAI,MAAM,YAAY,KAAK,GAAG,gCAAgC;AAAA,IACtE;AACA,+BAAQ,QAAA,EAAK,UAAU,IAAI,KAAK,KAAK,EAAE,YAAA,GAAe,OAAO,OAAO,KAAK,GAAI,UAAA,IAAI,KAAK,KAAK,EAAE,eAAc;AAAA,EAC7G;AACA,MAAI,SAAS,aAAa,OAAO,UAAU,WAAW;AACpD,UAAM,IAAI,MAAM,YAAY,KAAK,GAAG,sBAAsB;AAAA,EAC5D;AACA,MAAI,OAAO,UAAU,WAAW;AAC9B,+BAAQ,SAAA,EAAM,MAAK,YAAW,SAAS,OAAO,UAAQ,MAAC,cAAY,GAAG,KAAK,GAAG,UAAU,OAAO,OAAO,KAAK,GAAG,WAAU,0BAAyB;AAAA,EACnJ;AACA,6BAAQ,QAAA,EAAK,WAAU,6CAA6C,UAAA,OAAO,KAAK,GAAE;AACpF;"}
|
package/dist/data/Tree.cjs
CHANGED
|
@@ -127,6 +127,7 @@ function Tree({
|
|
|
127
127
|
ariaLabel,
|
|
128
128
|
showControls = true,
|
|
129
129
|
showSearch = false,
|
|
130
|
+
searchLabel,
|
|
130
131
|
searchQuery,
|
|
131
132
|
onSearchQueryChange,
|
|
132
133
|
expandAll: controlledExpandAll,
|
|
@@ -216,9 +217,9 @@ function Tree({
|
|
|
216
217
|
type: "search",
|
|
217
218
|
value: filterQuery,
|
|
218
219
|
onChange: (event) => setFilterQuery(event.target.value),
|
|
219
|
-
placeholder: "Filter tree",
|
|
220
|
-
className: "h-5 w-full min-w-0 border-0 bg-transparent p-0 text-xs outline-none placeholder:text-placeholder",
|
|
221
|
-
"aria-label": "Filter tree nodes"
|
|
220
|
+
placeholder: searchLabel ?? "Filter tree",
|
|
221
|
+
className: "h-5 w-full min-w-0 border-0 bg-transparent p-0 text-xs outline-none placeholder:text-placeholder [&::-webkit-search-cancel-button]:appearance-none",
|
|
222
|
+
"aria-label": searchLabel ?? "Filter tree nodes"
|
|
222
223
|
}
|
|
223
224
|
),
|
|
224
225
|
filterQuery && /* @__PURE__ */ jsxRuntime.jsx(
|
package/dist/data/Tree.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tree.cjs","sources":["../../src/data/Tree.tsx"],"sourcesContent":["import { useMemo, useState, type ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { Icon } from \"./Icon\";\nimport { UiClose, UiCollapseAll, UiExpandAll, UiSearch } from \"../icons\";\nimport { TreeNode, type TreeNodeProps } from \"./TreeNode\";\n\nexport type TreeProps<T> = Omit<\n TreeNodeProps<T>,\n \"node\" | \"depth\" | \"expandAll\" | \"forcedOpenKeys\"\n> & {\n /** Root nodes to render. */\n roots: T[];\n /** Empty-state content when no roots are provided. */\n empty?: ReactNode;\n /** Classes applied to the tree root. */\n className?: string;\n /** Accessible name applied to the tree root. */\n ariaLabel?: string;\n /**\n * Render the Expand all / Collapse all toolbar above the tree. Enabled by\n * default. Set to false to suppress when the tree is tiny or the controls\n * are owned externally.\n */\n showControls?: boolean;\n /** Keep search visible for small or empty trees. */\n showSearch?: boolean;\n /** URL or parent-controlled search query. */\n searchQuery?: string;\n onSearchQueryChange?: (query: string) => void;\n /**\n * Externally controlled expand-all state. When provided together with\n * `onExpandAllChange`, the tree is controlled; otherwise it manages the\n * toolbar state internally.\n */\n expandAll?: boolean | null;\n /** Called when the toolbar expand-all state changes. */\n onExpandAllChange?: (next: boolean | null) => void;\n /** Classes applied to the search/control toolbar. */\n toolbarClassName?: string;\n /**\n * Extra controls rendered in the toolbar's right-hand group, before Expand\n * all / Collapse all. Providing actions shows the toolbar even when the tree\n * is too small for the filter and `showControls` is off.\n */\n actions?: ReactNode;\n /**\n * Override the text the filter matches against for a given node.\n * Defaults to a recursive walk of the node's own fields (excluding\n * its `children` and any secondary children), which works for\n * plain-shape trees but leaks text from nested domain objects —\n * e.g. a SQL Table's Field rows are marked secondary, yet the\n * parent record still carries `record.fields[].field` strings that\n * the default walker would collect. Callers that need precise\n * control over search behaviour should return only the text they\n * want surfaced (the node's own display label / id / type).\n */\n getSearchText?: (node: T) => string;\n /**\n * Force-open the ancestors of the `selected` node so it is always revealed,\n * even when its branch was collapsed (a deep-link, a programmatic selection\n * from outside the tree, or simply a folder the user never opened). While a\n * node is selected its ancestors cannot be collapsed. Off by default; other\n * nodes keep their normal expand state. Requires `selected` to be set.\n */\n revealSelected?: boolean;\n};\n\n// ancestorPathKeys returns the keys of every ancestor on the path from a root\n// down to `target` (excluding target itself — opening the ancestors is what\n// makes target render). Matches by getKey so it is robust to object identity\n// across roots rebuilds. Returns null when target is not found.\nfunction ancestorPathKeys<T>(\n roots: T[],\n getChildren: TreeProps<T>[\"getChildren\"],\n getKey: TreeProps<T>[\"getKey\"],\n target: T,\n): Set<string | number> | null {\n const targetKey = getKey(target);\n const path: (string | number)[] = [];\n const visit = (node: T): boolean => {\n if (getKey(node) === targetKey) return true;\n for (const child of getChildren(node) ?? []) {\n if (visit(child)) {\n path.push(getKey(node));\n return true;\n }\n }\n return false;\n };\n for (const root of roots) {\n if (visit(root)) return path.length ? new Set(path) : null;\n }\n return null;\n}\n\n// mergeKeySets unions two optional key sets, preserving the null fast-path when\n// both are empty so consumers without a filter or reveal pass null downstream.\nfunction mergeKeySets(\n a: Set<string | number> | null,\n b: Set<string | number> | null,\n): Set<string | number> | null {\n if (!a) return b;\n if (!b) return a;\n return new Set([...a, ...b]);\n}\n\n// Edge counting, search-text collection and filtering all walk the tree through\n// the synchronous `getChildren` only. A lazy node (one declared via\n// `hasMoreChildren` whose children have not been fetched yet) therefore\n// contributes no edges and no search text until the operator expands it — so it\n// is invisible to \"expand all\" and to the filter while still collapsed. This is\n// intentional: we never trigger network loads from bulk/search operations.\nfunction countTreeEdges<T>(roots: T[], getChildren: TreeProps<T>[\"getChildren\"]) {\n let total = 0;\n const stack = [...roots];\n\n while (stack.length > 0) {\n const node = stack.pop()!;\n const children = getChildren(node) ?? [];\n total += children.length;\n stack.push(...children);\n }\n\n return total;\n}\n\nfunction collectTreeSearchText(\n value: unknown,\n excluded = new Set<unknown>(),\n seen = new Set<unknown>(),\n): string {\n if (value == null || excluded.has(value)) return \"\";\n\n if (\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\" ||\n typeof value === \"bigint\"\n ) {\n return String(value);\n }\n\n if (typeof value !== \"object\") return \"\";\n if (seen.has(value)) return \"\";\n seen.add(value);\n\n if (Array.isArray(value)) {\n return value\n .map((entry) => collectTreeSearchText(entry, excluded, seen))\n .filter(Boolean)\n .join(\" \");\n }\n\n const preferredKeys = [\"label\", \"name\", \"title\", \"text\", \"plain\", \"id\", \"content\"];\n const record = value as Record<string, unknown>;\n const chunks: string[] = [];\n\n for (const key of preferredKeys) {\n if (!(key in record)) continue;\n const text = collectTreeSearchText(record[key], excluded, seen);\n if (text) chunks.push(text);\n }\n\n for (const [key, entry] of Object.entries(record)) {\n if (key === \"children\" || preferredKeys.includes(key)) continue;\n const text = collectTreeSearchText(entry, excluded, seen);\n if (text) chunks.push(text);\n }\n\n return chunks.join(\" \");\n}\n\nfunction nodeSearchText<T>(node: T, children: ReturnType<TreeProps<T>[\"getChildren\"]>) {\n const excluded = new Set<unknown>();\n if (children) excluded.add(children);\n return collectTreeSearchText(node, excluded).trim().toLowerCase();\n}\n\nfunction filterTreeRoots<T>(\n roots: T[],\n getChildren: TreeProps<T>[\"getChildren\"],\n getKey: TreeProps<T>[\"getKey\"],\n query: string,\n isSecondary?: (node: T) => boolean,\n getSearchText?: (node: T) => string,\n) {\n const normalizedQuery = query.trim().toLowerCase();\n if (!normalizedQuery) {\n return {\n roots,\n filteredChildren: null as Map<string | number, T[]> | null,\n forcedOpenKeys: null as Set<string | number> | null,\n };\n }\n\n const filteredChildren = new Map<string | number, T[]>();\n const forcedOpenKeys = new Set<string | number>();\n\n function matchText(node: T, children: T[]): string {\n // Honour the caller-supplied text extractor first — it's the\n // only way to get precise control over what the filter sees when\n // the node carries domain data whose fields would otherwise leak\n // into the default walker.\n if (getSearchText) return getSearchText(node).trim().toLowerCase();\n // Match-text skips secondary children so e.g. a Table's search\n // text only draws from the Table itself, not from its Field\n // rows. The Table is primary, so its own text still counts.\n const searchChildren = children.filter((c) => !isSecondary?.(c));\n return nodeSearchText(node, searchChildren);\n }\n\n function visit(node: T): boolean {\n // A secondary node never drives a filter match — it's\n // effectively invisible to search. Still rendered when the\n // caller opens the parent manually. This is what lets a 28k-row\n // field tree stay searchable at the record level without \"field\n // name contains 'x'\" matches spamming the results.\n if (isSecondary?.(node)) return false;\n\n const key = getKey(node);\n const children = getChildren(node) ?? [];\n const childrenAllSecondary =\n children.length > 0 && children.every((child) => isSecondary?.(child));\n const matches = matchText(node, children).includes(normalizedQuery);\n const visibleChildren: T[] = [];\n\n for (const child of children) {\n if (visit(child)) visibleChildren.push(child);\n }\n\n if (matches) {\n if (children.length > 0) {\n filteredChildren.set(key, children);\n if (!childrenAllSecondary) forcedOpenKeys.add(key);\n }\n return true;\n }\n\n if (visibleChildren.length > 0) {\n filteredChildren.set(key, visibleChildren);\n forcedOpenKeys.add(key);\n return true;\n }\n\n return false;\n }\n\n return {\n roots: roots.filter((root) => visit(root)),\n filteredChildren,\n forcedOpenKeys,\n };\n}\n\nexport function Tree<T>({\n roots,\n empty,\n className,\n ariaLabel,\n showControls = true,\n showSearch = false,\n searchQuery,\n onSearchQueryChange,\n expandAll: controlledExpandAll,\n onExpandAllChange,\n toolbarClassName,\n actions,\n getSearchText,\n revealSelected = false,\n ...nodeProps\n}: TreeProps<T>) {\n const [internalExpandAll, setInternalExpandAll] = useState<boolean | null>(null);\n const [internalFilterQuery, setInternalFilterQuery] = useState(\"\");\n const filterQuery = searchQuery ?? internalFilterQuery;\n const setFilterQuery = (next: string) => {\n if (searchQuery !== undefined) onSearchQueryChange?.(next);\n else setInternalFilterQuery(next);\n };\n const basePaddingPx = nodeProps.basePaddingPx ?? 8;\n const isControlled = onExpandAllChange !== undefined;\n const expandAll = isControlled ? (controlledExpandAll ?? null) : internalExpandAll;\n const totalEdges = useMemo(\n () => countTreeEdges(roots, nodeProps.getChildren),\n [roots, nodeProps.getChildren],\n );\n const showFilter = showSearch || totalEdges > 20 || Boolean(searchQuery);\n const activeFilter = showFilter ? filterQuery : \"\";\n const filteredTree = useMemo(\n () =>\n filterTreeRoots(\n roots,\n nodeProps.getChildren,\n nodeProps.getKey,\n activeFilter,\n nodeProps.isSecondary,\n getSearchText,\n ),\n [\n roots,\n nodeProps.getChildren,\n nodeProps.getKey,\n activeFilter,\n nodeProps.isSecondary,\n getSearchText,\n ],\n );\n const treeRoots = filteredTree.roots;\n const filteredChildren = filteredTree.filteredChildren;\n // Force-open the selected node's ancestors when revealSelected is set, unioned\n // with the filter's own forced-open keys. Recomputed when the selection moves\n // so the tree follows it without a remount.\n const revealKeys = useMemo(\n () =>\n revealSelected && nodeProps.selected\n ? ancestorPathKeys(roots, nodeProps.getChildren, nodeProps.getKey, nodeProps.selected)\n : null,\n [revealSelected, roots, nodeProps.getChildren, nodeProps.getKey, nodeProps.selected],\n );\n const forcedOpenKeys = useMemo(\n () => mergeKeySets(filteredTree.forcedOpenKeys, revealKeys),\n [filteredTree.forcedOpenKeys, revealKeys],\n );\n const effectiveGetChildren = filteredChildren\n ? (node: T) => filteredChildren.get(nodeProps.getKey(node)) ?? []\n : nodeProps.getChildren;\n const effectiveExpandAll = expandAll;\n const effectiveEmpty = activeFilter.trim() ? (\n <div className=\"px-3 py-4 text-sm text-muted-foreground\">No matching tree nodes.</div>\n ) : (\n empty\n );\n const showControlButtons = showControls && roots.length > 0;\n const showVirtualRow = showFilter || showControlButtons || actions != null;\n const setExpandAll = (next: boolean | null) => {\n if (isControlled) onExpandAllChange?.(next);\n else setInternalExpandAll(next);\n };\n\n if (treeRoots.length === 0 && !showVirtualRow) return <>{effectiveEmpty ?? null}</>;\n\n return (\n <div className={cn(\"flex flex-col min-h-0\", className)}>\n <div\n role=\"tree\"\n aria-label={ariaLabel}\n className=\"min-h-0 flex-1 overflow-auto\"\n >\n {showVirtualRow && (\n <div\n role=\"presentation\"\n className={cn(\n \"sticky top-0 z-10 flex items-center gap-1.5 border-b border-border/70 bg-background/95 py-1 pr-2 text-sm backdrop-blur supports-[backdrop-filter]:bg-background/80\",\n toolbarClassName,\n )}\n style={{ paddingLeft: `${basePaddingPx}px` }}\n >\n {showFilter ? (\n <Icon icon={UiSearch} className=\"w-3 shrink-0 text-xs text-muted-foreground\" />\n ) : (\n <span className=\"w-3 shrink-0\" aria-hidden />\n )}\n\n {showFilter ? (\n <label className=\"flex min-w-0 flex-1 items-center gap-2 rounded-md border border-border bg-background px-2 py-1 text-xs text-foreground shadow-sm\">\n <input\n type=\"search\"\n value={filterQuery}\n onChange={(event) => setFilterQuery(event.target.value)}\n placeholder=\"Filter tree\"\n className=\"h-5 w-full min-w-0 border-0 bg-transparent p-0 text-xs outline-none placeholder:text-placeholder\"\n aria-label=\"Filter tree nodes\"\n />\n {filterQuery && (\n <button\n type=\"button\"\n onClick={() => setFilterQuery(\"\")}\n className=\"inline-flex items-center rounded p-0.5 text-muted-foreground hover:bg-accent hover:text-accent-foreground\"\n aria-label=\"Clear tree filter\"\n title=\"Clear tree filter\"\n >\n <Icon icon={UiClose} className=\"text-xs\" />\n </button>\n )}\n </label>\n ) : (\n <span className=\"flex-1\" />\n )}\n\n {(showControlButtons || actions != null) && (\n <div className=\"ml-auto flex items-center gap-1\">\n {actions}\n {showControlButtons && (\n <>\n <button\n type=\"button\"\n onClick={() => setExpandAll(true)}\n aria-pressed={effectiveExpandAll === true}\n aria-label=\"Expand all\"\n title=\"Expand all\"\n disabled={activeFilter.trim().length > 0}\n className={cn(\n \"inline-flex h-6 w-6 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-accent-foreground disabled:cursor-not-allowed disabled:opacity-50\",\n effectiveExpandAll === true && \"bg-accent text-accent-foreground\",\n )}\n >\n <Icon icon={UiExpandAll} className=\"text-sm\" />\n </button>\n <button\n type=\"button\"\n onClick={() => setExpandAll(false)}\n aria-pressed={effectiveExpandAll === false}\n aria-label=\"Collapse all\"\n title=\"Collapse all\"\n disabled={activeFilter.trim().length > 0}\n className={cn(\n \"inline-flex h-6 w-6 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-accent-foreground disabled:cursor-not-allowed disabled:opacity-50\",\n effectiveExpandAll === false && \"bg-accent text-accent-foreground\",\n )}\n >\n <Icon icon={UiCollapseAll} className=\"text-sm\" />\n </button>\n </>\n )}\n </div>\n )}\n </div>\n )}\n\n {treeRoots.length === 0 ? (\n (effectiveEmpty ?? null)\n ) : (\n <>\n {treeRoots.map((root) => (\n <TreeNode<T>\n {...nodeProps}\n key={nodeProps.getKey(root)}\n node={root}\n expandAll={effectiveExpandAll}\n forcedOpenKeys={forcedOpenKeys}\n getChildren={effectiveGetChildren}\n />\n ))}\n </>\n )}\n </div>\n </div>\n );\n}\n"],"names":["useState","useMemo","jsx","Fragment","cn","jsxs","Icon","UiSearch","UiClose","UiExpandAll","UiCollapseAll","createElement","TreeNode"],"mappings":";;;;;;;;;;;AAuEA,SAAS,iBACP,OACA,aACA,QACA,QAC6B;AAC7B,QAAM,YAAY,OAAO,MAAM;AAC/B,QAAM,OAA4B,CAAA;AAClC,QAAM,QAAQ,CAAC,SAAqB;AAClC,QAAI,OAAO,IAAI,MAAM,UAAW,QAAO;AACvC,eAAW,SAAS,YAAY,IAAI,KAAK,CAAA,GAAI;AAC3C,UAAI,MAAM,KAAK,GAAG;AAChB,aAAK,KAAK,OAAO,IAAI,CAAC;AACtB,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACA,aAAW,QAAQ,OAAO;AACxB,QAAI,MAAM,IAAI,EAAG,QAAO,KAAK,SAAS,IAAI,IAAI,IAAI,IAAI;AAAA,EACxD;AACA,SAAO;AACT;AAIA,SAAS,aACP,GACA,GAC6B;AAC7B,MAAI,CAAC,EAAG,QAAO;AACf,MAAI,CAAC,EAAG,QAAO;AACf,6BAAW,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;AAC7B;AAQA,SAAS,eAAkB,OAAY,aAA0C;AAC/E,MAAI,QAAQ;AACZ,QAAM,QAAQ,CAAC,GAAG,KAAK;AAEvB,SAAO,MAAM,SAAS,GAAG;AACvB,UAAM,OAAO,MAAM,IAAA;AACnB,UAAM,WAAW,YAAY,IAAI,KAAK,CAAA;AACtC,aAAS,SAAS;AAClB,UAAM,KAAK,GAAG,QAAQ;AAAA,EACxB;AAEA,SAAO;AACT;AAEA,SAAS,sBACP,OACA,WAAW,oBAAI,OACf,OAAO,oBAAI,OACH;AACR,MAAI,SAAS,QAAQ,SAAS,IAAI,KAAK,EAAG,QAAO;AAEjD,MACE,OAAO,UAAU,YACjB,OAAO,UAAU,YACjB,OAAO,UAAU,aACjB,OAAO,UAAU,UACjB;AACA,WAAO,OAAO,KAAK;AAAA,EACrB;AAEA,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,MAAI,KAAK,IAAI,KAAK,EAAG,QAAO;AAC5B,OAAK,IAAI,KAAK;AAEd,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,WAAO,MACJ,IAAI,CAAC,UAAU,sBAAsB,OAAO,UAAU,IAAI,CAAC,EAC3D,OAAO,OAAO,EACd,KAAK,GAAG;AAAA,EACb;AAEA,QAAM,gBAAgB,CAAC,SAAS,QAAQ,SAAS,QAAQ,SAAS,MAAM,SAAS;AACjF,QAAM,SAAS;AACf,QAAM,SAAmB,CAAA;AAEzB,aAAW,OAAO,eAAe;AAC/B,QAAI,EAAE,OAAO,QAAS;AACtB,UAAM,OAAO,sBAAsB,OAAO,GAAG,GAAG,UAAU,IAAI;AAC9D,QAAI,KAAM,QAAO,KAAK,IAAI;AAAA,EAC5B;AAEA,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,QAAI,QAAQ,cAAc,cAAc,SAAS,GAAG,EAAG;AACvD,UAAM,OAAO,sBAAsB,OAAO,UAAU,IAAI;AACxD,QAAI,KAAM,QAAO,KAAK,IAAI;AAAA,EAC5B;AAEA,SAAO,OAAO,KAAK,GAAG;AACxB;AAEA,SAAS,eAAkB,MAAS,UAAmD;AACrF,QAAM,+BAAe,IAAA;AACrB,MAAI,SAAU,UAAS,IAAI,QAAQ;AACnC,SAAO,sBAAsB,MAAM,QAAQ,EAAE,KAAA,EAAO,YAAA;AACtD;AAEA,SAAS,gBACP,OACA,aACA,QACA,OACA,aACA,eACA;AACA,QAAM,kBAAkB,MAAM,KAAA,EAAO,YAAA;AACrC,MAAI,CAAC,iBAAiB;AACpB,WAAO;AAAA,MACL;AAAA,MACA,kBAAkB;AAAA,MAClB,gBAAgB;AAAA,IAAA;AAAA,EAEpB;AAEA,QAAM,uCAAuB,IAAA;AAC7B,QAAM,qCAAqB,IAAA;AAE3B,WAAS,UAAU,MAAS,UAAuB;AAKjD,QAAI,cAAe,QAAO,cAAc,IAAI,EAAE,KAAA,EAAO,YAAA;AAIrD,UAAM,iBAAiB,SAAS,OAAO,CAAC,MAAM,EAAC,2CAAc,GAAE;AAC/D,WAAO,eAAe,MAAM,cAAc;AAAA,EAC5C;AAEA,WAAS,MAAM,MAAkB;AAM/B,QAAI,2CAAc,MAAO,QAAO;AAEhC,UAAM,MAAM,OAAO,IAAI;AACvB,UAAM,WAAW,YAAY,IAAI,KAAK,CAAA;AACtC,UAAM,uBACJ,SAAS,SAAS,KAAK,SAAS,MAAM,CAAC,UAAU,2CAAc,MAAM;AACvE,UAAM,UAAU,UAAU,MAAM,QAAQ,EAAE,SAAS,eAAe;AAClE,UAAM,kBAAuB,CAAA;AAE7B,eAAW,SAAS,UAAU;AAC5B,UAAI,MAAM,KAAK,EAAG,iBAAgB,KAAK,KAAK;AAAA,IAC9C;AAEA,QAAI,SAAS;AACX,UAAI,SAAS,SAAS,GAAG;AACvB,yBAAiB,IAAI,KAAK,QAAQ;AAClC,YAAI,CAAC,qBAAsB,gBAAe,IAAI,GAAG;AAAA,MACnD;AACA,aAAO;AAAA,IACT;AAEA,QAAI,gBAAgB,SAAS,GAAG;AAC9B,uBAAiB,IAAI,KAAK,eAAe;AACzC,qBAAe,IAAI,GAAG;AACtB,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL,OAAO,MAAM,OAAO,CAAC,SAAS,MAAM,IAAI,CAAC;AAAA,IACzC;AAAA,IACA;AAAA,EAAA;AAEJ;AAEO,SAAS,KAAQ;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,eAAe;AAAA,EACf,aAAa;AAAA,EACb;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,iBAAiB;AAAA,EACjB,GAAG;AACL,GAAiB;AACf,QAAM,CAAC,mBAAmB,oBAAoB,IAAIA,MAAAA,SAAyB,IAAI;AAC/E,QAAM,CAAC,qBAAqB,sBAAsB,IAAIA,MAAAA,SAAS,EAAE;AACjE,QAAM,cAAc,eAAe;AACnC,QAAM,iBAAiB,CAAC,SAAiB;AACvC,QAAI,gBAAgB,OAAW,4DAAsB;AAAA,gCACzB,IAAI;AAAA,EAClC;AACA,QAAM,gBAAgB,UAAU,iBAAiB;AACjD,QAAM,eAAe,sBAAsB;AAC3C,QAAM,YAAY,eAAgB,uBAAuB,OAAQ;AACjE,QAAM,aAAaC,MAAAA;AAAAA,IACjB,MAAM,eAAe,OAAO,UAAU,WAAW;AAAA,IACjD,CAAC,OAAO,UAAU,WAAW;AAAA,EAAA;AAE/B,QAAM,aAAa,cAAc,aAAa,MAAM,QAAQ,WAAW;AACvE,QAAM,eAAe,aAAa,cAAc;AAChD,QAAM,eAAeA,MAAAA;AAAAA,IACnB,MACE;AAAA,MACE;AAAA,MACA,UAAU;AAAA,MACV,UAAU;AAAA,MACV;AAAA,MACA,UAAU;AAAA,MACV;AAAA,IAAA;AAAA,IAEJ;AAAA,MACE;AAAA,MACA,UAAU;AAAA,MACV,UAAU;AAAA,MACV;AAAA,MACA,UAAU;AAAA,MACV;AAAA,IAAA;AAAA,EACF;AAEF,QAAM,YAAY,aAAa;AAC/B,QAAM,mBAAmB,aAAa;AAItC,QAAM,aAAaA,MAAAA;AAAAA,IACjB,MACE,kBAAkB,UAAU,WACxB,iBAAiB,OAAO,UAAU,aAAa,UAAU,QAAQ,UAAU,QAAQ,IACnF;AAAA,IACN,CAAC,gBAAgB,OAAO,UAAU,aAAa,UAAU,QAAQ,UAAU,QAAQ;AAAA,EAAA;AAErF,QAAM,iBAAiBA,MAAAA;AAAAA,IACrB,MAAM,aAAa,aAAa,gBAAgB,UAAU;AAAA,IAC1D,CAAC,aAAa,gBAAgB,UAAU;AAAA,EAAA;AAE1C,QAAM,uBAAuB,mBACzB,CAAC,SAAY,iBAAiB,IAAI,UAAU,OAAO,IAAI,CAAC,KAAK,CAAA,IAC7D,UAAU;AACd,QAAM,qBAAqB;AAC3B,QAAM,iBAAiB,aAAa,KAAA,mCACjC,OAAA,EAAI,WAAU,2CAA0C,UAAA,0BAAA,CAAuB,IAEhF;AAEF,QAAM,qBAAqB,gBAAgB,MAAM,SAAS;AAC1D,QAAM,iBAAiB,cAAc,sBAAsB,WAAW;AACtE,QAAM,eAAe,CAAC,SAAyB;AAC7C,QAAI,qEAAkC;AAAA,8BACZ,IAAI;AAAA,EAChC;AAEA,MAAI,UAAU,WAAW,KAAK,CAAC,eAAgB,QAAOC,+BAAAC,WAAAA,UAAA,EAAG,4BAAkB,KAAA,CAAK;AAEhF,wCACG,OAAA,EAAI,WAAWC,MAAAA,GAAG,yBAAyB,SAAS,GACnD,UAAAC,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,cAAY;AAAA,MACZ,WAAU;AAAA,MAET,UAAA;AAAA,QAAA,kBACCA,2BAAAA;AAAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,WAAWD,MAAAA;AAAAA,cACT;AAAA,cACA;AAAA,YAAA;AAAA,YAEF,OAAO,EAAE,aAAa,GAAG,aAAa,KAAA;AAAA,YAErC,UAAA;AAAA,cAAA,aACCF,2BAAAA,IAACI,KAAAA,MAAA,EAAK,MAAMC,SAAAA,UAAU,WAAU,6CAAA,CAA6C,IAE7EL,2BAAAA,IAAC,QAAA,EAAK,WAAU,gBAAe,eAAW,MAAC;AAAA,cAG5C,aACCG,2BAAAA,KAAC,SAAA,EAAM,WAAU,oIACf,UAAA;AAAA,gBAAAH,2BAAAA;AAAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,MAAK;AAAA,oBACL,OAAO;AAAA,oBACP,UAAU,CAAC,UAAU,eAAe,MAAM,OAAO,KAAK;AAAA,oBACtD,aAAY;AAAA,oBACZ,WAAU;AAAA,oBACV,cAAW;AAAA,kBAAA;AAAA,gBAAA;AAAA,gBAEZ,eACCA,2BAAAA;AAAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,MAAK;AAAA,oBACL,SAAS,MAAM,eAAe,EAAE;AAAA,oBAChC,WAAU;AAAA,oBACV,cAAW;AAAA,oBACX,OAAM;AAAA,oBAEN,UAAAA,2BAAAA,IAACI,WAAA,EAAK,MAAME,QAAAA,SAAS,WAAU,UAAA,CAAU;AAAA,kBAAA;AAAA,gBAAA;AAAA,cAC3C,EAAA,CAEJ,IAEAN,2BAAAA,IAAC,QAAA,EAAK,WAAU,SAAA,CAAS;AAAA,eAGzB,sBAAsB,WAAW,SACjCG,2BAAAA,KAAC,OAAA,EAAI,WAAU,mCACZ,UAAA;AAAA,gBAAA;AAAA,gBACA,sBACCA,2BAAAA,KAAAF,qBAAA,EACF,UAAA;AAAA,kBAAAD,2BAAAA;AAAAA,oBAAC;AAAA,oBAAA;AAAA,sBACC,MAAK;AAAA,sBACL,SAAS,MAAM,aAAa,IAAI;AAAA,sBAChC,gBAAc,uBAAuB;AAAA,sBACrC,cAAW;AAAA,sBACX,OAAM;AAAA,sBACN,UAAU,aAAa,KAAA,EAAO,SAAS;AAAA,sBACvC,WAAWE,MAAAA;AAAAA,wBACT;AAAA,wBACA,uBAAuB,QAAQ;AAAA,sBAAA;AAAA,sBAGjC,UAAAF,2BAAAA,IAACI,WAAA,EAAK,MAAMG,YAAAA,aAAa,WAAU,UAAA,CAAU;AAAA,oBAAA;AAAA,kBAAA;AAAA,kBAE/CP,2BAAAA;AAAAA,oBAAC;AAAA,oBAAA;AAAA,sBACC,MAAK;AAAA,sBACL,SAAS,MAAM,aAAa,KAAK;AAAA,sBACjC,gBAAc,uBAAuB;AAAA,sBACrC,cAAW;AAAA,sBACX,OAAM;AAAA,sBACN,UAAU,aAAa,KAAA,EAAO,SAAS;AAAA,sBACvC,WAAWE,MAAAA;AAAAA,wBACT;AAAA,wBACA,uBAAuB,SAAS;AAAA,sBAAA;AAAA,sBAGlC,UAAAF,2BAAAA,IAACI,WAAA,EAAK,MAAMI,cAAAA,eAAe,WAAU,UAAA,CAAU;AAAA,oBAAA;AAAA,kBAAA;AAAA,gBACjD,EAAA,CACE;AAAA,cAAA,EAAA,CAEJ;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,QAKL,UAAU,WAAW,IACnB,kBAAkB,OAEnBR,2BAAAA,IAAAC,qBAAA,EACG,UAAA,UAAU,IAAI,CAAC,SACdQ,sBAAAA;AAAAA,UAACC,SAAAA;AAAAA,UAAA;AAAA,YACE,GAAG;AAAA,YACJ,KAAK,UAAU,OAAO,IAAI;AAAA,YAC1B,MAAM;AAAA,YACN,WAAW;AAAA,YACX;AAAA,YACA,aAAa;AAAA,UAAA;AAAA,QAAA,CAEhB,EAAA,CACH;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA,GAGN;AAEJ;;"}
|
|
1
|
+
{"version":3,"file":"Tree.cjs","sources":["../../src/data/Tree.tsx"],"sourcesContent":["import { useMemo, useState, type ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { Icon } from \"./Icon\";\nimport { UiClose, UiCollapseAll, UiExpandAll, UiSearch } from \"../icons\";\nimport { TreeNode, type TreeNodeProps } from \"./TreeNode\";\n\nexport type TreeProps<T> = Omit<\n TreeNodeProps<T>,\n \"node\" | \"depth\" | \"expandAll\" | \"forcedOpenKeys\"\n> & {\n /** Root nodes to render. */\n roots: T[];\n /** Empty-state content when no roots are provided. */\n empty?: ReactNode;\n /** Classes applied to the tree root. */\n className?: string;\n /** Accessible name applied to the tree root. */\n ariaLabel?: string;\n /**\n * Render the Expand all / Collapse all toolbar above the tree. Enabled by\n * default. Set to false to suppress when the tree is tiny or the controls\n * are owned externally.\n */\n showControls?: boolean;\n /** Keep search visible for small or empty trees. */\n showSearch?: boolean;\n /** Placeholder and accessible name of the search box, e.g. \"Filter tests\". */\n searchLabel?: string;\n /** URL or parent-controlled search query. */\n searchQuery?: string;\n onSearchQueryChange?: (query: string) => void;\n /**\n * Externally controlled expand-all state. When provided together with\n * `onExpandAllChange`, the tree is controlled; otherwise it manages the\n * toolbar state internally.\n */\n expandAll?: boolean | null;\n /** Called when the toolbar expand-all state changes. */\n onExpandAllChange?: (next: boolean | null) => void;\n /** Classes applied to the search/control toolbar. */\n toolbarClassName?: string;\n /**\n * Extra controls rendered in the toolbar's right-hand group, before Expand\n * all / Collapse all. Providing actions shows the toolbar even when the tree\n * is too small for the filter and `showControls` is off.\n */\n actions?: ReactNode;\n /**\n * Override the text the filter matches against for a given node.\n * Defaults to a recursive walk of the node's own fields (excluding\n * its `children` and any secondary children), which works for\n * plain-shape trees but leaks text from nested domain objects —\n * e.g. a SQL Table's Field rows are marked secondary, yet the\n * parent record still carries `record.fields[].field` strings that\n * the default walker would collect. Callers that need precise\n * control over search behaviour should return only the text they\n * want surfaced (the node's own display label / id / type).\n */\n getSearchText?: (node: T) => string;\n /**\n * Force-open the ancestors of the `selected` node so it is always revealed,\n * even when its branch was collapsed (a deep-link, a programmatic selection\n * from outside the tree, or simply a folder the user never opened). While a\n * node is selected its ancestors cannot be collapsed. Off by default; other\n * nodes keep their normal expand state. Requires `selected` to be set.\n */\n revealSelected?: boolean;\n};\n\n// ancestorPathKeys returns the keys of every ancestor on the path from a root\n// down to `target` (excluding target itself — opening the ancestors is what\n// makes target render). Matches by getKey so it is robust to object identity\n// across roots rebuilds. Returns null when target is not found.\nfunction ancestorPathKeys<T>(\n roots: T[],\n getChildren: TreeProps<T>[\"getChildren\"],\n getKey: TreeProps<T>[\"getKey\"],\n target: T,\n): Set<string | number> | null {\n const targetKey = getKey(target);\n const path: (string | number)[] = [];\n const visit = (node: T): boolean => {\n if (getKey(node) === targetKey) return true;\n for (const child of getChildren(node) ?? []) {\n if (visit(child)) {\n path.push(getKey(node));\n return true;\n }\n }\n return false;\n };\n for (const root of roots) {\n if (visit(root)) return path.length ? new Set(path) : null;\n }\n return null;\n}\n\n// mergeKeySets unions two optional key sets, preserving the null fast-path when\n// both are empty so consumers without a filter or reveal pass null downstream.\nfunction mergeKeySets(\n a: Set<string | number> | null,\n b: Set<string | number> | null,\n): Set<string | number> | null {\n if (!a) return b;\n if (!b) return a;\n return new Set([...a, ...b]);\n}\n\n// Edge counting, search-text collection and filtering all walk the tree through\n// the synchronous `getChildren` only. A lazy node (one declared via\n// `hasMoreChildren` whose children have not been fetched yet) therefore\n// contributes no edges and no search text until the operator expands it — so it\n// is invisible to \"expand all\" and to the filter while still collapsed. This is\n// intentional: we never trigger network loads from bulk/search operations.\nfunction countTreeEdges<T>(roots: T[], getChildren: TreeProps<T>[\"getChildren\"]) {\n let total = 0;\n const stack = [...roots];\n\n while (stack.length > 0) {\n const node = stack.pop()!;\n const children = getChildren(node) ?? [];\n total += children.length;\n stack.push(...children);\n }\n\n return total;\n}\n\nfunction collectTreeSearchText(\n value: unknown,\n excluded = new Set<unknown>(),\n seen = new Set<unknown>(),\n): string {\n if (value == null || excluded.has(value)) return \"\";\n\n if (\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\" ||\n typeof value === \"bigint\"\n ) {\n return String(value);\n }\n\n if (typeof value !== \"object\") return \"\";\n if (seen.has(value)) return \"\";\n seen.add(value);\n\n if (Array.isArray(value)) {\n return value\n .map((entry) => collectTreeSearchText(entry, excluded, seen))\n .filter(Boolean)\n .join(\" \");\n }\n\n const preferredKeys = [\"label\", \"name\", \"title\", \"text\", \"plain\", \"id\", \"content\"];\n const record = value as Record<string, unknown>;\n const chunks: string[] = [];\n\n for (const key of preferredKeys) {\n if (!(key in record)) continue;\n const text = collectTreeSearchText(record[key], excluded, seen);\n if (text) chunks.push(text);\n }\n\n for (const [key, entry] of Object.entries(record)) {\n if (key === \"children\" || preferredKeys.includes(key)) continue;\n const text = collectTreeSearchText(entry, excluded, seen);\n if (text) chunks.push(text);\n }\n\n return chunks.join(\" \");\n}\n\nfunction nodeSearchText<T>(node: T, children: ReturnType<TreeProps<T>[\"getChildren\"]>) {\n const excluded = new Set<unknown>();\n if (children) excluded.add(children);\n return collectTreeSearchText(node, excluded).trim().toLowerCase();\n}\n\nfunction filterTreeRoots<T>(\n roots: T[],\n getChildren: TreeProps<T>[\"getChildren\"],\n getKey: TreeProps<T>[\"getKey\"],\n query: string,\n isSecondary?: (node: T) => boolean,\n getSearchText?: (node: T) => string,\n) {\n const normalizedQuery = query.trim().toLowerCase();\n if (!normalizedQuery) {\n return {\n roots,\n filteredChildren: null as Map<string | number, T[]> | null,\n forcedOpenKeys: null as Set<string | number> | null,\n };\n }\n\n const filteredChildren = new Map<string | number, T[]>();\n const forcedOpenKeys = new Set<string | number>();\n\n function matchText(node: T, children: T[]): string {\n // Honour the caller-supplied text extractor first — it's the\n // only way to get precise control over what the filter sees when\n // the node carries domain data whose fields would otherwise leak\n // into the default walker.\n if (getSearchText) return getSearchText(node).trim().toLowerCase();\n // Match-text skips secondary children so e.g. a Table's search\n // text only draws from the Table itself, not from its Field\n // rows. The Table is primary, so its own text still counts.\n const searchChildren = children.filter((c) => !isSecondary?.(c));\n return nodeSearchText(node, searchChildren);\n }\n\n function visit(node: T): boolean {\n // A secondary node never drives a filter match — it's\n // effectively invisible to search. Still rendered when the\n // caller opens the parent manually. This is what lets a 28k-row\n // field tree stay searchable at the record level without \"field\n // name contains 'x'\" matches spamming the results.\n if (isSecondary?.(node)) return false;\n\n const key = getKey(node);\n const children = getChildren(node) ?? [];\n const childrenAllSecondary =\n children.length > 0 && children.every((child) => isSecondary?.(child));\n const matches = matchText(node, children).includes(normalizedQuery);\n const visibleChildren: T[] = [];\n\n for (const child of children) {\n if (visit(child)) visibleChildren.push(child);\n }\n\n if (matches) {\n if (children.length > 0) {\n filteredChildren.set(key, children);\n if (!childrenAllSecondary) forcedOpenKeys.add(key);\n }\n return true;\n }\n\n if (visibleChildren.length > 0) {\n filteredChildren.set(key, visibleChildren);\n forcedOpenKeys.add(key);\n return true;\n }\n\n return false;\n }\n\n return {\n roots: roots.filter((root) => visit(root)),\n filteredChildren,\n forcedOpenKeys,\n };\n}\n\nexport function Tree<T>({\n roots,\n empty,\n className,\n ariaLabel,\n showControls = true,\n showSearch = false,\n searchLabel,\n searchQuery,\n onSearchQueryChange,\n expandAll: controlledExpandAll,\n onExpandAllChange,\n toolbarClassName,\n actions,\n getSearchText,\n revealSelected = false,\n ...nodeProps\n}: TreeProps<T>) {\n const [internalExpandAll, setInternalExpandAll] = useState<boolean | null>(null);\n const [internalFilterQuery, setInternalFilterQuery] = useState(\"\");\n const filterQuery = searchQuery ?? internalFilterQuery;\n const setFilterQuery = (next: string) => {\n if (searchQuery !== undefined) onSearchQueryChange?.(next);\n else setInternalFilterQuery(next);\n };\n const basePaddingPx = nodeProps.basePaddingPx ?? 8;\n const isControlled = onExpandAllChange !== undefined;\n const expandAll = isControlled ? (controlledExpandAll ?? null) : internalExpandAll;\n const totalEdges = useMemo(\n () => countTreeEdges(roots, nodeProps.getChildren),\n [roots, nodeProps.getChildren],\n );\n const showFilter = showSearch || totalEdges > 20 || Boolean(searchQuery);\n const activeFilter = showFilter ? filterQuery : \"\";\n const filteredTree = useMemo(\n () =>\n filterTreeRoots(\n roots,\n nodeProps.getChildren,\n nodeProps.getKey,\n activeFilter,\n nodeProps.isSecondary,\n getSearchText,\n ),\n [\n roots,\n nodeProps.getChildren,\n nodeProps.getKey,\n activeFilter,\n nodeProps.isSecondary,\n getSearchText,\n ],\n );\n const treeRoots = filteredTree.roots;\n const filteredChildren = filteredTree.filteredChildren;\n // Force-open the selected node's ancestors when revealSelected is set, unioned\n // with the filter's own forced-open keys. Recomputed when the selection moves\n // so the tree follows it without a remount.\n const revealKeys = useMemo(\n () =>\n revealSelected && nodeProps.selected\n ? ancestorPathKeys(roots, nodeProps.getChildren, nodeProps.getKey, nodeProps.selected)\n : null,\n [revealSelected, roots, nodeProps.getChildren, nodeProps.getKey, nodeProps.selected],\n );\n const forcedOpenKeys = useMemo(\n () => mergeKeySets(filteredTree.forcedOpenKeys, revealKeys),\n [filteredTree.forcedOpenKeys, revealKeys],\n );\n const effectiveGetChildren = filteredChildren\n ? (node: T) => filteredChildren.get(nodeProps.getKey(node)) ?? []\n : nodeProps.getChildren;\n const effectiveExpandAll = expandAll;\n const effectiveEmpty = activeFilter.trim() ? (\n <div className=\"px-3 py-4 text-sm text-muted-foreground\">No matching tree nodes.</div>\n ) : (\n empty\n );\n const showControlButtons = showControls && roots.length > 0;\n const showVirtualRow = showFilter || showControlButtons || actions != null;\n const setExpandAll = (next: boolean | null) => {\n if (isControlled) onExpandAllChange?.(next);\n else setInternalExpandAll(next);\n };\n\n if (treeRoots.length === 0 && !showVirtualRow) return <>{effectiveEmpty ?? null}</>;\n\n return (\n <div className={cn(\"flex flex-col min-h-0\", className)}>\n <div\n role=\"tree\"\n aria-label={ariaLabel}\n className=\"min-h-0 flex-1 overflow-auto\"\n >\n {showVirtualRow && (\n <div\n role=\"presentation\"\n className={cn(\n \"sticky top-0 z-10 flex items-center gap-1.5 border-b border-border/70 bg-background/95 py-1 pr-2 text-sm backdrop-blur supports-[backdrop-filter]:bg-background/80\",\n toolbarClassName,\n )}\n style={{ paddingLeft: `${basePaddingPx}px` }}\n >\n {showFilter ? (\n <Icon icon={UiSearch} className=\"w-3 shrink-0 text-xs text-muted-foreground\" />\n ) : (\n <span className=\"w-3 shrink-0\" aria-hidden />\n )}\n\n {showFilter ? (\n <label className=\"flex min-w-0 flex-1 items-center gap-2 rounded-md border border-border bg-background px-2 py-1 text-xs text-foreground shadow-sm\">\n <input\n type=\"search\"\n value={filterQuery}\n onChange={(event) => setFilterQuery(event.target.value)}\n placeholder={searchLabel ?? \"Filter tree\"}\n className=\"h-5 w-full min-w-0 border-0 bg-transparent p-0 text-xs outline-none placeholder:text-placeholder [&::-webkit-search-cancel-button]:appearance-none\"\n aria-label={searchLabel ?? \"Filter tree nodes\"}\n />\n {filterQuery && (\n <button\n type=\"button\"\n onClick={() => setFilterQuery(\"\")}\n className=\"inline-flex items-center rounded p-0.5 text-muted-foreground hover:bg-accent hover:text-accent-foreground\"\n aria-label=\"Clear tree filter\"\n title=\"Clear tree filter\"\n >\n <Icon icon={UiClose} className=\"text-xs\" />\n </button>\n )}\n </label>\n ) : (\n <span className=\"flex-1\" />\n )}\n\n {(showControlButtons || actions != null) && (\n <div className=\"ml-auto flex items-center gap-1\">\n {actions}\n {showControlButtons && (\n <>\n <button\n type=\"button\"\n onClick={() => setExpandAll(true)}\n aria-pressed={effectiveExpandAll === true}\n aria-label=\"Expand all\"\n title=\"Expand all\"\n disabled={activeFilter.trim().length > 0}\n className={cn(\n \"inline-flex h-6 w-6 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-accent-foreground disabled:cursor-not-allowed disabled:opacity-50\",\n effectiveExpandAll === true && \"bg-accent text-accent-foreground\",\n )}\n >\n <Icon icon={UiExpandAll} className=\"text-sm\" />\n </button>\n <button\n type=\"button\"\n onClick={() => setExpandAll(false)}\n aria-pressed={effectiveExpandAll === false}\n aria-label=\"Collapse all\"\n title=\"Collapse all\"\n disabled={activeFilter.trim().length > 0}\n className={cn(\n \"inline-flex h-6 w-6 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-accent-foreground disabled:cursor-not-allowed disabled:opacity-50\",\n effectiveExpandAll === false && \"bg-accent text-accent-foreground\",\n )}\n >\n <Icon icon={UiCollapseAll} className=\"text-sm\" />\n </button>\n </>\n )}\n </div>\n )}\n </div>\n )}\n\n {treeRoots.length === 0 ? (\n (effectiveEmpty ?? null)\n ) : (\n <>\n {treeRoots.map((root) => (\n <TreeNode<T>\n {...nodeProps}\n key={nodeProps.getKey(root)}\n node={root}\n expandAll={effectiveExpandAll}\n forcedOpenKeys={forcedOpenKeys}\n getChildren={effectiveGetChildren}\n />\n ))}\n </>\n )}\n </div>\n </div>\n );\n}\n"],"names":["useState","useMemo","jsx","Fragment","cn","jsxs","Icon","UiSearch","UiClose","UiExpandAll","UiCollapseAll","createElement","TreeNode"],"mappings":"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"}
|
package/dist/data/Tree.d.ts
CHANGED
|
@@ -17,6 +17,8 @@ export type TreeProps<T> = Omit<TreeNodeProps<T>, "node" | "depth" | "expandAll"
|
|
|
17
17
|
showControls?: boolean;
|
|
18
18
|
/** Keep search visible for small or empty trees. */
|
|
19
19
|
showSearch?: boolean;
|
|
20
|
+
/** Placeholder and accessible name of the search box, e.g. "Filter tests". */
|
|
21
|
+
searchLabel?: string;
|
|
20
22
|
/** URL or parent-controlled search query. */
|
|
21
23
|
searchQuery?: string;
|
|
22
24
|
onSearchQueryChange?: (query: string) => void;
|
|
@@ -57,5 +59,5 @@ export type TreeProps<T> = Omit<TreeNodeProps<T>, "node" | "depth" | "expandAll"
|
|
|
57
59
|
*/
|
|
58
60
|
revealSelected?: boolean;
|
|
59
61
|
};
|
|
60
|
-
export declare function Tree<T>({ roots, empty, className, ariaLabel, showControls, showSearch, searchQuery, onSearchQueryChange, expandAll: controlledExpandAll, onExpandAllChange, toolbarClassName, actions, getSearchText, revealSelected, ...nodeProps }: TreeProps<T>): import("react").JSX.Element;
|
|
62
|
+
export declare function Tree<T>({ roots, empty, className, ariaLabel, showControls, showSearch, searchLabel, searchQuery, onSearchQueryChange, expandAll: controlledExpandAll, onExpandAllChange, toolbarClassName, actions, getSearchText, revealSelected, ...nodeProps }: TreeProps<T>): import("react").JSX.Element;
|
|
61
63
|
//# sourceMappingURL=Tree.d.ts.map
|
package/dist/data/Tree.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tree.d.ts","sourceRoot":"","sources":["../../src/data/Tree.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAI1D,OAAO,EAAY,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AAE1D,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI,IAAI,CAC7B,aAAa,CAAC,CAAC,CAAC,EAChB,MAAM,GAAG,OAAO,GAAG,WAAW,GAAG,gBAAgB,CAClD,GAAG;IACF,4BAA4B;IAC5B,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,sDAAsD;IACtD,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,wCAAwC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gDAAgD;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,oDAAoD;IACpD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,6CAA6C;IAC7C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mBAAmB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAC3B,wDAAwD;IACxD,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,KAAK,IAAI,CAAC;IACnD,qDAAqD;IACrD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB;;;;;;;;;;OAUG;IACH,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,CAAC;IACpC;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC;AA6LF,wBAAgB,IAAI,CAAC,CAAC,EAAE,EACtB,KAAK,EACL,KAAK,EACL,SAAS,EACT,SAAS,EACT,YAAmB,EACnB,UAAkB,EAClB,WAAW,EACX,mBAAmB,EACnB,SAAS,EAAE,mBAAmB,EAC9B,iBAAiB,EACjB,gBAAgB,EAChB,OAAO,EACP,aAAa,EACb,cAAsB,EACtB,GAAG,SAAS,EACb,EAAE,SAAS,CAAC,CAAC,CAAC,+BAiLd"}
|
|
1
|
+
{"version":3,"file":"Tree.d.ts","sourceRoot":"","sources":["../../src/data/Tree.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAI1D,OAAO,EAAY,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AAE1D,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI,IAAI,CAC7B,aAAa,CAAC,CAAC,CAAC,EAChB,MAAM,GAAG,OAAO,GAAG,WAAW,GAAG,gBAAgB,CAClD,GAAG;IACF,4BAA4B;IAC5B,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,sDAAsD;IACtD,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,wCAAwC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gDAAgD;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,oDAAoD;IACpD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,8EAA8E;IAC9E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6CAA6C;IAC7C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mBAAmB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAC3B,wDAAwD;IACxD,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,KAAK,IAAI,CAAC;IACnD,qDAAqD;IACrD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB;;;;;;;;;;OAUG;IACH,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,CAAC;IACpC;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC;AA6LF,wBAAgB,IAAI,CAAC,CAAC,EAAE,EACtB,KAAK,EACL,KAAK,EACL,SAAS,EACT,SAAS,EACT,YAAmB,EACnB,UAAkB,EAClB,WAAW,EACX,WAAW,EACX,mBAAmB,EACnB,SAAS,EAAE,mBAAmB,EAC9B,iBAAiB,EACjB,gBAAgB,EAChB,OAAO,EACP,aAAa,EACb,cAAsB,EACtB,GAAG,SAAS,EACb,EAAE,SAAS,CAAC,CAAC,CAAC,+BAiLd"}
|
package/dist/data/Tree.js
CHANGED
|
@@ -125,6 +125,7 @@ function Tree({
|
|
|
125
125
|
ariaLabel,
|
|
126
126
|
showControls = true,
|
|
127
127
|
showSearch = false,
|
|
128
|
+
searchLabel,
|
|
128
129
|
searchQuery,
|
|
129
130
|
onSearchQueryChange,
|
|
130
131
|
expandAll: controlledExpandAll,
|
|
@@ -214,9 +215,9 @@ function Tree({
|
|
|
214
215
|
type: "search",
|
|
215
216
|
value: filterQuery,
|
|
216
217
|
onChange: (event) => setFilterQuery(event.target.value),
|
|
217
|
-
placeholder: "Filter tree",
|
|
218
|
-
className: "h-5 w-full min-w-0 border-0 bg-transparent p-0 text-xs outline-none placeholder:text-placeholder",
|
|
219
|
-
"aria-label": "Filter tree nodes"
|
|
218
|
+
placeholder: searchLabel ?? "Filter tree",
|
|
219
|
+
className: "h-5 w-full min-w-0 border-0 bg-transparent p-0 text-xs outline-none placeholder:text-placeholder [&::-webkit-search-cancel-button]:appearance-none",
|
|
220
|
+
"aria-label": searchLabel ?? "Filter tree nodes"
|
|
220
221
|
}
|
|
221
222
|
),
|
|
222
223
|
filterQuery && /* @__PURE__ */ jsx(
|