@jant/core 0.3.25 → 0.3.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/dist/app.js +70 -563
  2. package/dist/auth.js +3 -0
  3. package/dist/client.js +1 -0
  4. package/dist/i18n/locales/en.js +1 -1
  5. package/dist/i18n/locales/zh-Hans.js +1 -1
  6. package/dist/i18n/locales/zh-Hant.js +1 -1
  7. package/dist/lib/avatar-upload.js +134 -0
  8. package/dist/lib/config.js +39 -0
  9. package/dist/lib/constants.js +10 -10
  10. package/dist/lib/favicon.js +102 -0
  11. package/dist/lib/image.js +13 -17
  12. package/dist/lib/media-helpers.js +2 -2
  13. package/dist/lib/navigation.js +23 -3
  14. package/dist/lib/render.js +10 -1
  15. package/dist/lib/schemas.js +31 -0
  16. package/dist/lib/timezones.js +388 -0
  17. package/dist/lib/view.js +1 -1
  18. package/dist/routes/api/posts.js +1 -1
  19. package/dist/routes/api/upload.js +3 -3
  20. package/dist/routes/auth/reset.js +221 -0
  21. package/dist/routes/auth/setup.js +194 -0
  22. package/dist/routes/auth/signin.js +176 -0
  23. package/dist/routes/dash/collections.js +23 -415
  24. package/dist/routes/dash/media.js +12 -392
  25. package/dist/routes/dash/pages.js +7 -330
  26. package/dist/routes/dash/redirects.js +18 -12
  27. package/dist/routes/dash/settings.js +198 -577
  28. package/dist/routes/feed/rss.js +2 -1
  29. package/dist/routes/feed/sitemap.js +4 -2
  30. package/dist/routes/pages/featured.js +5 -1
  31. package/dist/routes/pages/home.js +26 -1
  32. package/dist/routes/pages/latest.js +45 -0
  33. package/dist/services/post.js +30 -50
  34. package/dist/types/bindings.js +3 -0
  35. package/dist/types/config.js +147 -0
  36. package/dist/types/constants.js +27 -0
  37. package/dist/types/entities.js +3 -0
  38. package/dist/types/operations.js +3 -0
  39. package/dist/types/props.js +3 -0
  40. package/dist/types/views.js +5 -0
  41. package/dist/types.js +8 -111
  42. package/dist/ui/color-themes.js +33 -33
  43. package/dist/ui/compose/ComposeDialog.js +36 -21
  44. package/dist/ui/dash/PageForm.js +21 -15
  45. package/dist/ui/dash/PostForm.js +22 -16
  46. package/dist/ui/dash/collections/CollectionForm.js +152 -0
  47. package/dist/ui/dash/collections/CollectionsListContent.js +68 -0
  48. package/dist/ui/dash/collections/ViewCollectionContent.js +96 -0
  49. package/dist/ui/dash/media/MediaListContent.js +166 -0
  50. package/dist/ui/dash/media/ViewMediaContent.js +212 -0
  51. package/dist/ui/dash/pages/LinkFormContent.js +130 -0
  52. package/dist/ui/dash/pages/UnifiedPagesContent.js +193 -0
  53. package/dist/ui/dash/settings/AccountContent.js +209 -0
  54. package/dist/ui/dash/settings/AppearanceContent.js +259 -0
  55. package/dist/ui/dash/settings/GeneralContent.js +536 -0
  56. package/dist/ui/dash/settings/SettingsNav.js +41 -0
  57. package/dist/ui/font-themes.js +36 -0
  58. package/dist/ui/layouts/BaseLayout.js +24 -2
  59. package/dist/ui/layouts/SiteLayout.js +47 -19
  60. package/package.json +1 -1
  61. package/src/app.tsx +95 -553
  62. package/src/auth.ts +4 -1
  63. package/src/client.ts +1 -0
  64. package/src/i18n/locales/en.po +240 -175
  65. package/src/i18n/locales/en.ts +1 -1
  66. package/src/i18n/locales/zh-Hans.po +240 -175
  67. package/src/i18n/locales/zh-Hans.ts +1 -1
  68. package/src/i18n/locales/zh-Hant.po +240 -175
  69. package/src/i18n/locales/zh-Hant.ts +1 -1
  70. package/src/lib/__tests__/config.test.ts +192 -0
  71. package/src/lib/__tests__/favicon.test.ts +151 -0
  72. package/src/lib/__tests__/image.test.ts +2 -6
  73. package/src/lib/__tests__/timezones.test.ts +61 -0
  74. package/src/lib/__tests__/view.test.ts +2 -2
  75. package/src/lib/avatar-upload.ts +165 -0
  76. package/src/lib/config.ts +47 -0
  77. package/src/lib/constants.ts +19 -11
  78. package/src/lib/favicon.ts +115 -0
  79. package/src/lib/image.ts +13 -21
  80. package/src/lib/media-helpers.ts +2 -2
  81. package/src/lib/navigation.ts +33 -2
  82. package/src/lib/render.tsx +15 -1
  83. package/src/lib/schemas.ts +39 -0
  84. package/src/lib/timezones.ts +325 -0
  85. package/src/lib/view.ts +1 -1
  86. package/src/routes/api/posts.ts +1 -1
  87. package/src/routes/api/upload.ts +2 -3
  88. package/src/routes/auth/reset.tsx +239 -0
  89. package/src/routes/auth/setup.tsx +189 -0
  90. package/src/routes/auth/signin.tsx +163 -0
  91. package/src/routes/dash/__tests__/settings-avatar.test.ts +89 -0
  92. package/src/routes/dash/collections.tsx +17 -366
  93. package/src/routes/dash/media.tsx +12 -414
  94. package/src/routes/dash/pages.tsx +8 -348
  95. package/src/routes/dash/redirects.tsx +20 -14
  96. package/src/routes/dash/settings.tsx +243 -534
  97. package/src/routes/feed/__tests__/rss.test.ts +141 -0
  98. package/src/routes/feed/rss.ts +3 -1
  99. package/src/routes/feed/sitemap.ts +4 -2
  100. package/src/routes/pages/featured.tsx +7 -1
  101. package/src/routes/pages/home.tsx +25 -2
  102. package/src/routes/pages/latest.tsx +59 -0
  103. package/src/services/post.ts +34 -66
  104. package/src/styles/components.css +0 -65
  105. package/src/styles/tokens.css +1 -1
  106. package/src/styles/ui.css +24 -40
  107. package/src/types/bindings.ts +30 -0
  108. package/src/types/config.ts +183 -0
  109. package/src/types/constants.ts +26 -0
  110. package/src/types/entities.ts +109 -0
  111. package/src/types/operations.ts +88 -0
  112. package/src/types/props.ts +115 -0
  113. package/src/types/views.ts +172 -0
  114. package/src/types.ts +8 -644
  115. package/src/ui/__tests__/font-themes.test.ts +34 -0
  116. package/src/ui/color-themes.ts +34 -34
  117. package/src/ui/compose/ComposeDialog.tsx +40 -21
  118. package/src/ui/dash/PageForm.tsx +25 -19
  119. package/src/ui/dash/PostForm.tsx +26 -20
  120. package/src/ui/dash/collections/CollectionForm.tsx +153 -0
  121. package/src/ui/dash/collections/CollectionsListContent.tsx +85 -0
  122. package/src/ui/dash/collections/ViewCollectionContent.tsx +92 -0
  123. package/src/ui/dash/media/MediaListContent.tsx +201 -0
  124. package/src/ui/dash/media/ViewMediaContent.tsx +208 -0
  125. package/src/ui/dash/pages/LinkFormContent.tsx +119 -0
  126. package/src/ui/dash/pages/UnifiedPagesContent.tsx +203 -0
  127. package/src/ui/dash/settings/AccountContent.tsx +176 -0
  128. package/src/ui/dash/settings/AppearanceContent.tsx +254 -0
  129. package/src/ui/dash/settings/GeneralContent.tsx +533 -0
  130. package/src/ui/dash/settings/SettingsNav.tsx +56 -0
  131. package/src/ui/font-themes.ts +54 -0
  132. package/src/ui/layouts/BaseLayout.tsx +17 -0
  133. package/src/ui/layouts/SiteLayout.tsx +45 -31
