1import { with_opacity } from "../theme/color"
2import {
3 Border,
4 TextStyle,
5 background,
6 border,
7 foreground,
8 text,
9} from "./components"
10import { interactive, toggleable } from "../element"
11import merge from "ts-deepmerge"
12import { useTheme } from "../theme"
13export default function project_panel(): any {
14 const theme = useTheme()
15
16 const { is_light } = theme
17
18 type EntryStateProps = {
19 background?: string
20 border?: Border
21 text?: TextStyle
22 icon_color?: string
23 }
24
25 type EntryState = {
26 default: EntryStateProps
27 hovered?: EntryStateProps
28 clicked?: EntryStateProps
29 }
30
31 const entry = (unselected?: EntryState, selected?: EntryState) => {
32 const git_status = {
33 git: {
34 modified: is_light
35 ? theme.ramps.yellow(0.6).hex()
36 : theme.ramps.yellow(0.5).hex(),
37 inserted: is_light
38 ? theme.ramps.green(0.45).hex()
39 : theme.ramps.green(0.5).hex(),
40 conflict: is_light
41 ? theme.ramps.red(0.6).hex()
42 : theme.ramps.red(0.5).hex(),
43 },
44 }
45
46 const base_properties = {
47 height: 22,
48 background: background(theme.middle),
49 chevron_color: foreground(theme.middle, "variant"),
50 icon_color: with_opacity(foreground(theme.middle, "active"), 0.3),
51 chevron_size: 7,
52 icon_size: 14,
53 icon_spacing: 6,
54 text: text(theme.middle, "sans", "variant", { size: "sm" }),
55 status: {
56 ...git_status,
57 },
58 }
59
60 const selected_style: EntryState | undefined = selected
61 ? selected
62 : unselected
63
64 const unselected_default_style = merge(
65 base_properties,
66 unselected?.default ?? {},
67 {}
68 )
69 const unselected_hovered_style = merge(
70 base_properties,
71 { background: background(theme.middle, "hovered") },
72 unselected?.hovered ?? {}
73 )
74 const unselected_clicked_style = merge(
75 base_properties,
76 { background: background(theme.middle, "pressed") },
77 unselected?.clicked ?? {}
78 )
79 const selected_default_style = merge(
80 base_properties,
81 {
82 background: background(theme.lowest),
83 text: text(theme.lowest, "sans", { size: "sm" }),
84 },
85 selected_style?.default ?? {}
86 )
87 const selected_hovered_style = merge(
88 base_properties,
89 {
90 background: background(theme.lowest, "hovered"),
91 text: text(theme.lowest, "sans", { size: "sm" }),
92 },
93 selected_style?.hovered ?? {}
94 )
95 const selected_clicked_style = merge(
96 base_properties,
97 {
98 background: background(theme.lowest, "pressed"),
99 text: text(theme.lowest, "sans", { size: "sm" }),
100 },
101 selected_style?.clicked ?? {}
102 )
103
104 return toggleable({
105 state: {
106 inactive: interactive({
107 state: {
108 default: unselected_default_style,
109 hovered: unselected_hovered_style,
110 clicked: unselected_clicked_style,
111 },
112 }),
113 active: interactive({
114 state: {
115 default: selected_default_style,
116 hovered: selected_hovered_style,
117 clicked: selected_clicked_style,
118 },
119 }),
120 },
121 })
122 }
123
124 const default_entry = entry()
125
126 return {
127 open_project_button: interactive({
128 base: {
129 background: background(theme.middle),
130 border: border(theme.middle, "active"),
131 corner_radius: 4,
132 margin: {
133 top: 16,
134 left: 16,
135 right: 16,
136 },
137 padding: {
138 top: 3,
139 bottom: 3,
140 left: 7,
141 right: 7,
142 },
143 ...text(theme.middle, "sans", "default", { size: "sm" }),
144 },
145 state: {
146 hovered: {
147 ...text(theme.middle, "sans", "default", { size: "sm" }),
148 background: background(theme.middle, "hovered"),
149 border: border(theme.middle, "active"),
150 },
151 clicked: {
152 ...text(theme.middle, "sans", "default", { size: "sm" }),
153 background: background(theme.middle, "pressed"),
154 border: border(theme.middle, "active"),
155 },
156 },
157 }),
158 background: background(theme.middle),
159 padding: { left: 6, right: 6, top: 0, bottom: 6 },
160 indent_width: 20,
161 entry: default_entry,
162 dragged_entry: {
163 ...default_entry.inactive.default,
164 text: text(theme.middle, "sans", "on", { size: "sm" }),
165 background: with_opacity(background(theme.middle, "on"), 0.9),
166 border: border(theme.middle),
167 },
168 ignored_entry: entry(
169 {
170 default: {
171 text: text(theme.middle, "sans", "disabled"),
172 },
173 },
174 {
175 default: {
176 icon_color: foreground(theme.middle, "variant"),
177 },
178 }
179 ),
180 cut_entry: entry(
181 {
182 default: {
183 text: text(theme.middle, "sans", "disabled"),
184 },
185 },
186 {
187 default: {
188 background: background(theme.middle, "active"),
189 text: text(theme.middle, "sans", "disabled", {
190 size: "sm",
191 }),
192 },
193 }
194 ),
195 filename_editor: {
196 background: background(theme.middle, "on"),
197 text: text(theme.middle, "sans", "on", { size: "sm" }),
198 selection: theme.players[0],
199 },
200 }
201}