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 icon_color: foreground(theme.middle, "variant"),
50 icon_size: 7,
51 icon_spacing: 5,
52 text: text(theme.middle, "sans", "variant", { size: "sm" }),
53 status: {
54 ...git_status,
55 },
56 }
57
58 const selected_style: EntryState | undefined = selected
59 ? selected
60 : unselected
61
62 const unselected_default_style = merge(
63 base_properties,
64 unselected?.default ?? {},
65 {}
66 )
67 const unselected_hovered_style = merge(
68 base_properties,
69 { background: background(theme.middle, "hovered") },
70 unselected?.hovered ?? {}
71 )
72 const unselected_clicked_style = merge(
73 base_properties,
74 { background: background(theme.middle, "pressed") },
75 unselected?.clicked ?? {}
76 )
77 const selected_default_style = merge(
78 base_properties,
79 {
80 background: background(theme.lowest),
81 text: text(theme.lowest, "sans", { size: "sm" }),
82 },
83 selected_style?.default ?? {}
84 )
85 const selected_hovered_style = merge(
86 base_properties,
87 {
88 background: background(theme.lowest, "hovered"),
89 text: text(theme.lowest, "sans", { size: "sm" }),
90 },
91 selected_style?.hovered ?? {}
92 )
93 const selected_clicked_style = merge(
94 base_properties,
95 {
96 background: background(theme.lowest, "pressed"),
97 text: text(theme.lowest, "sans", { size: "sm" }),
98 },
99 selected_style?.clicked ?? {}
100 )
101
102 return toggleable({
103 state: {
104 inactive: interactive({
105 state: {
106 default: unselected_default_style,
107 hovered: unselected_hovered_style,
108 clicked: unselected_clicked_style,
109 },
110 }),
111 active: interactive({
112 state: {
113 default: selected_default_style,
114 hovered: selected_hovered_style,
115 clicked: selected_clicked_style,
116 },
117 }),
118 },
119 })
120 }
121
122 const default_entry = entry()
123
124 return {
125 open_project_button: interactive({
126 base: {
127 background: background(theme.middle),
128 border: border(theme.middle, "active"),
129 corner_radius: 4,
130 margin: {
131 top: 16,
132 left: 16,
133 right: 16,
134 },
135 padding: {
136 top: 3,
137 bottom: 3,
138 left: 7,
139 right: 7,
140 },
141 ...text(theme.middle, "sans", "default", { size: "sm" }),
142 },
143 state: {
144 hovered: {
145 ...text(theme.middle, "sans", "default", { size: "sm" }),
146 background: background(theme.middle, "hovered"),
147 border: border(theme.middle, "active"),
148 },
149 clicked: {
150 ...text(theme.middle, "sans", "default", { size: "sm" }),
151 background: background(theme.middle, "pressed"),
152 border: border(theme.middle, "active"),
153 },
154 },
155 }),
156 background: background(theme.middle),
157 padding: { left: 6, right: 6, top: 0, bottom: 6 },
158 indent_width: 12,
159 entry: default_entry,
160 dragged_entry: {
161 ...default_entry.inactive.default,
162 text: text(theme.middle, "sans", "on", { size: "sm" }),
163 background: with_opacity(background(theme.middle, "on"), 0.9),
164 border: border(theme.middle),
165 },
166 ignored_entry: entry(
167 {
168 default: {
169 text: text(theme.middle, "sans", "disabled"),
170 },
171 },
172 {
173 default: {
174 icon_color: foreground(theme.middle, "variant"),
175 },
176 }
177 ),
178 cut_entry: entry(
179 {
180 default: {
181 text: text(theme.middle, "sans", "disabled"),
182 },
183 },
184 {
185 default: {
186 background: background(theme.middle, "active"),
187 text: text(theme.middle, "sans", "disabled", {
188 size: "sm",
189 }),
190 },
191 }
192 ),
193 filename_editor: {
194 background: background(theme.middle, "on"),
195 text: text(theme.middle, "sans", "on", { size: "sm" }),
196 selection: theme.players[0],
197 },
198 }
199}