@@ -0,0 +1,193 @@
1
+ /**
2
+ * Unified pages list - navigation items + other pages
3
+ */ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "hono/jsx/jsx-runtime";
4
+ import { useLingui as $_useLingui } from "@jant/core/i18n";
5
+ import { ListItemRow, ActionButtons, CrudPageHeader } from "../index.js";
6
+ export function UnifiedPagesContent({ navItems, otherPages }) {
7
+ const { i18n: $__i18n, _: $__ } = $_useLingui();
8
+ return /*#__PURE__*/ _jsxs(_Fragment, {
9
+ children: [
10
+ /*#__PURE__*/ _jsx(CrudPageHeader, {
11
+ title: $__i18n._({
12
+ id: "wRR604",
13
+ message: "Pages"
14
+ }),
15
+ children: /*#__PURE__*/ _jsxs("div", {
16
+ class: "flex gap-2",
17
+ children: [
18
+ /*#__PURE__*/ _jsx("a", {
19
+ href: "/dash/pages/links/new",
20
+ class: "btn-outline",
21
+ children: $__i18n._({
22
+ id: "V4WsyL",
23
+ message: "Add Link"
24
+ })
25
+ }),
26
+ /*#__PURE__*/ _jsx("a", {
27
+ href: "/dash/pages/new",
28
+ class: "btn",
29
+ children: $__i18n._({
30
+ id: "GrZ6fH",
31
+ message: "New Page"
32
+ })
33
+ })
34
+ ]
35
+ })
36
+ }),
37
+ /*#__PURE__*/ _jsxs("section", {
38
+ class: "mb-8",
39
+ children: [
40
+ /*#__PURE__*/ _jsx("h2", {
41
+ class: "text-lg font-medium mb-3",
42
+ children: $__i18n._({
43
+ id: "GTPbOX",
44
+ message: "Your site navigation"
45
+ })
46
+ }),
47
+ navItems.length === 0 ? /*#__PURE__*/ _jsx("p", {
48
+ class: "text-sm text-muted-foreground py-4",
49
+ children: $__i18n._({
50
+ id: "vh0C9b",
51
+ message: "No navigation links yet. Add pages to navigation or create links."
52
+ })
53
+ }) : /*#__PURE__*/ _jsx("div", {
54
+ id: "nav-links-list",
55
+ class: "flex flex-col divide-y",
56
+ children: navItems.map((item)=>/*#__PURE__*/ _jsx(ListItemRow, {
57
+ actions: item.type === "page" ? /*#__PURE__*/ _jsxs(_Fragment, {
58
+ children: [
59
+ /*#__PURE__*/ _jsx(ActionButtons, {
60
+ editHref: item.pageId ? `/dash/pages/${item.pageId}/edit` : undefined,
61
+ editLabel: $__i18n._({
62
+ id: "ePK91l",
63
+ message: "Edit"
64
+ })
65
+ }),
66
+ /*#__PURE__*/ _jsx("button", {
67
+ type: "button",
68
+ class: "btn-sm-ghost",
69
+ "data-on:click__prevent": `@post('/dash/pages/${item.pageId}/remove-from-nav')`,
70
+ children: $__i18n._({
71
+ id: "g3mKmM",
72
+ message: "Un-nav"
73
+ })
74
+ })
75
+ ]
76
+ }) : /*#__PURE__*/ _jsx(_Fragment, {
77
+ children: /*#__PURE__*/ _jsx(ActionButtons, {
78
+ editHref: `/dash/pages/links/${item.id}/edit`,
79
+ editLabel: $__i18n._({
80
+ id: "ePK91l",
81
+ message: "Edit"
82
+ }),
83
+ deleteAction: `/dash/pages/links/${item.id}/delete`,
84
+ deleteLabel: $__i18n._({
85
+ id: "cnGeoo",
86
+ message: "Delete"
87
+ })
88
+ })
89
+ }),
90
+ children: /*#__PURE__*/ _jsxs("div", {
91
+ class: "flex items-center gap-3 cursor-grab",
92
+ "data-id": item.id,
93
+ children: [
94
+ /*#__PURE__*/ _jsx("span", {
95
+ class: "text-muted-foreground select-none",
96
+ children: "⠿"
97
+ }),
98
+ /*#__PURE__*/ _jsxs("div", {
99
+ class: "flex items-center gap-2",
100
+ children: [
101
+ /*#__PURE__*/ _jsx("span", {
102
+ class: "font-medium",
103
+ children: item.label
104
+ }),
105
+ /*#__PURE__*/ _jsx("code", {
106
+ class: "text-sm text-muted-foreground bg-muted px-1 rounded",
107
+ children: item.url
108
+ }),
109
+ /*#__PURE__*/ _jsx("span", {
110
+ class: "badge-secondary",
111
+ children: item.type === "page" ? $__i18n._({
112
+ id: "MnbH31",
113
+ message: "page"
114
+ }) : $__i18n._({
115
+ id: "LdyooL",
116
+ message: "link"
117
+ })
118
+ })
119
+ ]
120
+ })
121
+ ]
122
+ })
123
+ }, item.id))
124
+ })
125
+ ]
126
+ }),
127
+ /*#__PURE__*/ _jsxs("section", {
128
+ children: [
129
+ /*#__PURE__*/ _jsx("h2", {
130
+ class: "text-lg font-medium mb-3",
131
+ children: $__i18n._({
132
+ id: "Y75ho6",
133
+ message: "Other pages"
134
+ })
135
+ }),
136
+ otherPages.length === 0 ? /*#__PURE__*/ _jsx("p", {
137
+ class: "text-sm text-muted-foreground py-4",
138
+ children: $__i18n._({
139
+ id: "/rkqRV",
140
+ message: "All pages are in your navigation."
141
+ })
142
+ }) : /*#__PURE__*/ _jsx("div", {
143
+ class: "flex flex-col divide-y",
144
+ children: otherPages.map((page)=>/*#__PURE__*/ _jsxs(ListItemRow, {
145
+ actions: /*#__PURE__*/ _jsxs(_Fragment, {
146
+ children: [
147
+ /*#__PURE__*/ _jsx("button", {
148
+ type: "button",
149
+ class: "btn-sm-outline",
150
+ "data-on:click__prevent": `@post('/dash/pages/${page.id}/add-to-nav')`,
151
+ children: $__i18n._({
152
+ id: "+MH6k9",
153
+ message: "Add to nav"
154
+ })
155
+ }),
156
+ /*#__PURE__*/ _jsx(ActionButtons, {
157
+ editHref: `/dash/pages/${page.id}/edit`,
158
+ editLabel: $__i18n._({
159
+ id: "ePK91l",
160
+ message: "Edit"
161
+ }),
162
+ viewHref: page.status !== "draft" ? `/${page.slug}` : undefined,
163
+ viewLabel: $__i18n._({
164
+ id: "jpctdh",
165
+ message: "View"
166
+ })
167
+ })
168
+ ]
169
+ }),
170
+ children: [
171
+ /*#__PURE__*/ _jsx("a", {
172
+ href: `/dash/pages/${page.id}`,
173
+ class: "font-medium hover:underline",
174
+ children: page.title || $__i18n._({
175
+ id: "wja8aL",
176
+ message: "Untitled"
177
+ })
178
+ }),
179
+ /*#__PURE__*/ _jsxs("p", {
180
+ class: "text-sm text-muted-foreground mt-1",
181
+ children: [
182
+ "/",
183
+ page.slug
184
+ ]
185
+ })
186
+ ]
187
+ }, page.id))
188
+ })
189
+ ]
190
+ })
191
+ ]
192
+ });
193
+ }
@@ -0,0 +1,209 @@
1
+ /**
2
+ * Account settings: profile + password change forms
3
+ */ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "hono/jsx/jsx-runtime";
4
+ import { useLingui as $_useLingui } from "@jant/core/i18n";
5
+ import { SettingsNav } from "./SettingsNav.js";
6
+ export function AccountContent({ userName }) {
7
+ const { i18n: $__i18n, _: $__ } = $_useLingui();
8
+ const profileSignals = JSON.stringify({
9
+ userName
10
+ }).replace(/</g, "\\u003c");
11
+ return /*#__PURE__*/ _jsxs(_Fragment, {
12
+ children: [
13
+ /*#__PURE__*/ _jsx("h1", {
14
+ class: "text-2xl font-semibold mb-2",
15
+ children: $__i18n._({
16
+ id: "Tz0i8g",
17
+ message: "Settings"
18
+ })
19
+ }),
20
+ /*#__PURE__*/ _jsx(SettingsNav, {
21
+ currentTab: "account"
22
+ }),
23
+ /*#__PURE__*/ _jsxs("div", {
24
+ class: "flex flex-col gap-6 max-w-lg",
25
+ children: [
26
+ /*#__PURE__*/ _jsxs("form", {
27
+ "data-signals": profileSignals,
28
+ "data-on:submit__prevent": "@post('/dash/settings/account')",
29
+ "data-indicator": "_profileLoading",
30
+ children: [
31
+ /*#__PURE__*/ _jsxs("div", {
32
+ class: "card",
33
+ children: [
34
+ /*#__PURE__*/ _jsx("header", {
35
+ children: /*#__PURE__*/ _jsx("h2", {
36
+ children: $__i18n._({
37
+ id: "vERlcd",
38
+ message: "Profile"
39
+ })
40
+ })
41
+ }),
42
+ /*#__PURE__*/ _jsx("section", {
43
+ class: "flex flex-col gap-4",
44
+ children: /*#__PURE__*/ _jsxs("div", {
45
+ class: "field",
46
+ children: [
47
+ /*#__PURE__*/ _jsx("label", {
48
+ class: "label",
49
+ children: $__i18n._({
50
+ id: "6YtxFj",
51
+ message: "Name"
52
+ })
53
+ }),
54
+ /*#__PURE__*/ _jsx("input", {
55
+ type: "text",
56
+ "data-bind": "userName",
57
+ class: "input",
58
+ required: true
59
+ })
60
+ ]
61
+ })
62
+ })
63
+ ]
64
+ }),
65
+ /*#__PURE__*/ _jsxs("button", {
66
+ type: "submit",
67
+ class: "btn mt-4",
68
+ "data-attr:disabled": "$_profileLoading",
69
+ children: [
70
+ /*#__PURE__*/ _jsx("svg", {
71
+ "data-show": "$_profileLoading",
72
+ style: "display:none",
73
+ class: "animate-spin size-4",
74
+ xmlns: "http://www.w3.org/2000/svg",
75
+ viewBox: "0 0 24 24",
76
+ fill: "none",
77
+ stroke: "currentColor",
78
+ "stroke-width": "2",
79
+ "stroke-linecap": "round",
80
+ "stroke-linejoin": "round",
81
+ role: "status",
82
+ children: /*#__PURE__*/ _jsx("path", {
83
+ d: "M21 12a9 9 0 1 1-6.219-8.56"
84
+ })
85
+ }),
86
+ $__i18n._({
87
+ id: "ssqvZi",
88
+ message: "Save Profile"
89
+ })
90
+ ]
91
+ })
92
+ ]
93
+ }),
94
+ /*#__PURE__*/ _jsxs("form", {
95
+ "data-signals": "{currentPassword: '', newPassword: '', confirmPassword: ''}",
96
+ "data-on:submit__prevent": "@post('/dash/settings/password')",
97
+ "data-indicator": "_passwordLoading",
98
+ children: [
99
+ /*#__PURE__*/ _jsxs("div", {
100
+ class: "card",
101
+ children: [
102
+ /*#__PURE__*/ _jsx("header", {
103
+ children: /*#__PURE__*/ _jsx("h2", {
104
+ children: $__i18n._({
105
+ id: "VhMDMg",
106
+ message: "Change Password"
107
+ })
108
+ })
109
+ }),
110
+ /*#__PURE__*/ _jsxs("section", {
111
+ class: "flex flex-col gap-4",
112
+ children: [
113
+ /*#__PURE__*/ _jsxs("div", {
114
+ class: "field",
115
+ children: [
116
+ /*#__PURE__*/ _jsx("label", {
117
+ class: "label",
118
+ children: $__i18n._({
119
+ id: "DCKkhU",
120
+ message: "Current Password"
121
+ })
122
+ }),
123
+ /*#__PURE__*/ _jsx("input", {
124
+ type: "password",
125
+ "data-bind": "currentPassword",
126
+ class: "input",
127
+ required: true,
128
+ autocomplete: "current-password"
129
+ })
130
+ ]
131
+ }),
132
+ /*#__PURE__*/ _jsxs("div", {
133
+ class: "field",
134
+ children: [
135
+ /*#__PURE__*/ _jsx("label", {
136
+ class: "label",
137
+ children: $__i18n._({
138
+ id: "7vhWI8",
139
+ message: "New Password"
140
+ })
141
+ }),
142
+ /*#__PURE__*/ _jsx("input", {
143
+ type: "password",
144
+ "data-bind": "newPassword",
145
+ class: "input",
146
+ required: true,
147
+ minlength: 8,
148
+ autocomplete: "new-password"
149
+ })
150
+ ]
151
+ }),
152
+ /*#__PURE__*/ _jsxs("div", {
153
+ class: "field",
154
+ children: [
155
+ /*#__PURE__*/ _jsx("label", {
156
+ class: "label",
157
+ children: $__i18n._({
158
+ id: "yjkELF",
159
+ message: "Confirm New Password"
160
+ })
161
+ }),
162
+ /*#__PURE__*/ _jsx("input", {
163
+ type: "password",
164
+ "data-bind": "confirmPassword",
165
+ class: "input",
166
+ required: true,
167
+ minlength: 8,
168
+ autocomplete: "new-password"
169
+ })
170
+ ]
171
+ })
172
+ ]
173
+ })
174
+ ]
175
+ }),
176
+ /*#__PURE__*/ _jsxs("button", {
177
+ type: "submit",
178
+ class: "btn mt-4",
179
+ "data-attr:disabled": "$_passwordLoading",
180
+ children: [
181
+ /*#__PURE__*/ _jsx("svg", {
182
+ "data-show": "$_passwordLoading",
183
+ style: "display:none",
184
+ class: "animate-spin size-4",
185
+ xmlns: "http://www.w3.org/2000/svg",
186
+ viewBox: "0 0 24 24",
187
+ fill: "none",
188
+ stroke: "currentColor",
189
+ "stroke-width": "2",
190
+ "stroke-linecap": "round",
191
+ "stroke-linejoin": "round",
192
+ role: "status",
193
+ children: /*#__PURE__*/ _jsx("path", {
194
+ d: "M21 12a9 9 0 1 1-6.219-8.56"
195
+ })
196
+ }),
197
+ $__i18n._({
198
+ id: "VhMDMg",
199
+ message: "Change Password"
200
+ })
201
+ ]
202
+ })
203
+ ]
204
+ })
205
+ ]
206
+ })
207
+ ]
208
+ });
209
+ }
@@ -0,0 +1,259 @@
1
+ /**
2
+ * Appearance settings: color theme picker + custom CSS form
3
+ */ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "hono/jsx/jsx-runtime";
4
+ import { useLingui as $_useLingui } from "@jant/core/i18n";
5
+ import { SettingsNav } from "./SettingsNav.js";
6
+ function ThemeCard({ theme, selected }) {
7
+ const expr = `$theme === '${theme.id}'`;
8
+ const { preview } = theme;
9
+ return /*#__PURE__*/ _jsx("label", {
10
+ class: `block cursor-pointer rounded-lg border overflow-hidden transition-colors ${selected ? "border-primary" : "border-border"}`,
11
+ "data-class:border-primary": expr,
12
+ "data-class:border-border": `$theme !== '${theme.id}'`,
13
+ children: /*#__PURE__*/ _jsxs("div", {
14
+ class: "grid grid-cols-2",
15
+ children: [
16
+ /*#__PURE__*/ _jsxs("div", {
17
+ class: "p-5",
18
+ style: `background-color:${preview.lightBg};color:${preview.lightText}`,
19
+ children: [
20
+ /*#__PURE__*/ _jsx("input", {
21
+ type: "radio",
22
+ name: "theme",
23
+ value: theme.id,
24
+ "data-bind": "theme",
25
+ checked: selected || undefined,
26
+ class: "mb-1"
27
+ }),
28
+ /*#__PURE__*/ _jsx("h3", {
29
+ class: "font-bold text-lg",
30
+ children: theme.name
31
+ }),
32
+ /*#__PURE__*/ _jsxs("p", {
33
+ class: "text-sm mt-2 leading-relaxed",
34
+ children: [
35
+ "This is the ",
36
+ theme.name,
37
+ " theme in light mode. Links",
38
+ " ",
39
+ /*#__PURE__*/ _jsx("a", {
40
+ tabIndex: -1,
41
+ class: "underline",
42
+ style: `color:${preview.lightLink}`,
43
+ children: "look like this"
44
+ }),
45
+ ". We'll show the correct light or dark mode based on your visitor's settings."
46
+ ]
47
+ })
48
+ ]
49
+ }),
50
+ /*#__PURE__*/ _jsxs("div", {
51
+ class: "p-5",
52
+ style: `background-color:${preview.darkBg};color:${preview.darkText}`,
53
+ children: [
54
+ /*#__PURE__*/ _jsx("h3", {
55
+ class: "font-bold text-lg",
56
+ children: theme.name
57
+ }),
58
+ /*#__PURE__*/ _jsxs("p", {
59
+ class: "text-sm mt-2 leading-relaxed",
60
+ children: [
61
+ "This is the ",
62
+ theme.name,
63
+ " theme in dark mode. Links",
64
+ " ",
65
+ /*#__PURE__*/ _jsx("a", {
66
+ tabIndex: -1,
67
+ class: "underline",
68
+ style: `color:${preview.darkLink}`,
69
+ children: "look like this"
70
+ }),
71
+ ". We'll show the correct light or dark mode based on your visitor's settings."
72
+ ]
73
+ })
74
+ ]
75
+ })
76
+ ]
77
+ })
78
+ });
79
+ }
80
+ export function AppearanceContent({ themes, currentThemeId, fontThemes, currentFontThemeId, customCSS }) {
81
+ const { i18n: $__i18n, _: $__ } = $_useLingui();
82
+ const themeSignals = JSON.stringify({
83
+ theme: currentThemeId
84
+ }).replace(/</g, "\\u003c");
85
+ const cssSignals = JSON.stringify({
86
+ customCSS
87
+ }).replace(/</g, "\\u003c");
88
+ return /*#__PURE__*/ _jsxs(_Fragment, {
89
+ children: [
90
+ /*#__PURE__*/ _jsx("h1", {
91
+ class: "text-2xl font-semibold mb-2",
92
+ children: $__i18n._({
93
+ id: "Tz0i8g",
94
+ message: "Settings"
95
+ })
96
+ }),
97
+ /*#__PURE__*/ _jsx(SettingsNav, {
98
+ currentTab: "appearance"
99
+ }),
100
+ /*#__PURE__*/ _jsx("div", {
101
+ "data-signals": themeSignals,
102
+ "data-on:change": "@post('/dash/settings/appearance')",
103
+ class: "max-w-3xl mb-8",
104
+ children: /*#__PURE__*/ _jsxs("fieldset", {
105
+ children: [
106
+ /*#__PURE__*/ _jsx("legend", {
107
+ class: "text-lg font-semibold",
108
+ children: $__i18n._({
109
+ id: "rFmBG3",
110
+ message: "Color theme"
111
+ })
112
+ }),
113
+ /*#__PURE__*/ _jsx("p", {
114
+ class: "text-sm text-muted-foreground mb-4",
115
+ children: $__i18n._({
116
+ id: "07Epll",
117
+ message: "This will theme both your site and your dashboard. All color themes support dark mode."
118
+ })
119
+ }),
120
+ /*#__PURE__*/ _jsx("div", {
121
+ class: "flex flex-col gap-4",
122
+ children: themes.map((theme)=>/*#__PURE__*/ _jsx(ThemeCard, {
123
+ theme: theme,
124
+ selected: theme.id === currentThemeId
125
+ }, theme.id))
126
+ })
127
+ ]
128
+ })
129
+ }),
130
+ /*#__PURE__*/ _jsx("div", {
131
+ "data-signals": JSON.stringify({
132
+ fontTheme: currentFontThemeId
133
+ }).replace(/</g, "\\u003c"),
134
+ "data-on:change": "@post('/dash/settings/font-theme')",
135
+ class: "max-w-3xl",
136
+ children: /*#__PURE__*/ _jsxs("fieldset", {
137
+ children: [
138
+ /*#__PURE__*/ _jsx("legend", {
139
+ class: "text-lg font-semibold",
140
+ children: $__i18n._({
141
+ id: "M2kIWU",
142
+ message: "Font theme"
143
+ })
144
+ }),
145
+ /*#__PURE__*/ _jsx("p", {
146
+ class: "text-sm text-muted-foreground mb-4",
147
+ children: $__i18n._({
148
+ id: "3SAro+",
149
+ message: "Choose a font for your site. All options use system fonts for fast loading."
150
+ })
151
+ }),
152
+ /*#__PURE__*/ _jsx("div", {
153
+ class: "flex flex-col gap-2",
154
+ children: fontThemes.map((ft)=>/*#__PURE__*/ _jsxs("label", {
155
+ class: `flex items-start gap-3 p-3 rounded-lg border cursor-pointer transition-colors ${ft.id === currentFontThemeId ? "border-primary" : "border-border"}`,
156
+ "data-class:border-primary": `$fontTheme === '${ft.id}'`,
157
+ "data-class:border-border": `$fontTheme !== '${ft.id}'`,
158
+ children: [
159
+ /*#__PURE__*/ _jsx("input", {
160
+ type: "radio",
161
+ name: "fontTheme",
162
+ value: ft.id,
163
+ "data-bind": "fontTheme",
164
+ checked: ft.id === currentFontThemeId || undefined,
165
+ class: "mt-1"
166
+ }),
167
+ /*#__PURE__*/ _jsxs("div", {
168
+ children: [
169
+ /*#__PURE__*/ _jsx("div", {
170
+ class: "font-medium",
171
+ children: ft.name
172
+ }),
173
+ /*#__PURE__*/ _jsx("div", {
174
+ class: "text-sm text-muted-foreground",
175
+ children: ft.description
176
+ }),
177
+ /*#__PURE__*/ _jsxs("div", {
178
+ class: "mt-1 text-sm",
179
+ style: `font-family:${ft.fontFamily}`,
180
+ children: [
181
+ "The quick brown fox jumps over the lazy dog.",
182
+ " ",
183
+ "敏捷的棕色狐狸跳过了懒狗。"
184
+ ]
185
+ })
186
+ ]
187
+ })
188
+ ]
189
+ }, ft.id))
190
+ })
191
+ ]
192
+ })
193
+ }),
194
+ /*#__PURE__*/ _jsxs("form", {
195
+ "data-signals": cssSignals,
196
+ "data-on:submit__prevent": "@post('/dash/settings/custom-css')",
197
+ "data-indicator": "_cssLoading",
198
+ class: "max-w-3xl mt-8",
199
+ children: [
200
+ /*#__PURE__*/ _jsxs("fieldset", {
201
+ children: [
202
+ /*#__PURE__*/ _jsx("legend", {
203
+ class: "text-lg font-semibold",
204
+ children: $__i18n._({
205
+ id: "9+vGLh",
206
+ message: "Custom CSS"
207
+ })
208
+ }),
209
+ /*#__PURE__*/ _jsx("p", {
210
+ class: "text-sm text-muted-foreground mb-4",
211
+ children: $__i18n._({
212
+ id: "vmQmHx",
213
+ message: "Add custom CSS to override any styles. Use data attributes like [data-page], [data-post], [data-format] to target specific elements."
214
+ })
215
+ }),
216
+ /*#__PURE__*/ _jsx("textarea", {
217
+ "data-bind": "customCSS",
218
+ class: "textarea font-mono text-sm min-h-32",
219
+ rows: 8,
220
+ placeholder: $__i18n._({
221
+ id: "wc+17X",
222
+ message: "/* Your custom CSS here */"
223
+ }),
224
+ children: customCSS
225
+ })
226
+ ]
227
+ }),
228
+ /*#__PURE__*/ _jsxs("button", {
229
+ type: "submit",
230
+ class: "btn mt-4",
231
+ "data-attr:disabled": "$_cssLoading",
232
+ children: [
233
+ /*#__PURE__*/ _jsx("svg", {
234
+ "data-show": "$_cssLoading",
235
+ style: "display:none",
236
+ class: "animate-spin size-4",
237
+ xmlns: "http://www.w3.org/2000/svg",
238
+ viewBox: "0 0 24 24",
239
+ fill: "none",
240
+ stroke: "currentColor",
241
+ "stroke-width": "2",
242
+ "stroke-linecap": "round",
243
+ "stroke-linejoin": "round",
244
+ role: "status",
245
+ children: /*#__PURE__*/ _jsx("path", {
246
+ d: "M21 12a9 9 0 1 1-6.219-8.56"
247
+ })
248
+ }),
249
+ $__i18n._({
250
+ id: "NU2Fqi",
251
+ message: "Save CSS"
252
+ })
253
+ ]
254
+ })
255
+ ]
256
+ })
257
+ ]
258
+ });
259
+ }