WIP components (as built)
This commit is contained in:
102 files changed
+6538
-1
No files matched your search
@@ -0,0 +1,99 @@
|
||||
package mujica
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"strings"
|
||||
|
||||
"github.com/egoist/mygo/ui"
|
||||
|
||||
"mujicaui/internal"
|
||||
"mujicaui/theme"
|
||||
)
|
||||
|
||||
// TaskItemOptions configure a TaskItem.
|
||||
type TaskItemOptions struct {
|
||||
Members []Member
|
||||
// Today anchors the overdue mark; zero uses the system clock.
|
||||
Today Date
|
||||
Disabled bool
|
||||
}
|
||||
|
||||
// taskItemEdit is a title being edited inline.
|
||||
type taskItemEdit struct {
|
||||
on bool
|
||||
draft string
|
||||
}
|
||||
|
||||
// TaskItem displays task fields with completion and inline editing.
|
||||
func TaskItem(c *ui.Context, task *Task, opts TaskItemOptions) ProjectResult {
|
||||
projectCheckPriority(task.Priority)
|
||||
for _, id := range task.Assignees {
|
||||
projectMember(opts.Members, id)
|
||||
}
|
||||
k := Tokens(c)
|
||||
d := Density(c)
|
||||
today := datetimeToday(c, opts.Today)
|
||||
r := ProjectResult{}
|
||||
row := ui.Row(c).MinHeight(d.ControlHeight()).Gap(d.Unit() * 3).AlignItems(ui.Center).PaddingX(d.Unit() * 2).
|
||||
Role(ui.RoleListItem).Label(task.Title).Disabled(opts.Disabled)
|
||||
r.Element = row
|
||||
edit := ui.Local(row, "task-item-edit", func() taskItemEdit { return taskItemEdit{} })
|
||||
if row.Hovered() {
|
||||
row.Background(k.SurfaceHover)
|
||||
}
|
||||
row.Children(func() {
|
||||
done := task.Done
|
||||
if Checkbox(c, &done, "", CheckboxOptions{Disabled: opts.Disabled}).Label(task.Title).Changed() && !row.IsDisabled() {
|
||||
task.Done, r.changed = done, task.ID
|
||||
slog.Debug("mujica: task_item done", "id", task.ID, "done", done)
|
||||
}
|
||||
if edit.on && !row.IsDisabled() {
|
||||
in := TextInput(c, &edit.draft, TextInputOptions{Label: msg(c, "task_item.rename")})
|
||||
in.Element.Grow(1)
|
||||
in.Input.AutoFocus()
|
||||
switch {
|
||||
case in.Submitted() && strings.TrimSpace(edit.draft) != "":
|
||||
if t := strings.TrimSpace(edit.draft); t != task.Title {
|
||||
task.Title, r.changed = t, task.ID
|
||||
slog.Debug("mujica: task_item rename", "id", task.ID)
|
||||
}
|
||||
edit.on = false
|
||||
case in.Input.Shortcut(0, ui.KeyEscape):
|
||||
edit.on = false
|
||||
}
|
||||
return
|
||||
}
|
||||
edit.on = false
|
||||
title := ui.ButtonBase(c).Grow(1).Shrink(1).Justify(ui.Start).MinHeight(theme.MinHitSize).Radius(theme.ControlRadius).Label(task.Title)
|
||||
internal.Ring(title, k.Focus, theme.ControlRadius)
|
||||
title.Children(func() {
|
||||
t := ui.Text(c, task.Title).SingleLine().Ellipsis("…").TextColor(k.Text)
|
||||
if task.Done {
|
||||
t.Strikethrough().TextColor(k.TextMuted)
|
||||
}
|
||||
})
|
||||
if !title.IsDisabled() {
|
||||
if title.DoubleClicked() || title.Shortcut(0, ui.KeyF2) {
|
||||
*edit = taskItemEdit{on: true, draft: task.Title}
|
||||
} else if title.Clicked() {
|
||||
r.opened = task.ID
|
||||
}
|
||||
}
|
||||
PriorityIndicator(c, task.Priority, PriorityIndicatorOptions{IconOnly: true})
|
||||
if text, late := projectDueText(c, task.Due, today, task.Done); text != "" {
|
||||
fg := k.TextMuted
|
||||
if late {
|
||||
fg = k.Danger
|
||||
}
|
||||
ui.Text(c, text).FontSize(FontSize(c, theme.CaptionSize)).TextColor(fg).SingleLine().Shrink(0)
|
||||
}
|
||||
if len(task.Assignees) > 0 {
|
||||
items := make([]AvatarItem, len(task.Assignees))
|
||||
for i, id := range task.Assignees {
|
||||
items[i] = AvatarItem{Name: projectMember(opts.Members, id).Name}
|
||||
}
|
||||
AvatarGroup(c, items, AvatarGroupOptions{Max: 2, Size: 24})
|
||||
}
|
||||
})
|
||||
return r
|
||||
}
|
||||
Reference in new issue
Block a user