@@ -56,9 +56,11 @@ import { openBlockInSidebar, createBlock } from "roamjs-components/writes";
5656import getPageTitleByPageUid from "roamjs-components/queries/getPageTitleByPageUid" ;
5757import getPageUidByPageTitle from "roamjs-components/queries/getPageUidByPageTitle" ;
5858import findDiscourseNode from "~/utils/findDiscourseNode" ;
59+ import getDiscourseNodes from "~/utils/getDiscourseNodes" ;
5960import calcCanvasNodeSizeAndImg from "~/utils/calcCanvasNodeSizeAndImg" ;
6061import { useExtensionAPI } from "roamjs-components/components/ExtensionApiContext" ;
6162import { getDiscourseNodeColors } from "~/utils/getDiscourseNodeColors" ;
63+ import { formatHexColor } from "~/components/settings/DiscourseNodeCanvasSettings" ;
6264import { MAX_WIDTH } from "./Tldraw" ;
6365import getBlockProps from "~/utils/getBlockProps" ;
6466import setBlockProps from "~/utils/setBlockProps" ;
@@ -427,15 +429,13 @@ const ClipboardPageSection = ({
427429 onRemove,
428430 showNodesOnCanvas,
429431 searchQuery,
430- sortDirection,
431432 selectedNodeType,
432433 onNodeTypesChange,
433434} : {
434435 page : ClipboardPage ;
435436 onRemove : ( uid : string ) => void ;
436437 showNodesOnCanvas : boolean ;
437438 searchQuery : string ;
438- sortDirection : "asc" | "desc" ;
439439 selectedNodeType : string ;
440440 onNodeTypesChange : ( pageUid : string , types : string [ ] ) => void ;
441441} ) => {
@@ -576,18 +576,8 @@ const ClipboardPageSection = ({
576576 ? group . type === selectedNodeType
577577 : true ,
578578 )
579- . sort ( ( a , b ) =>
580- sortDirection === "asc"
581- ? a . text . localeCompare ( b . text )
582- : b . text . localeCompare ( a . text ) ,
583- ) ,
584- [
585- groupedNodes ,
586- showNodesOnCanvas ,
587- searchQuery ,
588- selectedNodeType ,
589- sortDirection ,
590- ] ,
579+ . sort ( ( a , b ) => a . text . localeCompare ( b . text ) ) ,
580+ [ groupedNodes , showNodesOnCanvas , searchQuery , selectedNodeType ] ,
591581 ) ;
592582
593583 useEffect ( ( ) => {
@@ -1140,8 +1130,6 @@ export const ClipboardPanel = () => {
11401130 const [ isModalOpen , setIsModalOpen ] = useState ( false ) ;
11411131 const [ isCollapsed , setIsCollapsed ] = useState ( false ) ;
11421132 const [ searchQuery , setSearchQuery ] = useState ( "" ) ;
1143- const [ isSearchExpanded , setIsSearchExpanded ] = useState ( false ) ;
1144- const [ sortDirection , setSortDirection ] = useState < "asc" | "desc" > ( "asc" ) ;
11451133 const [ selectedNodeType , setSelectedNodeType ] = useState ( "All" ) ;
11461134 const [ nodeTypesByPage , setNodeTypesByPage ] = useState <
11471135 Record < string , string [ ] >
@@ -1164,6 +1152,15 @@ export const ClipboardPanel = () => {
11641152 return [ "All" , ...Array . from ( allTypes ) . sort ( ) ] ;
11651153 } , [ nodeTypesByPage , pages ] ) ;
11661154
1155+ const nodeTypeColorMap = useMemo ( ( ) => {
1156+ return Object . fromEntries (
1157+ getDiscourseNodes ( ) . map ( ( n ) => [
1158+ n . text ,
1159+ formatHexColor ( n . canvasSettings ?. color ) || "#000000" ,
1160+ ] ) ,
1161+ ) ;
1162+ } , [ ] ) ;
1163+
11671164 useEffect ( ( ) => {
11681165 if (
11691166 selectedNodeType !== "All" &&
@@ -1202,7 +1199,7 @@ export const ClipboardPanel = () => {
12021199 </ h2 >
12031200 < div className = "flex-shrink-0" >
12041201 < Button
1205- icon = { < Icon icon = { isCollapsed ? "chevron-down" : " minus"} /> }
1202+ icon = { < Icon icon = " minus" /> }
12061203 onClick = { ( ) => setIsCollapsed ( ! isCollapsed ) }
12071204 minimal
12081205 small
@@ -1221,126 +1218,99 @@ export const ClipboardPanel = () => {
12211218 </ div >
12221219 { ! isCollapsed && (
12231220 < >
1224- { isSearchExpanded ? (
1225- < div
1226- className = "px-2 py-1"
1227- style = { { borderTop : "1px solid hsl(0, 0%, 91%)" } }
1228- >
1229- < InputGroup
1230- autoFocus
1231- leftIcon = "search"
1232- placeholder = "Find page"
1233- value = { searchQuery }
1234- onChange = { ( e ) => setSearchQuery ( e . target . value ) }
1235- onBlur = { ( ) => {
1236- if ( ! searchQuery ) setIsSearchExpanded ( false ) ;
1237- } }
1238- rightElement = {
1221+ < div
1222+ className = "flex items-center gap-1 px-2 py-1"
1223+ style = { { borderTop : "1px solid hsl(0, 0%, 91%)" } }
1224+ >
1225+ < InputGroup
1226+ small
1227+ leftIcon = "search"
1228+ placeholder = "Find page"
1229+ value = { searchQuery }
1230+ onChange = { ( e ) => setSearchQuery ( e . target . value ) }
1231+ className = "flex-1"
1232+ rightElement = {
1233+ searchQuery ? (
12391234 < Button
12401235 minimal
12411236 small
12421237 icon = "cross"
1243- onClick = { ( ) => {
1244- setSearchQuery ( "" ) ;
1245- setIsSearchExpanded ( false ) ;
1246- } }
1238+ onClick = { ( ) => setSearchQuery ( "" ) }
12471239 />
1248- }
1249- />
1250- </ div >
1251- ) : (
1252- < div
1253- className = "flex items-center gap-1 px-2 py-1"
1254- style = { { borderTop : "1px solid hsl(0, 0%, 91%)" } }
1240+ ) : undefined
1241+ }
1242+ />
1243+ < Popover
1244+ position = { Position . BOTTOM }
1245+ content = {
1246+ < Menu >
1247+ { availableNodeTypes . map ( ( type ) => (
1248+ < MenuItem
1249+ key = { type }
1250+ active = { selectedNodeType === type }
1251+ onClick = { ( ) => setSelectedNodeType ( type ) }
1252+ text = {
1253+ < span className = "flex items-center gap-2" >
1254+ { type !== "All" && (
1255+ < span
1256+ className = "inline-block h-3 w-3 shrink-0 rounded-full"
1257+ style = { {
1258+ backgroundColor :
1259+ nodeTypeColorMap [ type ] || "#000000" ,
1260+ } }
1261+ />
1262+ ) }
1263+ { type }
1264+ </ span >
1265+ }
1266+ />
1267+ ) ) }
1268+ </ Menu >
1269+ }
12551270 >
12561271 < Button
12571272 minimal
12581273 small
1259- icon = "search"
1260- onClick = { ( ) => setIsSearchExpanded ( true ) }
1261- />
1262- < Button
1263- minimal
1264- small
1265- icon = {
1266- sortDirection === "asc"
1267- ? "sort-alphabetical"
1268- : "sort-alphabetical-desc"
1269- }
1270- title = {
1271- sortDirection === "asc"
1272- ? "Sorted A→Z (click for Z→A)"
1273- : "Sorted Z→A (click for A→Z)"
1274- }
1275- onClick = { ( ) =>
1276- setSortDirection ( ( d ) => ( d === "asc" ? "desc" : "asc" ) )
1277- }
1274+ rightIcon = "caret-down"
1275+ text = { selectedNodeType }
12781276 />
1279- < Popover
1280- position = { Position . BOTTOM }
1281- content = {
1282- < Menu >
1283- { availableNodeTypes . map ( ( type ) => (
1284- < MenuItem
1285- key = { type }
1286- text = { type }
1287- active = { selectedNodeType === type }
1288- onClick = { ( ) => setSelectedNodeType ( type ) }
1289- />
1290- ) ) }
1291- </ Menu >
1292- }
1293- >
1294- < Button
1295- minimal
1296- small
1297- rightIcon = "caret-down"
1298- text = { selectedNodeType }
1299- />
1300- </ Popover >
1301- { hasActiveFilters && (
1302- < Button
1303- minimal
1304- small
1305- icon = "filter-remove"
1306- onClick = { ( ) => {
1307- setSearchQuery ( "" ) ;
1308- setSelectedNodeType ( "All" ) ;
1309- } }
1310- title = "Clear filters"
1311- />
1312- ) }
1313- < Popover
1314- position = { Position . BOTTOM_RIGHT }
1315- content = {
1316- < div
1317- className = "p-3"
1318- onPointerDown = { ( e ) => e . stopPropagation ( ) }
1319- style = { { pointerEvents : "all" } }
1320- >
1321- < Switch
1322- checked = { showNodesOnCanvas }
1323- alignIndicator = "right"
1324- className = "m-0 w-full"
1325- label = "Show nodes on canvas"
1326- onChange = { ( e ) =>
1327- setShowNodesOnCanvas (
1328- ( e . target as HTMLInputElement ) . checked ,
1329- )
1330- }
1331- />
1332- </ div >
1333- }
1334- >
1335- < Button
1336- minimal
1337- small
1338- icon = "settings"
1339- title = "Clipboard options"
1340- />
1341- </ Popover >
1342- </ div >
1343- ) }
1277+ </ Popover >
1278+ < Button
1279+ minimal
1280+ small
1281+ icon = "filter-remove"
1282+ disabled = { ! hasActiveFilters }
1283+ onClick = { ( ) => {
1284+ setSearchQuery ( "" ) ;
1285+ setSelectedNodeType ( "All" ) ;
1286+ } }
1287+ title = "Clear filters"
1288+ />
1289+ < Popover
1290+ position = { Position . BOTTOM_RIGHT }
1291+ content = {
1292+ < div
1293+ className = "p-3"
1294+ onPointerDown = { ( e ) => e . stopPropagation ( ) }
1295+ style = { { pointerEvents : "all" } }
1296+ >
1297+ < Switch
1298+ checked = { showNodesOnCanvas }
1299+ alignIndicator = "right"
1300+ className = "m-0 w-full"
1301+ label = "Show nodes on canvas"
1302+ onChange = { ( e ) =>
1303+ setShowNodesOnCanvas (
1304+ ( e . target as HTMLInputElement ) . checked ,
1305+ )
1306+ }
1307+ />
1308+ </ div >
1309+ }
1310+ >
1311+ < Button minimal small icon = "settings" title = "Clipboard options" />
1312+ </ Popover >
1313+ </ div >
13441314 < div className = "max-h-96 overflow-y-auto px-4 pb-4" >
13451315 { pages . length === 0 ? (
13461316 < NonIdealState
@@ -1363,7 +1333,6 @@ export const ClipboardPanel = () => {
13631333 onRemove = { removePage }
13641334 showNodesOnCanvas = { showNodesOnCanvas }
13651335 searchQuery = { searchQuery }
1366- sortDirection = { sortDirection }
13671336 selectedNodeType = { selectedNodeType }
13681337 onNodeTypesChange = { handleNodeTypesChange }
13691338 />
0 commit comments