@@ -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 ( ( ) => {
@@ -1141,8 +1131,6 @@ export const ClipboardPanel = () => {
11411131 const [ isModalOpen , setIsModalOpen ] = useState ( false ) ;
11421132 const [ isCollapsed , setIsCollapsed ] = useState ( false ) ;
11431133 const [ searchQuery , setSearchQuery ] = useState ( "" ) ;
1144- const [ isSearchExpanded , setIsSearchExpanded ] = useState ( false ) ;
1145- const [ sortDirection , setSortDirection ] = useState < "asc" | "desc" > ( "asc" ) ;
11461134 const [ selectedNodeType , setSelectedNodeType ] = useState ( "All" ) ;
11471135 const [ nodeTypesByPage , setNodeTypesByPage ] = useState <
11481136 Record < string , string [ ] >
@@ -1165,6 +1153,15 @@ export const ClipboardPanel = () => {
11651153 return [ "All" , ...Array . from ( allTypes ) . sort ( ) ] ;
11661154 } , [ nodeTypesByPage , pages ] ) ;
11671155
1156+ const nodeTypeColorMap = useMemo ( ( ) => {
1157+ return Object . fromEntries (
1158+ getDiscourseNodes ( ) . map ( ( n ) => [
1159+ n . text ,
1160+ formatHexColor ( n . canvasSettings ?. color ) || "#000000" ,
1161+ ] ) ,
1162+ ) ;
1163+ } , [ ] ) ;
1164+
11681165 useEffect ( ( ) => {
11691166 if (
11701167 selectedNodeType !== "All" &&
@@ -1203,7 +1200,7 @@ export const ClipboardPanel = () => {
12031200 </ h2 >
12041201 < div className = "flex-shrink-0" >
12051202 < Button
1206- icon = { < Icon icon = { isCollapsed ? "chevron-down" : " minus"} /> }
1203+ icon = { < Icon icon = " minus" /> }
12071204 onClick = { ( ) => setIsCollapsed ( ! isCollapsed ) }
12081205 minimal
12091206 small
@@ -1222,126 +1219,99 @@ export const ClipboardPanel = () => {
12221219 </ div >
12231220 { ! isCollapsed && (
12241221 < >
1225- { isSearchExpanded ? (
1226- < div
1227- className = "px-2 py-1"
1228- style = { { borderTop : "1px solid hsl(0, 0%, 91%)" } }
1229- >
1230- < InputGroup
1231- autoFocus
1232- leftIcon = "search"
1233- placeholder = "Find page"
1234- value = { searchQuery }
1235- onChange = { ( e ) => setSearchQuery ( e . target . value ) }
1236- onBlur = { ( ) => {
1237- if ( ! searchQuery ) setIsSearchExpanded ( false ) ;
1238- } }
1239- rightElement = {
1222+ < div
1223+ className = "flex items-center gap-1 px-2 py-1"
1224+ style = { { borderTop : "1px solid hsl(0, 0%, 91%)" } }
1225+ >
1226+ < InputGroup
1227+ small
1228+ leftIcon = "search"
1229+ placeholder = "Find page"
1230+ value = { searchQuery }
1231+ onChange = { ( e ) => setSearchQuery ( e . target . value ) }
1232+ className = "flex-1"
1233+ rightElement = {
1234+ searchQuery ? (
12401235 < Button
12411236 minimal
12421237 small
12431238 icon = "cross"
1244- onClick = { ( ) => {
1245- setSearchQuery ( "" ) ;
1246- setIsSearchExpanded ( false ) ;
1247- } }
1239+ onClick = { ( ) => setSearchQuery ( "" ) }
12481240 />
1249- }
1250- />
1251- </ div >
1252- ) : (
1253- < div
1254- className = "flex items-center gap-1 px-2 py-1"
1255- style = { { borderTop : "1px solid hsl(0, 0%, 91%)" } }
1241+ ) : undefined
1242+ }
1243+ />
1244+ < Popover
1245+ position = { Position . BOTTOM }
1246+ content = {
1247+ < Menu >
1248+ { availableNodeTypes . map ( ( type ) => (
1249+ < MenuItem
1250+ key = { type }
1251+ active = { selectedNodeType === type }
1252+ onClick = { ( ) => setSelectedNodeType ( type ) }
1253+ text = {
1254+ < span className = "flex items-center gap-2" >
1255+ { type !== "All" && (
1256+ < span
1257+ className = "inline-block h-3 w-3 shrink-0 rounded-full"
1258+ style = { {
1259+ backgroundColor :
1260+ nodeTypeColorMap [ type ] || "#000000" ,
1261+ } }
1262+ />
1263+ ) }
1264+ { type }
1265+ </ span >
1266+ }
1267+ />
1268+ ) ) }
1269+ </ Menu >
1270+ }
12561271 >
12571272 < Button
12581273 minimal
12591274 small
1260- icon = "search"
1261- onClick = { ( ) => setIsSearchExpanded ( true ) }
1262- />
1263- < Button
1264- minimal
1265- small
1266- icon = {
1267- sortDirection === "asc"
1268- ? "sort-alphabetical"
1269- : "sort-alphabetical-desc"
1270- }
1271- title = {
1272- sortDirection === "asc"
1273- ? "Sorted A→Z (click for Z→A)"
1274- : "Sorted Z→A (click for A→Z)"
1275- }
1276- onClick = { ( ) =>
1277- setSortDirection ( ( d ) => ( d === "asc" ? "desc" : "asc" ) )
1278- }
1275+ rightIcon = "caret-down"
1276+ text = { selectedNodeType }
12791277 />
1280- < Popover
1281- position = { Position . BOTTOM }
1282- content = {
1283- < Menu >
1284- { availableNodeTypes . map ( ( type ) => (
1285- < MenuItem
1286- key = { type }
1287- text = { type }
1288- active = { selectedNodeType === type }
1289- onClick = { ( ) => setSelectedNodeType ( type ) }
1290- />
1291- ) ) }
1292- </ Menu >
1293- }
1294- >
1295- < Button
1296- minimal
1297- small
1298- rightIcon = "caret-down"
1299- text = { selectedNodeType }
1300- />
1301- </ Popover >
1302- { hasActiveFilters && (
1303- < Button
1304- minimal
1305- small
1306- icon = "filter-remove"
1307- onClick = { ( ) => {
1308- setSearchQuery ( "" ) ;
1309- setSelectedNodeType ( "All" ) ;
1310- } }
1311- title = "Clear filters"
1312- />
1313- ) }
1314- < Popover
1315- position = { Position . BOTTOM_RIGHT }
1316- content = {
1317- < div
1318- className = "p-3"
1319- onPointerDown = { ( e ) => e . stopPropagation ( ) }
1320- style = { { pointerEvents : "all" } }
1321- >
1322- < Switch
1323- checked = { showNodesOnCanvas }
1324- alignIndicator = "right"
1325- className = "m-0 w-full"
1326- label = "Show nodes on canvas"
1327- onChange = { ( e ) =>
1328- setShowNodesOnCanvas (
1329- ( e . target as HTMLInputElement ) . checked ,
1330- )
1331- }
1332- />
1333- </ div >
1334- }
1335- >
1336- < Button
1337- minimal
1338- small
1339- icon = "settings"
1340- title = "Clipboard options"
1341- />
1342- </ Popover >
1343- </ div >
1344- ) }
1278+ </ Popover >
1279+ < Button
1280+ minimal
1281+ small
1282+ icon = "filter-remove"
1283+ disabled = { ! hasActiveFilters }
1284+ onClick = { ( ) => {
1285+ setSearchQuery ( "" ) ;
1286+ setSelectedNodeType ( "All" ) ;
1287+ } }
1288+ title = "Clear filters"
1289+ />
1290+ < Popover
1291+ position = { Position . BOTTOM_RIGHT }
1292+ content = {
1293+ < div
1294+ className = "p-3"
1295+ onPointerDown = { ( e ) => e . stopPropagation ( ) }
1296+ style = { { pointerEvents : "all" } }
1297+ >
1298+ < Switch
1299+ checked = { showNodesOnCanvas }
1300+ alignIndicator = "right"
1301+ className = "m-0 w-full"
1302+ label = "Show nodes on canvas"
1303+ onChange = { ( e ) =>
1304+ setShowNodesOnCanvas (
1305+ ( e . target as HTMLInputElement ) . checked ,
1306+ )
1307+ }
1308+ />
1309+ </ div >
1310+ }
1311+ >
1312+ < Button minimal small icon = "settings" title = "Clipboard options" />
1313+ </ Popover >
1314+ </ div >
13451315 < div className = "max-h-96 overflow-y-auto px-4 pb-4" >
13461316 { pages . length === 0 ? (
13471317 < NonIdealState
@@ -1364,7 +1334,6 @@ export const ClipboardPanel = () => {
13641334 onRemove = { removePage }
13651335 showNodesOnCanvas = { showNodesOnCanvas }
13661336 searchQuery = { searchQuery }
1367- sortDirection = { sortDirection }
13681337 selectedNodeType = { selectedNodeType }
13691338 onNodeTypesChange = { handleNodeTypesChange }
13701339 />
0 commit comments