Split into category packages; module github.com/ZacharyZhang-NY/MujicaUI

This commit is contained in:
ZacharyZhang-NY committed 2026-10-05 16:18:48 -04:00
1 parent 5a7e921c7e
commit 22b53e9e9e
1822 files changed
+24568 -21314

No files matched your search

+85 -84
View File
@@ -6,8 +6,9 @@ import (
"github.com/egoist/mygo/ui"
mujica "mujicaui"
"mujicaui/theme"
"github.com/ZacharyZhang-NY/MujicaUI/core"
"github.com/ZacharyZhang-NY/MujicaUI/datetime"
"github.com/ZacharyZhang-NY/MujicaUI/theme"
)
const dtCategory = "Date & Time"
@@ -33,20 +34,20 @@ var datetimePages = []page{
// dtSection lays out a captioned block of a demo.
func dtSection(c *ui.Context, title string, fn func()) {
k := mujica.Tokens(c)
k := core.Tokens(c)
ui.Column(c).Gap(8).Children(func() {
ui.Text(c, title).Font(theme.SerifFont).FontSize(mujica.FontSize(c, theme.H3Size)).TextColor(k.Text)
ui.Text(c, title).Font(theme.SerifFont).FontSize(core.FontSize(c, theme.H3Size)).TextColor(k.Text)
fn()
})
}
// dtStates lays labeled variants side by side.
func dtStates(c *ui.Context, fn func(state func(name string, body func()))) {
k := mujica.Tokens(c)
k := core.Tokens(c)
ui.Row(c).Gap(24).Wrap().AlignItems(ui.Start).Children(func() {
fn(func(name string, body func()) {
ui.Column(c).Gap(6).AlignItems(ui.Start).Children(func() {
ui.Text(c, name).FontSize(mujica.FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted)
ui.Text(c, name).FontSize(core.FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted)
body()
})
})
@@ -59,10 +60,10 @@ func dtControls(c *ui.Context, fn func()) {
var dtWeekStarts = []string{"Locale", "Sunday", "Monday", "Saturday"}
func dtWeekStart(s string) mujica.WeekStart {
func dtWeekStart(s string) datetime.WeekStart {
for i, n := range dtWeekStarts {
if n == s {
return mujica.WeekStart(i)
return datetime.WeekStart(i)
}
}
panic("gallery: unknown week start " + s)
@@ -70,11 +71,11 @@ func dtWeekStart(s string) mujica.WeekStart {
func dtCalendarDemo(c *ui.Context, log func(string)) {
type state struct {
day mujica.Date
day core.Date
weekStart string
weekends, bound, frozen bool
}
s := ui.Local(c.Root(), "051", func() state { return state{day: mujica.DateOf(time.Now()), weekStart: "Locale"} })
s := ui.Local(c.Root(), "051", func() state { return state{day: core.DateOf(time.Now()), weekStart: "Locale"} })
dtSection(c, "Calendar", func() {
dtControls(c, func() {
ui.Select(c, &s.weekStart, dtWeekStarts)
@@ -82,16 +83,16 @@ func dtCalendarDemo(c *ui.Context, log func(string)) {
ui.Checkbox(c, &s.bound, "Only this month")
ui.Checkbox(c, &s.frozen, "Disabled")
})
opts := mujica.CalendarOptions{WeekStart: dtWeekStart(s.weekStart), Disabled: s.frozen, Label: "Calendar demo"}
opts := datetime.CalendarOptions{WeekStart: dtWeekStart(s.weekStart), Disabled: s.frozen, Label: "Calendar demo"}
if s.weekends {
opts.DisableDate = func(d mujica.Date) bool { return d.Weekday() == time.Saturday || d.Weekday() == time.Sunday }
opts.DisableDate = func(d core.Date) bool { return d.Weekday() == time.Saturday || d.Weekday() == time.Sunday }
}
if s.bound {
now := mujica.DateOf(time.Now())
opts.Min = mujica.Date{Year: now.Year, Month: now.Month, Day: 1}
now := core.DateOf(time.Now())
opts.Min = core.Date{Year: now.Year, Month: now.Month, Day: 1}
opts.Max = opts.Min.AddMonths(1).AddDays(-1)
}
if mujica.Calendar(c, &s.day, opts).Changed() {
if datetime.Calendar(c, &s.day, opts).Changed() {
log("Calendar changed: " + s.day.String())
}
})
@@ -99,11 +100,11 @@ func dtCalendarDemo(c *ui.Context, log func(string)) {
func dtDatePickerDemo(c *ui.Context, log func(string)) {
type state struct {
a, b, d mujica.Date
a, b, d core.Date
clearable, slash bool
}
s := ui.Local(c.Root(), "052", func() state {
t := mujica.DateOf(time.Now())
t := core.DateOf(time.Now())
return state{a: t, d: t, clearable: true}
})
dtSection(c, "DatePicker", func() {
@@ -115,24 +116,24 @@ func dtDatePickerDemo(c *ui.Context, log func(string)) {
if s.slash {
layout = "02/01/2006"
}
now := mujica.DateOf(time.Now())
now := core.DateOf(time.Now())
dtStates(c, func(state func(string, func())) {
state("Default", func() {
if mujica.DatePicker(c, &s.a, mujica.DatePickerOptions{Label: "Due date", Layout: layout, Clearable: s.clearable}).Changed() {
if datetime.DatePicker(c, &s.a, datetime.DatePickerOptions{Label: "Due date", Layout: layout, Clearable: s.clearable}).Changed() {
log("DatePicker changed: " + s.a.String())
}
})
state("Next 30 days only", func() {
opts := mujica.DatePickerOptions{Label: "Delivery", Layout: layout, Clearable: s.clearable, Min: now, Max: now.AddDays(30)}
if mujica.DatePicker(c, &s.b, opts).Changed() {
opts := datetime.DatePickerOptions{Label: "Delivery", Layout: layout, Clearable: s.clearable, Min: now, Max: now.AddDays(30)}
if datetime.DatePicker(c, &s.b, opts).Changed() {
log("DatePicker (bounded) changed: " + s.b.String())
}
})
state("Read-only", func() {
mujica.DatePicker(c, &s.d, mujica.DatePickerOptions{Label: "Signed on", Layout: layout, ReadOnly: true})
datetime.DatePicker(c, &s.d, datetime.DatePickerOptions{Label: "Signed on", Layout: layout, ReadOnly: true})
})
state("Disabled", func() {
mujica.DatePicker(c, &s.d, mujica.DatePickerOptions{Label: "Locked", Layout: layout, Disabled: true})
datetime.DatePicker(c, &s.d, datetime.DatePickerOptions{Label: "Locked", Layout: layout, Disabled: true})
})
})
})
@@ -140,7 +141,7 @@ func dtDatePickerDemo(c *ui.Context, log func(string)) {
func dtDateRangeDemo(c *ui.Context, log func(string)) {
type state struct {
a mujica.DateRange
a datetime.DateRange
noTuesdays bool
frozen bool
fromThisWeek bool
@@ -152,14 +153,14 @@ func dtDateRangeDemo(c *ui.Context, log func(string)) {
ui.Checkbox(c, &s.fromThisWeek, "Start from today")
ui.Checkbox(c, &s.frozen, "Disabled")
})
opts := mujica.DateRangePickerOptions{Label: "Stay", Disabled: s.frozen}
opts := datetime.DateRangePickerOptions{Label: "Stay", Disabled: s.frozen}
if s.noTuesdays {
opts.DisableDate = func(d mujica.Date) bool { return d.Weekday() == time.Tuesday }
opts.DisableDate = func(d core.Date) bool { return d.Weekday() == time.Tuesday }
}
if s.fromThisWeek {
opts.Min = mujica.DateOf(time.Now())
opts.Min = core.DateOf(time.Now())
}
r := mujica.DateRangePicker(c, &s.a, opts)
r := datetime.DateRangePicker(c, &s.a, opts)
if r.Changed() {
log(fmt.Sprintf("DateRangePicker changed: %v – %v (%d days)", s.a.Start, s.a.End, s.a.Days()))
}
@@ -171,12 +172,12 @@ func dtDateRangeDemo(c *ui.Context, log func(string)) {
func dtTimePickerDemo(c *ui.Context, log func(string)) {
type state struct {
a, b mujica.TimeOfDay
a, b datetime.TimeOfDay
seconds, hour12 bool
step string
}
s := ui.Local(c.Root(), "054", func() state {
return state{a: mujica.TimeOfDay{Hour: 9, Minute: 30}, b: mujica.TimeOfDay{Hour: 10}, step: "1"}
return state{a: datetime.TimeOfDay{Hour: 9, Minute: 30}, b: datetime.TimeOfDay{Hour: 10}, step: "1"}
})
dtSection(c, "TimePicker", func() {
dtControls(c, func() {
@@ -189,31 +190,31 @@ func dtTimePickerDemo(c *ui.Context, log func(string)) {
if _, err := fmt.Sscan(s.step, &step); err != nil {
panic(err)
}
base := mujica.TimePickerOptions{Seconds: s.seconds, Hour12: s.hour12, MinuteStep: step}
base := datetime.TimePickerOptions{Seconds: s.seconds, Hour12: s.hour12, MinuteStep: step}
dtStates(c, func(state func(string, func())) {
state("Any time", func() {
o := base
o.Label = "Alarm"
if mujica.TimePicker(c, &s.a, o).Changed() {
if datetime.TimePicker(c, &s.a, o).Changed() {
log("TimePicker changed: " + s.a.String())
}
})
state("Office hours 09:00–18:00", func() {
o := base
o.Label, o.Min, o.Max = "Meeting", mujica.TimeOfDay{Hour: 9}, mujica.TimeOfDay{Hour: 18}
if mujica.TimePicker(c, &s.b, o).Changed() {
o.Label, o.Min, o.Max = "Meeting", datetime.TimeOfDay{Hour: 9}, datetime.TimeOfDay{Hour: 18}
if datetime.TimePicker(c, &s.b, o).Changed() {
log("TimePicker (bounded) changed: " + s.b.String())
}
})
state("Read-only", func() {
o := base
o.Label, o.ReadOnly = "Logged at", true
mujica.TimePicker(c, &s.a, o)
datetime.TimePicker(c, &s.a, o)
})
state("Disabled", func() {
o := base
o.Label, o.Disabled = "Locked", true
mujica.TimePicker(c, &s.a, o)
datetime.TimePicker(c, &s.a, o)
})
})
})
@@ -221,21 +222,21 @@ func dtTimePickerDemo(c *ui.Context, log func(string)) {
func dtTimeRangeDemo(c *ui.Context, log func(string)) {
type state struct {
v mujica.TimeRange
v datetime.TimeRange
overnight bool
}
s := ui.Local(c.Root(), "055", func() state {
return state{v: mujica.TimeRange{Start: mujica.TimeOfDay{Hour: 9}, End: mujica.TimeOfDay{Hour: 17}}}
return state{v: datetime.TimeRange{Start: datetime.TimeOfDay{Hour: 9}, End: datetime.TimeOfDay{Hour: 17}}}
})
dtSection(c, "TimeRangePicker", func() {
dtControls(c, func() {
if ui.Checkbox(c, &s.overnight, "Allow overnight").Changed() && !s.overnight && s.v.Overnight() {
s.v = mujica.TimeRange{Start: s.v.End, End: s.v.Start}
s.v = datetime.TimeRange{Start: s.v.End, End: s.v.Start}
log("TimeRangePicker swapped ends: overnight turned off")
}
})
opts := mujica.TimeRangePickerOptions{Label: "Opening hours", AllowOvernight: s.overnight, MinuteStep: 15}
if mujica.TimeRangePicker(c, &s.v, opts).Changed() {
opts := datetime.TimeRangePickerOptions{Label: "Opening hours", AllowOvernight: s.overnight, MinuteStep: 15}
if datetime.TimeRangePicker(c, &s.v, opts).Changed() {
log(fmt.Sprintf("TimeRangePicker changed: %v – %v overnight=%v", s.v.Start, s.v.End, s.v.Overnight()))
}
})
@@ -260,22 +261,22 @@ func dtDateTimeDemo(c *ui.Context, log func(string)) {
if err != nil {
panic(err)
}
r := mujica.DateTimePicker(c, &s.v, mujica.DateTimePickerOptions{Label: "Meeting", Location: loc, Hour12: s.hour12})
r := datetime.DateTimePicker(c, &s.v, datetime.DateTimePickerOptions{Label: "Meeting", Location: loc, Hour12: s.hour12})
if r.Changed() {
log("DateTimePicker changed: " + s.v.Format(time.RFC3339))
}
if r.Canceled() {
log("DateTimePicker canceled")
}
k := mujica.Tokens(c)
k := core.Tokens(c)
ui.Text(c, "Try 2026-03-08 02:30 in America/New_York: the picker reports the DST gap.").
FontSize(mujica.FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted)
FontSize(core.FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted)
})
}
func dtMonthDemo(c *ui.Context, log func(string)) {
type state struct {
v mujica.YearMonth
v datetime.YearMonth
clearable, past bool
}
s := ui.Local(c.Root(), "057", func() state { return state{clearable: true} })
@@ -284,23 +285,23 @@ func dtMonthDemo(c *ui.Context, log func(string)) {
ui.Checkbox(c, &s.clearable, "Clearable")
ui.Checkbox(c, &s.past, "Past months only")
})
opts := mujica.MonthPickerOptions{Label: "Billing month", Clearable: s.clearable,
DisableMonth: func(m mujica.YearMonth) bool { return m.Month == time.February }}
opts := datetime.MonthPickerOptions{Label: "Billing month", Clearable: s.clearable,
DisableMonth: func(m datetime.YearMonth) bool { return m.Month == time.February }}
if s.past {
now := time.Now()
opts.Max = mujica.YearMonth{Year: now.Year(), Month: now.Month()}
opts.Max = datetime.YearMonth{Year: now.Year(), Month: now.Month()}
}
dtStates(c, func(state func(string, func())) {
state("February unavailable", func() {
if mujica.MonthPicker(c, &s.v, opts).Changed() {
if datetime.MonthPicker(c, &s.v, opts).Changed() {
log("MonthPicker changed: " + s.v.String())
}
})
state("Read-only", func() {
mujica.MonthPicker(c, &s.v, mujica.MonthPickerOptions{Label: "Closed month", ReadOnly: true})
datetime.MonthPicker(c, &s.v, datetime.MonthPickerOptions{Label: "Closed month", ReadOnly: true})
})
state("Disabled", func() {
mujica.MonthPicker(c, &s.v, mujica.MonthPickerOptions{Label: "Locked", Disabled: true})
datetime.MonthPicker(c, &s.v, datetime.MonthPickerOptions{Label: "Locked", Disabled: true})
})
})
})
@@ -314,19 +315,19 @@ func dtYearDemo(c *ui.Context, log func(string)) {
s := ui.Local(c.Root(), "058", func() state { return state{v: time.Now().Year(), clearable: true} })
dtSection(c, "YearPicker", func() {
dtControls(c, func() { ui.Checkbox(c, &s.clearable, "Clearable") })
opts := mujica.YearPickerOptions{Label: "Vintage", Min: 1990, Max: time.Now().Year(), Clearable: s.clearable,
opts := datetime.YearPickerOptions{Label: "Vintage", Min: 1990, Max: time.Now().Year(), Clearable: s.clearable,
DisableYear: func(y int) bool { return y == 2020 }}
dtStates(c, func(state func(string, func())) {
state("1990 to now, 2020 unavailable", func() {
if mujica.YearPicker(c, &s.v, opts).Changed() {
if datetime.YearPicker(c, &s.v, opts).Changed() {
log(fmt.Sprintf("YearPicker changed: %d", s.v))
}
})
state("Read-only", func() {
mujica.YearPicker(c, &s.v, mujica.YearPickerOptions{Label: "Founded", ReadOnly: true})
datetime.YearPicker(c, &s.v, datetime.YearPickerOptions{Label: "Founded", ReadOnly: true})
})
state("Disabled", func() {
mujica.YearPicker(c, &s.v, mujica.YearPickerOptions{Label: "Locked", Disabled: true})
datetime.YearPicker(c, &s.v, datetime.YearPickerOptions{Label: "Locked", Disabled: true})
})
})
})
@@ -334,47 +335,47 @@ func dtYearDemo(c *ui.Context, log func(string)) {
// Code snippets mirror example_datetime_test.go.
const (
dtCalendarCode = `day := mujica.Date{Year: 2026, Month: time.October, Day: 5}
dtCalendarCode = `day := core.Date{Year: 2026, Month: time.October, Day: 5}
view := func(c *ui.Context) {
mujica.Use(c, mujica.Settings{})
if mujica.Calendar(c, &day, mujica.CalendarOptions{WeekStart: mujica.WeekStartMonday}).Changed() {
core.Use(c, core.Settings{})
if datetime.Calendar(c, &day, datetime.CalendarOptions{WeekStart: datetime.WeekStartMonday}).Changed() {
fmt.Println("chosen", day)
}
}
ui.Render(view, 400, 300, 1)`
dtDatePickerCode = `due := mujica.Date{Year: 2026, Month: time.October, Day: 5}
dtDatePickerCode = `due := core.Date{Year: 2026, Month: time.October, Day: 5}
view := func(c *ui.Context) {
mujica.Use(c, mujica.Settings{})
opts := mujica.DatePickerOptions{Label: "Due date", Clearable: true,
Min: mujica.Date{Year: 2026, Month: time.January, Day: 1}}
if mujica.DatePicker(c, &due, opts).Changed() {
core.Use(c, core.Settings{})
opts := datetime.DatePickerOptions{Label: "Due date", Clearable: true,
Min: core.Date{Year: 2026, Month: time.January, Day: 1}}
if datetime.DatePicker(c, &due, opts).Changed() {
fmt.Println("due", due)
}
}
ui.Render(view, 400, 300, 1)`
dtDateRangeCode = `var stay mujica.DateRange
dtDateRangeCode = `var stay datetime.DateRange
view := func(c *ui.Context) {
mujica.Use(c, mujica.Settings{})
r := mujica.DateRangePicker(c, &stay, mujica.DateRangePickerOptions{Label: "Stay"})
core.Use(c, core.Settings{})
r := datetime.DateRangePicker(c, &stay, datetime.DateRangePickerOptions{Label: "Stay"})
if r.Changed() {
fmt.Println("stay", stay.Start, stay.End, stay.Days())
}
}
ui.Render(view, 400, 300, 1)`
dtTimePickerCode = `alarm := mujica.TimeOfDay{Hour: 7, Minute: 30}
dtTimePickerCode = `alarm := datetime.TimeOfDay{Hour: 7, Minute: 30}
view := func(c *ui.Context) {
mujica.Use(c, mujica.Settings{})
opts := mujica.TimePickerOptions{Label: "Alarm", Hour12: true, MinuteStep: 5}
if mujica.TimePicker(c, &alarm, opts).Changed() {
core.Use(c, core.Settings{})
opts := datetime.TimePickerOptions{Label: "Alarm", Hour12: true, MinuteStep: 5}
if datetime.TimePicker(c, &alarm, opts).Changed() {
fmt.Println("alarm", alarm)
}
}
ui.Render(view, 400, 300, 1)`
dtTimeRangeCode = `shift := mujica.TimeRange{Start: mujica.TimeOfDay{Hour: 22}, End: mujica.TimeOfDay{Hour: 6}}
dtTimeRangeCode = `shift := datetime.TimeRange{Start: datetime.TimeOfDay{Hour: 22}, End: datetime.TimeOfDay{Hour: 6}}
view := func(c *ui.Context) {
mujica.Use(c, mujica.Settings{})
opts := mujica.TimeRangePickerOptions{Label: "Night shift", AllowOvernight: true}
if mujica.TimeRangePicker(c, &shift, opts).Changed() {
core.Use(c, core.Settings{})
opts := datetime.TimeRangePickerOptions{Label: "Night shift", AllowOvernight: true}
if datetime.TimeRangePicker(c, &shift, opts).Changed() {
fmt.Println("shift", shift.Start, shift.End, shift.Overnight())
}
}
@@ -385,27 +386,27 @@ if err != nil {
}
var meeting time.Time
view := func(c *ui.Context) {
mujica.Use(c, mujica.Settings{})
opts := mujica.DateTimePickerOptions{Label: "Meeting", Location: tokyo, MinuteStep: 15}
if mujica.DateTimePicker(c, &meeting, opts).Changed() {
core.Use(c, core.Settings{})
opts := datetime.DateTimePickerOptions{Label: "Meeting", Location: tokyo, MinuteStep: 15}
if datetime.DateTimePicker(c, &meeting, opts).Changed() {
fmt.Println("meeting", meeting)
}
}
ui.Render(view, 400, 300, 1)`
dtMonthCode = `var month mujica.YearMonth
dtMonthCode = `var month datetime.YearMonth
view := func(c *ui.Context) {
mujica.Use(c, mujica.Settings{})
opts := mujica.MonthPickerOptions{Label: "Billing month", Clearable: true}
if mujica.MonthPicker(c, &month, opts).Changed() {
core.Use(c, core.Settings{})
opts := datetime.MonthPickerOptions{Label: "Billing month", Clearable: true}
if datetime.MonthPicker(c, &month, opts).Changed() {
fmt.Println("month", month)
}
}
ui.Render(view, 400, 300, 1)`
dtYearCode = `year := 2026
view := func(c *ui.Context) {
mujica.Use(c, mujica.Settings{})
opts := mujica.YearPickerOptions{Label: "Vintage", Min: 1990, Max: 2030}
if mujica.YearPicker(c, &year, opts).Changed() {
core.Use(c, core.Settings{})
opts := datetime.YearPickerOptions{Label: "Vintage", Min: 1990, Max: 2030}
if datetime.YearPicker(c, &year, opts).Changed() {
fmt.Println("year", year)
}
}