1- import { useState } from "react" ;
1+ import { useState , useRef , useEffect } from "react" ;
22import { DiscourseRelationType } from "~/types" ;
33import { Notice } from "obsidian" ;
44import { usePlugin } from "./PluginContext" ;
55import generateUid from "~/utils/generateUid" ;
66import { ConfirmationModal } from "./ConfirmationModal" ;
7+ import {
8+ TLDRAW_COLOR_NAMES ,
9+ TLDRAW_COLOR_LABELS ,
10+ DEFAULT_TLDRAW_COLOR ,
11+ COLOR_PALETTE ,
12+ type TldrawColorName ,
13+ } from "~/utils/tldrawColors" ;
14+ import { getContrastColor } from "~/utils/colorUtils" ;
15+
16+ type ColorPickerProps = {
17+ value : string ;
18+ onChange : ( color : TldrawColorName ) => void ;
19+ } ;
20+
21+ const ColorPicker = ( { value, onChange } : ColorPickerProps ) => {
22+ const [ isOpen , setIsOpen ] = useState ( false ) ;
23+ const dropdownRef = useRef < HTMLDivElement > ( null ) ;
24+
25+ useEffect ( ( ) => {
26+ const handleClickOutside = ( event : MouseEvent ) => {
27+ if (
28+ dropdownRef . current &&
29+ ! dropdownRef . current . contains ( event . target as Node )
30+ ) {
31+ setIsOpen ( false ) ;
32+ }
33+ } ;
34+
35+ if ( isOpen ) {
36+ document . addEventListener ( "mousedown" , handleClickOutside ) ;
37+ return ( ) => {
38+ document . removeEventListener ( "mousedown" , handleClickOutside ) ;
39+ } ;
40+ }
41+ } , [ isOpen ] ) ;
42+
43+ const currentColor = value as TldrawColorName ;
44+ const bgColor = COLOR_PALETTE [ currentColor ] ?? COLOR_PALETTE . black ;
45+ const textColor = getContrastColor ( bgColor ?? DEFAULT_TLDRAW_COLOR ) ;
46+
47+ return (
48+ < div ref = { dropdownRef } className = "relative min-w-32" >
49+ < button
50+ type = "button"
51+ onClick = { ( ) => setIsOpen ( ! isOpen ) }
52+ className = "flex w-full items-center justify-between rounded border px-3 py-2 text-left"
53+ style = { { backgroundColor : bgColor , color : textColor } }
54+ >
55+ < span className = "flex items-center gap-2" >
56+ < span
57+ className = "inline-block h-3 w-3 rounded-full border-2 border-solid"
58+ style = { { backgroundColor : bgColor , border : `${ textColor } ` } }
59+ />
60+ { TLDRAW_COLOR_LABELS [ currentColor ] }
61+ </ span >
62+ < span className = "text-sm" > { isOpen ? "▲" : "▼" } </ span >
63+ </ button >
64+
65+ { isOpen && (
66+ < div className = "absolute z-50 mt-1 max-h-40 w-full overflow-y-auto" >
67+ { TLDRAW_COLOR_NAMES . map ( ( colorName ) => {
68+ const bgColor = COLOR_PALETTE [ colorName ] ?? COLOR_PALETTE . black ;
69+ return (
70+ < button
71+ key = { colorName }
72+ type = "button"
73+ onClick = { ( ) => {
74+ onChange ( colorName ) ;
75+ setIsOpen ( false ) ;
76+ } }
77+ className = "flex w-full flex-row justify-start gap-2 rounded-none px-3 py-2"
78+ >
79+ < span
80+ className = "inline-block h-3 w-3 rounded-full"
81+ style = { { backgroundColor : bgColor } }
82+ />
83+ { TLDRAW_COLOR_LABELS [ colorName ] }
84+ </ button >
85+ ) ;
86+ } ) }
87+ </ div >
88+ ) }
89+ </ div >
90+ ) ;
91+ } ;
792
893const RelationshipTypeSettings = ( ) => {
994 const plugin = usePlugin ( ) ;
@@ -24,11 +109,14 @@ const RelationshipTypeSettings = () => {
24109 id : newId ,
25110 label : "" ,
26111 complement : "" ,
27- color : "#000000" ,
112+ color : DEFAULT_TLDRAW_COLOR ,
28113 } ;
29114 }
30-
31- updatedRelationTypes [ index ] [ field ] = value ;
115+ if ( field === "color" ) {
116+ updatedRelationTypes [ index ] . color = value as TldrawColorName ;
117+ } else {
118+ updatedRelationTypes [ index ] [ field ] = value ;
119+ }
32120 setRelationTypes ( updatedRelationTypes ) ;
33121 setHasUnsavedChanges ( true ) ;
34122 } ;
@@ -42,7 +130,7 @@ const RelationshipTypeSettings = () => {
42130 id : newId ,
43131 label : "" ,
44132 complement : "" ,
45- color : "#000000" ,
133+ color : DEFAULT_TLDRAW_COLOR ,
46134 } ,
47135 ] ;
48136 setRelationTypes ( updatedRelationTypes ) ;
@@ -53,7 +141,7 @@ const RelationshipTypeSettings = () => {
53141 const relationType = relationTypes [ index ] || {
54142 label : "Unnamed" ,
55143 complement : "" ,
56- color : "#000000" ,
144+ color : DEFAULT_TLDRAW_COLOR ,
57145 } ;
58146 const modal = new ConfirmationModal ( plugin . app , {
59147 title : "Delete Relation Type" ,
@@ -132,14 +220,11 @@ const RelationshipTypeSettings = () => {
132220 }
133221 className = "flex-1"
134222 />
135- < input
136- type = "color"
223+ < ColorPicker
137224 value = { relationType . color }
138- onChange = { ( e ) =>
139- handleRelationTypeChange ( index , "color" , e . target . value )
225+ onChange = { ( color ) =>
226+ handleRelationTypeChange ( index , "color" , color )
140227 }
141- className = "w-12 h-8 rounded border"
142- title = "Relation color"
143228 />
144229 < button
145230 onClick = { ( ) => confirmDeleteRelationType ( index ) }
0 commit comments