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            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}