Core

/app/lib/theme/theme.go (3.2 KB)

  1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package theme

import (
"cmp"
"fmt"
"io"
"slices"
"strings"

"github.com/samber/lo"

"{{{ .Package }}}/app/util"
)

type Theme struct {
Key string `json:"-"`
Light *Colors `json:"light"`
Dark *Colors `json:"dark"`
css string
}

func (t *Theme) CSS(indent int) string {
if t.css != "" {
return t.css
}
sb := &strings.Builder{}
sb.WriteString(t.Light.CSS(":root", 0))
sb.WriteString(t.Light.CSS(".mode-light", indent))
sb.WriteString(t.Dark.CSS(".mode-dark", indent))
addLine(sb, "", indent)
addLine(sb, "@media (prefers-color-scheme: dark) {", indent)
sb.WriteString(t.Dark.CSS(":root", indent+1))
sb.WriteString(t.Light.CSS(".mode-light", indent+1))
sb.WriteString(t.Dark.CSS(".mode-dark", indent+1))
addLine(sb, "}", indent)
t.css = sb.String()
return t.css
}

func (t *Theme) Clone(key string) *Theme {
return &Theme{Key: key, Light: t.Light.Clone(), Dark: t.Dark.Clone()}
}

func (t *Theme) Equals(x *Theme) bool {
return t.Light.Equals(x.Light) && t.Dark.Equals(x.Dark)
}

func (t *Theme) ToGo() string {
var ret []string
add := func(ind int, s string, args ...any) {
ret = append(ret, util.StringRepeat("\t", ind+1)+fmt.Sprintf(s, args...))
}
addColors := func(c *Colors) {
add(2, "Border: %q, LinkDecoration: %q,", c.Border, c.LinkDecoration)
add(2, "Foreground: %q, ForegroundMuted: %q,", c.Foreground, c.ForegroundMuted)
add(2, "Background: %q, BackgroundMuted: %q,", c.Background, c.BackgroundMuted)
add(2, "LinkForeground: %q, LinkVisitedForeground: %q,", c.LinkForeground, c.LinkVisitedForeground)
add(2, "NavForeground: %q, NavBackground: %q,", c.NavForeground, c.NavBackground)
add(2, "MenuForeground: %q, MenuSelectedForeground: %q,", c.MenuForeground, c.MenuSelectedForeground)
add(2, "MenuBackground: %q, MenuSelectedBackground: %q,", c.MenuBackground, c.MenuSelectedBackground)
add(2, "ModalBackdrop: %q, Success: %q, Error: %q,", c.ModalBackdrop, c.Success, c.Error)
}
add(0, "&Theme{")
add(1, "Key: %q,", t.Key)
add(1, "Light: &Colors{")
addColors(t.Light)
add(1, "},")
add(1, "Dark: &Colors{")
addColors(t.Dark)
add(1, "},")
add(0, "},")
return strings.Join(ret, util.StringDefaultLinebreak)
}

type Themes []*Theme

func (t Themes) Sort() Themes {
slices.SortFunc(t, func(l *Theme, r *Theme) int {
if l.Key == Default.Key {
return 0
}
if r.Key == Default.Key {
return 0
}
return cmp.Compare(strings.ToLower(l.Key), strings.ToLower(r.Key))
})
return t
}

func (t Themes) Replace(n *Theme) Themes {
for idx, o := range t {
if o.Key == n.Key {
t[idx] = n
return t
}
}
ret := append(Themes{}, t...)
ret = append(ret, n)
return ret.Sort()
}

func (t Themes) Contains(key string) bool {
return lo.ContainsBy(t, func(x *Theme) bool {
return x.Key == key
})
}

func (t Themes) Get(key string) *Theme {
return lo.FindOrElse(t, nil, func(x *Theme) bool {
return x.Key == key
})
}

func (t Themes) Remove(key string) Themes {
return lo.Filter(t, func(thm *Theme, _ int) bool {
return thm.Key != key
})
}

func addLine(sb io.StringWriter, s string, indent int) {
indention := util.StringRepeat(" ", indent)
_, _ = sb.WriteString(indention + s + "\n")
}