1import { ColorScheme } from "../theme/colorScheme"
2import { withOpacity } from "../theme/color"
3import {
4 Border,
5 TextStyle,
6 background,
7 border,
8 foreground,
9 text,
10} from "./components"
11import { interactive, toggleable } from "../element"
12import merge from "ts-deepmerge"
13export default function projectPanel(colorScheme: ColorScheme) {
14 const { isLight } = colorScheme
15
16 let layer = colorScheme.middle
17
18 type EntryStateProps = {
19 background?: string
20 border?: Border
21 text?: TextStyle
22 iconColor?: 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: isLight
35 ? colorScheme.ramps.yellow(0.6).hex()
36 : colorScheme.ramps.yellow(0.5).hex(),
37 inserted: isLight
38 ? colorScheme.ramps.green(0.45).hex()
39 : colorScheme.ramps.green(0.5).hex(),
40 conflict: isLight
41 ? colorScheme.ramps.red(0.6).hex()
42 : colorScheme.ramps.red(0.5).hex(),
43 },
44 }
45
46 const base_properties = {
47 height: 22,
48 background: background(layer),
49 iconColor: foreground(layer, "variant"),
50 iconSize: 7,
51 iconSpacing: 5,
52 text: text(layer, "mono", "variant", { size: "sm" }),
53 status: {
54 ...git_status,
55 },
56 }
57
58 const selectedStyle: 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 unselected?.hovered ?? {},
70 { background: background(layer, "variant", "hovered") }
71 )
72 const unselected_clicked_style = merge(
73 base_properties,
74 unselected?.clicked ?? {},
75 { background: background(layer, "variant", "pressed") }
76 )
77 const selected_default_style = merge(
78 base_properties,
79 selectedStyle?.default ?? {},
80 { background: background(layer) }
81 )
82 const selected_hovered_style = merge(
83 base_properties,
84 selectedStyle?.hovered ?? {},
85 { background: background(layer, "variant", "hovered") }
86 )
87 const selected_clicked_style = merge(
88 base_properties,
89 selectedStyle?.clicked ?? {},
90 { background: background(layer, "variant", "pressed") }
91 )
92
93 return toggleable({
94 state: {
95 inactive: interactive({
96 state: {
97 default: unselected_default_style,
98 hovered: unselected_hovered_style,
99 clicked: unselected_clicked_style,
100 },
101 }),
102 active: interactive({
103 state: {
104 default: selected_default_style,
105 hovered: selected_hovered_style,
106 clicked: selected_clicked_style,
107 },
108 }),
109 },
110 })
111 }
112
113 const defaultEntry = entry()
114
115 return {
116 openProjectButton: interactive({
117 base: {
118 background: background(layer),
119 border: border(layer, "active"),
120 cornerRadius: 4,
121 margin: {
122 top: 16,
123 left: 16,
124 right: 16,
125 },
126 padding: {
127 top: 3,
128 bottom: 3,
129 left: 7,
130 right: 7,
131 },
132 ...text(layer, "sans", "default", { size: "sm" }),
133 },
134 state: {
135 hovered: {
136 ...text(layer, "sans", "default", { size: "sm" }),
137 background: background(layer, "hovered"),
138 border: border(layer, "active"),
139 },
140 clicked: {
141 ...text(layer, "sans", "default", { size: "sm" }),
142 background: background(layer, "pressed"),
143 border: border(layer, "active"),
144 },
145 },
146 }),
147 background: background(layer),
148 padding: { left: 6, right: 6, top: 0, bottom: 6 },
149 indentWidth: 12,
150 entry: defaultEntry,
151 draggedEntry: {
152 ...defaultEntry.inactive.default,
153 text: text(layer, "mono", "on", { size: "sm" }),
154 background: withOpacity(background(layer, "on"), 0.9),
155 border: border(layer),
156 },
157 ignoredEntry: entry(
158 {
159 default: {
160 text: text(layer, "mono", "disabled"),
161 },
162 },
163 {
164 default: {
165 iconColor: foreground(layer, "variant"),
166 },
167 }
168 ),
169 cutEntry: entry(
170 {
171 default: {
172 text: text(layer, "mono", "disabled"),
173 },
174 },
175 {
176 default: {
177 background: background(layer, "active"),
178 text: text(layer, "mono", "disabled", { size: "sm" }),
179 },
180 }
181 ),
182 filenameEditor: {
183 background: background(layer, "on"),
184 text: text(layer, "mono", "on", { size: "sm" }),
185 selection: colorScheme.players[0],
186 },
187 }
188}