project_panel.ts

  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}