Merge branch 'main' into worktree-agent-ae66cd6d621c16060
This commit is contained in:
151 files changed
+2401
-670
No files matched your search
@@ -39,7 +39,7 @@ var dataPages = []page{
|
||||
// dataSection lays out a titled block of a demo.
|
||||
func dataSection(c *ui.Context, title string, fn func()) {
|
||||
ui.Column(c).Gap(12).Children(func() {
|
||||
ui.Text(c, title).Font(theme.SerifFont).FontSize(theme.H3Size)
|
||||
ui.Text(c, title).Font(theme.SerifFont).FontSize(mujica.FontSize(c, theme.H3Size))
|
||||
fn()
|
||||
})
|
||||
}
|
||||
@@ -50,7 +50,7 @@ func dataStates(c *ui.Context, fn func(state func(name string, body func()))) {
|
||||
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(theme.CaptionSize).TextColor(k.TextMuted)
|
||||
ui.Text(c, name).FontSize(mujica.FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted)
|
||||
body()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -134,7 +134,6 @@ func dataTableDemo(c *ui.Context, log func(string)) {
|
||||
ui.Checkbox(c, &s.multiple, "Multiple")
|
||||
ui.Select(c, &s.status, dataStatuses)
|
||||
ui.TextInput(c, &s.table.Filter).Width(180).Placeholder("Filter")
|
||||
mujica.DataTableColumnPicker(c, &s.table, cols)
|
||||
})
|
||||
v := mujica.DataTable(c, &s.table, rows, mujica.DataTableOptions[dataRelic, int]{
|
||||
Columns: cols, Key: func(r dataRelic) int { return r.ID }, Multiple: s.multiple, Status: st,
|
||||
|
||||
@@ -63,7 +63,9 @@ func dataAccordionDemo(c *ui.Context, log func(string)) {
|
||||
{ID: "nave", Title: "Nave", Content: func() { ui.Text(c, "Pews of black oak, polished for the feast.") }},
|
||||
{ID: "crypt", Title: "Crypt (disabled)", Disabled: true, Content: func() {}},
|
||||
{ID: "bells", Title: "Bells", Content: func() {
|
||||
mujica.Button(c, "Ring", mujica.ButtonOptions{})
|
||||
if mujica.Button(c, "Ring", mujica.ButtonOptions{}).Clicked() {
|
||||
log("ring the bells")
|
||||
}
|
||||
}},
|
||||
}, mujica.AccordionOptions{Multiple: s.multiple, KeepOne: s.keepOne}).Width(420).Changed() {
|
||||
log(fmt.Sprintf("open %v", s.open))
|
||||
@@ -84,7 +86,9 @@ func dataCollapsibleDemo(c *ui.Context, log func(string)) {
|
||||
})
|
||||
if mujica.Collapsible(c, &s.open, mujica.CollapsibleOptions{Title: "Rites of the evening", Disabled: s.disabled}, func() {
|
||||
ui.Text(c, "Candles are lit at the seventh bell; the choir enters from the north door.")
|
||||
mujica.Button(c, "Light candles", mujica.ButtonOptions{Variant: mujica.Outline})
|
||||
if mujica.Button(c, "Light candles", mujica.ButtonOptions{Variant: mujica.Outline}).Clicked() {
|
||||
log("light candles")
|
||||
}
|
||||
}).Changed() {
|
||||
log(fmt.Sprintf("open=%v", s.open))
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"testing"
|
||||
|
||||
"github.com/egoist/mygo/ui"
|
||||
|
||||
mujica "mujicaui"
|
||||
)
|
||||
|
||||
// dataDemo runs the demo of page id and returns its tester and event log.
|
||||
func dataDemo(t *testing.T, id string) (*ui.Tester, *[]string) {
|
||||
t.Helper()
|
||||
i := slices.IndexFunc(dataPages, func(p page) bool { return p.ID == id })
|
||||
if i < 0 {
|
||||
t.Fatalf("no page %s", id)
|
||||
}
|
||||
events := &[]string{}
|
||||
tt := ui.NewTester(func(c *ui.Context) {
|
||||
mujica.Use(c, mujica.Settings{})
|
||||
ui.Scroll(c).Fill().Padding(24).Children(func() {
|
||||
dataPages[i].Demo(c, func(s string) { *events = append(*events, s) })
|
||||
})
|
||||
}, 900, 700)
|
||||
tt.SetPreferences(ui.Preferences{ReduceMotion: true, TextScale: 1})
|
||||
return tt, events
|
||||
}
|
||||
|
||||
func TestDataDemoButtonsLog(t *testing.T) {
|
||||
tt, events := dataDemo(t, "074")
|
||||
for _, s := range []string{"Bells", "Ring"} {
|
||||
if err := tt.Click(s); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
if !slices.Contains(*events, "ring the bells") {
|
||||
t.Fatalf("Ring not logged: %q", *events)
|
||||
}
|
||||
tt, events = dataDemo(t, "075")
|
||||
for _, s := range []string{"Open from outside", "Light candles"} {
|
||||
if err := tt.Click(s); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
if !slices.Contains(*events, "light candles") {
|
||||
t.Fatalf("Light candles not logged: %q", *events)
|
||||
}
|
||||
}
|
||||
@@ -35,7 +35,7 @@ var datetimePages = []page{
|
||||
func dtSection(c *ui.Context, title string, fn func()) {
|
||||
k := mujica.Tokens(c)
|
||||
ui.Column(c).Gap(8).Children(func() {
|
||||
ui.Text(c, title).Font(theme.SerifFont).FontSize(theme.H3Size).TextColor(k.Text)
|
||||
ui.Text(c, title).Font(theme.SerifFont).FontSize(mujica.FontSize(c, theme.H3Size)).TextColor(k.Text)
|
||||
fn()
|
||||
})
|
||||
}
|
||||
@@ -46,7 +46,7 @@ func dtStates(c *ui.Context, fn func(state func(name string, body func()))) {
|
||||
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(theme.CaptionSize).TextColor(k.TextMuted)
|
||||
ui.Text(c, name).FontSize(mujica.FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted)
|
||||
body()
|
||||
})
|
||||
})
|
||||
@@ -128,6 +128,9 @@ func dtDatePickerDemo(c *ui.Context, log func(string)) {
|
||||
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})
|
||||
})
|
||||
state("Disabled", func() {
|
||||
mujica.DatePicker(c, &s.d, mujica.DatePickerOptions{Label: "Locked", Layout: layout, Disabled: true})
|
||||
})
|
||||
@@ -202,6 +205,11 @@ func dtTimePickerDemo(c *ui.Context, log func(string)) {
|
||||
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)
|
||||
})
|
||||
state("Disabled", func() {
|
||||
o := base
|
||||
o.Label, o.Disabled = "Locked", true
|
||||
@@ -261,7 +269,7 @@ func dtDateTimeDemo(c *ui.Context, log func(string)) {
|
||||
}
|
||||
k := mujica.Tokens(c)
|
||||
ui.Text(c, "Try 2026-03-08 02:30 in America/New_York: the picker reports the DST gap.").
|
||||
FontSize(theme.CaptionSize).TextColor(k.TextMuted)
|
||||
FontSize(mujica.FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -288,6 +296,9 @@ func dtMonthDemo(c *ui.Context, log func(string)) {
|
||||
log("MonthPicker changed: " + s.v.String())
|
||||
}
|
||||
})
|
||||
state("Read-only", func() {
|
||||
mujica.MonthPicker(c, &s.v, mujica.MonthPickerOptions{Label: "Closed month", ReadOnly: true})
|
||||
})
|
||||
state("Disabled", func() {
|
||||
mujica.MonthPicker(c, &s.v, mujica.MonthPickerOptions{Label: "Locked", Disabled: true})
|
||||
})
|
||||
@@ -311,6 +322,9 @@ func dtYearDemo(c *ui.Context, log func(string)) {
|
||||
log(fmt.Sprintf("YearPicker changed: %d", s.v))
|
||||
}
|
||||
})
|
||||
state("Read-only", func() {
|
||||
mujica.YearPicker(c, &s.v, mujica.YearPickerOptions{Label: "Founded", ReadOnly: true})
|
||||
})
|
||||
state("Disabled", func() {
|
||||
mujica.YearPicker(c, &s.v, mujica.YearPickerOptions{Label: "Locked", Disabled: true})
|
||||
})
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
@@ -172,116 +171,6 @@ const iconCode = `ui.Row(c).Gap(8).Children(func() {
|
||||
mujica.Icon(c, "circle-check", mujica.IconOptions{Size: 20, Tone: mujica.IconSuccess, Label: "Done"})
|
||||
})`
|
||||
|
||||
type imageState struct {
|
||||
crop, loading, fail, empty bool
|
||||
err error
|
||||
}
|
||||
|
||||
var displayPicture = func() *ui.SVG {
|
||||
return ui.MustParseSVG([]byte(`<svg xmlns="http://www.w3.org/2000/svg" width="240" height="160" viewBox="0 0 240 160">
|
||||
<rect width="240" height="160" fill="#2B2126"/><rect x="20" y="20" width="200" height="120" fill="none" stroke="#BDA172" stroke-width="2"/>
|
||||
<path d="M120 40 L150 80 L120 120 L90 80 Z" fill="#7D2034"/><circle cx="120" cy="80" r="8" fill="#F2EBDD"/></svg>`))
|
||||
}()
|
||||
|
||||
func imageDemo(c *ui.Context, log func(string)) {
|
||||
s := ui.Local(c.Root(), "014", func() imageState { return imageState{crop: true} })
|
||||
mujica.Heading(c, "Image", mujica.HeadingOptions{Subtitle: "位图与 SVG;包含或裁切;占位、加载、错误;替代说明", Divider: true})
|
||||
displaySection(c, "Parameters", func() {
|
||||
displayControls(c, func() {
|
||||
displayLog(log, ui.Checkbox(c, &s.crop, "Crop"), "crop", &s.crop)
|
||||
displayLog(log, ui.Checkbox(c, &s.empty, "No source"), "empty", &s.empty)
|
||||
displayLog(log, ui.Checkbox(c, &s.loading, "Loading"), "loading", &s.loading)
|
||||
if ui.Checkbox(c, &s.fail, "Error").Changed() {
|
||||
log(fmt.Sprintf("fail = %v", s.fail))
|
||||
s.err = nil
|
||||
if s.fail {
|
||||
s.err = errors.New("connection reset")
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
displaySection(c, "Preview", func() {
|
||||
var src ui.ImageSource = displayPicture
|
||||
if s.empty {
|
||||
src = nil
|
||||
}
|
||||
v := mujica.Image(c, src, mujica.ImageOptions{Width: 200, Height: 200, Crop: s.crop, Alt: "Gothic emblem", Loading: s.loading, Err: s.err})
|
||||
if v.Retry {
|
||||
s.fail, s.err = false, nil
|
||||
log("retry")
|
||||
}
|
||||
})
|
||||
displaySection(c, "States", func() {
|
||||
ui.Row(c).Gap(12).Wrap().Children(func() {
|
||||
mujica.Image(c, displayPicture, mujica.ImageOptions{Width: 120, Height: 120})
|
||||
mujica.Image(c, displayPicture, mujica.ImageOptions{Width: 120, Height: 120, Crop: true})
|
||||
mujica.Image(c, nil, mujica.ImageOptions{Width: 120, Height: 120})
|
||||
mujica.Image(c, nil, mujica.ImageOptions{Width: 120, Height: 120, Loading: true})
|
||||
if mujica.Image(c, nil, mujica.ImageOptions{Width: 160, Height: 140, Err: errors.New("404")}).Retry {
|
||||
log("retry (static example)")
|
||||
}
|
||||
})
|
||||
})
|
||||
displayCode(c, imageCode, log)
|
||||
}
|
||||
|
||||
const imageCode = `img := mujica.Image(c, photo, mujica.ImageOptions{
|
||||
Width: 160, Height: 120, Crop: true, Alt: "Hall of mirrors",
|
||||
Loading: loading, Err: loadErr,
|
||||
})
|
||||
if img.Retry {
|
||||
loading, loadErr = true, nil // start loading again here
|
||||
}`
|
||||
|
||||
type avatarState struct {
|
||||
name string
|
||||
size float64
|
||||
img bool
|
||||
}
|
||||
|
||||
var displayBitmap = func() *ui.Bitmap {
|
||||
return ui.NewBitmap(ui.Render(func(c *ui.Context) {
|
||||
mujica.Use(c, mujica.Settings{Mode: mujica.Dark})
|
||||
ui.Box(c).Fill().Background(ui.Hex("#7D2034"))
|
||||
}, 64, 64, 1))
|
||||
}()
|
||||
|
||||
func avatarDemo(c *ui.Context, log func(string)) {
|
||||
s := ui.Local(c.Root(), "015", func() avatarState { return avatarState{name: "Sakiko Togawa", size: 48} })
|
||||
mujica.Heading(c, "Avatar", mujica.HeadingOptions{Subtitle: "图片、姓名首字母与默认图标回退", Divider: true})
|
||||
displaySection(c, "Parameters", func() {
|
||||
displayControls(c, func() {
|
||||
if ui.TextInput(c, &s.name).Width(200).Changed() {
|
||||
log("name " + s.name)
|
||||
}
|
||||
ui.Text(c, fmt.Sprintf("Size %d", int(s.size)))
|
||||
displayLog(log, ui.StepSlider(c, &s.size, 24, 80, 4).Width(160), "size", &s.size)
|
||||
displayLog(log, ui.Checkbox(c, &s.img, "Image"), "img", &s.img)
|
||||
})
|
||||
})
|
||||
displaySection(c, "Preview", func() {
|
||||
var img *ui.Bitmap
|
||||
if s.img {
|
||||
img = displayBitmap
|
||||
}
|
||||
mujica.Avatar(c, s.name, mujica.AvatarOptions{Size: float32(s.size), Image: img})
|
||||
})
|
||||
displaySection(c, "Fallbacks", func() {
|
||||
ui.Row(c).Gap(12).AlignItems(ui.Center).Children(func() {
|
||||
mujica.Avatar(c, "Photo", mujica.AvatarOptions{Image: displayBitmap, Size: 40})
|
||||
mujica.Avatar(c, "Uika Misumi", mujica.AvatarOptions{Size: 40})
|
||||
mujica.Avatar(c, "若叶睦", mujica.AvatarOptions{Size: 40})
|
||||
mujica.Avatar(c, "", mujica.AvatarOptions{Size: 40})
|
||||
})
|
||||
})
|
||||
displayCode(c, avatarCode, log)
|
||||
}
|
||||
|
||||
const avatarCode = `ui.Row(c).Gap(8).Children(func() {
|
||||
mujica.Avatar(c, "Sakiko Togawa", mujica.AvatarOptions{Size: 40})
|
||||
mujica.Avatar(c, "", mujica.AvatarOptions{})
|
||||
})`
|
||||
|
||||
var displayPeople = []mujica.AvatarItem{
|
||||
{Name: "Sakiko Togawa"}, {Name: "Uika Misumi"}, {Name: "Mutsumi Wakaba"}, {Name: "Umiri Yahata"},
|
||||
{Name: "Nyamu Yutenji"}, {Name: "Tomori Takamatsu"}, {Name: "Anon Chihaya"}, {Name: "Rana Kaname"},
|
||||
@@ -444,6 +333,7 @@ func linkDemo(c *ui.Context, log func(string)) {
|
||||
}
|
||||
if mujica.Button(c, "Clear error", mujica.ButtonOptions{Variant: mujica.Ghost}).Clicked() {
|
||||
s.external = ""
|
||||
log("open failure cleared")
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/egoist/mygo/ui"
|
||||
|
||||
mujica "mujicaui"
|
||||
)
|
||||
|
||||
type imageState struct {
|
||||
crop, loading, fail, empty bool
|
||||
err error
|
||||
}
|
||||
|
||||
var displayPicture = func() *ui.SVG {
|
||||
return ui.MustParseSVG([]byte(`<svg xmlns="http://www.w3.org/2000/svg" width="240" height="160" viewBox="0 0 240 160">
|
||||
<rect width="240" height="160" fill="#2B2126"/><rect x="20" y="20" width="200" height="120" fill="none" stroke="#BDA172" stroke-width="2"/>
|
||||
<path d="M120 40 L150 80 L120 120 L90 80 Z" fill="#7D2034"/><circle cx="120" cy="80" r="8" fill="#F2EBDD"/></svg>`))
|
||||
}()
|
||||
|
||||
func imageDemo(c *ui.Context, log func(string)) {
|
||||
s := ui.Local(c.Root(), "014", func() imageState { return imageState{crop: true} })
|
||||
mujica.Heading(c, "Image", mujica.HeadingOptions{Subtitle: "位图与 SVG;包含或裁切;占位、加载、错误;替代说明", Divider: true})
|
||||
displaySection(c, "Parameters", func() {
|
||||
displayControls(c, func() {
|
||||
displayLog(log, ui.Checkbox(c, &s.crop, "Crop"), "crop", &s.crop)
|
||||
displayLog(log, ui.Checkbox(c, &s.empty, "No source"), "empty", &s.empty)
|
||||
displayLog(log, ui.Checkbox(c, &s.loading, "Loading"), "loading", &s.loading)
|
||||
if ui.Checkbox(c, &s.fail, "Error").Changed() {
|
||||
log(fmt.Sprintf("fail = %v", s.fail))
|
||||
s.err = nil
|
||||
if s.fail {
|
||||
s.err = errors.New("connection reset")
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
displaySection(c, "Preview", func() {
|
||||
var src ui.ImageSource = displayPicture
|
||||
if s.empty {
|
||||
src = nil
|
||||
}
|
||||
v := mujica.Image(c, src, mujica.ImageOptions{Width: 200, Height: 200, Crop: s.crop, Alt: "Gothic emblem", Loading: s.loading, Err: s.err})
|
||||
if v.Retry {
|
||||
s.fail, s.err = false, nil
|
||||
log("retry")
|
||||
}
|
||||
})
|
||||
displaySection(c, "States", func() {
|
||||
ui.Row(c).Gap(12).Wrap().Children(func() {
|
||||
mujica.Image(c, displayPicture, mujica.ImageOptions{Width: 120, Height: 120})
|
||||
mujica.Image(c, displayPicture, mujica.ImageOptions{Width: 120, Height: 120, Crop: true})
|
||||
mujica.Image(c, nil, mujica.ImageOptions{Width: 120, Height: 120})
|
||||
mujica.Image(c, nil, mujica.ImageOptions{Width: 120, Height: 120, Loading: true})
|
||||
if mujica.Image(c, nil, mujica.ImageOptions{Width: 160, Height: 140, Err: errors.New("404")}).Retry {
|
||||
log("retry (static example)")
|
||||
}
|
||||
})
|
||||
})
|
||||
displayCode(c, imageCode, log)
|
||||
}
|
||||
|
||||
const imageCode = `img := mujica.Image(c, photo, mujica.ImageOptions{
|
||||
Width: 160, Height: 120, Crop: true, Alt: "Hall of mirrors",
|
||||
Loading: loading, Err: loadErr,
|
||||
})
|
||||
if img.Retry {
|
||||
loading, loadErr = true, nil // start loading again here
|
||||
}`
|
||||
|
||||
type avatarState struct {
|
||||
name string
|
||||
size float64
|
||||
img bool
|
||||
}
|
||||
|
||||
var displayBitmap = func() *ui.Bitmap {
|
||||
return ui.NewBitmap(ui.Render(func(c *ui.Context) {
|
||||
mujica.Use(c, mujica.Settings{Mode: mujica.Dark})
|
||||
ui.Box(c).Fill().Background(ui.Hex("#7D2034"))
|
||||
}, 64, 64, 1))
|
||||
}()
|
||||
|
||||
func avatarDemo(c *ui.Context, log func(string)) {
|
||||
s := ui.Local(c.Root(), "015", func() avatarState { return avatarState{name: "Sakiko Togawa", size: 48} })
|
||||
mujica.Heading(c, "Avatar", mujica.HeadingOptions{Subtitle: "图片、姓名首字母与默认图标回退", Divider: true})
|
||||
displaySection(c, "Parameters", func() {
|
||||
displayControls(c, func() {
|
||||
if ui.TextInput(c, &s.name).Width(200).Changed() {
|
||||
log("name " + s.name)
|
||||
}
|
||||
ui.Text(c, fmt.Sprintf("Size %d", int(s.size)))
|
||||
displayLog(log, ui.StepSlider(c, &s.size, 24, 80, 4).Width(160), "size", &s.size)
|
||||
displayLog(log, ui.Checkbox(c, &s.img, "Image"), "img", &s.img)
|
||||
})
|
||||
})
|
||||
displaySection(c, "Preview", func() {
|
||||
var img *ui.Bitmap
|
||||
if s.img {
|
||||
img = displayBitmap
|
||||
}
|
||||
mujica.Avatar(c, s.name, mujica.AvatarOptions{Size: float32(s.size), Image: img})
|
||||
})
|
||||
displaySection(c, "Fallbacks", func() {
|
||||
ui.Row(c).Gap(12).AlignItems(ui.Center).Children(func() {
|
||||
mujica.Avatar(c, "Photo", mujica.AvatarOptions{Image: displayBitmap, Size: 40})
|
||||
mujica.Avatar(c, "Uika Misumi", mujica.AvatarOptions{Size: 40})
|
||||
mujica.Avatar(c, "若叶睦", mujica.AvatarOptions{Size: 40})
|
||||
mujica.Avatar(c, "", mujica.AvatarOptions{Size: 40})
|
||||
})
|
||||
})
|
||||
displayCode(c, avatarCode, log)
|
||||
}
|
||||
|
||||
const avatarCode = `ui.Row(c).Gap(8).Children(func() {
|
||||
mujica.Avatar(c, "Sakiko Togawa", mujica.AvatarOptions{Size: 40})
|
||||
mujica.Avatar(c, "", mujica.AvatarOptions{})
|
||||
})`
|
||||
@@ -177,10 +177,12 @@ var formPages = []page{
|
||||
e = "This name is already in the guest list."
|
||||
}
|
||||
mujica.FormField(c, "Guest name", mujica.FormFieldOptions{Required: d.required, Horizontal: d.horizontal,
|
||||
Description: "As written on the invitation.", Error: e}, func() {
|
||||
if mujica.InputGroup(c, &d.value, mujica.InputGroupOptions{Invalid: d.withError}).Changed() {
|
||||
Description: "As written on the invitation.", Error: e}, func() *ui.Element {
|
||||
g := mujica.InputGroup(c, &d.value, mujica.InputGroupOptions{Invalid: d.withError})
|
||||
if g.Changed() {
|
||||
log(fmt.Sprintf("value %q", d.value))
|
||||
}
|
||||
return g.Input
|
||||
})
|
||||
}},
|
||||
{ID: "043", Name: "InputGroup", ZhName: "输入组合", Category: "Forms", Code: formCode["InputGroup"],
|
||||
@@ -346,8 +348,8 @@ ui.Render(view, 400, 300, 1)`,
|
||||
"FormField": `email := ""
|
||||
view := func(c *ui.Context) {
|
||||
mujica.Use(c, mujica.Settings{})
|
||||
mujica.FormField(c, "Email", mujica.FormFieldOptions{Required: true, Description: "For receipts."}, func() {
|
||||
mujica.InputGroup(c, &email, mujica.InputGroupOptions{})
|
||||
mujica.FormField(c, "Email", mujica.FormFieldOptions{Required: true, Description: "For receipts."}, func() *ui.Element {
|
||||
return mujica.InputGroup(c, &email, mujica.InputGroupOptions{}).Input
|
||||
})
|
||||
}
|
||||
ui.Render(view, 400, 300, 1)`,
|
||||
|
||||
Reference in new issue
Block a user