projectPanel.ts

  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}